/*** The net library Exposes various structs, constants, and functions for passing messages @module net */ extern "C" { #include #include #include } #include #include #include #include #include #include #include #include #include #include #include #include "load_net.hpp" #include #include "stream.hpp" std::map> netfuncs; /*** Read an integer from the stream @function stream:readint() @treturn number The number read from the stream */ // stream:readInt() int lstream_readint(lua_State* L){//self lua_getfield(L,-1,"data");//self,lightuserdata if(!lua_islightuserdata(L,-1)){ lua_pushstring(L,"data field was not light userdata"); lua_error(L); } struct stream* s = (struct stream*)lua_touserdata(L,-1);//self,lightuserdata stream_print(s); int i = stream_readInt(s); lua_pop(L,2);// lua_pushinteger(L,i);//int return 1; } /*** Read double percision float from the stream @function stream:readdouble() @treturn number The number read from the stream */ // stream:readdouble() int lstream_readdouble(lua_State* L){ lua_getfield(L,-1,"data");//self,lightuserdata struct stream* s = (struct stream*)lua_touserdata(L,-1);//self,lightuserdata double d = stream_readDouble(s);//self,lightuserdata lua_pop(L,2);// lua_pushinteger(L,d);//double return 1; } /*** Read some data from the stream @function stream:readdata() @tparam number size The size of the data to read from the stream @treturn string The data read from the stream */ // stream:readdata(size) int lstream_readdata(lua_State* L){ long size = lua_tonumber(L,-1);//{stream},size lua_pop(L,1);//{stream} lua_getfield(L,-1,"data");//{stream},ud_stream struct stream* s = (struct stream*)lua_touserdata(L,-1);//{stream},ud_stream char buf[size]; stream_readData(s,size,buf); lua_pop(L,2);// lua_pushlstring(L,buf,size);//data return 1; } /*** Read a string from the stream @function stream:readstring() @treturn string The string read from the stream */ // stream:readstring() int lstream_readstring(lua_State* L){ lua_getfield(L,-1,"data");//{stream},ud_stream struct stream* s = (struct stream*)lua_touserdata(L,-1);//{stream},ud_stream char* str = stream_readString(s); lua_pop(L,2); lua_pushstring(L,str);//data return 1; } /*** Write an integer to the stream @function stream:writeint() @tparam number i The integer to write to the stream */ // stream:writeInt(number) int lstream_writeint(lua_State* L){//self,number lua_getfield(L,-2,"data");//self,number,lightuserdata struct stream* s = (struct stream*)lua_touserdata(L,-1);//self,number,lightuserdata stream_print(s); int num = lua_tointeger(L,-2);//self,number,lightuserdata stream_writeInt(s,num); lua_pop(L,3);// return 0; } /*** Write a double percision float to the stream @function stream:writedouble() @tparam number d The number to write to the stream */ // stream:writeDouble(number) int lstream_writedouble(lua_State* L){ lua_getfield(L,-2,"data");//{stream},number,ud_stream struct stream* s = (struct stream*)lua_touserdata(L,-1);//{stream},number,ud_stream lua_pop(L,1);//{stream},number double d = lua_tonumber(L,-1);//{stream},number stream_writeDouble(s,d);//{stream},number lua_pop(L,2);// return 0; } /*** Write some data to the stream @function stream:writedata() @tparam number d The number to write to the stream @treturn number The number of bytes written to the stream */ // stream:writedata(data) int lstream_writedata(lua_State* L){ size_t* datalen = NULL; const char* data = lua_tolstring(L,-1,datalen);//{stream},"data" lua_pop(L,1);//{stream} lua_getfield(L,-1,"data");//{stream},ud_stream struct stream* s = (struct stream*)lua_touserdata(L,-1);//{stream},ud_stream stream_writeData(s,data,*datalen); lua_pop(L,2);// lua_pushinteger(L,*datalen);//size return 1; } /*** Write a string to the stream @function stream:writestring() @tparam string s The string to the stream */ // stream:writestring(string) int lstream_writestring(lua_State* L){ size_t slen = 0; const char* str = lua_tolstring(L,-1,&slen);//{stream},"string" lua_pop(L,1);//{stream} lua_getfield(L,-1,"data");//{stream},ud_stream struct stream* s = (struct stream*)lua_touserdata(L,-1);//{stream},ud_stream stream_writeString(s,str,slen); lua_pop(L,2); return 0; } void gameloop_net(lua_State* L){ //printf("Doing net of gameloop\n"); for(std::map>::iterator it = netfuncs.begin(); it != netfuncs.end(); ++it){ char* buf = NULL; int bytes = nn_recv(it->first, &buf, NN_MSG,NN_DONTWAIT); if(bytes < 0 && nn_errno() != EAGAIN){ lua_pushstring(L,"Failed to receive"); lua_error(L); }else if( bytes < 0 && nn_errno() == EAGAIN){ //do nothing }else{ //find how long until the first null character struct stream* stream = stream_create(); stream->length = bytes; stream->data = buf; stream_print(stream); char* msg = stream_readString(stream); std::map themap = it->second; std::string s = std::string(msg); std::map::iterator in = themap.find(s); if(in != themap.end()){ lua_rawgeti(L,LUA_REGISTRYINDEX,(*in).second);//function(stream) lua_newtable(L);//function(stream),{} lua_pushlightuserdata(L,stream);//function(stream),{},ud_stream lua_setfield(L,-2,"data");//function(stream),{data=ud_stream} luaL_getmetatable(L,"net.stream");//function(stream),{data=ud_stream},{m_net.stream} lua_setmetatable(L,-2);//function(stream),{stream} lua_call(L,1,0);// } nn_freemsg(buf); free(stream);//We manually set stream->data so free_stream would crash here } } } /*** @function socket:bind @tparam string where Where to connect this socket to @usage local s = net.newsocket() s:bind("tcp://127.0.0.1:8765") s:receive("ping",function(stream) print(instream:readstring()) end) local c = net.newsocket() c:connect("127.0.0.1") */ //bind({self},"where") int bindsocket(lua_State*L){ const char* s = lua_tostring(L,-1);//{self},"where" lua_pop(L,1);//{self} lua_getfield(L,-1,"fd");//{self},num_socket int fd = (int)lua_tonumber(L,-1); lua_pop(L,1);//{self} int id = nn_bind(fd,s); if(id < 0){ printf("Socket error\n"); const char* errstr = nn_strerror(nn_errno()); char* failmsg = (char*)"Failed to bind socket: "; int faillen = strlen(failmsg + 2); char buf[faillen + strlen(errstr)]; sprintf(buf,"%s%s\n",failmsg,errstr); lua_pushstring(L,buf); lua_error(L); } lua_pushinteger(L,id);//{self},endpoint lua_setfield(L,-2,"endpoint");//{self} netfuncs[fd] = std::map(); return 0; } int connectsocket(lua_State* L){ const char* s = lua_tostring(L,-1); lua_pushstring(L,"fd"); lua_gettable(L,-2); int fd = lua_tonumber(L,-1); lua_pop(L,2); int id = nn_connect(fd,s); lua_pushstring(L,"endpoint"); lua_pushinteger(L,id); lua_settable(L,-3); netfuncs[fd] = std::map(); return 0; } //socket:send("name",function(stream)) int send(lua_State* L){ const char* data = lua_tostring(L,-2);//{socket},"name",function(stream) lua_getfield(L,-3,"fd");//{socket},"name",function(stream),int_socketdescriptor int fd = lua_tonumber(L,-1);//socket,"name",function(stream),int_socketdescriptor lua_pop(L,1);//socket,"name",function(stream) int dlen = strlen(data); struct stream* s = stream_create(); stream_writeString(s,data,dlen); lua_newtable(L);//socket,"name",function(stream),streamtable luaL_getmetatable(L,"net.stream");//socket,"name",function(stream),streamtable,net.stream lua_setmetatable(L,-2);//socket,"name",function(stream),streamtable lua_pushlightuserdata(L,s);//socket,"name",function(stream),streamtable,lightudata lua_setfield(L,-2,"data");//socket,"name",function(stream),streamtable lua_call(L,1,0);//socket,"name" lua_pop(L,2);// int err = nn_send(fd,s->data,s->length,0); stream_free(s); if(err < 0){ const char* errstr = nn_strerror(nn_errno()); char* failmsg = (char*)"Failed to bind socket: "; int faillen = strlen(failmsg + 2); char buf[faillen + strlen(errstr)]; lua_pushstring(L,buf); lua_error(L); } return 0; } /*** @function net.receive @tparam string message The message to bind this function to @tparam function callback The function to call when this message is received */ //LUA: //socket:receive(s_name,function(stream)) int netreceive(lua_State* L){ const char* name = lua_tostring(L,-2); //int slen = strlen(name); std::string s = std::string(name); int func = luaL_ref(L,LUA_REGISTRYINDEX); lua_pushstring(L,"fd"); lua_gettable(L,-2); int fd = lua_tonumber(L,-1); lua_pop(L,1); netfuncs[fd].insert(std::pair(s,func)); return 0; } /*** @field fd @table net.socket @domain shared */ /*** @function net.newsocket @return net.socket @domain shared */ //net.newsocket(domain, type) int socketFactory(lua_State*L){ //int domain = luaL_optint(L,-1,0); //int type = luaL_optint(L,-2,0); int c = nn_socket(AF_SP,NN_PAIR); if(c < 0){ lua_pushstring(L,"Failed to create socket"); lua_error(L); } lua_newtable(L);//{} lua_pushinteger(L,c);//{},c lua_setfield(L,-2,"fd");//{fd=c} luaL_getmetatable(L,"net.socket");//{},{m_net.socket} lua_setmetatable(L,-2);//{socket} //lua_newtable(L); //lua_pushstring(L,"fd"); //lua_pushinteger(L,c); //lua_settable(L,-3); //lua_pushstring(L,"bind"); //lua_pushcfunction(L,bindsocket); //lua_settable(L,-3); //lua_pushstring(L,"connect"); //lua_pushcfunction(L,connectsocket); //lua_settable(L,-3); //lua_pushstring(L,"send"); //lua_pushcfunction(L,send); //lua_settable(L,-3); //lua_pushstring(L,"receive"); //lua_pushcfunction(L,netreceive); //lua_settable(L,-3); return 1; } static const struct luaL_Reg stream_m[] = { {"writeint",lstream_writeint}, {"writedouble",lstream_writedouble}, {"writedata",lstream_writedata}, {"writestring",lstream_writestring}, {"readint",lstream_readint}, {"readdouble",lstream_readdouble}, {"readdata",lstream_readdata}, {"readstring",lstream_readstring}, {NULL,NULL} }; static const struct luaL_Reg socket_m[] = { {"bind", bindsocket}, {"connect", connectsocket}, {"send",send}, {"receive", netreceive}, {NULL,NULL} }; static const struct luaL_Reg net_f[] = { {"newsocket", socketFactory}, {NULL,NULL} }; #define set_const(l,x) lua_pushstring(l,#x);lua_pushinteger(l,x);lua_settable(l,-3); void loadNetLibs(lua_State* L){ //A table to hold all our net funcs lua_newtable(L);//{} //Push some enums set_const(L,AF_SP); set_const(L,AF_SP_RAW); set_const(L,NN_PROTO_PAIR); set_const(L,NN_PAIR); set_const(L,NN_SUB); set_const(L,NN_SUB_SUBSCRIBE); set_const(L,NN_PUB); set_const(L,NN_SUB_UNSUBSCRIBE); set_const(L,NN_PUSH); set_const(L,NN_PULL); set_const(L,NN_PROTO_PIPELINE); set_const(L,NN_PROTO_SURVEY); set_const(L,NN_SURVEYOR); set_const(L,NN_RESPONDENT); set_const(L,NN_SURVEYOR_DEADLINE); set_const(L,NN_TCP_NODELAY); set_const(L,NN_TCP); set_const(L,NN_PROTO_BUS); set_const(L,NN_BUS); set_const(L,NN_DONTWAIT); set_const(L,PROTO_SP); set_const(L,SP_HDR); luaL_register(L,NULL,net_f); //Set the table to gobal "net" lua_setglobal(L,"net"); //Create the metatable for streams luaL_newmetatable(L,"net.stream"); //net.stream lua_newtable(L);//net.stream,{} luaL_register(L,NULL,stream_m);//net.stream,{net.stream} lua_setfield(L,-2,"__index");//{m_net.stream} lua_pop(L,1);// //Create the metatable for sockets luaL_newmetatable(L,"net.socket");//net.socket lua_newtable(L);//net.socket,{} luaL_register(L,NULL,socket_m);//net.socket,{net.socket} lua_setfield(L,-2,"__index");//{m_net.socket} lua_pop(L,1);// }