#include #include #include #define NNG_STATIC_LIB #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lua-nng-aio.h" /*** The lua binding of Nanomessage Next Generation @namespace nng */ @namespace nng #define OPEN(name)\ int lnng_ ## name ## _open(lua_State *L){\ nng_socket *s = (nng_socket*)lua_newuserdata(L,sizeof(nng_socket));\ int err = nng_ ## name ## _open(s);\ if(err == 0){\ luaL_setmetatable(L,"nng.socket");\ return 1;\ }else{\ lua_pushboolean(L,0);\ lua_pushstring(L,nng_strerror(err));\ return 2;\ }\ } /*** Opens a socket using the bus scaleability protocol Sockets are not connected to anything at initalization, and some options may error. See the [options](/options) section for information on options. See [nng_bus](https://nng.nanomsg.org/man/tip/nng_bus.7.html) for more information on the protocol. @function nng.open_bus0() @returns nng.socket A socket using the bus protocol */ OPEN(bus0); OPEN(pair1); OPEN(pub0); OPEN(sub0); OPEN(pull0); OPEN(push0); OPEN(req0); OPEN(rep0); OPEN(surveyor0); OPEN(respondent0); //sleep(ms) int lnng_msleep(lua_State *L){ int ms = luaL_checkinteger(L,1); nng_msleep(ms); lua_pop(L,1); return 0; } nng_socket* tosocket(lua_State *L, int offset){ luaL_checkudata(L,offset,"nng.socket"); return (nng_socket*)lua_touserdata(L,offset); } nng_listener* tolistener(lua_State *L, int offset){ luaL_checkudata(L,offset,"nng.listener"); return (nng_listener*)lua_touserdata(L,offset); } nng_dialer* todialer(lua_State *L, int offset){ luaL_checkudata(L,offset,"nng.dialer"); return (nng_dialer*)lua_touserdata(L,offset); } nng_sockaddr* tosockaddr(lua_State *L, int offset){ luaL_checkudata(L,offset,"nng.sockaddr"); return (nng_sockaddr*)lua_touserdata(L,offset); } //socket:listen(url[, flags]) :: listener int lnng_listen(lua_State *L){ int argc = lua_gettop(L); int flags = 0; nng_socket *sock = tosocket(L,1); const char *url = luaL_checkstring(L,2); if(argc >= 3){ flags = luaL_checkinteger(L,3); } lua_pop(L,argc); nng_listener *lp = (nng_listener*)lua_newuserdata(L,sizeof(nng_listener)); int err = nng_listen(*sock, url, lp, flags); if(err == 0){ luaL_setmetatable(L,"nng.listener"); return 1; }else{ lua_pushboolean(L,0); lua_pushstring(L,nng_strerror(err)); return 2; } } //socket:dial(url[, flags]) :: dialer int lnng_dial(lua_State *L){ int argc = lua_gettop(L); int flags = 0; nng_socket *sock = tosocket(L,1); const char *url = luaL_checkstring(L,2); if(argc >= 3){ flags = luaL_checkinteger(L,3); } lua_pop(L,argc); nng_dialer *dp = (nng_dialer*)lua_newuserdata(L,sizeof(nng_dialer)); int err = nng_dial(*sock, url, dp, flags); if(err == 0){ luaL_setmetatable(L,"nng.dialer"); return 1; }else{ lua_pushboolean(L,0); lua_pushstring(L,nng_strerror(err)); return 2; } } //socket:send("data"[, flags]) int lnng_send(lua_State *L){ int argc = lua_gettop(L); int flags = 0; nng_socket *sock = tosocket(L,1); size_t datasize; const char *data = luaL_checklstring(L,2,&datasize); if(argc >= 3){ flags = luaL_checkinteger(L,3); } //No garentee that *data is valid after it gets poped from the stack //so we have to send it (which copies the value) before poping it from //the stack. int err = nng_send(*sock, (void*)data, datasize, flags); lua_pop(L,argc); if(err == 0){ lua_pushboolean(L,1); return 1; }else{ lua_pushboolean(L,0); lua_pushstring(L,nng_strerror(err)); return 2; } } //socket:recv([flags]) int lnng_recv(lua_State *L){ int argc = lua_gettop(L); int flags = NNG_FLAG_ALLOC; //don't support zero copy nng_socket *sock = tosocket(L,1); if(argc >= 2){ flags += luaL_checkinteger(L,2); } char *data = NULL; size_t datasize; int err = nng_recv(*sock, &data, &datasize, flags); if(err == 0){ lua_pushlstring(L,data,datasize); nng_free(data,datasize); return 1; }else{ lua_pushboolean(L,0); lua_pushstring(L,nng_strerror(err)); return 2; } } //socket:close() int lnng_socket_close(lua_State *L){ /*printf("Garbage collecting socket...");*/ nng_socket *sock = tosocket(L,1); int err = nng_close(*sock); lua_pop(L,1); return 0; } //close(ud_dialer) int lnng_dialer_close(lua_State *L){ nng_dialer *dp = (nng_dialer*)lua_touserdata(L,1); nng_dialer_close(*dp); lua_pop(L,1); return 0; } //close(ud_listener) int lnng_listener_close(lua_State *L){ nng_listener *lp = (nng_listener*)lua_touserdata(L,1); int err = nng_listener_close(*lp); lua_pop(L,1); return 0; } //subscribe(socket,"topic") int lnng_subscribe(lua_State *L){ nng_socket *sock = tosocket(L,1); size_t size; const char *topic = luaL_checklstring(L,2,&size); lua_pop(L,2); int err = nng_socket_set(*sock,NNG_OPT_SUB_SUBSCRIBE,topic,size); if(err == 0){ lua_pushboolean(L,1); return 1; }else{ lua_pushboolean(L,0); lua_pushstring(L,nng_strerror(err)); return 2; } } //unsubscribe(socket,"topic") int lnng_unsubscribe(lua_State *L){ nng_socket *sock = tosocket(L,1); size_t size; const char *topic = luaL_checklstring(L,2,&size); lua_pop(L,2); int err = nng_socket_set(*sock,NNG_OPT_SUB_UNSUBSCRIBE,topic,size); if(err == 0){ lua_pushboolean(L,1); return 1; }else{ lua_pushboolean(L,0); lua_pushstring(L,nng_strerror(err)); return 2; } } //Option types #define SOCKET_OPTION_SET(L, socket, flag, matches, ntype, gets, sets) \ if(strcmp(flag, matches) == 0){\ ntype value = (ntype)gets(L,3);\ int err = sets(*socket, flag, value);\ lua_pop(L,lua_gettop(L));\ if(err != 0){\ lua_pushboolean(L,0);\ lua_pushfstring(L,nng_strerror(err));\ return 2;\ }else{\ return 0;\ }\ } #define SOCKET_OPTION_GET(L, socket, flag, matches, ntype, gets, pushes) \ if(strcmp(flag, matches) == 0){\ ntype value;\ int err = gets(*socket, flag, &value);\ lua_pop(L,lua_gettop(L));\ if(err != 0){\ lua_pushboolean(L,0);\ lua_pushfstring(L,nng_strerror(err));\ return 2;\ }else{\ pushes(L,value);\ return 1;\ }\ } //TODO //set(listener,"flag",value) int lnng_listener_set(lua_State *L){ return 0; } int lnng_sockaddr_get(lua_State *L){ nng_sockaddr *sa = tosockaddr(L,1); unsigned int f = sa->s_family; const char *field = luaL_checkstring(L,2); lua_pop(L,2); printf("Getting %s from sockaddr\n",field); if(strcmp(field,"type") == 0){ lua_pushnumber(L,f); return 1; } if(f == NNG_AF_UNSPEC){ printf("Unspec\n"); lua_pushnil(L); return 1; }else if(f == NNG_AF_INPROC){ printf("Inproc\n"); nng_sockaddr_inproc sai = sa->s_inproc; if(strcmp(field,"name") == 0){ lua_pushstring(L, sai.sa_name); return 1; } }else if(f == NNG_AF_IPC){ printf("IPC\n"); nng_sockaddr_ipc sai = sa->s_ipc; if(strcmp(field,"path") == 0){ lua_pushstring(L, sai.sa_path); return 1; } }else if(f == NNG_AF_INET){ printf("Inet\n"); nng_sockaddr_in sai = sa->s_in; if(strcmp(field,"addr") == 0){ lua_pushnumber(L, sai.sa_addr); return 1; }else if(strcmp(field,"port") == 0){ lua_pushnumber(L, sai.sa_port); return 1; } }else if(f == NNG_AF_INET6){ nng_sockaddr_in6 sai = sa->s_in6; if(strcmp(field,"addr") == 0){ lua_pushlstring(L,sai.sa_addr,16); return 1; }else if(strcmp(field,"port") == 0){ lua_pushnumber(L,sai.sa_port); return 1; } }else if(f == NNG_AF_ZT){ nng_sockaddr_zt sai = sa->s_zt; if(strcmp(field,"nwid") == 0){ lua_pushnumber(L,sai.sa_nwid); return 1; }else if(strcmp(field,"nodeid") == 0){ lua_pushnumber(L,sai.sa_nodeid); return 1; }else if(strcmp(field,"port") == 0){ lua_pushnumber(L,sai.sa_port); return 1; } } } //set(socket, "flag", value) int lnng_socket_set(lua_State *L){ nng_socket *sock = tosocket(L,1); const char *flag = luaL_checkstring(L,2); //NNG_OPT_LOCADDR - read-only SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_RECONNMINT, nng_duration, luaL_checkinteger, nng_socket_set_ms); SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_RECONNMAXT, nng_duration, luaL_checkinteger, nng_socket_set_ms); SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_RECVBUF, int, luaL_checkinteger, nng_socket_set_int); //NNG_OPT_RECVFD - read-only SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_RECVMAXSZ, size_t, luaL_checkinteger, nng_socket_set_uint64); SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_RECVTIMEO, nng_duration, luaL_checkinteger, nng_socket_set_ms); //NNG_OPT_REMADDR - read-only SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_SENDBUF, int, luaL_checkinteger, nng_socket_set_int); //NNG_OPT_SENDFD - read-only SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_SENDTIMEO, nng_duration, luaL_checkinteger, nng_socket_set_ms); SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_SOCKNAME, const char*, luaL_checkstring, nng_socket_set_string); SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_MAXTTL, int, luaL_checkinteger, nng_socket_set_int); //NNG_OPT_UR - read-only //NNG_OPT_PROTO - read-only //NNG_OPT_PEER - read-only //NNG_OPT_PROTONAME - read-only //NNG_OPT_PEERNAME - read-only //TCP options SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_TCP_NODELAY, bool, lua_toboolean, nng_socket_set_bool); SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_TCP_KEEPALIVE, bool, lua_toboolean, nng_socket_set_bool); //NNG_OPT_TCP_BOUND_PORT - read-only? documentation doesn't say it, but it would be wierd if we could write to it. //TLS options SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_TLS_AUTH_MODE, int, luaL_checkinteger, nng_socket_set_int); //write-only SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_TLS_CA_FILE, const char*, luaL_checkstring, nng_socket_set_string); //write-only SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_TLS_CERT_KEY_FILE, const char*, luaL_checkstring, nng_socket_set_string); //write-only //SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_TLS TODO: NNG_OPT_TLS_CONFIG SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_TLS_SERVER_NAME, const char*, luaL_checkstring, nng_socket_set_string); //NNG_OPT_TLS_VERIFIED - read-only //IPC options //NNG_OPT_IPC_PEER_GID - read-only //NNG_OPT_IPC_PEER_PID - read-only //NNG_OPT_IPC_PEER_UID - read-only //NNG_OPT_IPC_PEER_ZONEID - read-only SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_IPC_PERMISSIONS, int, luaL_checkinteger, nng_socket_set_int); //TODO: NNG_OPT_IPC_SECURITY_DESCRIPTOR - windows-only, sets a pointer to a PSECURITY_DESCRIPTOR //PUB/SUB options SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_SUB_PREFNEW, bool, lua_toboolean, nng_socket_set_bool); //REQ/REP options SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_REQ_RESENDTIME, nng_duration, luaL_checkinteger, nng_socket_set_ms); //Survayor/respondent options SOCKET_OPTION_SET(L, sock, flag, NNG_OPT_SURVEYOR_SURVEYTIME, nng_duration, luaL_checkinteger, nng_socket_set_ms); } //get(socket,"flag",value) int lnng_socket_get(lua_State *L){ /*printf("Lua stack is %d\n",lua_gettop(L));*/ nng_socket *sock = tosocket(L,1); const char *flag = luaL_checkstring(L,2); //NNG_OPT_LOCADDR - listeners, dialers, and connected pipes SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_RAW, bool, nng_socket_get_bool, lua_pushboolean); //read-only SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_RECONNMINT, nng_duration, nng_socket_get_ms, lua_pushinteger);//sockets and dialers, if both dialer and socket are set, dialer overrides socket SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_RECONNMAXT, nng_duration, nng_socket_get_ms, lua_pushinteger); //sockets and dialers, if both dialer and socket are set, dialer overrides socket SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_RECVBUF, int, nng_socket_get_int, lua_pushinteger);//socket only SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_RECVFD, int, nng_socket_get_int, lua_pushinteger); //socket only, read-only SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_RECVMAXSZ, size_t, nng_socket_get_size, lua_pushinteger);//sockets, dialers and listeners SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_RECVTIMEO, nng_duration, nng_socket_get_ms, lua_pushinteger);//socket only if(strcmp(flag, NNG_OPT_REMADDR) == 0){ lua_pop(L,lua_gettop(L)); nng_sockaddr *sa = (nng_sockaddr*)lua_newuserdata(L,sizeof(nng_sockaddr));//{udata} int err = nng_socket_get_addr(*sock, NNG_OPT_REMADDR, sa);//{udata} if(err == 0){ luaL_setmetatable(L,"nng.sockaddr"); return 1; }else{ return luaL_error(L,"Failed to lookup local address - %s",nng_strerror(err)); } } SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_SENDBUF, int, nng_socket_get_int, lua_pushinteger); SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_SENDFD, int, nng_socket_get_int, lua_pushinteger); //read-only SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_SENDTIMEO, nng_duration, nng_socket_get_ms, lua_pushinteger); SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_SOCKNAME, char*, nng_socket_get_string, lua_pushstring); SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_MAXTTL, int, nng_socket_get_int, lua_pushinteger); //SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_URL, char*, nng_socket_get_string, lua_pushstring); //read-only for dialers, listeners, and pipes SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_PROTO, int, nng_socket_get_int, lua_pushinteger); //read-only SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_PEER, int, nng_socket_get_int, lua_pushinteger); //read-only SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_PROTONAME, char*, nng_socket_get_string, lua_pushstring); //read-only SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_PEERNAME, char*, nng_socket_get_string, lua_pushstring); //read-only //TCP options SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_TCP_NODELAY, bool, nng_socket_get_bool, lua_pushboolean); SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_TCP_KEEPALIVE, bool, nng_socket_get_bool, lua_pushboolean); SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_TCP_BOUND_PORT, int, nng_socket_get_int, lua_pushinteger); //TLS options //NNG_OPT_TLS_MODE - write-only option //NNG_OPT_TLS_CA_FILE - write-only option //NNG_OPT_TLS_CERT_KEY_FILE - write-only option //TODO: NNG_OPT_TLS_CONFIG //NNG_OPT_TLS_SERVER_NAME - write-only option SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_TLS_VERIFIED, bool, nng_socket_get_bool, lua_pushboolean); //read-only option //IPC options SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_IPC_PEER_GID, uint64_t, nng_socket_get_uint64, lua_pushinteger); //read-only option SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_IPC_PEER_PID, uint64_t, nng_socket_get_uint64, lua_pushinteger); //read-only option SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_IPC_PEER_UID, uint64_t, nng_socket_get_uint64, lua_pushinteger); //read-only option SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_IPC_PEER_ZONEID, uint64_t, nng_socket_get_uint64, lua_pushinteger); //read-only option on Solaris and illumos systems only //NNG_OPT_IPC_PERMISSIONS - write-only option //NNG_OPT_IPC_SECURITY_DESCRIPTOR - write-only option //PUB/SUB options SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_SUB_PREFNEW, bool, nng_socket_get_bool, lua_pushboolean); //REQ/REP options SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_REQ_RESENDTIME, nng_duration, nng_socket_get_ms, lua_pushinteger); //Survayor/respondent options SOCKET_OPTION_GET(L, sock, flag, NNG_OPT_SURVEYOR_SURVEYTIME, nng_duration, nng_socket_get_ms, lua_pushinteger); lua_pop(L,2); //If none of the above options matched, get the value from the metatable int type = luaL_getmetatable(L,"nng.socket_m");////{socket_m} /*luaL_newlib(L,nng_socket_m);*/ lua_getfield(L,-1,"__index"); lua_getfield(L,-1,flag);//{socket_m},{socket},any int ref = luaL_ref(L,LUA_REGISTRYINDEX);//{socket_m},{socket} lua_pop(L,2);// lua_rawgeti(L,LUA_REGISTRYINDEX,ref);//any return 1; } /*#define DIALER_OPTION_SET(L, socket, flag, matches, ntype, gets, sets) \*/ /*if(strcmp(flag, matches) == 0){\*/ /*ntype value = (ntype)gets(L,3);\*/ /*int err = sets(*socket, flag, value);\*/ /*lua_pop(L,lua_gettop(L));\*/ /*if(err != 0){\*/ /*lua_pushboolean(L,0);\*/ /*lua_pushfstring(L,nng_strerror(err));\*/ /*return 2;\*/ /*}else{\*/ /*return 0;\*/ /*}\*/ /*}*/ /*#define DIALER_OPTION_GET(L, dialer, flag, matches, ntype, gets, pushes) \*/ /*if(strcmp(flag, matches) == 0){\*/ /*ntype value;\*/ /*int err = gets(*socket, flag, &value);\*/ /*lua_pop(L,lua_gettop(L));\*/ /*if(err != 0){\*/ /*lua_pushboolean(L,0);\*/ /*lua_pushfstring(L,nng_strerror(err));\*/ /*return 2;\*/ /*}else{\*/ /*pushes(L,value);\*/ /*return 1;\*/ /*}\*/ /*}*/ int lnng_dialer_get(lua_State *L){ nng_dialer *dialer = todialer(L,1); const char *flag = luaL_checkstring(L,2); if(strcmp(flag, NNG_OPT_LOCADDR) == 0){ printf("Looking for dialer's locaddr\n"); lua_pop(L,lua_gettop(L)); nng_sockaddr *sa = (nng_sockaddr*)lua_newuserdata(L,sizeof(nng_sockaddr));//{udata} int err = nng_dialer_get_addr(*dialer , NNG_OPT_LOCADDR, sa);//{udata} if(err == 0){ luaL_setmetatable(L,"nng.sockaddr"); return 1; }else{ return luaL_error(L,"Failed to lookup local address - %s",nng_strerror(err)); } } SOCKET_OPTION_GET(L, dialer, flag, NNG_OPT_RECONNMINT, nng_duration, nng_dialer_get_ms, lua_pushinteger);//sockets and dialers, if both dialer and socket are set, dialer overrides socket SOCKET_OPTION_GET(L, dialer, flag, NNG_OPT_RECONNMAXT, nng_duration, nng_dialer_get_ms, lua_pushinteger); //sockets and dialers, if both dialer and socket are set, dialer overrides socket SOCKET_OPTION_GET(L, dialer, flag, NNG_OPT_RECVMAXSZ, size_t, nng_dialer_get_size, lua_pushinteger);//sockets, dialers and listeners if(strcmp(flag, NNG_OPT_REMADDR) == 0){ lua_pop(L,lua_gettop(L)); nng_sockaddr *sa = (nng_sockaddr*)lua_newuserdata(L,sizeof(nng_sockaddr));//{udata} int err = nng_dialer_get_addr(*dialer, NNG_OPT_REMADDR, sa);//{udata} if(err == 0){ luaL_setmetatable(L,"nng.sockaddr"); return 1; }else{ return luaL_error(L,"Failed to lookup remote address - %s",nng_strerror(err)); } } SOCKET_OPTION_GET(L, dialer, flag, NNG_OPT_URL, char*, nng_dialer_get_string, lua_pushstring); //read-only for dialers, listeners, and pipes //If none of the above options matched, get the value from the metatable int type = luaL_getmetatable(L,"nng.dialer_m");////{socket_m} /*luaL_newlib(L,nng_socket_m);*/ lua_getfield(L,-1,"__index"); lua_getfield(L,-1,flag);//{socket_m},{socket},any int ref = luaL_ref(L,LUA_REGISTRYINDEX);//{socket_m},{socket} lua_pop(L,2);// lua_rawgeti(L,LUA_REGISTRYINDEX,ref);//any return 1; } int lnng_dialer_set(lua_State *L){ } static const struct luaL_Reg nng_dialer_m[] = { {"close",lnng_dialer_close}, {NULL, NULL} }; static const struct luaL_Reg nng_listener_m[] = { {"close",lnng_listener_close}, {NULL, NULL} }; static const struct luaL_Reg nng_socket_m[] = { {"dial", lnng_dial}, {"listen", lnng_listen}, {"send", lnng_send}, {"recv", lnng_recv}, {"close", lnng_socket_close}, //pub/sub only {"subscribe",lnng_subscribe}, {"unsubscribe",lnng_unsubscribe}, {NULL, NULL} }; static const struct luaL_Reg nng_f[] = { {"bus0_open", lnng_bus0_open}, {"pair1_open", lnng_pair1_open}, {"pub0_open", lnng_pub0_open}, {"sub0_open", lnng_sub0_open}, {"pull0_open", lnng_pull0_open}, {"push0_open", lnng_push0_open}, {"req0_open", lnng_req0_open}, {"rep0_open", lnng_rep0_open}, {"surveyor0_open",lnng_surveyor0_open}, {"respondent0_open",lnng_respondent0_open}, {"sleep",lnng_msleep}, {NULL, NULL} }; #define flag(name) lua_pushnumber(L,name); lua_setfield(L,-2,#name); #define option(name) lua_pushstring(L,name); lua_setfield(L,-2,#name); int luaopen_nng(lua_State *L){ luaL_newmetatable(L,"nng.socket_m");//{} luaL_newlib(L,nng_socket_m);//{},{socket_m} lua_setfield(L,-2,"__index");//{__index={socket_m}} lua_pop(L,1);// luaL_newmetatable(L,"nng.socket");//{} lua_pushcfunction(L,lnng_socket_get);//{},socket_get() lua_setfield(L,-2,"__index");//{__index = socket_get()} lua_pushcfunction(L,lnng_socket_close);//{__index = {socket_m}},close() lua_setfield(L,-2,"__gc");//{__index = {socket_m}, __gc = close()} lua_pushcfunction(L,lnng_socket_set);//{__index = {socket_m}, __gc = close()}, set() lua_setfield(L,-2,"__newindex");//{__index = {socket_m}, __gc = close(), __newindex = set()} lua_pop(L,1); luaL_newmetatable(L,"nng.dialer");//{} lua_pushcfunction(L,lnng_dialer_get);//{},dialer_get() lua_setfield(L,-2,"__index"); lua_pushcfunction(L,lnng_dialer_set); lua_setfield(L,-2,"__newindex"); luaL_newmetatable(L,"nng.dialer_m"); luaL_newlib(L,nng_dialer_m); lua_setfield(L,-2,"__index"); /*lua_pushcfunction(L,lnng_dialer_close);*/ /*lua_setfield(L,-2,"__gc");*/ lua_pop(L,1); luaL_newmetatable(L,"nng.listener"); luaL_newlib(L,nng_listener_m); lua_setfield(L,-2,"__index"); /*lua_pushcfunction(L,lnng_listener_close);*/ /*lua_setfield(L,-2,"__gc");*/ lua_pop(L,1); luaL_newmetatable(L,"nng.sockaddr");//{nng.sockaddr} lua_pushcfunction(L,lnng_sockaddr_get);//{nng.sockaddr},sockaddr_get lua_setfield(L,-2,"__index");//{nng_sockaddr} lua_pop(L,1); luaL_newlib(L,nng_f); luaopen_nng_aio(L); lua_setfield(L,-2,"aio"); //Flags flag(NNG_FLAG_NONBLOCK); flag(NNG_FLAG_ALLOC); //Options option(NNG_OPT_SOCKNAME); option(NNG_OPT_SOCKNAME); option(NNG_OPT_RAW); option(NNG_OPT_PROTO); option(NNG_OPT_PROTONAME); option(NNG_OPT_PEER); option(NNG_OPT_PEERNAME); option(NNG_OPT_RECVBUF); option(NNG_OPT_SENDBUF); option(NNG_OPT_RECVFD); option(NNG_OPT_SENDFD); option(NNG_OPT_RECVTIMEO); option(NNG_OPT_SENDTIMEO); option(NNG_OPT_LOCADDR); option(NNG_OPT_REMADDR); option(NNG_OPT_URL); option(NNG_OPT_MAXTTL); option(NNG_OPT_RECVMAXSZ); option(NNG_OPT_RECONNMINT); option(NNG_OPT_RECONNMAXT); //TCP options option(NNG_OPT_TCP_NODELAY); option(NNG_OPT_TCP_KEEPALIVE); option(NNG_OPT_TCP_BOUND_PORT); //IPC options option(NNG_OPT_IPC_PEER_GID); option(NNG_OPT_IPC_PEER_PID); option(NNG_OPT_IPC_PEER_UID); option(NNG_OPT_IPC_PEER_ZONEID); option(NNG_OPT_IPC_PERMISSIONS); option(NNG_OPT_IPC_SECURITY_DESCRIPTOR); //Pub/sub options /*option(NNG_OPT_SUB_SUBSCRIBE);//should use socket:subscribe() instead (so that nil is not counted as part of the subscription)*/ /*option(NNG_OPT_SUB_UNSUBSCRIBE);//should use socket:unsubscribe() instead (same reason as above)*/ option(NNG_OPT_SUB_PREFNEW); //Req/rep options option(NNG_OPT_SURVEYOR_SURVEYTIME); return 1; }