net.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100
  1. // Module for network
  2. #include "module.h"
  3. #include "lauxlib.h"
  4. #include "platform.h"
  5. #include "lmem.h"
  6. #include <string.h>
  7. #include <strings.h>
  8. #include <stddef.h>
  9. #include <stdint.h>
  10. #include "mem.h"
  11. #include "osapi.h"
  12. #include "lwip/err.h"
  13. #include "lwip/ip_addr.h"
  14. #include "lwip/dns.h"
  15. #include "lwip/igmp.h"
  16. #include "lwip/tcp.h"
  17. #include "lwip/udp.h"
  18. #include "lwip/dhcp.h"
  19. #include "net_ping.h"
  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. /* FALLTHROUGH */
  101. case TYPE_UDP_SOCKET:
  102. ud->client.wait_dns = 0;
  103. ud->client.cb_dns_ref = LUA_NOREF;
  104. ud->client.cb_receive_ref = LUA_NOREF;
  105. ud->client.cb_sent_ref = LUA_NOREF;
  106. break;
  107. case TYPE_TCP_SERVER:
  108. ud->server.cb_accept_ref = LUA_NOREF;
  109. break;
  110. }
  111. return ud;
  112. }
  113. #pragma mark - LWIP callbacks
  114. static void net_err_cb(void *arg, err_t err) {
  115. lnet_userdata *ud = (lnet_userdata*)arg;
  116. if (!ud || ud->type != TYPE_TCP_CLIENT || ud->self_ref == LUA_NOREF) return;
  117. ud->pcb = NULL; // Will be freed at LWIP level
  118. lua_State *L = lua_getstate();
  119. int ref;
  120. if (err != ERR_OK && ud->client.cb_reconnect_ref != LUA_NOREF)
  121. ref = ud->client.cb_reconnect_ref;
  122. else ref = ud->client.cb_disconnect_ref;
  123. if (ref != LUA_NOREF) {
  124. lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
  125. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref);
  126. lua_pushinteger(L, err);
  127. lua_call(L, 2, 0);
  128. }
  129. if (ud->client.wait_dns == 0) {
  130. int selfref = ud->self_ref;
  131. ud->self_ref = LUA_NOREF;
  132. luaL_unref(L, LUA_REGISTRYINDEX, selfref);
  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. int selfref = ud->self_ref;
  175. ud->self_ref = LUA_NOREF;
  176. luaL_unref(L, LUA_REGISTRYINDEX, selfref);
  177. }
  178. }
  179. static void net_recv_cb(lnet_userdata *ud, struct pbuf *p, ip_addr_t *addr, u16_t port) {
  180. if (ud->client.cb_receive_ref == LUA_NOREF) {
  181. pbuf_free(p);
  182. return;
  183. }
  184. int num_args = 2;
  185. char iptmp[16] = { 0, };
  186. if (ud->type == TYPE_UDP_SOCKET)
  187. {
  188. num_args += 2;
  189. ets_sprintf(iptmp, IPSTR, IP2STR(&addr->addr));
  190. }
  191. lua_State *L = lua_getstate();
  192. struct pbuf *pp = p;
  193. while (pp)
  194. {
  195. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->client.cb_receive_ref);
  196. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref);
  197. lua_pushlstring(L, pp->payload, pp->len);
  198. if (ud->type == TYPE_UDP_SOCKET) {
  199. lua_pushinteger(L, port);
  200. lua_pushstring(L, iptmp);
  201. }
  202. lua_call(L, num_args, 0);
  203. pp = pp->next;
  204. }
  205. pbuf_free(p);
  206. }
  207. static void net_udp_recv_cb(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) {
  208. lnet_userdata *ud = (lnet_userdata*)arg;
  209. if (!ud || !ud->pcb || ud->type != TYPE_UDP_SOCKET || ud->self_ref == LUA_NOREF) {
  210. if (p) pbuf_free(p);
  211. return;
  212. }
  213. net_recv_cb(ud, p, addr, port);
  214. }
  215. static err_t net_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
  216. lnet_userdata *ud = (lnet_userdata*)arg;
  217. if (!ud || !ud->pcb || ud->type != TYPE_TCP_CLIENT || ud->self_ref == LUA_NOREF)
  218. return ERR_ABRT;
  219. if (!p) {
  220. net_err_cb(arg, err);
  221. return tcp_close(tpcb);
  222. }
  223. net_recv_cb(ud, p, 0, 0);
  224. tcp_recved(tpcb, ud->client.hold ? 0 : TCP_WND);
  225. return ERR_OK;
  226. }
  227. static err_t net_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len) {
  228. lnet_userdata *ud = (lnet_userdata*)arg;
  229. if (!ud || !ud->pcb || ud->type != TYPE_TCP_CLIENT || ud->self_ref == LUA_NOREF) return ERR_ABRT;
  230. if (ud->client.cb_sent_ref == LUA_NOREF) return ERR_OK;
  231. lua_State *L = lua_getstate();
  232. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->client.cb_sent_ref);
  233. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref);
  234. lua_call(L, 1, 0);
  235. return ERR_OK;
  236. }
  237. static err_t net_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err) {
  238. lnet_userdata *ud = (lnet_userdata*)arg;
  239. if (!ud || ud->type != TYPE_TCP_SERVER || !ud->pcb) return ERR_ABRT;
  240. if (ud->self_ref == LUA_NOREF || ud->server.cb_accept_ref == LUA_NOREF) return ERR_ABRT;
  241. lua_State *L = lua_getstate();
  242. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->server.cb_accept_ref);
  243. lnet_userdata *nud = net_create(L, TYPE_TCP_CLIENT);
  244. lua_pushvalue(L, 2);
  245. nud->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  246. nud->tcp_pcb = newpcb;
  247. tcp_arg(nud->tcp_pcb, nud);
  248. tcp_err(nud->tcp_pcb, net_err_cb);
  249. tcp_recv(nud->tcp_pcb, net_tcp_recv_cb);
  250. tcp_sent(nud->tcp_pcb, net_sent_cb);
  251. nud->tcp_pcb->so_options |= SOF_KEEPALIVE;
  252. nud->tcp_pcb->keep_idle = ud->server.timeout * 1000;
  253. nud->tcp_pcb->keep_cnt = 1;
  254. tcp_accepted(ud->tcp_pcb);
  255. lua_call(L, 1, 0);
  256. return net_connected_cb(nud, nud->tcp_pcb, ERR_OK);
  257. }
  258. #pragma mark - Lua API - create
  259. // Lua: net.createUDPSocket()
  260. int net_createUDPSocket( lua_State *L ) {
  261. net_create(L, TYPE_UDP_SOCKET);
  262. return 1;
  263. }
  264. // Lua: net.createServer(type, timeout)
  265. int net_createServer( lua_State *L ) {
  266. int type, timeout;
  267. timeout = luaL_optlong(L, 1, 30);
  268. lnet_userdata *u = net_create(L, TYPE_TCP_SERVER);
  269. u->server.timeout = timeout;
  270. return 1;
  271. }
  272. // Lua: net.createConnection(type, secure)
  273. int net_createConnection( lua_State *L ) {
  274. net_create(L, TYPE_TCP_CLIENT);
  275. return 1;
  276. }
  277. #pragma mark - Get & check userdata
  278. lnet_userdata *net_get_udata_s( lua_State *L, int stack ) {
  279. if (!lua_isuserdata(L, stack)) return NULL;
  280. lnet_userdata *ud = (lnet_userdata *)lua_touserdata(L, stack);
  281. switch (ud->type) {
  282. case TYPE_TCP_CLIENT:
  283. case TYPE_TCP_SERVER:
  284. case TYPE_UDP_SOCKET:
  285. break;
  286. default: return NULL;
  287. }
  288. const char *mt = NET_TABLES[ud->type];
  289. ud = luaL_checkudata(L, stack, mt);
  290. return ud;
  291. }
  292. #define net_get_udata(L) net_get_udata_s(L, 1)
  293. #pragma mark - Lua API
  294. // Lua: server:listen(port, addr, function(c)), socket:listen(port, addr)
  295. int net_listen( lua_State *L ) {
  296. lnet_userdata *ud = net_get_udata(L);
  297. if (!ud || ud->type == TYPE_TCP_CLIENT)
  298. return luaL_error(L, "invalid user data");
  299. if (ud->pcb)
  300. return luaL_error(L, "already listening");
  301. int stack = 2;
  302. uint16_t port = 0;
  303. const char *domain = "0.0.0.0";
  304. if (lua_isnumber(L, stack))
  305. port = lua_tointeger(L, stack++);
  306. if (lua_isstring(L, stack)) {
  307. size_t dl = 0;
  308. domain = luaL_checklstring(L, stack++, &dl);
  309. }
  310. ip_addr_t addr;
  311. if (!ipaddr_aton(domain, &addr))
  312. return luaL_error(L, "invalid IP address");
  313. if (ud->type == TYPE_TCP_SERVER) {
  314. if (lua_isfunction(L, stack)) {
  315. lua_pushvalue(L, stack++);
  316. luaL_unref(L, LUA_REGISTRYINDEX, ud->server.cb_accept_ref);
  317. ud->server.cb_accept_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  318. } else {
  319. return luaL_error(L, "need callback");
  320. }
  321. }
  322. err_t err = ERR_OK;
  323. switch (ud->type) {
  324. case TYPE_TCP_SERVER:
  325. ud->tcp_pcb = tcp_new();
  326. if (!ud->tcp_pcb)
  327. return luaL_error(L, "cannot allocate PCB");
  328. ud->tcp_pcb->so_options |= SOF_REUSEADDR;
  329. err = tcp_bind(ud->tcp_pcb, &addr, port);
  330. if (err == ERR_OK) {
  331. tcp_arg(ud->tcp_pcb, ud);
  332. struct tcp_pcb *pcb = tcp_listen(ud->tcp_pcb);
  333. if (!pcb) {
  334. err = ERR_MEM;
  335. } else {
  336. ud->tcp_pcb = pcb;
  337. tcp_accept(ud->tcp_pcb, net_accept_cb);
  338. }
  339. }
  340. break;
  341. case TYPE_UDP_SOCKET:
  342. ud->udp_pcb = udp_new();
  343. if (!ud->udp_pcb)
  344. return luaL_error(L, "cannot allocate PCB");
  345. udp_recv(ud->udp_pcb, net_udp_recv_cb, ud);
  346. err = udp_bind(ud->udp_pcb, &addr, port);
  347. break;
  348. }
  349. if (err != ERR_OK) {
  350. switch (ud->type) {
  351. case TYPE_TCP_SERVER:
  352. tcp_close(ud->tcp_pcb);
  353. ud->tcp_pcb = NULL;
  354. break;
  355. case TYPE_UDP_SOCKET:
  356. udp_remove(ud->udp_pcb);
  357. ud->udp_pcb = NULL;
  358. break;
  359. }
  360. return lwip_lua_checkerr(L, err);
  361. }
  362. if (ud->self_ref == LUA_NOREF) {
  363. lua_pushvalue(L, 1);
  364. ud->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  365. }
  366. return 0;
  367. }
  368. // Lua: client:connect(port, addr)
  369. int net_connect( lua_State *L ) {
  370. lnet_userdata *ud = net_get_udata(L);
  371. if (!ud || ud->type != TYPE_TCP_CLIENT)
  372. return luaL_error(L, "invalid user data");
  373. if (ud->pcb)
  374. return luaL_error(L, "already connected");
  375. uint16_t port = luaL_checkinteger(L, 2);
  376. if (port == 0)
  377. return luaL_error(L, "specify port");
  378. const char *domain = "127.0.0.1";
  379. if (lua_isstring(L, 3)) {
  380. size_t dl = 0;
  381. domain = luaL_checklstring(L, 3, &dl);
  382. }
  383. if (lua_gettop(L) > 3) {
  384. luaL_argcheck(L, lua_isfunction(L, 4), 4, "not a function");
  385. lua_pushvalue(L, 4);
  386. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_connect_ref);
  387. ud->client.cb_connect_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  388. }
  389. ud->tcp_pcb = tcp_new();
  390. if (!ud->tcp_pcb)
  391. return luaL_error(L, "cannot allocate PCB");
  392. tcp_arg(ud->tcp_pcb, ud);
  393. tcp_err(ud->tcp_pcb, net_err_cb);
  394. tcp_recv(ud->tcp_pcb, net_tcp_recv_cb);
  395. tcp_sent(ud->tcp_pcb, net_sent_cb);
  396. ud->tcp_pcb->remote_port = port;
  397. ip_addr_t addr;
  398. ud->client.wait_dns ++;
  399. int unref = 0;
  400. if (ud->self_ref == LUA_NOREF) {
  401. unref = 1;
  402. lua_pushvalue(L, 1);
  403. ud->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  404. }
  405. err_t err = dns_gethostbyname(domain, &addr, net_dns_cb, ud);
  406. if (err == ERR_OK) {
  407. net_dns_cb(domain, &addr, ud);
  408. } else if (err != ERR_INPROGRESS) {
  409. ud->client.wait_dns --;
  410. if (unref) {
  411. luaL_unref(L, LUA_REGISTRYINDEX, ud->self_ref);
  412. ud->self_ref = LUA_NOREF;
  413. }
  414. tcp_abort(ud->tcp_pcb);
  415. ud->tcp_pcb = NULL;
  416. return lwip_lua_checkerr(L, err);
  417. }
  418. return 0;
  419. }
  420. // Lua: client/socket:on(name, callback)
  421. int net_on( lua_State *L ) {
  422. lnet_userdata *ud = net_get_udata(L);
  423. if (!ud || ud->type == TYPE_TCP_SERVER)
  424. return luaL_error(L, "invalid user data");
  425. int *refptr = NULL;
  426. const char *name = luaL_checkstring(L, 2);
  427. if (!name) return luaL_error(L, "need callback name");
  428. switch (ud->type) {
  429. case TYPE_TCP_CLIENT:
  430. if (strcmp("connection",name)==0)
  431. { refptr = &ud->client.cb_connect_ref; break; }
  432. if (strcmp("disconnection",name)==0)
  433. { refptr = &ud->client.cb_disconnect_ref; break; }
  434. if (strcmp("reconnection",name)==0)
  435. { refptr = &ud->client.cb_reconnect_ref; break; }
  436. case TYPE_UDP_SOCKET:
  437. if (strcmp("dns",name)==0)
  438. { refptr = &ud->client.cb_dns_ref; break; }
  439. if (strcmp("receive",name)==0)
  440. { refptr = &ud->client.cb_receive_ref; break; }
  441. if (strcmp("sent",name)==0)
  442. { refptr = &ud->client.cb_sent_ref; break; }
  443. break;
  444. default: return luaL_error(L, "invalid user data");
  445. }
  446. if (refptr == NULL)
  447. return luaL_error(L, "invalid callback name");
  448. if (lua_isfunction(L, 3)) {
  449. lua_pushvalue(L, 3);
  450. luaL_unref(L, LUA_REGISTRYINDEX, *refptr);
  451. *refptr = luaL_ref(L, LUA_REGISTRYINDEX);
  452. } else if (lua_isnil(L, 3)) {
  453. luaL_unref(L, LUA_REGISTRYINDEX, *refptr);
  454. *refptr = LUA_NOREF;
  455. } else {
  456. return luaL_error(L, "invalid callback function");
  457. }
  458. return 0;
  459. }
  460. // Lua: client:send(data, function(c)), socket:send(port, ip, data, function(s))
  461. int net_send( lua_State *L ) {
  462. lnet_userdata *ud = net_get_udata(L);
  463. if (!ud || ud->type == TYPE_TCP_SERVER)
  464. return luaL_error(L, "invalid user data");
  465. ip_addr_t addr;
  466. uint16_t port;
  467. const char *data;
  468. size_t datalen = 0;
  469. int stack = 2;
  470. if (ud->type == TYPE_UDP_SOCKET) {
  471. size_t dl = 0;
  472. port = luaL_checkinteger(L, stack++);
  473. if (port == 0) return luaL_error(L, "need port");
  474. const char *domain = luaL_checklstring(L, stack++, &dl);
  475. if (!domain) return luaL_error(L, "need IP address");
  476. if (!ipaddr_aton(domain, &addr)) return luaL_error(L, "invalid IP address");
  477. }
  478. data = luaL_checklstring(L, stack++, &datalen);
  479. if (!data || datalen == 0) return luaL_error(L, "no data to send");
  480. if (lua_isfunction(L, stack)) {
  481. lua_pushvalue(L, stack++);
  482. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_sent_ref);
  483. ud->client.cb_sent_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  484. }
  485. if (ud->type == TYPE_UDP_SOCKET && !ud->pcb) {
  486. ud->udp_pcb = udp_new();
  487. if (!ud->udp_pcb)
  488. return luaL_error(L, "cannot allocate PCB");
  489. udp_recv(ud->udp_pcb, net_udp_recv_cb, ud);
  490. ip_addr_t laddr = {0};
  491. err_t err = udp_bind(ud->udp_pcb, &laddr, 0);
  492. if (err != ERR_OK) {
  493. udp_remove(ud->udp_pcb);
  494. ud->udp_pcb = NULL;
  495. return lwip_lua_checkerr(L, err);
  496. }
  497. if (ud->self_ref == LUA_NOREF) {
  498. lua_pushvalue(L, 1);
  499. ud->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  500. }
  501. }
  502. if (!ud->pcb || ud->self_ref == LUA_NOREF)
  503. return luaL_error(L, "not connected");
  504. err_t err;
  505. if (ud->type == TYPE_UDP_SOCKET) {
  506. struct pbuf *pb = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
  507. if (!pb)
  508. return luaL_error(L, "cannot allocate message buffer");
  509. pbuf_take(pb, data, datalen);
  510. err = udp_sendto(ud->udp_pcb, pb, &addr, port);
  511. pbuf_free(pb);
  512. if (ud->client.cb_sent_ref != LUA_NOREF) {
  513. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->client.cb_sent_ref);
  514. lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref);
  515. lua_call(L, 1, 0);
  516. }
  517. } else if (ud->type == TYPE_TCP_CLIENT) {
  518. err = tcp_write(ud->tcp_pcb, data, datalen, TCP_WRITE_FLAG_COPY);
  519. }
  520. return lwip_lua_checkerr(L, err);
  521. }
  522. // Lua: client:hold()
  523. int net_hold( lua_State *L ) {
  524. lnet_userdata *ud = net_get_udata(L);
  525. if (!ud || ud->type != TYPE_TCP_CLIENT)
  526. return luaL_error(L, "invalid user data");
  527. if (!ud->client.hold && ud->tcp_pcb) {
  528. ud->client.hold = 1;
  529. }
  530. return 0;
  531. }
  532. // Lua: client:unhold()
  533. int net_unhold( lua_State *L ) {
  534. lnet_userdata *ud = net_get_udata(L);
  535. if (!ud || ud->type != TYPE_TCP_CLIENT)
  536. return luaL_error(L, "invalid user data");
  537. if (ud->client.hold && ud->tcp_pcb) {
  538. ud->client.hold = 0;
  539. ud->tcp_pcb->flags |= TF_ACK_NOW;
  540. tcp_recved(ud->tcp_pcb, TCP_WND);
  541. }
  542. return 0;
  543. }
  544. // Lua: client/socket:dns(domain, callback(socket, addr))
  545. int net_dns( lua_State *L ) {
  546. lnet_userdata *ud = net_get_udata(L);
  547. if (!ud || ud->type == TYPE_TCP_SERVER)
  548. return luaL_error(L, "invalid user data");
  549. size_t dl = 0;
  550. const char *domain = luaL_checklstring(L, 2, &dl);
  551. if (!domain)
  552. return luaL_error(L, "no domain specified");
  553. if (lua_isfunction(L, 3)) {
  554. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_dns_ref);
  555. lua_pushvalue(L, 3);
  556. ud->client.cb_dns_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  557. }
  558. if (ud->client.cb_dns_ref == LUA_NOREF)
  559. return luaL_error(L, "no callback specified");
  560. ud->client.wait_dns ++;
  561. int unref = 0;
  562. if (ud->self_ref == LUA_NOREF) {
  563. unref = 1;
  564. lua_pushvalue(L, 1);
  565. ud->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  566. }
  567. ip_addr_t addr;
  568. err_t err = dns_gethostbyname(domain, &addr, net_dns_cb, ud);
  569. if (err == ERR_OK) {
  570. net_dns_cb(domain, &addr, ud);
  571. } else if (err != ERR_INPROGRESS) {
  572. ud->client.wait_dns --;
  573. if (unref) {
  574. luaL_unref(L, LUA_REGISTRYINDEX, ud->self_ref);
  575. ud->self_ref = LUA_NOREF;
  576. }
  577. return lwip_lua_checkerr(L, err);
  578. }
  579. return 0;
  580. }
  581. // Lua: client/socket:ttl([ttl])
  582. int net_ttl( lua_State *L ) {
  583. lnet_userdata *ud = net_get_udata(L);
  584. if (!ud || ud->type == TYPE_TCP_SERVER)
  585. return luaL_error(L, "invalid user data");
  586. if (!ud->pcb)
  587. return luaL_error(L, "socket is not open/bound yet");
  588. int ttl = luaL_optinteger(L, 2, -1);
  589. // Since `ttl` field is part of IP_PCB macro
  590. // (which are at beginning of both udp_pcb/tcp_pcb)
  591. // and PCBs declared as `union` there is safe to
  592. // access ttl field without checking for type.
  593. if (ttl == -1) {
  594. ttl = ud->udp_pcb->ttl;
  595. } else {
  596. ud->udp_pcb->ttl = ttl;
  597. }
  598. lua_pushinteger(L, ttl);
  599. return 1;
  600. }
  601. // Lua: client:getpeer()
  602. int net_getpeer( lua_State *L ) {
  603. lnet_userdata *ud = net_get_udata(L);
  604. if (!ud || ud->type != TYPE_TCP_CLIENT)
  605. return luaL_error(L, "invalid user data");
  606. if (!ud->pcb) {
  607. lua_pushnil(L);
  608. lua_pushnil(L);
  609. return 2;
  610. }
  611. uint16_t port = ud->tcp_pcb->remote_port;
  612. ip_addr_t addr = ud->tcp_pcb->remote_ip;
  613. if (port == 0) {
  614. lua_pushnil(L);
  615. lua_pushnil(L);
  616. return 2;
  617. }
  618. char addr_str[16];
  619. bzero(addr_str, 16);
  620. ets_sprintf(addr_str, IPSTR, IP2STR(&addr.addr));
  621. lua_pushinteger(L, port);
  622. lua_pushstring(L, addr_str);
  623. return 2;
  624. }
  625. // Lua: client/server/socket:getaddr()
  626. int net_getaddr( lua_State *L ) {
  627. lnet_userdata *ud = net_get_udata(L);
  628. if (!ud) return luaL_error(L, "invalid user data");
  629. if (!ud->pcb) {
  630. lua_pushnil(L);
  631. lua_pushnil(L);
  632. return 2;
  633. }
  634. uint16_t port;
  635. ip_addr_t addr;
  636. switch (ud->type) {
  637. case TYPE_TCP_CLIENT:
  638. case TYPE_TCP_SERVER:
  639. addr = ud->tcp_pcb->local_ip;
  640. port = ud->tcp_pcb->local_port;
  641. break;
  642. case TYPE_UDP_SOCKET:
  643. addr = ud->udp_pcb->local_ip;
  644. port = ud->udp_pcb->local_port;
  645. break;
  646. }
  647. if (port == 0) {
  648. lua_pushnil(L);
  649. lua_pushnil(L);
  650. return 2;
  651. }
  652. char addr_str[16];
  653. bzero(addr_str, 16);
  654. ets_sprintf(addr_str, IPSTR, IP2STR(&addr.addr));
  655. lua_pushinteger(L, port);
  656. lua_pushstring(L, addr_str);
  657. return 2;
  658. }
  659. #if 0
  660. static void dbg_print_ud(const char *title, lnet_userdata *ud) {
  661. int i;
  662. dbg_printf("%s: Userdata %p:", title, ud);
  663. for (i=0; i<(sizeof(*ud)/sizeof(uint32_t)); i++)
  664. dbg_printf( " 0x%08x", ((uint32_t *)ud)[i]);
  665. dbg_printf("\n");
  666. #endif
  667. // Lua: client/server/socket:close()
  668. int net_close( lua_State *L ) {
  669. lnet_userdata *ud = net_get_udata(L);
  670. if (!ud) return luaL_error(L, "invalid user data");
  671. if (ud->pcb) {
  672. switch (ud->type) {
  673. case TYPE_TCP_CLIENT:
  674. if (ERR_OK != tcp_close(ud->tcp_pcb)) {
  675. tcp_arg(ud->tcp_pcb, NULL);
  676. tcp_abort(ud->tcp_pcb);
  677. }
  678. ud->tcp_pcb = NULL;
  679. break;
  680. case TYPE_TCP_SERVER:
  681. tcp_close(ud->tcp_pcb);
  682. ud->tcp_pcb = NULL;
  683. break;
  684. case TYPE_UDP_SOCKET:
  685. udp_remove(ud->udp_pcb);
  686. ud->udp_pcb = NULL;
  687. break;
  688. }
  689. } else {
  690. return luaL_error(L, "not connected");
  691. }
  692. if (ud->type == TYPE_TCP_SERVER ||
  693. (ud->pcb == NULL && ud->client.wait_dns == 0)) {
  694. int selfref = ud->self_ref;
  695. ud->self_ref = LUA_NOREF;
  696. luaL_unref(L, LUA_REGISTRYINDEX, selfref);
  697. }
  698. #if 0
  699. dbg_print_ud("close exit", ud);
  700. #endif
  701. return 0;
  702. }
  703. int net_delete( lua_State *L ) {
  704. lnet_userdata *ud = net_get_udata(L);
  705. if (!ud) return luaL_error(L, "no user data");
  706. if (ud->pcb) {
  707. switch (ud->type) {
  708. case TYPE_TCP_CLIENT:
  709. tcp_arg(ud->tcp_pcb, NULL);
  710. tcp_abort(ud->tcp_pcb);
  711. ud->tcp_pcb = NULL;
  712. break;
  713. case TYPE_TCP_SERVER:
  714. tcp_close(ud->tcp_pcb);
  715. ud->tcp_pcb = NULL;
  716. break;
  717. case TYPE_UDP_SOCKET:
  718. udp_remove(ud->udp_pcb);
  719. ud->udp_pcb = NULL;
  720. break;
  721. }
  722. }
  723. switch (ud->type) {
  724. case TYPE_TCP_CLIENT:
  725. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_connect_ref);
  726. ud->client.cb_connect_ref = LUA_NOREF;
  727. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_disconnect_ref);
  728. ud->client.cb_disconnect_ref = LUA_NOREF;
  729. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_reconnect_ref);
  730. ud->client.cb_reconnect_ref = LUA_NOREF;
  731. case TYPE_UDP_SOCKET:
  732. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_dns_ref);
  733. ud->client.cb_dns_ref = LUA_NOREF;
  734. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_receive_ref);
  735. ud->client.cb_receive_ref = LUA_NOREF;
  736. luaL_unref(L, LUA_REGISTRYINDEX, ud->client.cb_sent_ref);
  737. ud->client.cb_sent_ref = LUA_NOREF;
  738. break;
  739. case TYPE_TCP_SERVER:
  740. luaL_unref(L, LUA_REGISTRYINDEX, ud->server.cb_accept_ref);
  741. ud->server.cb_accept_ref = LUA_NOREF;
  742. break;
  743. }
  744. int selfref = ud->self_ref;
  745. ud->self_ref = LUA_NOREF;
  746. luaL_unref(L, LUA_REGISTRYINDEX, selfref);
  747. #if 0
  748. dbg_print_ud("delete end", ud);
  749. #endif
  750. return 0;
  751. }
  752. #pragma mark - Multicast
  753. static int net_multicastJoinLeave( lua_State *L, int join) {
  754. size_t il;
  755. ip_addr_t multicast_addr;
  756. ip_addr_t if_addr;
  757. const char *multicast_ip;
  758. const char *if_ip;
  759. NODE_DBG("net_multicastJoin is called.\n");
  760. if(! lua_isstring(L,1) ) return luaL_error( L, "wrong arg type" );
  761. if_ip = luaL_checklstring( L, 1, &il );
  762. if (if_ip != NULL)
  763. if ( if_ip[0] == '\0' || stricmp(if_ip,"any") == 0)
  764. {
  765. if_ip = "0.0.0.0";
  766. il = 7;
  767. }
  768. if (if_ip == NULL || il > 15 || il < 7) return luaL_error( L, "invalid if ip" );
  769. if_addr.addr = ipaddr_addr(if_ip);
  770. if(! lua_isstring(L,2) ) return luaL_error( L, "wrong arg type" );
  771. multicast_ip = luaL_checklstring( L, 2, &il );
  772. if (multicast_ip == NULL || il > 15 || il < 7) return luaL_error( L, "invalid multicast ip" );
  773. multicast_addr.addr = ipaddr_addr(multicast_ip);
  774. if (join)
  775. {
  776. igmp_joingroup(&if_addr, &multicast_addr);
  777. }
  778. else
  779. {
  780. igmp_leavegroup(&if_addr, &multicast_addr);
  781. }
  782. return 0;
  783. }
  784. // Lua: net.multicastJoin(ifip, multicastip)
  785. // if ifip "" or "any" all interfaces are affected
  786. static int net_multicastJoin( lua_State* L ) {
  787. return net_multicastJoinLeave(L,1);
  788. }
  789. // Lua: net.multicastLeave(ifip, multicastip)
  790. // if ifip "" or "any" all interfaces are affected
  791. static int net_multicastLeave( lua_State* L ) {
  792. return net_multicastJoinLeave(L,0);
  793. }
  794. #pragma mark - DNS
  795. static void net_dns_static_cb(const char *name, ip_addr_t *ipaddr, void *callback_arg) {
  796. ip_addr_t addr;
  797. if (ipaddr != NULL)
  798. addr = *ipaddr;
  799. else addr.addr = 0xFFFFFFFF;
  800. int cb_ref = (int)callback_arg;
  801. lua_State *L = lua_getstate();
  802. /*
  803. * Move reference from registry to stack before the call could possibly
  804. * longjmp us out of here.
  805. */
  806. lua_rawgeti(L, LUA_REGISTRYINDEX, cb_ref);
  807. luaL_unref(L, LUA_REGISTRYINDEX, cb_ref);
  808. // XXX I have no idea why the API insists on a `nil` here, but it does.
  809. lua_pushnil(L);
  810. if (addr.addr != 0xFFFFFFFF) {
  811. char iptmp[20];
  812. size_t ipl = sprintf(iptmp, IPSTR, IP2STR(&addr.addr));
  813. lua_pushlstring(L, iptmp, ipl);
  814. } else {
  815. lua_pushnil(L);
  816. }
  817. lua_call(L, 2, 0);
  818. }
  819. // Lua: net.dns.resolve( domain, function(sk, ip) )
  820. static int net_dns_static( lua_State* L ) {
  821. size_t dl;
  822. const char* domain = luaL_checklstring(L, 1, &dl);
  823. if (!domain && dl > 128) {
  824. return luaL_error(L, "wrong domain");
  825. }
  826. luaL_checktype(L, 2, LUA_TFUNCTION);
  827. lua_pushvalue(L, 2); // copy argument (func) to the top of stack
  828. int cbref = luaL_ref(L, LUA_REGISTRYINDEX);
  829. ip_addr_t addr;
  830. _Static_assert(sizeof(void *) >= sizeof(typeof(cbref)),
  831. "Can't upcast int to ptr");
  832. err_t err = dns_gethostbyname(domain, &addr, net_dns_static_cb, (void *)cbref);
  833. if (err == ERR_OK) {
  834. net_dns_static_cb(domain, &addr, (void *)cbref);
  835. return 0;
  836. } else if (err == ERR_INPROGRESS) {
  837. return 0;
  838. } else {
  839. /* Bail out! Unhook callback from registry, first */
  840. luaL_unref(L, LUA_REGISTRYINDEX, cbref);
  841. return lwip_lua_checkerr(L, err);
  842. }
  843. return 0;
  844. }
  845. // Lua: s = net.dns.setdnsserver(ip_addr, [index])
  846. static int net_setdnsserver( lua_State* L ) {
  847. size_t l;
  848. u32_t ip32;
  849. const char *server = luaL_checklstring( L, 1, &l );
  850. if (l>16 || server == NULL || (ip32 = ipaddr_addr(server)) == IPADDR_NONE || ip32 == IPADDR_ANY)
  851. return luaL_error( L, "invalid dns server ip" );
  852. int numdns = luaL_optint(L, 2, 0);
  853. if (numdns >= DNS_MAX_SERVERS)
  854. return luaL_error( L, "server index out of range [0-%d]", DNS_MAX_SERVERS - 1);
  855. ip_addr_t ipaddr;
  856. ip4_addr_set_u32(&ipaddr, ip32);
  857. dns_setserver(numdns,&ipaddr);
  858. return 0;
  859. }
  860. // Lua: s = net.dns.getdnsserver([index])
  861. static int net_getdnsserver( lua_State* L ) {
  862. int numdns = luaL_optint(L, 1, 0);
  863. if (numdns >= DNS_MAX_SERVERS)
  864. return luaL_error( L, "server index out of range [0-%d]", DNS_MAX_SERVERS - 1);
  865. // ip_addr_t ipaddr;
  866. // dns_getserver(numdns,&ipaddr);
  867. // Bug fix by @md5crypt https://github.com/nodemcu/nodemcu-firmware/pull/500
  868. ip_addr_t ipaddr = dns_getserver(numdns);
  869. if ( ip_addr_isany(&ipaddr) ) {
  870. lua_pushnil( L );
  871. } else {
  872. char temp[20] = {0};
  873. sprintf(temp, IPSTR, IP2STR( &ipaddr.addr ) );
  874. lua_pushstring( L, temp );
  875. }
  876. return 1;
  877. }
  878. #pragma mark - netif info
  879. /*
  880. * XXX This is internal to Espressif's SDK, but it's called from several places
  881. * in the NodeMCU tree. It would be nicer if there were a LwIP export for this
  882. * rather than this not-so-secret symbol.
  883. */
  884. extern struct netif *eagle_lwip_getif(uint8);
  885. static void
  886. push_ipaddr(lua_State *L, ip_addr_t *addr) {
  887. char temp[20];
  888. ssize_t ipl = snprintf(temp, sizeof temp, IPSTR, IP2STR(&addr->addr));
  889. lua_assert (ipl >= 0 && ipl < 20);
  890. lua_pushlstring( L, temp, ipl );
  891. }
  892. static void
  893. field_from_ipaddr(lua_State *L, const char * field_name, ip_addr_t* addr) {
  894. if ( ip_addr_isany(addr) ) {
  895. lua_pushnil(L);
  896. } else {
  897. push_ipaddr(L, addr);
  898. }
  899. lua_setfield(L, -2, field_name);
  900. }
  901. static int net_ifinfo( lua_State* L ) {
  902. int ifidx = luaL_optint(L, 1, 0);
  903. if (ifidx != 0 && ifidx != 1) {
  904. return 0;
  905. }
  906. struct netif * nif = eagle_lwip_getif(ifidx);
  907. if (nif == NULL) {
  908. return 0;
  909. }
  910. lua_createtable(L, 0,
  911. 4 + (nif->dhcp == NULL ? 0 : 1));
  912. lua_pushlstring(L, nif->hwaddr, nif->hwaddr_len);
  913. lua_setfield(L, -2, "hwaddr");
  914. field_from_ipaddr(L, "ip" , &nif->ip_addr);
  915. field_from_ipaddr(L, "netmask", &nif->netmask);
  916. field_from_ipaddr(L, "gateway", &nif->gw);
  917. if (nif->dhcp != NULL) {
  918. lua_createtable(L, 0, 3);
  919. field_from_ipaddr(L, "server_ip" , &nif->dhcp->server_ip_addr );
  920. field_from_ipaddr(L, "client_ip" , &nif->dhcp->offered_ip_addr );
  921. field_from_ipaddr(L, "ntp_server", &nif->dhcp->offered_ntp_addr);
  922. lua_setfield(L, -2, "dhcp");
  923. }
  924. return 1;
  925. }
  926. #pragma mark - Tables
  927. // Module function map
  928. LROT_BEGIN(net_tcpserver, NULL, LROT_MASK_GC_INDEX)
  929. LROT_FUNCENTRY( __gc, net_delete )
  930. LROT_TABENTRY( __index, net_tcpserver )
  931. LROT_FUNCENTRY( listen, net_listen )
  932. LROT_FUNCENTRY( getaddr, net_getaddr )
  933. LROT_FUNCENTRY( close, net_close )
  934. LROT_END(net_tcpserver, NULL, LROT_MASK_GC_INDEX)
  935. LROT_BEGIN(net_tcpsocket, NULL, LROT_MASK_GC_INDEX)
  936. LROT_FUNCENTRY( __gc, net_delete )
  937. LROT_TABENTRY( __index, net_tcpsocket )
  938. LROT_FUNCENTRY( connect, net_connect )
  939. LROT_FUNCENTRY( close, net_close )
  940. LROT_FUNCENTRY( on, net_on )
  941. LROT_FUNCENTRY( send, net_send )
  942. LROT_FUNCENTRY( hold, net_hold )
  943. LROT_FUNCENTRY( unhold, net_unhold )
  944. LROT_FUNCENTRY( dns, net_dns )
  945. LROT_FUNCENTRY( ttl, net_ttl )
  946. LROT_FUNCENTRY( getpeer, net_getpeer )
  947. LROT_FUNCENTRY( getaddr, net_getaddr )
  948. LROT_END(net_tcpsocket, NULL, LROT_MASK_GC_INDEX)
  949. LROT_BEGIN(net_udpsocket, NULL, LROT_MASK_GC_INDEX)
  950. LROT_FUNCENTRY( __gc, net_delete )
  951. LROT_TABENTRY( __index, net_udpsocket )
  952. LROT_FUNCENTRY( listen, net_listen )
  953. LROT_FUNCENTRY( close, net_close )
  954. LROT_FUNCENTRY( on, net_on )
  955. LROT_FUNCENTRY( send, net_send )
  956. LROT_FUNCENTRY( dns, net_dns )
  957. LROT_FUNCENTRY( ttl, net_ttl )
  958. LROT_FUNCENTRY( getaddr, net_getaddr )
  959. LROT_END(net_udpsocket, NULL, LROT_MASK_GC_INDEX)
  960. LROT_BEGIN(net_dns_map, NULL, 0)
  961. LROT_FUNCENTRY( setdnsserver, net_setdnsserver )
  962. LROT_FUNCENTRY( getdnsserver, net_getdnsserver )
  963. LROT_FUNCENTRY( resolve, net_dns_static )
  964. LROT_END(net_dns_map, NULL, 0)
  965. #ifdef TLS_MODULE_PRESENT
  966. extern LROT_TABLE(tls_cert);
  967. #endif
  968. LROT_BEGIN(net, NULL, 0)
  969. LROT_FUNCENTRY( createServer, net_createServer )
  970. LROT_FUNCENTRY( createConnection, net_createConnection )
  971. LROT_FUNCENTRY( createUDPSocket, net_createUDPSocket )
  972. LROT_FUNCENTRY( ifinfo, net_ifinfo )
  973. LROT_FUNCENTRY( multicastJoin, net_multicastJoin )
  974. LROT_FUNCENTRY( multicastLeave, net_multicastLeave )
  975. #ifdef NET_PING_ENABLE
  976. LROT_FUNCENTRY( ping, net_ping )
  977. #endif
  978. LROT_TABENTRY( dns, net_dns_map )
  979. #ifdef TLS_MODULE_PRESENT
  980. LROT_TABENTRY( cert, tls_cert )
  981. #endif
  982. LROT_NUMENTRY( TCP, TYPE_TCP )
  983. LROT_NUMENTRY( UDP, TYPE_UDP )
  984. LROT_END(net, NULL, 0)
  985. int luaopen_net( lua_State *L ) {
  986. igmp_init();
  987. luaL_rometatable(L, NET_TABLE_TCP_SERVER, LROT_TABLEREF(net_tcpserver));
  988. luaL_rometatable(L, NET_TABLE_TCP_CLIENT, LROT_TABLEREF(net_tcpsocket));
  989. luaL_rometatable(L, NET_TABLE_UDP_SOCKET, LROT_TABLEREF(net_udpsocket));
  990. return 0;
  991. }
  992. NODEMCU_MODULE(NET, "net", net, luaopen_net);