aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buffer.c24
-rw-r--r--src/inet.c132
-rw-r--r--src/inet.h10
-rw-r--r--src/io.h2
-rw-r--r--src/socket.lua10
-rw-r--r--src/tcp.c85
-rw-r--r--src/udp.c19
-rw-r--r--src/usocket.c9
8 files changed, 139 insertions, 152 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 8fc1166..fff1634 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -38,7 +38,7 @@ int buffer_open(lua_State *L) {
38} 38}
39 39
40/*-------------------------------------------------------------------------*\ 40/*-------------------------------------------------------------------------*\
41* Initializes C structure 41* Initializes C structure
42\*-------------------------------------------------------------------------*/ 42\*-------------------------------------------------------------------------*/
43void buffer_init(p_buffer buf, p_io io, p_timeout tm) { 43void buffer_init(p_buffer buf, p_io io, p_timeout tm) {
44 buf->first = buf->last = 0; 44 buf->first = buf->last = 0;
@@ -62,8 +62,8 @@ int buffer_meth_getstats(lua_State *L, p_buffer buf) {
62* object:setstats() interface 62* object:setstats() interface
63\*-------------------------------------------------------------------------*/ 63\*-------------------------------------------------------------------------*/
64int buffer_meth_setstats(lua_State *L, p_buffer buf) { 64int buffer_meth_setstats(lua_State *L, p_buffer buf) {
65 buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received); 65 buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received);
66 buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent); 66 buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent);
67 if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4); 67 if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4);
68 lua_pushnumber(L, 1); 68 lua_pushnumber(L, 1);
69 return 1; 69 return 1;
@@ -88,7 +88,7 @@ int buffer_meth_send(lua_State *L, p_buffer buf) {
88 /* check if there was an error */ 88 /* check if there was an error */
89 if (err != IO_DONE) { 89 if (err != IO_DONE) {
90 lua_pushnil(L); 90 lua_pushnil(L);
91 lua_pushstring(L, buf->io->error(buf->io->ctx, err)); 91 lua_pushstring(L, buf->io->error(buf->io->ctx, err));
92 lua_pushnumber(L, (lua_Number) (sent+start-1)); 92 lua_pushnumber(L, (lua_Number) (sent+start-1));
93 } else { 93 } else {
94 lua_pushnumber(L, (lua_Number) (sent+start-1)); 94 lua_pushnumber(L, (lua_Number) (sent+start-1));
@@ -111,7 +111,7 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
111 size_t size; 111 size_t size;
112 const char *part = luaL_optlstring(L, 3, "", &size); 112 const char *part = luaL_optlstring(L, 3, "", &size);
113 timeout_markstart(buf->tm); 113 timeout_markstart(buf->tm);
114 /* initialize buffer with optional extra prefix 114 /* initialize buffer with optional extra prefix
115 * (useful for concatenating previous partial results) */ 115 * (useful for concatenating previous partial results) */
116 luaL_buffinit(L, &b); 116 luaL_buffinit(L, &b);
117 luaL_addlstring(&b, part, size); 117 luaL_addlstring(&b, part, size);
@@ -119,12 +119,12 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
119 if (!lua_isnumber(L, 2)) { 119 if (!lua_isnumber(L, 2)) {
120 const char *p= luaL_optstring(L, 2, "*l"); 120 const char *p= luaL_optstring(L, 2, "*l");
121 if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b); 121 if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b);
122 else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); 122 else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b);
123 else luaL_argcheck(L, 0, 2, "invalid receive pattern"); 123 else luaL_argcheck(L, 0, 2, "invalid receive pattern");
124 /* get a fixed number of bytes (minus what was already partially 124 /* get a fixed number of bytes (minus what was already partially
125 * received) */ 125 * received) */
126 } else { 126 } else {
127 double n = lua_tonumber(L, 2); 127 double n = lua_tonumber(L, 2);
128 size_t wanted = (size_t) n; 128 size_t wanted = (size_t) n;
129 luaL_argcheck(L, n >= 0, 2, "invalid receive pattern"); 129 luaL_argcheck(L, n >= 0, 2, "invalid receive pattern");
130 if (size == 0 || wanted > size) 130 if (size == 0 || wanted > size)
@@ -135,8 +135,8 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
135 /* we can't push anyting in the stack before pushing the 135 /* we can't push anyting in the stack before pushing the
136 * contents of the buffer. this is the reason for the complication */ 136 * contents of the buffer. this is the reason for the complication */
137 luaL_pushresult(&b); 137 luaL_pushresult(&b);
138 lua_pushstring(L, buf->io->error(buf->io->ctx, err)); 138 lua_pushstring(L, buf->io->error(buf->io->ctx, err));
139 lua_pushvalue(L, -2); 139 lua_pushvalue(L, -2);
140 lua_pushnil(L); 140 lua_pushnil(L);
141 lua_replace(L, -4); 141 lua_replace(L, -4);
142 } else { 142 } else {
@@ -219,7 +219,7 @@ static int recvall(p_buffer buf, luaL_Buffer *b) {
219} 219}
220 220
221/*-------------------------------------------------------------------------*\ 221/*-------------------------------------------------------------------------*\
222* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF 222* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF
223* are not returned by the function and are discarded from the buffer 223* are not returned by the function and are discarded from the buffer
224\*-------------------------------------------------------------------------*/ 224\*-------------------------------------------------------------------------*/
225static int recvline(p_buffer buf, luaL_Buffer *b) { 225static int recvline(p_buffer buf, luaL_Buffer *b) {
@@ -249,7 +249,7 @@ static int recvline(p_buffer buf, luaL_Buffer *b) {
249static void buffer_skip(p_buffer buf, size_t count) { 249static void buffer_skip(p_buffer buf, size_t count) {
250 buf->received += count; 250 buf->received += count;
251 buf->first += count; 251 buf->first += count;
252 if (buffer_isempty(buf)) 252 if (buffer_isempty(buf))
253 buf->first = buf->last = 0; 253 buf->first = buf->last = 0;
254} 254}
255 255
diff --git a/src/inet.c b/src/inet.c
index 68087db..8f0fac2 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -94,7 +94,7 @@ static int inet_global_getnameinfo(lua_State *L) {
94 94
95 memset(&hints, 0, sizeof(hints)); 95 memset(&hints, 0, sizeof(hints));
96 hints.ai_socktype = SOCK_STREAM; 96 hints.ai_socktype = SOCK_STREAM;
97 hints.ai_family = PF_UNSPEC; 97 hints.ai_family = AF_UNSPEC;
98 98
99 ret = getaddrinfo(host, serv, &hints, &resolved); 99 ret = getaddrinfo(host, serv, &hints, &resolved);
100 if (ret != 0) { 100 if (ret != 0) {
@@ -105,8 +105,8 @@ static int inet_global_getnameinfo(lua_State *L) {
105 105
106 lua_newtable(L); 106 lua_newtable(L);
107 for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) { 107 for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) {
108 getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, 108 getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen,
109 hbuf, host? (socklen_t) sizeof(hbuf): 0, 109 hbuf, host? (socklen_t) sizeof(hbuf): 0,
110 sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0); 110 sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0);
111 if (host) { 111 if (host) {
112 lua_pushnumber(L, i); 112 lua_pushnumber(L, i);
@@ -146,7 +146,7 @@ static int inet_global_toip(lua_State *L)
146int inet_optfamily(lua_State* L, int narg, const char* def) 146int inet_optfamily(lua_State* L, int narg, const char* def)
147{ 147{
148 static const char* optname[] = { "unspec", "inet", "inet6", NULL }; 148 static const char* optname[] = { "unspec", "inet", "inet6", NULL };
149 static int optvalue[] = { PF_UNSPEC, PF_INET, PF_INET6, 0 }; 149 static int optvalue[] = { AF_UNSPEC, AF_INET, AF_INET6, 0 };
150 150
151 return optvalue[luaL_checkoption(L, narg, def, optname)]; 151 return optvalue[luaL_checkoption(L, narg, def, optname)];
152} 152}
@@ -167,7 +167,7 @@ static int inet_global_getaddrinfo(lua_State *L)
167 int i = 1, ret = 0; 167 int i = 1, ret = 0;
168 memset(&hints, 0, sizeof(hints)); 168 memset(&hints, 0, sizeof(hints));
169 hints.ai_socktype = SOCK_STREAM; 169 hints.ai_socktype = SOCK_STREAM;
170 hints.ai_family = PF_UNSPEC; 170 hints.ai_family = AF_UNSPEC;
171 ret = getaddrinfo(hostname, NULL, &hints, &resolved); 171 ret = getaddrinfo(hostname, NULL, &hints, &resolved);
172 if (ret != 0) { 172 if (ret != 0) {
173 lua_pushnil(L); 173 lua_pushnil(L);
@@ -177,7 +177,7 @@ static int inet_global_getaddrinfo(lua_State *L)
177 lua_newtable(L); 177 lua_newtable(L);
178 for (iterator = resolved; iterator; iterator = iterator->ai_next) { 178 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
179 char hbuf[NI_MAXHOST]; 179 char hbuf[NI_MAXHOST];
180 ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, 180 ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen,
181 hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST); 181 hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
182 if (ret){ 182 if (ret){
183 freeaddrinfo(resolved); 183 freeaddrinfo(resolved);
@@ -198,6 +198,16 @@ static int inet_global_getaddrinfo(lua_State *L)
198 lua_pushliteral(L, "inet6"); 198 lua_pushliteral(L, "inet6");
199 lua_settable(L, -3); 199 lua_settable(L, -3);
200 break; 200 break;
201 case AF_UNSPEC:
202 lua_pushliteral(L, "family");
203 lua_pushliteral(L, "unspec");
204 lua_settable(L, -3);
205 break;
206 default:
207 lua_pushliteral(L, "family");
208 lua_pushliteral(L, "unknown");
209 lua_settable(L, -3);
210 break;
201 } 211 }
202 lua_pushliteral(L, "addr"); 212 lua_pushliteral(L, "addr");
203 lua_pushstring(L, hbuf); 213 lua_pushstring(L, hbuf);
@@ -254,12 +264,11 @@ int inet_meth_getpeername(lua_State *L, p_socket ps, int family)
254 } 264 }
255 lua_pushstring(L, name); 265 lua_pushstring(L, name);
256 lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10)); 266 lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10));
257 if (family == PF_INET) { 267 switch (family) {
258 lua_pushliteral(L, "inet"); 268 case AF_INET: lua_pushliteral(L, "inet"); break;
259 } else if (family == PF_INET6) { 269 case AF_INET6: lua_pushliteral(L, "inet6"); break;
260 lua_pushliteral(L, "inet6"); 270 case AF_UNSPEC: lua_pushliteral(L, "unspec"); break;
261 } else { 271 default: lua_pushliteral(L, "unknown"); break;
262 lua_pushliteral(L, "uknown family");
263 } 272 }
264 return 3; 273 return 3;
265} 274}
@@ -279,7 +288,7 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family)
279 lua_pushstring(L, socket_strerror(errno)); 288 lua_pushstring(L, socket_strerror(errno));
280 return 2; 289 return 2;
281 } 290 }
282 err=getnameinfo((struct sockaddr *)&peer, peer_len, 291 err=getnameinfo((struct sockaddr *)&peer, peer_len,
283 name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV); 292 name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV);
284 if (err) { 293 if (err) {
285 lua_pushnil(L); 294 lua_pushnil(L);
@@ -288,12 +297,11 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family)
288 } 297 }
289 lua_pushstring(L, name); 298 lua_pushstring(L, name);
290 lua_pushstring(L, port); 299 lua_pushstring(L, port);
291 if (family == PF_INET) { 300 switch (family) {
292 lua_pushliteral(L, "inet"); 301 case AF_INET: lua_pushliteral(L, "inet"); break;
293 } else if (family == PF_INET6) { 302 case AF_INET6: lua_pushliteral(L, "inet6"); break;
294 lua_pushliteral(L, "inet6"); 303 case AF_UNSPEC: lua_pushliteral(L, "unspec"); break;
295 } else { 304 default: lua_pushliteral(L, "unknown"); break;
296 lua_pushliteral(L, "uknown family");
297 } 305 }
298 return 3; 306 return 3;
299} 307}
@@ -354,21 +362,21 @@ const char *inet_trycreate(p_socket ps, int family, int type) {
354const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm) 362const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm)
355{ 363{
356 switch (family) { 364 switch (family) {
357 case PF_INET: { 365 case AF_INET: {
358 struct sockaddr_in sin; 366 struct sockaddr_in sin;
359 memset((char *) &sin, 0, sizeof(sin)); 367 memset((char *) &sin, 0, sizeof(sin));
360 sin.sin_family = AF_UNSPEC; 368 sin.sin_family = AF_UNSPEC;
361 sin.sin_addr.s_addr = INADDR_ANY; 369 sin.sin_addr.s_addr = INADDR_ANY;
362 return socket_strerror(socket_connect(ps, (SA *) &sin, 370 return socket_strerror(socket_connect(ps, (SA *) &sin,
363 sizeof(sin), tm)); 371 sizeof(sin), tm));
364 } 372 }
365 case PF_INET6: { 373 case AF_INET6: {
366 struct sockaddr_in6 sin6; 374 struct sockaddr_in6 sin6;
367 struct in6_addr addrany = IN6ADDR_ANY_INIT; 375 struct in6_addr addrany = IN6ADDR_ANY_INIT;
368 memset((char *) &sin6, 0, sizeof(sin6)); 376 memset((char *) &sin6, 0, sizeof(sin6));
369 sin6.sin6_family = AF_UNSPEC; 377 sin6.sin6_family = AF_UNSPEC;
370 sin6.sin6_addr = addrany; 378 sin6.sin6_addr = addrany;
371 return socket_strerror(socket_connect(ps, (SA *) &sin6, 379 return socket_strerror(socket_connect(ps, (SA *) &sin6,
372 sizeof(sin6), tm)); 380 sizeof(sin6), tm));
373 } 381 }
374 } 382 }
@@ -383,6 +391,7 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
383{ 391{
384 struct addrinfo *iterator = NULL, *resolved = NULL; 392 struct addrinfo *iterator = NULL, *resolved = NULL;
385 const char *err = NULL; 393 const char *err = NULL;
394 int current_family = *family;
386 /* try resolving */ 395 /* try resolving */
387 err = socket_gaistrerror(getaddrinfo(address, serv, 396 err = socket_gaistrerror(getaddrinfo(address, serv,
388 connecthints, &resolved)); 397 connecthints, &resolved));
@@ -397,23 +406,23 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
397 * that shows up while iterating. if there was a 406 * that shows up while iterating. if there was a
398 * bind, all families will be the same and we will 407 * bind, all families will be the same and we will
399 * not enter this branch. */ 408 * not enter this branch. */
400 if (*family != iterator->ai_family) { 409 if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
401 socket_destroy(ps); 410 socket_destroy(ps);
402 err = socket_strerror(socket_create(ps, iterator->ai_family, 411 err = socket_strerror(socket_create(ps, iterator->ai_family,
403 iterator->ai_socktype, iterator->ai_protocol)); 412 iterator->ai_socktype, iterator->ai_protocol));
404 if (err != NULL) { 413 if (err) continue;
405 freeaddrinfo(resolved); 414 current_family = iterator->ai_family;
406 return err; 415 /* set non-blocking before connect */
407 }
408 *family = iterator->ai_family;
409 /* all sockets initially non-blocking */
410 socket_setnonblocking(ps); 416 socket_setnonblocking(ps);
411 } 417 }
412 /* try connecting to remote address */ 418 /* try connecting to remote address */
413 err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, 419 err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr,
414 (socklen_t) iterator->ai_addrlen, tm)); 420 (socklen_t) iterator->ai_addrlen, tm));
415 /* if success, break out of loop */ 421 /* if success, break out of loop */
416 if (err == NULL) break; 422 if (err == NULL) {
423 *family = current_family;
424 break;
425 }
417 } 426 }
418 freeaddrinfo(resolved); 427 freeaddrinfo(resolved);
419 /* here, if err is set, we failed */ 428 /* here, if err is set, we failed */
@@ -423,29 +432,27 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
423/*-------------------------------------------------------------------------*\ 432/*-------------------------------------------------------------------------*\
424* Tries to accept a socket 433* Tries to accept a socket
425\*-------------------------------------------------------------------------*/ 434\*-------------------------------------------------------------------------*/
426const char *inet_tryaccept(p_socket server, int family, p_socket client, 435const char *inet_tryaccept(p_socket server, int family, p_socket client,
427 p_timeout tm) 436 p_timeout tm) {
428{
429 socklen_t len; 437 socklen_t len;
430 t_sockaddr_storage addr; 438 t_sockaddr_storage addr;
431 if (family == PF_INET6) { 439 switch (family) {
432 len = sizeof(struct sockaddr_in6); 440 case AF_INET6: len = sizeof(struct sockaddr_in6); break;
433 } else { 441 case AF_INET: len = sizeof(struct sockaddr_in); break;
434 len = sizeof(struct sockaddr_in); 442 default: len = sizeof(addr); break;
435 } 443 }
436 return socket_strerror(socket_accept(server, client, (SA *) &addr, 444 return socket_strerror(socket_accept(server, client, (SA *) &addr,
437 &len, tm)); 445 &len, tm));
438} 446}
439 447
440/*-------------------------------------------------------------------------*\ 448/*-------------------------------------------------------------------------*\
441* Tries to bind socket to (address, port) 449* Tries to bind socket to (address, port)
442\*-------------------------------------------------------------------------*/ 450\*-------------------------------------------------------------------------*/
443const char *inet_trybind(p_socket ps, const char *address, const char *serv, 451const char *inet_trybind(p_socket ps, int *family, const char *address,
444 struct addrinfo *bindhints) 452 const char *serv, struct addrinfo *bindhints) {
445{
446 struct addrinfo *iterator = NULL, *resolved = NULL; 453 struct addrinfo *iterator = NULL, *resolved = NULL;
447 const char *err = NULL; 454 const char *err = NULL;
448 t_socket sock = *ps; 455 int current_family = *family;
449 /* translate luasocket special values to C */ 456 /* translate luasocket special values to C */
450 if (strcmp(address, "*") == 0) address = NULL; 457 if (strcmp(address, "*") == 0) address = NULL;
451 if (!serv) serv = "0"; 458 if (!serv) serv = "0";
@@ -457,35 +464,32 @@ const char *inet_trybind(p_socket ps, const char *address, const char *serv,
457 } 464 }
458 /* iterate over resolved addresses until one is good */ 465 /* iterate over resolved addresses until one is good */
459 for (iterator = resolved; iterator; iterator = iterator->ai_next) { 466 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
460 if(sock == SOCKET_INVALID) { 467 if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
461 err = socket_strerror(socket_create(&sock, iterator->ai_family, 468 socket_destroy(ps);
469 err = socket_strerror(socket_create(ps, iterator->ai_family,
462 iterator->ai_socktype, iterator->ai_protocol)); 470 iterator->ai_socktype, iterator->ai_protocol));
463 if(err) 471 if (err) continue;
464 continue; 472 current_family = iterator->ai_family;
465 } 473 }
466 /* try binding to local address */ 474 /* try binding to local address */
467 err = socket_strerror(socket_bind(&sock, 475 err = socket_strerror(socket_bind(ps, (SA *) iterator->ai_addr,
468 (SA *) iterator->ai_addr,
469 (socklen_t) iterator->ai_addrlen)); 476 (socklen_t) iterator->ai_addrlen));
470
471 /* keep trying unless bind succeeded */ 477 /* keep trying unless bind succeeded */
472 if (err) { 478 if (err == NULL) {
473 if(sock != *ps) 479 *family = current_family;
474 socket_destroy(&sock); 480 /* set to non-blocking after bind */
475 } else { 481 socket_setnonblocking(ps);
476 /* remember what we connected to, particularly the family */
477 *bindhints = *iterator;
478 break; 482 break;
479 } 483 }
480 } 484 }
481 /* cleanup and return error */ 485 /* cleanup and return error */
482 freeaddrinfo(resolved); 486 freeaddrinfo(resolved);
483 *ps = sock; 487 /* here, if err is set, we failed */
484 return err; 488 return err;
485} 489}
486 490
487/*-------------------------------------------------------------------------*\ 491/*-------------------------------------------------------------------------*\
488* Some systems do not provide these so that we provide our own. 492* Some systems do not provide these so that we provide our own.
489\*-------------------------------------------------------------------------*/ 493\*-------------------------------------------------------------------------*/
490#ifdef LUASOCKET_INET_ATON 494#ifdef LUASOCKET_INET_ATON
491int inet_aton(const char *cp, struct in_addr *inp) 495int inet_aton(const char *cp, struct in_addr *inp)
@@ -510,7 +514,7 @@ int inet_aton(const char *cp, struct in_addr *inp)
510#endif 514#endif
511 515
512#ifdef LUASOCKET_INET_PTON 516#ifdef LUASOCKET_INET_PTON
513int inet_pton(int af, const char *src, void *dst) 517int inet_pton(int af, const char *src, void *dst)
514{ 518{
515 struct addrinfo hints, *res; 519 struct addrinfo hints, *res;
516 int ret = 1; 520 int ret = 1;
@@ -527,7 +531,7 @@ int inet_pton(int af, const char *src, void *dst)
527 } else { 531 } else {
528 ret = -1; 532 ret = -1;
529 } 533 }
530 freeaddrinfo(res); 534 freeaddrinfo(res);
531 return ret; 535 return ret;
532} 536}
533 537
diff --git a/src/inet.h b/src/inet.h
index 1f1a96a..b85c20e 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -1,12 +1,12 @@
1#ifndef INET_H 1#ifndef INET_H
2#define INET_H 2#define INET_H
3/*=========================================================================*\ 3/*=========================================================================*\
4* Internet domain functions 4* Internet domain functions
5* LuaSocket toolkit 5* LuaSocket toolkit
6* 6*
7* This module implements the creation and connection of internet domain 7* This module implements the creation and connection of internet domain
8* sockets, on top of the socket.h interface, and the interface of with the 8* sockets, on top of the socket.h interface, and the interface of with the
9* resolver. 9* resolver.
10* 10*
11* The function inet_aton is provided for the platforms where it is not 11* The function inet_aton is provided for the platforms where it is not
12* available. The module also implements the interface of the internet 12* available. The module also implements the interface of the internet
@@ -27,8 +27,8 @@ int inet_open(lua_State *L);
27const char *inet_trycreate(p_socket ps, int family, int type); 27const char *inet_trycreate(p_socket ps, int family, int type);
28const char *inet_tryconnect(p_socket ps, int *family, const char *address, 28const char *inet_tryconnect(p_socket ps, int *family, const char *address,
29 const char *serv, p_timeout tm, struct addrinfo *connecthints); 29 const char *serv, p_timeout tm, struct addrinfo *connecthints);
30const char *inet_trybind(p_socket ps, const char *address, const char *serv, 30const char *inet_trybind(p_socket ps, int *family, const char *address,
31 struct addrinfo *bindhints); 31 const char *serv, struct addrinfo *bindhints);
32const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm); 32const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm);
33const char *inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm); 33const char *inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm);
34 34
diff --git a/src/io.h b/src/io.h
index 76a3e58..8cca08a 100644
--- a/src/io.h
+++ b/src/io.h
@@ -22,7 +22,7 @@ enum {
22 IO_DONE = 0, /* operation completed successfully */ 22 IO_DONE = 0, /* operation completed successfully */
23 IO_TIMEOUT = -1, /* operation timed out */ 23 IO_TIMEOUT = -1, /* operation timed out */
24 IO_CLOSED = -2, /* the connection has been closed */ 24 IO_CLOSED = -2, /* the connection has been closed */
25 IO_UNKNOWN = -3 25 IO_UNKNOWN = -3
26}; 26};
27 27
28/* interface to error message function */ 28/* interface to error message function */
diff --git a/src/socket.lua b/src/socket.lua
index 3913e6f..d1c0b16 100644
--- a/src/socket.lua
+++ b/src/socket.lua
@@ -32,23 +32,23 @@ function _M.bind(host, port, backlog)
32 err = "no info on address" 32 err = "no info on address"
33 for i, alt in base.ipairs(addrinfo) do 33 for i, alt in base.ipairs(addrinfo) do
34 if alt.family == "inet" then 34 if alt.family == "inet" then
35 sock, err = socket.tcp() 35 sock, err = socket.tcp4()
36 else 36 else
37 sock, err = socket.tcp6() 37 sock, err = socket.tcp6()
38 end 38 end
39 if not sock then return nil, err end 39 if not sock then return nil, err end
40 sock:setoption("reuseaddr", true) 40 sock:setoption("reuseaddr", true)
41 res, err = sock:bind(alt.addr, port) 41 res, err = sock:bind(alt.addr, port)
42 if not res then 42 if not res then
43 sock:close() 43 sock:close()
44 else 44 else
45 res, err = sock:listen(backlog) 45 res, err = sock:listen(backlog)
46 if not res then 46 if not res then
47 sock:close() 47 sock:close()
48 else 48 else
49 return sock 49 return sock
50 end 50 end
51 end 51 end
52 end 52 end
53 return nil, err 53 return nil, err
54end 54end
diff --git a/src/tcp.c b/src/tcp.c
index dcac0c8..4d12f08 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;
@@ -353,7 +356,12 @@ static int meth_settimeout(lua_State *L)
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 t_socket sock;
356 const char *err = inet_trycreate(&sock, family, SOCK_STREAM); 359 /* if family is AF_UNSPEC, we create an AF_INET socket
360 * but store AF_UNSPEC into tcp-family. This will allow it
361 * later be replaced with an AF_INET6 socket if
362 * trybind or tryconnect prefer it instead. */
363 const char *err = inet_trycreate(&sock, family == AF_UNSPEC?
364 AF_INET: family, SOCK_STREAM);
357 /* try to allocate a system socket */ 365 /* try to allocate a system socket */
358 if (!err) { 366 if (!err) {
359 /* allocate tcp object */ 367 /* allocate tcp object */
@@ -363,7 +371,7 @@ static int tcp_create(lua_State *L, int family) {
363 auxiliar_setclass(L, "tcp{master}", -1); 371 auxiliar_setclass(L, "tcp{master}", -1);
364 /* initialize remaining structure fields */ 372 /* initialize remaining structure fields */
365 socket_setnonblocking(&sock); 373 socket_setnonblocking(&sock);
366 if (family == PF_INET6) { 374 if (family == AF_INET6) {
367 int yes = 1; 375 int yes = 1;
368 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, 376 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
369 (void *)&yes, sizeof(yes)); 377 (void *)&yes, sizeof(yes));
@@ -383,6 +391,10 @@ static int tcp_create(lua_State *L, int family) {
383} 391}
384 392
385static int global_create(lua_State *L) { 393static int global_create(lua_State *L) {
394 return tcp_create(L, AF_UNSPEC);
395}
396
397static int global_create4(lua_State *L) {
386 return tcp_create(L, AF_INET); 398 return tcp_create(L, AF_INET);
387} 399}
388 400
@@ -390,53 +402,6 @@ static int global_create6(lua_State *L) {
390 return tcp_create(L, AF_INET6); 402 return tcp_create(L, AF_INET6);
391} 403}
392 404
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) { 405static int global_connect(lua_State *L) {
441 const char *remoteaddr = luaL_checkstring(L, 1); 406 const char *remoteaddr = luaL_checkstring(L, 1);
442 const char *remoteserv = luaL_checkstring(L, 2); 407 const char *remoteserv = luaL_checkstring(L, 2);
@@ -453,26 +418,26 @@ static int global_connect(lua_State *L) {
453 timeout_init(&tcp->tm, -1, -1); 418 timeout_init(&tcp->tm, -1, -1);
454 buffer_init(&tcp->buf, &tcp->io, &tcp->tm); 419 buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
455 tcp->sock = SOCKET_INVALID; 420 tcp->sock = SOCKET_INVALID;
456 tcp->family = PF_UNSPEC; 421 tcp->family = AF_UNSPEC;
457 /* allow user to pick local address and port */ 422 /* allow user to pick local address and port */
458 memset(&bindhints, 0, sizeof(bindhints)); 423 memset(&bindhints, 0, sizeof(bindhints));
459 bindhints.ai_socktype = SOCK_STREAM; 424 bindhints.ai_socktype = SOCK_STREAM;
460 bindhints.ai_family = family; 425 bindhints.ai_family = family;
461 bindhints.ai_flags = AI_PASSIVE; 426 bindhints.ai_flags = AI_PASSIVE;
462 if (localaddr) { 427 if (localaddr) {
463 err = inet_trybind(&tcp->sock, localaddr, localserv, &bindhints); 428 err = inet_trybind(&tcp->sock, &tcp->family, localaddr,
429 localserv, &bindhints);
464 if (err) { 430 if (err) {
465 lua_pushnil(L); 431 lua_pushnil(L);
466 lua_pushstring(L, err); 432 lua_pushstring(L, err);
467 return 2; 433 return 2;
468 } 434 }
469 tcp->family = bindhints.ai_family;
470 } 435 }
471 /* try to connect to remote address and port */ 436 /* try to connect to remote address and port */
472 memset(&connecthints, 0, sizeof(connecthints)); 437 memset(&connecthints, 0, sizeof(connecthints));
473 connecthints.ai_socktype = SOCK_STREAM; 438 connecthints.ai_socktype = SOCK_STREAM;
474 /* make sure we try to connect only to the same family */ 439 /* make sure we try to connect only to the same family */
475 connecthints.ai_family = bindhints.ai_family; 440 connecthints.ai_family = tcp->family;
476 err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv, 441 err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv,
477 &tcp->tm, &connecthints); 442 &tcp->tm, &connecthints);
478 if (err) { 443 if (err) {
diff --git a/src/udp.c b/src/udp.c
index 7ff00f5..6600859 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -27,6 +27,7 @@
27* Internal function prototypes 27* Internal function prototypes
28\*=========================================================================*/ 28\*=========================================================================*/
29static int global_create(lua_State *L); 29static int global_create(lua_State *L);
30static int global_create4(lua_State *L);
30static int global_create6(lua_State *L); 31static int global_create6(lua_State *L);
31static int meth_send(lua_State *L); 32static int meth_send(lua_State *L);
32static int meth_sendto(lua_State *L); 33static int meth_sendto(lua_State *L);
@@ -107,6 +108,7 @@ static t_opt optget[] = {
107/* functions in library namespace */ 108/* functions in library namespace */
108static luaL_Reg func[] = { 109static luaL_Reg func[] = {
109 {"udp", global_create}, 110 {"udp", global_create},
111 {"udp4", global_create4},
110 {"udp6", global_create6}, 112 {"udp6", global_create6},
111 {NULL, NULL} 113 {NULL, NULL}
112}; 114};
@@ -264,7 +266,7 @@ static int meth_receivefrom(lua_State *L)
264static int meth_getfamily(lua_State *L) 266static int meth_getfamily(lua_State *L)
265{ 267{
266 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); 268 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
267 if (udp->family == PF_INET6) { 269 if (udp->family == AF_INET6) {
268 lua_pushliteral(L, "inet6"); 270 lua_pushliteral(L, "inet6");
269 return 1; 271 return 1;
270 } else { 272 } else {
@@ -391,7 +393,7 @@ static int meth_setsockname(lua_State *L) {
391 bindhints.ai_socktype = SOCK_DGRAM; 393 bindhints.ai_socktype = SOCK_DGRAM;
392 bindhints.ai_family = udp->family; 394 bindhints.ai_family = udp->family;
393 bindhints.ai_flags = AI_PASSIVE; 395 bindhints.ai_flags = AI_PASSIVE;
394 err = inet_trybind(&udp->sock, address, port, &bindhints); 396 err = inet_trybind(&udp->sock, &udp->family, address, port, &bindhints);
395 if (err) { 397 if (err) {
396 lua_pushnil(L); 398 lua_pushnil(L);
397 lua_pushstring(L, err); 399 lua_pushstring(L, err);
@@ -409,7 +411,12 @@ static int meth_setsockname(lua_State *L) {
409\*-------------------------------------------------------------------------*/ 411\*-------------------------------------------------------------------------*/
410static int udp_create(lua_State *L, int family) { 412static int udp_create(lua_State *L, int family) {
411 t_socket sock; 413 t_socket sock;
412 const char *err = inet_trycreate(&sock, family, SOCK_DGRAM); 414 /* if family is AF_UNSPEC, we create an AF_INET socket
415 * but store AF_UNSPEC into tcp-family. This will allow it
416 * later be replaced with an AF_INET6 socket if
417 * trybind or tryconnect prefer it instead. */
418 const char *err = inet_trycreate(&sock, family == AF_UNSPEC?
419 AF_INET: family, SOCK_DGRAM);
413 /* try to allocate a system socket */ 420 /* try to allocate a system socket */
414 if (!err) { 421 if (!err) {
415 /* allocate udp object */ 422 /* allocate udp object */
@@ -417,7 +424,7 @@ static int udp_create(lua_State *L, int family) {
417 auxiliar_setclass(L, "udp{unconnected}", -1); 424 auxiliar_setclass(L, "udp{unconnected}", -1);
418 /* initialize remaining structure fields */ 425 /* initialize remaining structure fields */
419 socket_setnonblocking(&sock); 426 socket_setnonblocking(&sock);
420 if (family == PF_INET6) { 427 if (family == AF_INET6) {
421 int yes = 1; 428 int yes = 1;
422 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, 429 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
423 (void *)&yes, sizeof(yes)); 430 (void *)&yes, sizeof(yes));
@@ -434,6 +441,10 @@ static int udp_create(lua_State *L, int family) {
434} 441}
435 442
436static int global_create(lua_State *L) { 443static int global_create(lua_State *L) {
444 return udp_create(L, AF_UNSPEC);
445}
446
447static int global_create4(lua_State *L) {
437 return udp_create(L, AF_INET); 448 return udp_create(L, AF_INET);
438} 449}
439 450
diff --git a/src/usocket.c b/src/usocket.c
index 99e551b..8adc573 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -211,6 +211,8 @@ int socket_send(p_socket ps, const char *data, size_t count,
211 err = errno; 211 err = errno;
212 /* EPIPE means the connection was closed */ 212 /* EPIPE means the connection was closed */
213 if (err == EPIPE) return IO_CLOSED; 213 if (err == EPIPE) return IO_CLOSED;
214 /* EPROTOTYPE means the connection is being closed (on Yosemite!)*/
215 if (err == EPROTOTYPE) continue;
214 /* we call was interrupted, just try again */ 216 /* we call was interrupted, just try again */
215 if (err == EINTR) continue; 217 if (err == EINTR) continue;
216 /* if failed fatal reason, report error */ 218 /* if failed fatal reason, report error */
@@ -239,6 +241,7 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent,
239 } 241 }
240 err = errno; 242 err = errno;
241 if (err == EPIPE) return IO_CLOSED; 243 if (err == EPIPE) return IO_CLOSED;
244 if (err == EPROTOTYPE) continue;
242 if (err == EINTR) continue; 245 if (err == EINTR) continue;
243 if (err != EAGAIN) return err; 246 if (err != EAGAIN) return err;
244 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; 247 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
@@ -317,6 +320,8 @@ int socket_write(p_socket ps, const char *data, size_t count,
317 err = errno; 320 err = errno;
318 /* EPIPE means the connection was closed */ 321 /* EPIPE means the connection was closed */
319 if (err == EPIPE) return IO_CLOSED; 322 if (err == EPIPE) return IO_CLOSED;
323 /* EPROTOTYPE means the connection is being closed (on Yosemite!)*/
324 if (err == EPROTOTYPE) continue;
320 /* we call was interrupted, just try again */ 325 /* we call was interrupted, just try again */
321 if (err == EINTR) continue; 326 if (err == EINTR) continue;
322 /* if failed fatal reason, report error */ 327 /* if failed fatal reason, report error */
@@ -410,7 +415,9 @@ const char *socket_strerror(int err) {
410 case ECONNABORTED: return PIE_CONNABORTED; 415 case ECONNABORTED: return PIE_CONNABORTED;
411 case ECONNRESET: return PIE_CONNRESET; 416 case ECONNRESET: return PIE_CONNRESET;
412 case ETIMEDOUT: return PIE_TIMEDOUT; 417 case ETIMEDOUT: return PIE_TIMEDOUT;
413 default: return strerror(err); 418 default: {
419 return strerror(err);
420 }
414 } 421 }
415} 422}
416 423