tcp.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /*=========================================================================*\
  2. * TCP object
  3. * LuaSocket toolkit
  4. \*=========================================================================*/
  5. #include <string.h>
  6. #include "lua.h"
  7. #include "lauxlib.h"
  8. #include "auxiliar.h"
  9. #include "socket.h"
  10. #include "inet.h"
  11. #include "options.h"
  12. #include "tcp.h"
  13. #include "buffer.h"
  14. /*=========================================================================*\
  15. * Internal function prototypes
  16. \*=========================================================================*/
  17. static int global_create(lua_State *L);
  18. static int global_create6(lua_State *L);
  19. static int global_connect(lua_State *L);
  20. static int meth_connect(lua_State *L);
  21. static int meth_listen(lua_State *L);
  22. static int meth_getfamily(lua_State *L);
  23. static int meth_bind(lua_State *L);
  24. static int meth_send(lua_State *L);
  25. static int meth_getstats(lua_State *L);
  26. static int meth_setstats(lua_State *L);
  27. static int meth_getsockname(lua_State *L);
  28. static int meth_getpeername(lua_State *L);
  29. static int meth_shutdown(lua_State *L);
  30. static int meth_receive(lua_State *L);
  31. static int meth_accept(lua_State *L);
  32. static int meth_close(lua_State *L);
  33. static int meth_getoption(lua_State *L);
  34. static int meth_setoption(lua_State *L);
  35. static int meth_settimeout(lua_State *L);
  36. static int meth_getfd(lua_State *L);
  37. static int meth_setfd(lua_State *L);
  38. static int meth_dirty(lua_State *L);
  39. /* tcp object methods */
  40. static luaL_Reg tcp_methods[] = {
  41. {"__gc", meth_close},
  42. {"__tostring", auxiliar_tostring},
  43. {"accept", meth_accept},
  44. {"bind", meth_bind},
  45. {"close", meth_close},
  46. {"connect", meth_connect},
  47. {"dirty", meth_dirty},
  48. {"getfamily", meth_getfamily},
  49. {"getfd", meth_getfd},
  50. {"getoption", meth_getoption},
  51. {"getpeername", meth_getpeername},
  52. {"getsockname", meth_getsockname},
  53. {"getstats", meth_getstats},
  54. {"setstats", meth_setstats},
  55. {"listen", meth_listen},
  56. {"receive", meth_receive},
  57. {"send", meth_send},
  58. {"setfd", meth_setfd},
  59. {"setoption", meth_setoption},
  60. {"setpeername", meth_connect},
  61. {"setsockname", meth_bind},
  62. {"settimeout", meth_settimeout},
  63. {"shutdown", meth_shutdown},
  64. {NULL, NULL}
  65. };
  66. /* socket option handlers */
  67. static t_opt optget[] = {
  68. {"keepalive", opt_get_keepalive},
  69. {"reuseaddr", opt_get_reuseaddr},
  70. {"tcp-nodelay", opt_get_tcp_nodelay},
  71. {"linger", opt_get_linger},
  72. {"error", opt_get_error},
  73. {NULL, NULL}
  74. };
  75. static t_opt optset[] = {
  76. {"keepalive", opt_set_keepalive},
  77. {"reuseaddr", opt_set_reuseaddr},
  78. {"tcp-nodelay", opt_set_tcp_nodelay},
  79. {"ipv6-v6only", opt_set_ip6_v6only},
  80. {"linger", opt_set_linger},
  81. {NULL, NULL}
  82. };
  83. /* functions in library namespace */
  84. static luaL_Reg func[] = {
  85. {"tcp", global_create},
  86. {"tcp6", global_create6},
  87. {"connect", global_connect},
  88. {NULL, NULL}
  89. };
  90. /*-------------------------------------------------------------------------*\
  91. * Initializes module
  92. \*-------------------------------------------------------------------------*/
  93. int tcp_open(lua_State *L)
  94. {
  95. /* create classes */
  96. auxiliar_newclass(L, "tcp{master}", tcp_methods);
  97. auxiliar_newclass(L, "tcp{client}", tcp_methods);
  98. auxiliar_newclass(L, "tcp{server}", tcp_methods);
  99. /* create class groups */
  100. auxiliar_add2group(L, "tcp{master}", "tcp{any}");
  101. auxiliar_add2group(L, "tcp{client}", "tcp{any}");
  102. auxiliar_add2group(L, "tcp{server}", "tcp{any}");
  103. /* define library functions */
  104. #if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
  105. luaL_setfuncs(L, func, 0);
  106. #else
  107. luaL_openlib(L, NULL, func, 0);
  108. #endif
  109. return 0;
  110. }
  111. /*=========================================================================*\
  112. * Lua methods
  113. \*=========================================================================*/
  114. /*-------------------------------------------------------------------------*\
  115. * Just call buffered IO methods
  116. \*-------------------------------------------------------------------------*/
  117. static int meth_send(lua_State *L) {
  118. p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1);
  119. return buffer_meth_send(L, &tcp->buf);
  120. }
  121. static int meth_receive(lua_State *L) {
  122. p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1);
  123. return buffer_meth_receive(L, &tcp->buf);
  124. }
  125. static int meth_getstats(lua_State *L) {
  126. p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1);
  127. return buffer_meth_getstats(L, &tcp->buf);
  128. }
  129. static int meth_setstats(lua_State *L) {
  130. p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1);
  131. return buffer_meth_setstats(L, &tcp->buf);
  132. }
  133. /*-------------------------------------------------------------------------*\
  134. * Just call option handler
  135. \*-------------------------------------------------------------------------*/
  136. static int meth_getoption(lua_State *L)
  137. {
  138. p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
  139. return opt_meth_getoption(L, optget, &tcp->sock);
  140. }
  141. static int meth_setoption(lua_State *L)
  142. {
  143. p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
  144. return opt_meth_setoption(L, optset, &tcp->sock);
  145. }
  146. /*-------------------------------------------------------------------------*\
  147. * Select support methods
  148. \*-------------------------------------------------------------------------*/
  149. static int meth_getfd(lua_State *L)
  150. {
  151. p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
  152. lua_pushnumber(L, (int) tcp->sock);
  153. return 1;
  154. }
  155. /* this is very dangerous, but can be handy for those that are brave enough */
  156. static int meth_setfd(lua_State *L)
  157. {
  158. p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
  159. tcp->sock = (t_socket) luaL_checknumber(L, 2);
  160. return 0;
  161. }
  162. static int meth_dirty(lua_State *L)
  163. {
  164. p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
  165. lua_pushboolean(L, !buffer_isempty(&tcp->buf));
  166. return 1;
  167. }
  168. /*-------------------------------------------------------------------------*\
  169. * Waits for and returns a client object attempting connection to the
  170. * server object
  171. \*-------------------------------------------------------------------------*/
  172. static int meth_accept(lua_State *L)
  173. {
  174. p_tcp server = (p_tcp) auxiliar_checkclass(L, "tcp{server}", 1);
  175. p_timeout tm = timeout_markstart(&server->tm);
  176. t_socket sock;
  177. const char *err = inet_tryaccept(&server->sock, server->family, &sock, tm);
  178. /* if successful, push client socket */
  179. if (err == NULL) {
  180. p_tcp clnt = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
  181. auxiliar_setclass(L, "tcp{client}", -1);
  182. /* initialize structure fields */
  183. memset(clnt, 0, sizeof(t_tcp));
  184. socket_setnonblocking(&sock);
  185. clnt->sock = sock;
  186. io_init(&clnt->io, (p_send) socket_send, (p_recv) socket_recv,
  187. (p_error) socket_ioerror, &clnt->sock);
  188. timeout_init(&clnt->tm, -1, -1);
  189. buffer_init(&clnt->buf, &clnt->io, &clnt->tm);
  190. clnt->family = server->family;
  191. return 1;
  192. } else {
  193. lua_pushnil(L);
  194. lua_pushstring(L, err);
  195. return 2;
  196. }
  197. }
  198. /*-------------------------------------------------------------------------*\
  199. * Binds an object to an address
  200. \*-------------------------------------------------------------------------*/
  201. static int meth_bind(lua_State *L)
  202. {
  203. p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1);
  204. const char *address = luaL_checkstring(L, 2);
  205. const char *port = luaL_checkstring(L, 3);
  206. const char *err;
  207. struct addrinfo bindhints;
  208. memset(&bindhints, 0, sizeof(bindhints));
  209. bindhints.ai_socktype = SOCK_STREAM;
  210. bindhints.ai_family = tcp->family;
  211. bindhints.ai_flags = AI_PASSIVE;
  212. err = inet_trybind(&tcp->sock, address, port, &bindhints);
  213. if (err) {
  214. lua_pushnil(L);
  215. lua_pushstring(L, err);
  216. return 2;
  217. }
  218. lua_pushnumber(L, 1);
  219. return 1;
  220. }
  221. /*-------------------------------------------------------------------------*\
  222. * Turns a master tcp object into a client object.
  223. \*-------------------------------------------------------------------------*/
  224. static int meth_connect(lua_State *L)
  225. {
  226. p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
  227. const char *address = luaL_checkstring(L, 2);
  228. const char *port = luaL_checkstring(L, 3);
  229. struct addrinfo connecthints;
  230. const char *err;
  231. memset(&connecthints, 0, sizeof(connecthints));
  232. connecthints.ai_socktype = SOCK_STREAM;
  233. /* make sure we try to connect only to the same family */
  234. connecthints.ai_family = tcp->family;
  235. timeout_markstart(&tcp->tm);
  236. err = inet_tryconnect(&tcp->sock, &tcp->family, address, port,
  237. &tcp->tm, &connecthints);
  238. /* have to set the class even if it failed due to non-blocking connects */
  239. auxiliar_setclass(L, "tcp{client}", 1);
  240. if (err) {
  241. lua_pushnil(L);
  242. lua_pushstring(L, err);
  243. return 2;
  244. }
  245. lua_pushnumber(L, 1);
  246. return 1;
  247. }
  248. /*-------------------------------------------------------------------------*\
  249. * Closes socket used by object
  250. \*-------------------------------------------------------------------------*/
  251. static int meth_close(lua_State *L)
  252. {
  253. p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
  254. socket_destroy(&tcp->sock);
  255. lua_pushnumber(L, 1);
  256. return 1;
  257. }
  258. /*-------------------------------------------------------------------------*\
  259. * Returns family as string
  260. \*-------------------------------------------------------------------------*/
  261. static int meth_getfamily(lua_State *L)
  262. {
  263. p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
  264. if (tcp->family == PF_INET6) {
  265. lua_pushliteral(L, "inet6");
  266. return 1;
  267. } else {
  268. lua_pushliteral(L, "inet4");
  269. return 1;
  270. }
  271. }
  272. /*-------------------------------------------------------------------------*\
  273. * Puts the sockt in listen mode
  274. \*-------------------------------------------------------------------------*/
  275. static int meth_listen(lua_State *L)
  276. {
  277. p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1);
  278. int backlog = (int) luaL_optnumber(L, 2, 32);
  279. int err = socket_listen(&tcp->sock, backlog);
  280. if (err != IO_DONE) {
  281. lua_pushnil(L);
  282. lua_pushstring(L, socket_strerror(err));
  283. return 2;
  284. }
  285. /* turn master object into a server object */
  286. auxiliar_setclass(L, "tcp{server}", 1);
  287. lua_pushnumber(L, 1);
  288. return 1;
  289. }
  290. /*-------------------------------------------------------------------------*\
  291. * Shuts the connection down partially
  292. \*-------------------------------------------------------------------------*/
  293. static int meth_shutdown(lua_State *L)
  294. {
  295. /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */
  296. static const char* methods[] = { "receive", "send", "both", NULL };
  297. p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1);
  298. int how = luaL_checkoption(L, 2, "both", methods);
  299. socket_shutdown(&tcp->sock, how);
  300. lua_pushnumber(L, 1);
  301. return 1;
  302. }
  303. /*-------------------------------------------------------------------------*\
  304. * Just call inet methods
  305. \*-------------------------------------------------------------------------*/
  306. static int meth_getpeername(lua_State *L)
  307. {
  308. p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
  309. return inet_meth_getpeername(L, &tcp->sock, tcp->family);
  310. }
  311. static int meth_getsockname(lua_State *L)
  312. {
  313. p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
  314. return inet_meth_getsockname(L, &tcp->sock, tcp->family);
  315. }
  316. /*-------------------------------------------------------------------------*\
  317. * Just call tm methods
  318. \*-------------------------------------------------------------------------*/
  319. static int meth_settimeout(lua_State *L)
  320. {
  321. p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
  322. return timeout_meth_settimeout(L, &tcp->tm);
  323. }
  324. /*=========================================================================*\
  325. * Library functions
  326. \*=========================================================================*/
  327. /*-------------------------------------------------------------------------*\
  328. * Creates a master tcp object
  329. \*-------------------------------------------------------------------------*/
  330. static int tcp_create(lua_State *L, int family) {
  331. t_socket sock;
  332. const char *err = inet_trycreate(&sock, family, SOCK_STREAM);
  333. /* try to allocate a system socket */
  334. if (!err) {
  335. /* allocate tcp object */
  336. p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
  337. memset(tcp, 0, sizeof(t_tcp));
  338. /* set its type as master object */
  339. auxiliar_setclass(L, "tcp{master}", -1);
  340. /* initialize remaining structure fields */
  341. socket_setnonblocking(&sock);
  342. if (family == PF_INET6) {
  343. int yes = 1;
  344. setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
  345. (void *)&yes, sizeof(yes));
  346. }
  347. tcp->sock = sock;
  348. io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
  349. (p_error) socket_ioerror, &tcp->sock);
  350. timeout_init(&tcp->tm, -1, -1);
  351. buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
  352. tcp->family = family;
  353. return 1;
  354. } else {
  355. lua_pushnil(L);
  356. lua_pushstring(L, err);
  357. return 2;
  358. }
  359. }
  360. static int global_create(lua_State *L) {
  361. return tcp_create(L, AF_INET);
  362. }
  363. static int global_create6(lua_State *L) {
  364. return tcp_create(L, AF_INET6);
  365. }
  366. #if 0
  367. static const char *tryconnect6(const char *remoteaddr, const char *remoteserv,
  368. struct addrinfo *connecthints, p_tcp tcp) {
  369. struct addrinfo *iterator = NULL, *resolved = NULL;
  370. const char *err = NULL;
  371. /* try resolving */
  372. err = socket_gaistrerror(getaddrinfo(remoteaddr, remoteserv,
  373. connecthints, &resolved));
  374. if (err != NULL) {
  375. if (resolved) freeaddrinfo(resolved);
  376. return err;
  377. }
  378. /* iterate over all returned addresses trying to connect */
  379. for (iterator = resolved; iterator; iterator = iterator->ai_next) {
  380. p_timeout tm = timeout_markstart(&tcp->tm);
  381. /* create new socket if necessary. if there was no
  382. * bind, we need to create one for every new family
  383. * that shows up while iterating. if there was a
  384. * bind, all families will be the same and we will
  385. * not enter this branch. */
  386. if (tcp->family != iterator->ai_family) {
  387. socket_destroy(&tcp->sock);
  388. err = socket_strerror(socket_create(&tcp->sock,
  389. iterator->ai_family, iterator->ai_socktype,
  390. iterator->ai_protocol));
  391. if (err != NULL) {
  392. freeaddrinfo(resolved);
  393. return err;
  394. }
  395. tcp->family = iterator->ai_family;
  396. /* all sockets initially non-blocking */
  397. socket_setnonblocking(&tcp->sock);
  398. }
  399. /* finally try connecting to remote address */
  400. err = socket_strerror(socket_connect(&tcp->sock,
  401. (SA *) iterator->ai_addr,
  402. (socklen_t) iterator->ai_addrlen, tm));
  403. /* if success, break out of loop */
  404. if (err == NULL) break;
  405. }
  406. freeaddrinfo(resolved);
  407. /* here, if err is set, we failed */
  408. return err;
  409. }
  410. #endif
  411. static int global_connect(lua_State *L) {
  412. const char *remoteaddr = luaL_checkstring(L, 1);
  413. const char *remoteserv = luaL_checkstring(L, 2);
  414. const char *localaddr = luaL_optstring(L, 3, NULL);
  415. const char *localserv = luaL_optstring(L, 4, "0");
  416. int family = inet_optfamily(L, 5, "unspec");
  417. p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
  418. struct addrinfo bindhints, connecthints;
  419. const char *err = NULL;
  420. /* initialize tcp structure */
  421. memset(tcp, 0, sizeof(t_tcp));
  422. io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
  423. (p_error) socket_ioerror, &tcp->sock);
  424. timeout_init(&tcp->tm, -1, -1);
  425. buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
  426. tcp->sock = SOCKET_INVALID;
  427. tcp->family = PF_UNSPEC;
  428. /* allow user to pick local address and port */
  429. memset(&bindhints, 0, sizeof(bindhints));
  430. bindhints.ai_socktype = SOCK_STREAM;
  431. bindhints.ai_family = family;
  432. bindhints.ai_flags = AI_PASSIVE;
  433. if (localaddr) {
  434. err = inet_trybind(&tcp->sock, localaddr, localserv, &bindhints);
  435. if (err) {
  436. lua_pushnil(L);
  437. lua_pushstring(L, err);
  438. return 2;
  439. }
  440. tcp->family = bindhints.ai_family;
  441. }
  442. /* try to connect to remote address and port */
  443. memset(&connecthints, 0, sizeof(connecthints));
  444. connecthints.ai_socktype = SOCK_STREAM;
  445. /* make sure we try to connect only to the same family */
  446. connecthints.ai_family = bindhints.ai_family;
  447. err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv,
  448. &tcp->tm, &connecthints);
  449. if (err) {
  450. socket_destroy(&tcp->sock);
  451. lua_pushnil(L);
  452. lua_pushstring(L, err);
  453. return 2;
  454. }
  455. auxiliar_setclass(L, "tcp{client}", -1);
  456. return 1;
  457. }