net.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046
  1. // Module for network
  2. #include "module.h"
  3. #include "lauxlib.h"
  4. #include "platform.h"
  5. #include "lmem.h"
  6. #include "c_string.h"
  7. #include "c_stdlib.h"
  8. #include "c_types.h"
  9. #include "mem.h"
  10. #include "osapi.h"
  11. #include "lwip/err.h"
  12. #include "lwip/ip_addr.h"
  13. #include "lwip/dns.h"
  14. #include "lwip/igmp.h"
  15. #include "lwip/tcp.h"
  16. #include "lwip/udp.h"
  17. #if defined(CLIENT_SSL_ENABLE) && defined(LUA_USE_MODULES_NET) && defined(LUA_USE_MODULES_TLS)
  18. #define TLS_MODULE_PRESENT
  19. #endif
  20. typedef enum net_type {
  21. TYPE_TCP_SERVER = 0,
  22. TYPE_TCP_CLIENT,
  23. TYPE_UDP_SOCKET
  24. } net_type;
  25. typedef const char net_table_name[14];
  26. static const net_table_name NET_TABLES[] = {
  27. "net.tcpserver",
  28. "net.tcpsocket",
  29. "net.udpsocket"
  30. };
  31. #define NET_TABLE_TCP_SERVER NET_TABLES[0]
  32. #define NET_TABLE_TCP_CLIENT NET_TABLES[1]
  33. #define NET_TABLE_UDP_SOCKET NET_TABLES[2]
  34. #define TYPE_TCP TYPE_TCP_CLIENT
  35. #define TYPE_UDP TYPE_UDP_SOCKET
  36. typedef struct lnet_userdata {
  37. enum net_type type;
  38. int self_ref;
  39. union {
  40. struct tcp_pcb *tcp_pcb;
  41. struct udp_pcb *udp_pcb;
  42. void *pcb;
  43. };
  44. union {
  45. struct {
  46. int cb_accept_ref;
  47. int timeout;
  48. } server;
  49. struct {
  50. int wait_dns;
  51. int cb_dns_ref;
  52. int cb_receive_ref;
  53. int cb_sent_ref;
  54. // Only for TCP:
  55. int hold;
  56. int cb_connect_ref;
  57. int cb_disconnect_ref;
  58. int cb_reconnect_ref;
  59. } client;
  60. };
  61. } lnet_userdata;
  62. #pragma mark - LWIP errors
  63. int lwip_lua_checkerr (lua_State *L, err_t err) {
  64. switch (err) {
  65. case ERR_OK: return 0;
  66. case ERR_MEM: return luaL_error(L, "out of memory");
  67. case ERR_BUF: return luaL_error(L, "buffer error");
  68. case ERR_TIMEOUT: return luaL_error(L, "timeout");
  69. case ERR_RTE: return luaL_error(L, "routing problem");
  70. case ERR_INPROGRESS: return luaL_error(L, "in progress");
  71. case ERR_VAL: return luaL_error(L, "illegal value");
  72. case ERR_WOULDBLOCK: return luaL_error(L, "would block");
  73. case ERR_ABRT: return luaL_error(L, "connection aborted");
  74. case ERR_RST: return luaL_error(L, "connection reset");
  75. case ERR_CLSD: return luaL_error(L, "connection closed");
  76. case ERR_CONN: return luaL_error(L, "not connected");
  77. case ERR_ARG: return luaL_error(L, "illegal argument");
  78. case ERR_USE: return luaL_error(L, "address in use");
  79. case ERR_IF: return luaL_error(L, "netif error");
  80. case ERR_ISCONN: return luaL_error(L, "already connected");
  81. default: return luaL_error(L, "unknown error");
  82. }
  83. }
  84. #pragma mark - Create
  85. lnet_userdata *net_create( lua_State *L, enum net_type type ) {
  86. const char *mt = NET_TABLES[type];
  87. lnet_userdata *ud = (lnet_userdata *)lua_newuserdata(L, sizeof(lnet_userdata));
  88. if (!ud) return NULL;
  89. luaL_getmetatable(L, mt);
  90. lua_setmetatable(L, -2);
  91. ud->type = type;
  92. ud->self_ref = LUA_NOREF;
  93. ud->pcb = NULL;
  94. switch (type) {
  95. case TYPE_TCP_CLIENT:
  96. ud->client.cb_connect_ref = LUA_NOREF;
  97. ud->client.cb_reconnect_ref = LUA_NOREF;
  98. ud->client.cb_disconnect_ref = LUA_NOREF;
  99. ud->client.hold = 0;
  100. case TYPE_UDP_SOCKET:
  101. ud->client.wait_dns = 0;
  102. ud->client.cb_dns_ref = LUA_NOREF;
  103. ud->client.cb_receive_ref = LUA_NOREF;
  104. ud->client.cb_sent_ref = LUA_NOREF;
  105. break;
  106. case TYPE_TCP_SERVER:
  107. ud->server.cb_accept_ref = LUA_NOREF;
  108. break;
  109. }
  110. return ud;
  111. }
  112. #pragma mark - LWIP callbacks
  113. static void net_err_cb(void *arg, err_t err) {
  114. lnet_userdata *ud = (lnet_userdata*)arg;
  115. if (!ud || ud->type != TYPE_TCP_CLIENT || ud->self_ref == LUA_NOREF) return;
  116. ud->pcb = NULL; // Will be freed at LWIP level
  117. lua_State *L = lua_getstate();
  118. int ref;
  119. if (err != ERR_OK && ud->client.cb_reconnect_ref != LUA_NOREF)
  120. ref = ud->client.cb_reconnect_ref;
  121. else ref = ud->client.cb_disconnect_ref;
  122. if (ref != LUA_NOREF) {
  123. lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
  124. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref);
  125. lua_pushinteger(L, err);
  126. lua_call(L, 2, 0);
  127. }
  128. if (ud->client.wait_dns == 0) {
  129. lua_gc(L, LUA_GCSTOP, 0);
  130. luaL_unref(L, LUA_REGISTRYINDEX, ud->self_ref);
  131. ud->self_ref = LUA_NOREF;
  132. lua_gc(L, LUA_GCRESTART, 0);
  133. }
  134. }
  135. static err_t net_connected_cb(void *arg, struct tcp_pcb *tpcb, err_t err) {
  136. lnet_userdata *ud = (lnet_userdata*)arg;
  137. if (!ud || ud->pcb != tpcb) return ERR_ABRT;
  138. if (err != ERR_OK) {
  139. net_err_cb(arg, err);
  140. return ERR_ABRT;
  141. }
  142. lua_State *L = lua_getstate();
  143. if (ud->self_ref != LUA_NOREF && ud->client.cb_connect_ref != LUA_NOREF) {
  144. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->client.cb_connect_ref);
  145. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref);
  146. lua_call(L, 1, 0);
  147. }
  148. return ERR_OK;
  149. }
  150. static void net_dns_cb(const char *name, ip_addr_t *ipaddr, void *arg) {
  151. ip_addr_t addr;
  152. if (ipaddr != NULL) addr = *ipaddr;
  153. else addr.addr = 0xFFFFFFFF;
  154. lnet_userdata *ud = (lnet_userdata*)arg;
  155. if (!ud) return;
  156. lua_State *L = lua_getstate();
  157. if (ud->self_ref != LUA_NOREF && ud->client.cb_dns_ref != LUA_NOREF) {
  158. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->client.cb_dns_ref);
  159. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref);
  160. if (addr.addr != 0xFFFFFFFF) {
  161. char iptmp[16];
  162. bzero(iptmp, 16);
  163. ets_sprintf(iptmp, IPSTR, IP2STR(&addr.addr));
  164. lua_pushstring(L, iptmp);
  165. } else {
  166. lua_pushnil(L);
  167. }
  168. lua_call(L, 2, 0);
  169. }
  170. ud->client.wait_dns --;
  171. if (ud->pcb && ud->type == TYPE_TCP_CLIENT && ud->tcp_pcb->state == CLOSED) {
  172. tcp_connect(ud->tcp_pcb, &addr, ud->tcp_pcb->remote_port, net_connected_cb);
  173. } else if (!ud->pcb && ud->client.wait_dns == 0) {
  174. lua_gc(L, LUA_GCSTOP, 0);
  175. luaL_unref(L, LUA_REGISTRYINDEX, ud->self_ref);
  176. ud->self_ref = LUA_NOREF;
  177. lua_gc(L, LUA_GCRESTART, 0);
  178. }
  179. }
  180. static void net_recv_cb(lnet_userdata *ud, struct pbuf *p, ip_addr_t *addr, u16_t port) {
  181. if (ud->client.cb_receive_ref == LUA_NOREF) {
  182. pbuf_free(p);
  183. return;
  184. }
  185. int num_args = 2;
  186. char iptmp[16] = { 0, };
  187. if (ud->type == TYPE_UDP_SOCKET)
  188. {
  189. num_args += 2;
  190. ets_sprintf(iptmp, IPSTR, IP2STR(&addr->addr));
  191. }
  192. lua_State *L = lua_getstate();
  193. struct pbuf *pp = p;
  194. while (pp)
  195. {
  196. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->client.cb_receive_ref);
  197. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref);
  198. lua_pushlstring(L, pp->payload, pp->len);
  199. if (ud->type == TYPE_UDP_SOCKET) {
  200. lua_pushinteger(L, port);
  201. lua_pushstring(L, iptmp);
  202. }
  203. lua_call(L, num_args, 0);
  204. pp = pp->next;
  205. }
  206. pbuf_free(p);
  207. }
  208. static void net_udp_recv_cb(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) {
  209. lnet_userdata *ud = (lnet_userdata*)arg;
  210. if (!ud || !ud->pcb || ud->type != TYPE_UDP_SOCKET || ud->self_ref == LUA_NOREF) {
  211. if (p) pbuf_free(p);
  212. return;
  213. }
  214. net_recv_cb(ud, p, addr, port);
  215. }
  216. static err_t net_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
  217. lnet_userdata *ud = (lnet_userdata*)arg;
  218. if (!ud || !ud->pcb || ud->type != TYPE_TCP_CLIENT || ud->self_ref == LUA_NOREF)
  219. return ERR_ABRT;
  220. if (!p) {
  221. net_err_cb(arg, err);
  222. return tcp_close(tpcb);
  223. }
  224. net_recv_cb(ud, p, 0, 0);
  225. tcp_recved(tpcb, ud->client.hold ? 0 : TCP_WND);
  226. return ERR_OK;
  227. }
  228. static err_t net_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len) {
  229. lnet_userdata *ud = (lnet_userdata*)arg;
  230. if (!ud || !ud->pcb || ud->type != TYPE_TCP_CLIENT || ud->self_ref == LUA_NOREF) return ERR_ABRT;
  231. if (ud->client.cb_sent_ref == LUA_NOREF) return ERR_OK;
  232. lua_State *L = lua_getstate();
  233. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->client.cb_sent_ref);
  234. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref);
  235. lua_call(L, 1, 0);
  236. return ERR_OK;
  237. }
  238. static err_t net_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err) {
  239. lnet_userdata *ud = (lnet_userdata*)arg;
  240. if (!ud || ud->type != TYPE_TCP_SERVER || !ud->pcb) return ERR_ABRT;
  241. if (ud->self_ref == LUA_NOREF || ud->server.cb_accept_ref == LUA_NOREF) return ERR_ABRT;
  242. lua_State *L = lua_getstate();
  243. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->server.cb_accept_ref);
  244. lnet_userdata *nud = net_create(L, TYPE_TCP_CLIENT);
  245. lua_pushvalue(L, 2);
  246. nud->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  247. nud->tcp_pcb = newpcb;
  248. tcp_arg(nud->tcp_pcb, nud);
  249. tcp_err(nud->tcp_pcb, net_err_cb);
  250. tcp_recv(nud->tcp_pcb, net_tcp_recv_cb);
  251. tcp_sent(nud->tcp_pcb, net_sent_cb);
  252. nud->tcp_pcb->so_options |= SOF_KEEPALIVE;
  253. nud->tcp_pcb->keep_idle = ud->server.timeout * 1000;
  254. nud->tcp_pcb->keep_cnt = 1;
  255. tcp_accepted(ud->tcp_pcb);
  256. lua_call(L, 1, 0);
  257. return net_connected_cb(nud, nud->tcp_pcb, ERR_OK);
  258. }
  259. #pragma mark - Lua API - create
  260. #ifdef TLS_MODULE_PRESENT
  261. extern int tls_socket_create( lua_State *L );
  262. #endif
  263. // Lua: net.createUDPSocket()
  264. int net_createUDPSocket( lua_State *L ) {
  265. net_create(L, TYPE_UDP_SOCKET);
  266. return 1;
  267. }
  268. // Lua: net.createServer(type, timeout)
  269. int net_createServer( lua_State *L ) {
  270. int type, timeout;
  271. type = luaL_optlong(L, 1, TYPE_TCP);
  272. timeout = luaL_optlong(L, 2, 30);
  273. if (type == TYPE_UDP) {
  274. platform_print_deprecation_note("net.createServer with net.UDP type", "in next version");
  275. return net_createUDPSocket( L );
  276. }
  277. if (type != TYPE_TCP) return luaL_error(L, "invalid type");
  278. lnet_userdata *u = net_create(L, TYPE_TCP_SERVER);
  279. u->server.timeout = timeout;
  280. return 1;
  281. }
  282. // Lua: net.createConnection(type, secure)
  283. int net_createConnection( lua_State *L ) {
  284. int type, secure;
  285. type = luaL_optlong(L, 1, TYPE_TCP);
  286. secure = luaL_optlong(L, 2, 0);
  287. if (type == TYPE_UDP) {
  288. platform_print_deprecation_note("net.createConnection with net.UDP type", "in next version");
  289. return net_createUDPSocket( L );
  290. }
  291. if (type != TYPE_TCP) return luaL_error(L, "invalid type");
  292. if (secure) {
  293. platform_print_deprecation_note("net.createConnection with secure flag", "in next version");
  294. #ifdef TLS_MODULE_PRESENT
  295. return tls_socket_create( L );
  296. #else
  297. return luaL_error(L, "secure connections not enabled");
  298. #endif
  299. }
  300. net_create(L, TYPE_TCP_CLIENT);
  301. return 1;
  302. }
  303. #pragma mark - Get & check userdata
  304. lnet_userdata *net_get_udata_s( lua_State *L, int stack ) {
  305. if (!lua_isuserdata(L, stack)) return NULL;
  306. lnet_userdata *ud = (lnet_userdata *)lua_touserdata(L, stack);
  307. switch (ud->type) {
  308. case TYPE_TCP_CLIENT:
  309. case TYPE_TCP_SERVER:
  310. case TYPE_UDP_SOCKET:
  311. break;
  312. default: return NULL;
  313. }
  314. const char *mt = NET_TABLES[ud->type];
  315. ud = luaL_checkudata(L, stack, mt);
  316. return ud;
  317. }
  318. #define net_get_udata(L) net_get_udata_s(L, 1)
  319. #pragma mark - Lua API
  320. // Lua: server:listen(port, addr, function(c)), socket:listen(port, addr)
  321. int net_listen( lua_State *L ) {
  322. lnet_userdata *ud = net_get_udata(L);
  323. if (!ud || ud->type == TYPE_TCP_CLIENT)
  324. return luaL_error(L, "invalid user data");
  325. if (ud->pcb)
  326. return luaL_error(L, "already listening");
  327. int stack = 2;
  328. uint16_t port = 0;
  329. const char *domain = "0.0.0.0";
  330. if (lua_isnumber(L, stack))
  331. port = lua_tointeger(L, stack++);
  332. if (lua_isstring(L, stack)) {
  333. size_t dl = 0;
  334. domain = luaL_checklstring(L, stack++, &dl);
  335. }
  336. ip_addr_t addr;
  337. if (!ipaddr_aton(domain, &addr))
  338. return luaL_error(L, "invalid IP address");
  339. if (ud->type == TYPE_TCP_SERVER) {
  340. if (lua_isfunction(L, stack) || lua_islightfunction(L, stack)) {
  341. lua_pushvalue(L, stack++);
  342. luaL_unref(L, LUA_REGISTRYINDEX, ud->server.cb_accept_ref);
  343. ud->server.cb_accept_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  344. } else {
  345. return luaL_error(L, "need callback");
  346. }
  347. }
  348. err_t err = ERR_OK;
  349. switch (ud->type) {
  350. case TYPE_TCP_SERVER:
  351. ud->tcp_pcb = tcp_new();
  352. if (!ud->tcp_pcb)
  353. return luaL_error(L, "cannot allocate PCB");
  354. ud->tcp_pcb->so_options |= SOF_REUSEADDR;
  355. err = tcp_bind(ud->tcp_pcb, &addr, port);
  356. if (err == ERR_OK) {
  357. tcp_arg(ud->tcp_pcb, ud);
  358. struct tcp_pcb *pcb = tcp_listen(ud->tcp_pcb);
  359. if (!pcb) {
  360. err = ERR_MEM;
  361. } else {
  362. ud->tcp_pcb = pcb;
  363. tcp_accept(ud->tcp_pcb, net_accept_cb);
  364. }
  365. }
  366. break;
  367. case TYPE_UDP_SOCKET:
  368. ud->udp_pcb = udp_new();
  369. if (!ud->udp_pcb)
  370. return luaL_error(L, "cannot allocate PCB");
  371. udp_recv(ud->udp_pcb, net_udp_recv_cb, ud);
  372. err = udp_bind(ud->udp_pcb, &addr, port);
  373. break;
  374. }
  375. if (err != ERR_OK) {
  376. switch (ud->type) {
  377. case TYPE_TCP_SERVER:
  378. tcp_close(ud->tcp_pcb);
  379. ud->tcp_pcb = NULL;
  380. break;
  381. case TYPE_UDP_SOCKET:
  382. udp_remove(ud->udp_pcb);
  383. ud->udp_pcb = NULL;
  384. break;
  385. }
  386. return lwip_lua_checkerr(L, err);
  387. }
  388. if (ud->self_ref == LUA_NOREF) {
  389. lua_pushvalue(L, 1);
  390. ud->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  391. }
  392. return 0;
  393. }
  394. // Lua: client:connect(port, addr)
  395. int net_connect( lua_State *L ) {
  396. lnet_userdata *ud = net_get_udata(L);
  397. if (!ud || ud->type != TYPE_TCP_CLIENT)
  398. return luaL_error(L, "invalid user data");
  399. if (ud->pcb)
  400. return luaL_error(L, "already connected");
  401. uint16_t port = luaL_checkinteger(L, 2);
  402. if (port == 0)
  403. return luaL_error(L, "specify port");
  404. const char *domain = "127.0.0.1";
  405. if (lua_isstring(L, 3)) {
  406. size_t dl = 0;
  407. domain = luaL_checklstring(L, 3, &dl);
  408. }
  409. if (lua_gettop(L) > 3) {
  410. luaL_argcheck(L, lua_isfunction(L, 4) || lua_islightfunction(L, 4), 4, "not a function");
  411. lua_pushvalue(L, 4);
  412. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_connect_ref);
  413. ud->client.cb_connect_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  414. }
  415. ud->tcp_pcb = tcp_new();
  416. if (!ud->tcp_pcb)
  417. return luaL_error(L, "cannot allocate PCB");
  418. tcp_arg(ud->tcp_pcb, ud);
  419. tcp_err(ud->tcp_pcb, net_err_cb);
  420. tcp_recv(ud->tcp_pcb, net_tcp_recv_cb);
  421. tcp_sent(ud->tcp_pcb, net_sent_cb);
  422. ud->tcp_pcb->remote_port = port;
  423. ip_addr_t addr;
  424. ud->client.wait_dns ++;
  425. int unref = 0;
  426. if (ud->self_ref == LUA_NOREF) {
  427. unref = 1;
  428. lua_pushvalue(L, 1);
  429. ud->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  430. }
  431. err_t err = dns_gethostbyname(domain, &addr, net_dns_cb, ud);
  432. if (err == ERR_OK) {
  433. net_dns_cb(domain, &addr, ud);
  434. } else if (err != ERR_INPROGRESS) {
  435. ud->client.wait_dns --;
  436. if (unref) {
  437. luaL_unref(L, LUA_REGISTRYINDEX, ud->self_ref);
  438. ud->self_ref = LUA_NOREF;
  439. }
  440. tcp_abort(ud->tcp_pcb);
  441. ud->tcp_pcb = NULL;
  442. return lwip_lua_checkerr(L, err);
  443. }
  444. return 0;
  445. }
  446. // Lua: client/socket:on(name, callback)
  447. int net_on( lua_State *L ) {
  448. lnet_userdata *ud = net_get_udata(L);
  449. if (!ud || ud->type == TYPE_TCP_SERVER)
  450. return luaL_error(L, "invalid user data");
  451. int *refptr = NULL;
  452. const char *name = luaL_checkstring(L, 2);
  453. if (!name) return luaL_error(L, "need callback name");
  454. switch (ud->type) {
  455. case TYPE_TCP_CLIENT:
  456. if (strcmp("connection",name)==0)
  457. { refptr = &ud->client.cb_connect_ref; break; }
  458. if (strcmp("disconnection",name)==0)
  459. { refptr = &ud->client.cb_disconnect_ref; break; }
  460. if (strcmp("reconnection",name)==0)
  461. { refptr = &ud->client.cb_reconnect_ref; break; }
  462. case TYPE_UDP_SOCKET:
  463. if (strcmp("dns",name)==0)
  464. { refptr = &ud->client.cb_dns_ref; break; }
  465. if (strcmp("receive",name)==0)
  466. { refptr = &ud->client.cb_receive_ref; break; }
  467. if (strcmp("sent",name)==0)
  468. { refptr = &ud->client.cb_sent_ref; break; }
  469. break;
  470. default: return luaL_error(L, "invalid user data");
  471. }
  472. if (refptr == NULL)
  473. return luaL_error(L, "invalid callback name");
  474. if (lua_isfunction(L, 3) || lua_islightfunction(L, 3)) {
  475. lua_pushvalue(L, 3);
  476. luaL_unref(L, LUA_REGISTRYINDEX, *refptr);
  477. *refptr = luaL_ref(L, LUA_REGISTRYINDEX);
  478. } else if (lua_isnil(L, 3)) {
  479. luaL_unref(L, LUA_REGISTRYINDEX, *refptr);
  480. *refptr = LUA_NOREF;
  481. } else {
  482. return luaL_error(L, "invalid callback function");
  483. }
  484. return 0;
  485. }
  486. // Lua: client:send(data, function(c)), socket:send(port, ip, data, function(s))
  487. int net_send( lua_State *L ) {
  488. lnet_userdata *ud = net_get_udata(L);
  489. if (!ud || ud->type == TYPE_TCP_SERVER)
  490. return luaL_error(L, "invalid user data");
  491. ip_addr_t addr;
  492. uint16_t port;
  493. const char *data;
  494. size_t datalen = 0;
  495. int stack = 2;
  496. if (ud->type == TYPE_UDP_SOCKET) {
  497. size_t dl = 0;
  498. port = luaL_checkinteger(L, stack++);
  499. if (port == 0) return luaL_error(L, "need port");
  500. const char *domain = luaL_checklstring(L, stack++, &dl);
  501. if (!domain) return luaL_error(L, "need IP address");
  502. if (!ipaddr_aton(domain, &addr)) return luaL_error(L, "invalid IP address");
  503. }
  504. data = luaL_checklstring(L, stack++, &datalen);
  505. if (!data || datalen == 0) return luaL_error(L, "no data to send");
  506. if (lua_isfunction(L, stack) || lua_islightfunction(L, stack)) {
  507. lua_pushvalue(L, stack++);
  508. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_sent_ref);
  509. ud->client.cb_sent_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  510. }
  511. if (ud->type == TYPE_UDP_SOCKET && !ud->pcb) {
  512. ud->udp_pcb = udp_new();
  513. if (!ud->udp_pcb)
  514. return luaL_error(L, "cannot allocate PCB");
  515. udp_recv(ud->udp_pcb, net_udp_recv_cb, ud);
  516. ip_addr_t laddr = {0};
  517. err_t err = udp_bind(ud->udp_pcb, &laddr, 0);
  518. if (err != ERR_OK) {
  519. udp_remove(ud->udp_pcb);
  520. ud->udp_pcb = NULL;
  521. return lwip_lua_checkerr(L, err);
  522. }
  523. if (ud->self_ref == LUA_NOREF) {
  524. lua_pushvalue(L, 1);
  525. ud->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  526. }
  527. }
  528. if (!ud->pcb || ud->self_ref == LUA_NOREF)
  529. return luaL_error(L, "not connected");
  530. err_t err;
  531. if (ud->type == TYPE_UDP_SOCKET) {
  532. struct pbuf *pb = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
  533. if (!pb)
  534. return luaL_error(L, "cannot allocate message buffer");
  535. pbuf_take(pb, data, datalen);
  536. err = udp_sendto(ud->udp_pcb, pb, &addr, port);
  537. pbuf_free(pb);
  538. if (ud->client.cb_sent_ref != LUA_NOREF) {
  539. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->client.cb_sent_ref);
  540. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref);
  541. lua_call(L, 1, 0);
  542. }
  543. } else if (ud->type == TYPE_TCP_CLIENT) {
  544. err = tcp_write(ud->tcp_pcb, data, datalen, TCP_WRITE_FLAG_COPY);
  545. }
  546. return lwip_lua_checkerr(L, err);
  547. }
  548. // Lua: client:hold()
  549. int net_hold( lua_State *L ) {
  550. lnet_userdata *ud = net_get_udata(L);
  551. if (!ud || ud->type != TYPE_TCP_CLIENT)
  552. return luaL_error(L, "invalid user data");
  553. if (!ud->client.hold && ud->tcp_pcb) {
  554. ud->client.hold = 1;
  555. }
  556. return 0;
  557. }
  558. // Lua: client:unhold()
  559. int net_unhold( lua_State *L ) {
  560. lnet_userdata *ud = net_get_udata(L);
  561. if (!ud || ud->type != TYPE_TCP_CLIENT)
  562. return luaL_error(L, "invalid user data");
  563. if (ud->client.hold && ud->tcp_pcb) {
  564. ud->client.hold = 0;
  565. ud->tcp_pcb->flags |= TF_ACK_NOW;
  566. tcp_recved(ud->tcp_pcb, TCP_WND);
  567. }
  568. return 0;
  569. }
  570. // Lua: client/socket:dns(domain, callback(socket, addr))
  571. int net_dns( lua_State *L ) {
  572. lnet_userdata *ud = net_get_udata(L);
  573. if (!ud || ud->type == TYPE_TCP_SERVER)
  574. return luaL_error(L, "invalid user data");
  575. size_t dl = 0;
  576. const char *domain = luaL_checklstring(L, 2, &dl);
  577. if (!domain)
  578. return luaL_error(L, "no domain specified");
  579. if (lua_isfunction(L, 3) || lua_islightfunction(L, 3)) {
  580. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_dns_ref);
  581. lua_pushvalue(L, 3);
  582. ud->client.cb_dns_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  583. }
  584. if (ud->client.cb_dns_ref == LUA_NOREF)
  585. return luaL_error(L, "no callback specified");
  586. ud->client.wait_dns ++;
  587. int unref = 0;
  588. if (ud->self_ref == LUA_NOREF) {
  589. unref = 1;
  590. lua_pushvalue(L, 1);
  591. ud->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  592. }
  593. ip_addr_t addr;
  594. err_t err = dns_gethostbyname(domain, &addr, net_dns_cb, ud);
  595. if (err == ERR_OK) {
  596. net_dns_cb(domain, &addr, ud);
  597. } else if (err != ERR_INPROGRESS) {
  598. ud->client.wait_dns --;
  599. if (unref) {
  600. luaL_unref(L, LUA_REGISTRYINDEX, ud->self_ref);
  601. ud->self_ref = LUA_NOREF;
  602. }
  603. return lwip_lua_checkerr(L, err);
  604. }
  605. return 0;
  606. }
  607. // Lua: client/socket:ttl([ttl])
  608. int net_ttl( lua_State *L ) {
  609. lnet_userdata *ud = net_get_udata(L);
  610. if (!ud || ud->type == TYPE_TCP_SERVER)
  611. return luaL_error(L, "invalid user data");
  612. if (!ud->pcb)
  613. return luaL_error(L, "socket is not open/bound yet");
  614. int ttl = luaL_optinteger(L, 2, -1);
  615. // Since `ttl` field is part of IP_PCB macro
  616. // (which are at beginning of both udp_pcb/tcp_pcb)
  617. // and PCBs declared as `union` there is safe to
  618. // access ttl field without checking for type.
  619. if (ttl == -1) {
  620. ttl = ud->udp_pcb->ttl;
  621. } else {
  622. ud->udp_pcb->ttl = ttl;
  623. }
  624. lua_pushinteger(L, ttl);
  625. return 1;
  626. }
  627. // Lua: client:getpeer()
  628. int net_getpeer( lua_State *L ) {
  629. lnet_userdata *ud = net_get_udata(L);
  630. if (!ud || ud->type != TYPE_TCP_CLIENT)
  631. return luaL_error(L, "invalid user data");
  632. if (!ud->pcb) {
  633. lua_pushnil(L);
  634. lua_pushnil(L);
  635. return 2;
  636. }
  637. uint16_t port = ud->tcp_pcb->remote_port;
  638. ip_addr_t addr = ud->tcp_pcb->remote_ip;
  639. if (port == 0) {
  640. lua_pushnil(L);
  641. lua_pushnil(L);
  642. return 2;
  643. }
  644. char addr_str[16];
  645. bzero(addr_str, 16);
  646. ets_sprintf(addr_str, IPSTR, IP2STR(&addr.addr));
  647. lua_pushinteger(L, port);
  648. lua_pushstring(L, addr_str);
  649. return 2;
  650. }
  651. // Lua: client/server/socket:getaddr()
  652. int net_getaddr( lua_State *L ) {
  653. lnet_userdata *ud = net_get_udata(L);
  654. if (!ud) return luaL_error(L, "invalid user data");
  655. if (!ud->pcb) {
  656. lua_pushnil(L);
  657. lua_pushnil(L);
  658. return 2;
  659. }
  660. uint16_t port;
  661. ip_addr_t addr;
  662. switch (ud->type) {
  663. case TYPE_TCP_CLIENT:
  664. case TYPE_TCP_SERVER:
  665. addr = ud->tcp_pcb->local_ip;
  666. port = ud->tcp_pcb->local_port;
  667. break;
  668. case TYPE_UDP_SOCKET:
  669. addr = ud->udp_pcb->local_ip;
  670. port = ud->udp_pcb->local_port;
  671. break;
  672. }
  673. if (port == 0) {
  674. lua_pushnil(L);
  675. lua_pushnil(L);
  676. return 2;
  677. }
  678. char addr_str[16];
  679. bzero(addr_str, 16);
  680. ets_sprintf(addr_str, IPSTR, IP2STR(&addr.addr));
  681. lua_pushinteger(L, port);
  682. lua_pushstring(L, addr_str);
  683. return 2;
  684. }
  685. // Lua: client/server/socket:close()
  686. int net_close( lua_State *L ) {
  687. lnet_userdata *ud = net_get_udata(L);
  688. if (!ud) return luaL_error(L, "invalid user data");
  689. if (ud->pcb) {
  690. switch (ud->type) {
  691. case TYPE_TCP_CLIENT:
  692. if (ERR_OK != tcp_close(ud->tcp_pcb)) {
  693. tcp_arg(ud->tcp_pcb, NULL);
  694. tcp_abort(ud->tcp_pcb);
  695. }
  696. ud->tcp_pcb = NULL;
  697. break;
  698. case TYPE_TCP_SERVER:
  699. tcp_close(ud->tcp_pcb);
  700. ud->tcp_pcb = NULL;
  701. break;
  702. case TYPE_UDP_SOCKET:
  703. udp_remove(ud->udp_pcb);
  704. ud->udp_pcb = NULL;
  705. break;
  706. }
  707. } else {
  708. return luaL_error(L, "not connected");
  709. }
  710. if (ud->type == TYPE_TCP_SERVER ||
  711. (ud->pcb == NULL && ud->client.wait_dns == 0)) {
  712. lua_gc(L, LUA_GCSTOP, 0);
  713. luaL_unref(L, LUA_REGISTRYINDEX, ud->self_ref);
  714. ud->self_ref = LUA_NOREF;
  715. lua_gc(L, LUA_GCRESTART, 0);
  716. }
  717. return 0;
  718. }
  719. int net_delete( lua_State *L ) {
  720. lnet_userdata *ud = net_get_udata(L);
  721. if (!ud) return luaL_error(L, "no user data");
  722. if (ud->pcb) {
  723. switch (ud->type) {
  724. case TYPE_TCP_CLIENT:
  725. tcp_arg(ud->tcp_pcb, NULL);
  726. tcp_abort(ud->tcp_pcb);
  727. ud->tcp_pcb = NULL;
  728. break;
  729. case TYPE_TCP_SERVER:
  730. tcp_close(ud->tcp_pcb);
  731. ud->tcp_pcb = NULL;
  732. break;
  733. case TYPE_UDP_SOCKET:
  734. udp_remove(ud->udp_pcb);
  735. ud->udp_pcb = NULL;
  736. break;
  737. }
  738. }
  739. switch (ud->type) {
  740. case TYPE_TCP_CLIENT:
  741. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_connect_ref);
  742. ud->client.cb_connect_ref = LUA_NOREF;
  743. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_disconnect_ref);
  744. ud->client.cb_disconnect_ref = LUA_NOREF;
  745. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_reconnect_ref);
  746. ud->client.cb_reconnect_ref = LUA_NOREF;
  747. case TYPE_UDP_SOCKET:
  748. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_dns_ref);
  749. ud->client.cb_dns_ref = LUA_NOREF;
  750. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_receive_ref);
  751. ud->client.cb_receive_ref = LUA_NOREF;
  752. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_sent_ref);
  753. ud->client.cb_sent_ref = LUA_NOREF;
  754. break;
  755. case TYPE_TCP_SERVER:
  756. luaL_unref(L, LUA_REGISTRYINDEX, ud->server.cb_accept_ref);
  757. ud->server.cb_accept_ref = LUA_NOREF;
  758. break;
  759. }
  760. lua_gc(L, LUA_GCSTOP, 0);
  761. luaL_unref(L, LUA_REGISTRYINDEX, ud->self_ref);
  762. ud->self_ref = LUA_NOREF;
  763. lua_gc(L, LUA_GCRESTART, 0);
  764. return 0;
  765. }
  766. #pragma mark - Multicast
  767. static int net_multicastJoinLeave( lua_State *L, int join) {
  768. size_t il;
  769. ip_addr_t multicast_addr;
  770. ip_addr_t if_addr;
  771. const char *multicast_ip;
  772. const char *if_ip;
  773. NODE_DBG("net_multicastJoin is called.\n");
  774. if(! lua_isstring(L,1) ) return luaL_error( L, "wrong arg type" );
  775. if_ip = luaL_checklstring( L, 1, &il );
  776. if (if_ip != NULL)
  777. if ( if_ip[0] == '\0' || stricmp(if_ip,"any") == 0)
  778. {
  779. if_ip = "0.0.0.0";
  780. il = 7;
  781. }
  782. if (if_ip == NULL || il > 15 || il < 7) return luaL_error( L, "invalid if ip" );
  783. if_addr.addr = ipaddr_addr(if_ip);
  784. if(! lua_isstring(L,2) ) return luaL_error( L, "wrong arg type" );
  785. multicast_ip = luaL_checklstring( L, 2, &il );
  786. if (multicast_ip == NULL || il > 15 || il < 7) return luaL_error( L, "invalid multicast ip" );
  787. multicast_addr.addr = ipaddr_addr(multicast_ip);
  788. if (join)
  789. {
  790. igmp_joingroup(&if_addr, &multicast_addr);
  791. }
  792. else
  793. {
  794. igmp_leavegroup(&if_addr, &multicast_addr);
  795. }
  796. return 0;
  797. }
  798. // Lua: net.multicastJoin(ifip, multicastip)
  799. // if ifip "" or "any" all interfaces are affected
  800. static int net_multicastJoin( lua_State* L ) {
  801. return net_multicastJoinLeave(L,1);
  802. }
  803. // Lua: net.multicastLeave(ifip, multicastip)
  804. // if ifip "" or "any" all interfaces are affected
  805. static int net_multicastLeave( lua_State* L ) {
  806. return net_multicastJoinLeave(L,0);
  807. }
  808. #pragma mark - DNS
  809. static void net_dns_static_cb(const char *name, ip_addr_t *ipaddr, void *callback_arg) {
  810. ip_addr_t addr;
  811. if (ipaddr != NULL)
  812. addr = *ipaddr;
  813. else addr.addr = 0xFFFFFFFF;
  814. int cb_ref = ((int*)callback_arg)[0];
  815. c_free(callback_arg);
  816. lua_State *L = lua_getstate();
  817. lua_rawgeti(L, LUA_REGISTRYINDEX, cb_ref);
  818. lua_pushnil(L);
  819. if (addr.addr != 0xFFFFFFFF) {
  820. char iptmp[20];
  821. size_t ipl = c_sprintf(iptmp, IPSTR, IP2STR(&addr.addr));
  822. lua_pushlstring(L, iptmp, ipl);
  823. } else {
  824. lua_pushnil(L);
  825. }
  826. lua_call(L, 2, 0);
  827. luaL_unref(L, LUA_REGISTRYINDEX, cb_ref);
  828. }
  829. // Lua: net.dns.resolve( domain, function(sk, ip) )
  830. static int net_dns_static( lua_State* L ) {
  831. size_t dl;
  832. const char* domain = luaL_checklstring(L, 1, &dl);
  833. if (!domain && dl > 128) {
  834. return luaL_error(L, "wrong domain");
  835. }
  836. luaL_checkanyfunction(L, 2);
  837. lua_pushvalue(L, 2); // copy argument (func) to the top of stack
  838. int cbref = luaL_ref(L, LUA_REGISTRYINDEX);
  839. if (cbref == LUA_NOREF) {
  840. return luaL_error(L, "wrong callback");
  841. }
  842. int *cbref_ptr = c_zalloc(sizeof(int));
  843. cbref_ptr[0] = cbref;
  844. ip_addr_t addr;
  845. err_t err = dns_gethostbyname(domain, &addr, net_dns_static_cb, cbref_ptr);
  846. if (err == ERR_OK) {
  847. net_dns_static_cb(domain, &addr, cbref_ptr);
  848. return 0;
  849. } else if (err == ERR_INPROGRESS) {
  850. return 0;
  851. } else {
  852. int e = lwip_lua_checkerr(L, err);
  853. c_free(cbref_ptr);
  854. return e;
  855. }
  856. return 0;
  857. }
  858. // Lua: s = net.dns.setdnsserver(ip_addr, [index])
  859. static int net_setdnsserver( lua_State* L ) {
  860. size_t l;
  861. u32_t ip32;
  862. const char *server = luaL_checklstring( L, 1, &l );
  863. if (l>16 || server == NULL || (ip32 = ipaddr_addr(server)) == IPADDR_NONE || ip32 == IPADDR_ANY)
  864. return luaL_error( L, "invalid dns server ip" );
  865. int numdns = luaL_optint(L, 2, 0);
  866. if (numdns >= DNS_MAX_SERVERS)
  867. return luaL_error( L, "server index out of range [0-%d]", DNS_MAX_SERVERS - 1);
  868. ip_addr_t ipaddr;
  869. ip4_addr_set_u32(&ipaddr, ip32);
  870. dns_setserver(numdns,&ipaddr);
  871. return 0;
  872. }
  873. // Lua: s = net.dns.getdnsserver([index])
  874. static int net_getdnsserver( lua_State* L ) {
  875. int numdns = luaL_optint(L, 1, 0);
  876. if (numdns >= DNS_MAX_SERVERS)
  877. return luaL_error( L, "server index out of range [0-%d]", DNS_MAX_SERVERS - 1);
  878. // ip_addr_t ipaddr;
  879. // dns_getserver(numdns,&ipaddr);
  880. // Bug fix by @md5crypt https://github.com/nodemcu/nodemcu-firmware/pull/500
  881. ip_addr_t ipaddr = dns_getserver(numdns);
  882. if ( ip_addr_isany(&ipaddr) ) {
  883. lua_pushnil( L );
  884. } else {
  885. char temp[20] = {0};
  886. c_sprintf(temp, IPSTR, IP2STR( &ipaddr.addr ) );
  887. lua_pushstring( L, temp );
  888. }
  889. return 1;
  890. }
  891. #pragma mark - Tables
  892. #ifdef TLS_MODULE_PRESENT
  893. extern const LUA_REG_TYPE tls_cert_map[];
  894. #endif
  895. // Module function map
  896. static const LUA_REG_TYPE net_tcpserver_map[] = {
  897. { LSTRKEY( "listen" ), LFUNCVAL( net_listen ) },
  898. { LSTRKEY( "getaddr" ), LFUNCVAL( net_getaddr ) },
  899. { LSTRKEY( "close" ), LFUNCVAL( net_close ) },
  900. { LSTRKEY( "__gc" ), LFUNCVAL( net_delete ) },
  901. { LSTRKEY( "__index" ), LROVAL( net_tcpserver_map ) },
  902. { LNILKEY, LNILVAL }
  903. };
  904. static const LUA_REG_TYPE net_tcpsocket_map[] = {
  905. { LSTRKEY( "connect" ), LFUNCVAL( net_connect ) },
  906. { LSTRKEY( "close" ), LFUNCVAL( net_close ) },
  907. { LSTRKEY( "on" ), LFUNCVAL( net_on ) },
  908. { LSTRKEY( "send" ), LFUNCVAL( net_send ) },
  909. { LSTRKEY( "hold" ), LFUNCVAL( net_hold ) },
  910. { LSTRKEY( "unhold" ), LFUNCVAL( net_unhold ) },
  911. { LSTRKEY( "dns" ), LFUNCVAL( net_dns ) },
  912. { LSTRKEY( "ttl" ), LFUNCVAL( net_ttl ) },
  913. { LSTRKEY( "getpeer" ), LFUNCVAL( net_getpeer ) },
  914. { LSTRKEY( "getaddr" ), LFUNCVAL( net_getaddr ) },
  915. { LSTRKEY( "__gc" ), LFUNCVAL( net_delete ) },
  916. { LSTRKEY( "__index" ), LROVAL( net_tcpsocket_map ) },
  917. { LNILKEY, LNILVAL }
  918. };
  919. static const LUA_REG_TYPE net_udpsocket_map[] = {
  920. { LSTRKEY( "listen" ), LFUNCVAL( net_listen ) },
  921. { LSTRKEY( "close" ), LFUNCVAL( net_close ) },
  922. { LSTRKEY( "on" ), LFUNCVAL( net_on ) },
  923. { LSTRKEY( "send" ), LFUNCVAL( net_send ) },
  924. { LSTRKEY( "dns" ), LFUNCVAL( net_dns ) },
  925. { LSTRKEY( "ttl" ), LFUNCVAL( net_ttl ) },
  926. { LSTRKEY( "getaddr" ), LFUNCVAL( net_getaddr ) },
  927. { LSTRKEY( "__gc" ), LFUNCVAL( net_delete ) },
  928. { LSTRKEY( "__index" ), LROVAL( net_udpsocket_map ) },
  929. { LNILKEY, LNILVAL }
  930. };
  931. static const LUA_REG_TYPE net_dns_map[] = {
  932. { LSTRKEY( "setdnsserver" ), LFUNCVAL( net_setdnsserver ) },
  933. { LSTRKEY( "getdnsserver" ), LFUNCVAL( net_getdnsserver ) },
  934. { LSTRKEY( "resolve" ), LFUNCVAL( net_dns_static ) },
  935. { LNILKEY, LNILVAL }
  936. };
  937. static const LUA_REG_TYPE net_map[] = {
  938. { LSTRKEY( "createServer" ), LFUNCVAL( net_createServer ) },
  939. { LSTRKEY( "createConnection" ), LFUNCVAL( net_createConnection ) },
  940. { LSTRKEY( "createUDPSocket" ), LFUNCVAL( net_createUDPSocket ) },
  941. { LSTRKEY( "multicastJoin"), LFUNCVAL( net_multicastJoin ) },
  942. { LSTRKEY( "multicastLeave"), LFUNCVAL( net_multicastLeave ) },
  943. { LSTRKEY( "dns" ), LROVAL( net_dns_map ) },
  944. #ifdef TLS_MODULE_PRESENT
  945. { LSTRKEY( "cert" ), LROVAL( tls_cert_map ) },
  946. #endif
  947. { LSTRKEY( "TCP" ), LNUMVAL( TYPE_TCP ) },
  948. { LSTRKEY( "UDP" ), LNUMVAL( TYPE_UDP ) },
  949. { LSTRKEY( "__metatable" ), LROVAL( net_map ) },
  950. { LNILKEY, LNILVAL }
  951. };
  952. int luaopen_net( lua_State *L ) {
  953. igmp_init();
  954. luaL_rometatable(L, NET_TABLE_TCP_SERVER, (void *)net_tcpserver_map);
  955. luaL_rometatable(L, NET_TABLE_TCP_CLIENT, (void *)net_tcpsocket_map);
  956. luaL_rometatable(L, NET_TABLE_UDP_SOCKET, (void *)net_udpsocket_map);
  957. return 0;
  958. }
  959. NODEMCU_MODULE(NET, "net", net_map, luaopen_net);