aboutsummaryrefslogtreecommitdiff
path: root/src/tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tcp.c')
-rw-r--r--src/tcp.c111
1 files changed, 19 insertions, 92 deletions
diff --git a/src/tcp.c b/src/tcp.c
index 658f255..155f3bf 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -19,8 +19,8 @@
19* Internal function prototypes 19* Internal function prototypes
20\*=========================================================================*/ 20\*=========================================================================*/
21static int global_create(lua_State *L); 21static int global_create(lua_State *L);
22static int global_create6(lua_State *L);
22static int global_connect6(lua_State *L); 23static int global_connect6(lua_State *L);
23static int global_bind6(lua_State *L);
24static int meth_connect(lua_State *L); 24static int meth_connect(lua_State *L);
25static int meth_listen(lua_State *L); 25static int meth_listen(lua_State *L);
26static int meth_bind(lua_State *L); 26static int meth_bind(lua_State *L);
@@ -77,8 +77,8 @@ static t_opt optset[] = {
77/* functions in library namespace */ 77/* functions in library namespace */
78static luaL_reg func[] = { 78static luaL_reg func[] = {
79 {"tcp", global_create}, 79 {"tcp", global_create},
80 {"tcp6", global_create6},
80 {"connect6", global_connect6}, 81 {"connect6", global_connect6},
81 {"bind6", global_bind6},
82 {NULL, NULL} 82 {NULL, NULL}
83}; 83};
84 84
@@ -196,8 +196,14 @@ static int meth_bind(lua_State *L)
196{ 196{
197 p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1); 197 p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1);
198 const char *address = luaL_checkstring(L, 2); 198 const char *address = luaL_checkstring(L, 2);
199 unsigned short port = (unsigned short) luaL_checknumber(L, 3); 199 const char *port = luaL_checkstring(L, 3);
200 const char *err = inet_trybind(&tcp->sock, address, port); 200 const char *err;
201 struct addrinfo bindhints;
202 memset(&bindhints, 0, sizeof(bindhints));
203 bindhints.ai_socktype = SOCK_STREAM;
204 bindhints.ai_family = tcp->domain;
205 bindhints.ai_flags = AI_PASSIVE;
206 err = inet_trybind(&tcp->sock, address, port, &bindhints);
201 if (err) { 207 if (err) {
202 lua_pushnil(L); 208 lua_pushnil(L);
203 lua_pushstring(L, err); 209 lua_pushstring(L, err);
@@ -317,11 +323,11 @@ static int meth_settimeout(lua_State *L)
317/*-------------------------------------------------------------------------*\ 323/*-------------------------------------------------------------------------*\
318* Creates a master tcp object 324* Creates a master tcp object
319\*-------------------------------------------------------------------------*/ 325\*-------------------------------------------------------------------------*/
320static int global_create(lua_State *L) { 326static int tcp_create(lua_State *L, int domain) {
321 t_socket sock; 327 t_socket sock;
322 const char *err = inet_trycreate(&sock, SOCK_STREAM); 328 const char *err = inet_trycreate(&sock, domain, SOCK_STREAM);
323 /* try to allocate a system socket */ 329 /* try to allocate a system socket */
324 if (!err) { 330 if (!err) {
325 /* allocate tcp object */ 331 /* allocate tcp object */
326 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); 332 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
327 /* set its type as master object */ 333 /* set its type as master object */
@@ -333,6 +339,7 @@ static int global_create(lua_State *L) {
333 (p_error) socket_ioerror, &tcp->sock); 339 (p_error) socket_ioerror, &tcp->sock);
334 timeout_init(&tcp->tm, -1, -1); 340 timeout_init(&tcp->tm, -1, -1);
335 buffer_init(&tcp->buf, &tcp->io, &tcp->tm); 341 buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
342 tcp->domain = domain;
336 return 1; 343 return 1;
337 } else { 344 } else {
338 lua_pushnil(L); 345 lua_pushnil(L);
@@ -341,92 +348,12 @@ static int global_create(lua_State *L) {
341 } 348 }
342} 349}
343 350
344static const char *trybind6(const char *localaddr, const char *localserv, 351static int global_create(lua_State *L) {
345 struct addrinfo *bindhints, p_tcp tcp) { 352 return tcp_create(L, AF_INET);
346 struct addrinfo *iterator = NULL, *resolved = NULL;
347 const char *err = NULL;
348 /* translate luasocket special values to C */
349 if (strcmp(localaddr, "*") == 0) localaddr = NULL;
350 if (!localserv) localserv = "0";
351 /* try resolving */
352 err = socket_gaistrerror(getaddrinfo(localaddr, localserv,
353 bindhints, &resolved));
354 if (err) {
355 if (resolved) freeaddrinfo(resolved);
356 return err;
357 }
358 /* iterate over resolved addresses until one is good */
359 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
360 /* create a new socket each time because parameters
361 * may have changed */
362 err = socket_strerror(socket_create(&tcp->sock,
363 iterator->ai_family, iterator->ai_socktype,
364 iterator->ai_protocol));
365 /* if failed to create socket, bail out */
366 if (err != NULL) {
367 freeaddrinfo(resolved);
368 return err;
369 }
370 /* all sockets are set as non-blocking initially */
371 socket_setnonblocking(&tcp->sock);
372 /* try binding to local address */
373 err = socket_strerror(socket_bind(&tcp->sock,
374 (SA *) iterator->ai_addr,
375 iterator->ai_addrlen));
376 /* if faiiled, we try the next one */
377 if (err != NULL) socket_destroy(&tcp->sock);
378 /* if success, we abort loop */
379 else break;
380 }
381 /* at this point, if err is not set, se succeeded */
382 if (err == NULL) {
383 /* save family of chosen local address */
384 bindhints->ai_family = iterator->ai_family;
385 }
386 /* cleanup and return error */
387 freeaddrinfo(resolved);
388 return err;
389} 353}
390 354
391static int global_bind6(lua_State *L) { 355static int global_create6(lua_State *L) {
392 const char *localaddr = luaL_checkstring(L, 1); 356 return tcp_create(L, AF_INET6);
393 const char *localserv = luaL_checkstring(L, 2);
394 int backlog = luaL_checkint(L, 3);
395 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
396 struct addrinfo bindhints;
397 const char *err = NULL;
398 /* initialize tcp structure */
399 io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
400 (p_error) socket_ioerror, &tcp->sock);
401 timeout_init(&tcp->tm, -1, -1);
402 buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
403 tcp->sock = SOCKET_INVALID;
404 /* try binding to local address */
405 memset(&bindhints, 0, sizeof(bindhints));
406 bindhints.ai_socktype = SOCK_STREAM;
407 bindhints.ai_family = PF_UNSPEC;
408 bindhints.ai_flags = AI_PASSIVE;
409 err = trybind6(localaddr, localserv, &bindhints, tcp);
410 if (err == NULL) {
411 /* all server sockets initially with reuseaddr set */
412 int val = 1;
413 setsockopt(tcp->sock, SOL_SOCKET, SO_REUSEADDR,
414 (char *) &val, sizeof(val));
415 /* set the backlog and listen */
416 err = socket_strerror(socket_listen(&tcp->sock, backlog));
417 if (err) {
418 socket_destroy(&tcp->sock);
419 lua_pushnil(L);
420 lua_pushstring(L, err);
421 return 2;
422 }
423 auxiliar_setclass(L, "tcp{server}", -1);
424 return 1;
425 } else {
426 lua_pushnil(L);
427 lua_pushstring(L, err);
428 return 2;
429 }
430} 357}
431 358
432static const char *tryconnect6(const char *remoteaddr, const char *remoteserv, 359static const char *tryconnect6(const char *remoteaddr, const char *remoteserv,
@@ -488,7 +415,7 @@ static int global_connect6(lua_State *L) {
488 bindhints.ai_family = PF_UNSPEC; 415 bindhints.ai_family = PF_UNSPEC;
489 bindhints.ai_flags = AI_PASSIVE; 416 bindhints.ai_flags = AI_PASSIVE;
490 if (localaddr) { 417 if (localaddr) {
491 err = trybind6(localaddr, localserv, &bindhints, tcp); 418 err = inet_trybind(&tcp->sock, localaddr, localserv, &bindhints);
492 if (err) { 419 if (err) {
493 lua_pushnil(L); 420 lua_pushnil(L);
494 lua_pushstring(L, err); 421 lua_pushstring(L, err);