aboutsummaryrefslogtreecommitdiff
path: root/src/tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tcp.c')
-rw-r--r--src/tcp.c123
1 files changed, 39 insertions, 84 deletions
diff --git a/src/tcp.c b/src/tcp.c
index dcac0c8..7bf1af5 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -18,6 +18,7 @@
18* Internal function prototypes 18* Internal function prototypes
19\*=========================================================================*/ 19\*=========================================================================*/
20static int global_create(lua_State *L); 20static int global_create(lua_State *L);
21static int global_create4(lua_State *L);
21static int global_create6(lua_State *L); 22static int global_create6(lua_State *L);
22static int global_connect(lua_State *L); 23static int global_connect(lua_State *L);
23static int meth_connect(lua_State *L); 24static int meth_connect(lua_State *L);
@@ -90,6 +91,7 @@ static t_opt optset[] = {
90/* functions in library namespace */ 91/* functions in library namespace */
91static luaL_Reg func[] = { 92static luaL_Reg func[] = {
92 {"tcp", global_create}, 93 {"tcp", global_create},
94 {"tcp4", global_create4},
93 {"tcp6", global_create6}, 95 {"tcp6", global_create6},
94 {"connect", global_connect}, 96 {"connect", global_connect},
95 {NULL, NULL} 97 {NULL, NULL}
@@ -213,8 +215,7 @@ static int meth_accept(lua_State *L)
213/*-------------------------------------------------------------------------*\ 215/*-------------------------------------------------------------------------*\
214* Binds an object to an address 216* Binds an object to an address
215\*-------------------------------------------------------------------------*/ 217\*-------------------------------------------------------------------------*/
216static int meth_bind(lua_State *L) 218static int meth_bind(lua_State *L) {
217{
218 p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1); 219 p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1);
219 const char *address = luaL_checkstring(L, 2); 220 const char *address = luaL_checkstring(L, 2);
220 const char *port = luaL_checkstring(L, 3); 221 const char *port = luaL_checkstring(L, 3);
@@ -224,7 +225,7 @@ static int meth_bind(lua_State *L)
224 bindhints.ai_socktype = SOCK_STREAM; 225 bindhints.ai_socktype = SOCK_STREAM;
225 bindhints.ai_family = tcp->family; 226 bindhints.ai_family = tcp->family;
226 bindhints.ai_flags = AI_PASSIVE; 227 bindhints.ai_flags = AI_PASSIVE;
227 err = inet_trybind(&tcp->sock, address, port, &bindhints); 228 err = inet_trybind(&tcp->sock, &tcp->family, address, port, &bindhints);
228 if (err) { 229 if (err) {
229 lua_pushnil(L); 230 lua_pushnil(L);
230 lua_pushstring(L, err); 231 lua_pushstring(L, err);
@@ -237,8 +238,7 @@ static int meth_bind(lua_State *L)
237/*-------------------------------------------------------------------------*\ 238/*-------------------------------------------------------------------------*\
238* Turns a master tcp object into a client object. 239* Turns a master tcp object into a client object.
239\*-------------------------------------------------------------------------*/ 240\*-------------------------------------------------------------------------*/
240static int meth_connect(lua_State *L) 241static int meth_connect(lua_State *L) {
241{
242 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); 242 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
243 const char *address = luaL_checkstring(L, 2); 243 const char *address = luaL_checkstring(L, 2);
244 const char *port = luaL_checkstring(L, 3); 244 const char *port = luaL_checkstring(L, 3);
@@ -249,7 +249,7 @@ static int meth_connect(lua_State *L)
249 /* make sure we try to connect only to the same family */ 249 /* make sure we try to connect only to the same family */
250 connecthints.ai_family = tcp->family; 250 connecthints.ai_family = tcp->family;
251 timeout_markstart(&tcp->tm); 251 timeout_markstart(&tcp->tm);
252 err = inet_tryconnect(&tcp->sock, &tcp->family, address, port, 252 err = inet_tryconnect(&tcp->sock, &tcp->family, address, port,
253 &tcp->tm, &connecthints); 253 &tcp->tm, &connecthints);
254 /* have to set the class even if it failed due to non-blocking connects */ 254 /* have to set the class even if it failed due to non-blocking connects */
255 auxiliar_setclass(L, "tcp{client}", 1); 255 auxiliar_setclass(L, "tcp{client}", 1);
@@ -279,9 +279,12 @@ static int meth_close(lua_State *L)
279static int meth_getfamily(lua_State *L) 279static int meth_getfamily(lua_State *L)
280{ 280{
281 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); 281 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
282 if (tcp->family == PF_INET6) { 282 if (tcp->family == AF_INET6) {
283 lua_pushliteral(L, "inet6"); 283 lua_pushliteral(L, "inet6");
284 return 1; 284 return 1;
285 } else if (tcp->family == AF_INET) {
286 lua_pushliteral(L, "inet4");
287 return 1;
285 } else { 288 } else {
286 lua_pushliteral(L, "inet4"); 289 lua_pushliteral(L, "inet4");
287 return 1; 290 return 1;
@@ -352,37 +355,36 @@ static int meth_settimeout(lua_State *L)
352* Creates a master tcp object 355* Creates a master tcp object
353\*-------------------------------------------------------------------------*/ 356\*-------------------------------------------------------------------------*/
354static int tcp_create(lua_State *L, int family) { 357static int tcp_create(lua_State *L, int family) {
355 t_socket sock; 358 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
356 const char *err = inet_trycreate(&sock, family, SOCK_STREAM); 359 memset(tcp, 0, sizeof(t_tcp));
357 /* try to allocate a system socket */ 360 /* set its type as master object */
358 if (!err) { 361 auxiliar_setclass(L, "tcp{master}", -1);
359 /* allocate tcp object */ 362 /* if family is AF_UNSPEC, we leave the socket invalid and
360 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); 363 * store AF_UNSPEC into family. This will allow it to later be
361 memset(tcp, 0, sizeof(t_tcp)); 364 * replaced with an AF_INET6 or AF_INET socket upon first use. */
362 /* set its type as master object */ 365 tcp->sock = SOCKET_INVALID;
363 auxiliar_setclass(L, "tcp{master}", -1); 366 tcp->family = family;
364 /* initialize remaining structure fields */ 367 io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
365 socket_setnonblocking(&sock); 368 (p_error) socket_ioerror, &tcp->sock);
366 if (family == PF_INET6) { 369 timeout_init(&tcp->tm, -1, -1);
367 int yes = 1; 370 buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
368 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, 371 if (family != AF_UNSPEC) {
369 (void *)&yes, sizeof(yes)); 372 const char *err = inet_trycreate(&tcp->sock, family, SOCK_STREAM, 0);
373 if (err != NULL) {
374 lua_pushnil(L);
375 lua_pushstring(L, err);
376 return 2;
370 } 377 }
371 tcp->sock = sock; 378 socket_setnonblocking(&tcp->sock);
372 io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
373 (p_error) socket_ioerror, &tcp->sock);
374 timeout_init(&tcp->tm, -1, -1);
375 buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
376 tcp->family = family;
377 return 1;
378 } else {
379 lua_pushnil(L);
380 lua_pushstring(L, err);
381 return 2;
382 } 379 }
380 return 1;
383} 381}
384 382
385static int global_create(lua_State *L) { 383static int global_create(lua_State *L) {
384 return tcp_create(L, AF_UNSPEC);
385}
386
387static int global_create4(lua_State *L) {
386 return tcp_create(L, AF_INET); 388 return tcp_create(L, AF_INET);
387} 389}
388 390
@@ -390,53 +392,6 @@ static int global_create6(lua_State *L) {
390 return tcp_create(L, AF_INET6); 392 return tcp_create(L, AF_INET6);
391} 393}
392 394
393#if 0
394static const char *tryconnect6(const char *remoteaddr, const char *remoteserv,
395 struct addrinfo *connecthints, p_tcp tcp) {
396 struct addrinfo *iterator = NULL, *resolved = NULL;
397 const char *err = NULL;
398 /* try resolving */
399 err = socket_gaistrerror(getaddrinfo(remoteaddr, remoteserv,
400 connecthints, &resolved));
401 if (err != NULL) {
402 if (resolved) freeaddrinfo(resolved);
403 return err;
404 }
405 /* iterate over all returned addresses trying to connect */
406 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
407 p_timeout tm = timeout_markstart(&tcp->tm);
408 /* create new socket if necessary. if there was no
409 * bind, we need to create one for every new family
410 * that shows up while iterating. if there was a
411 * bind, all families will be the same and we will
412 * not enter this branch. */
413 if (tcp->family != iterator->ai_family) {
414 socket_destroy(&tcp->sock);
415 err = socket_strerror(socket_create(&tcp->sock,
416 iterator->ai_family, iterator->ai_socktype,
417 iterator->ai_protocol));
418 if (err != NULL) {
419 freeaddrinfo(resolved);
420 return err;
421 }
422 tcp->family = iterator->ai_family;
423 /* all sockets initially non-blocking */
424 socket_setnonblocking(&tcp->sock);
425 }
426 /* finally try connecting to remote address */
427 err = socket_strerror(socket_connect(&tcp->sock,
428 (SA *) iterator->ai_addr,
429 (socklen_t) iterator->ai_addrlen, tm));
430 /* if success, break out of loop */
431 if (err == NULL) break;
432 }
433
434 freeaddrinfo(resolved);
435 /* here, if err is set, we failed */
436 return err;
437}
438#endif
439
440static int global_connect(lua_State *L) { 395static int global_connect(lua_State *L) {
441 const char *remoteaddr = luaL_checkstring(L, 1); 396 const char *remoteaddr = luaL_checkstring(L, 1);
442 const char *remoteserv = luaL_checkstring(L, 2); 397 const char *remoteserv = luaL_checkstring(L, 2);
@@ -453,26 +408,26 @@ static int global_connect(lua_State *L) {
453 timeout_init(&tcp->tm, -1, -1); 408 timeout_init(&tcp->tm, -1, -1);
454 buffer_init(&tcp->buf, &tcp->io, &tcp->tm); 409 buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
455 tcp->sock = SOCKET_INVALID; 410 tcp->sock = SOCKET_INVALID;
456 tcp->family = PF_UNSPEC; 411 tcp->family = AF_UNSPEC;
457 /* allow user to pick local address and port */ 412 /* allow user to pick local address and port */
458 memset(&bindhints, 0, sizeof(bindhints)); 413 memset(&bindhints, 0, sizeof(bindhints));
459 bindhints.ai_socktype = SOCK_STREAM; 414 bindhints.ai_socktype = SOCK_STREAM;
460 bindhints.ai_family = family; 415 bindhints.ai_family = family;
461 bindhints.ai_flags = AI_PASSIVE; 416 bindhints.ai_flags = AI_PASSIVE;
462 if (localaddr) { 417 if (localaddr) {
463 err = inet_trybind(&tcp->sock, localaddr, localserv, &bindhints); 418 err = inet_trybind(&tcp->sock, &tcp->family, localaddr,
419 localserv, &bindhints);
464 if (err) { 420 if (err) {
465 lua_pushnil(L); 421 lua_pushnil(L);
466 lua_pushstring(L, err); 422 lua_pushstring(L, err);
467 return 2; 423 return 2;
468 } 424 }
469 tcp->family = bindhints.ai_family;
470 } 425 }
471 /* try to connect to remote address and port */ 426 /* try to connect to remote address and port */
472 memset(&connecthints, 0, sizeof(connecthints)); 427 memset(&connecthints, 0, sizeof(connecthints));
473 connecthints.ai_socktype = SOCK_STREAM; 428 connecthints.ai_socktype = SOCK_STREAM;
474 /* make sure we try to connect only to the same family */ 429 /* make sure we try to connect only to the same family */
475 connecthints.ai_family = bindhints.ai_family; 430 connecthints.ai_family = tcp->family;
476 err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv, 431 err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv,
477 &tcp->tm, &connecthints); 432 &tcp->tm, &connecthints);
478 if (err) { 433 if (err) {