aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buffer.c24
-rw-r--r--src/inet.c145
-rw-r--r--src/inet.h12
-rw-r--r--src/io.h2
-rw-r--r--src/socket.lua10
-rw-r--r--src/tcp.c123
-rw-r--r--src/udp.c57
-rw-r--r--src/usocket.c9
8 files changed, 177 insertions, 205 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..331b800 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}
@@ -344,8 +352,13 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp)
344/*-------------------------------------------------------------------------*\ 352/*-------------------------------------------------------------------------*\
345* Tries to create a new inet socket 353* Tries to create a new inet socket
346\*-------------------------------------------------------------------------*/ 354\*-------------------------------------------------------------------------*/
347const char *inet_trycreate(p_socket ps, int family, int type) { 355const char *inet_trycreate(p_socket ps, int family, int type, int protocol) {
348 return socket_strerror(socket_create(ps, family, type, 0)); 356 const char *err = socket_strerror(socket_create(ps, family, type, protocol));
357 if (err == NULL && family == AF_INET6) {
358 int yes = 1;
359 setsockopt(*ps, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes));
360 }
361 return err;
349} 362}
350 363
351/*-------------------------------------------------------------------------*\ 364/*-------------------------------------------------------------------------*\
@@ -354,21 +367,21 @@ const char *inet_trycreate(p_socket ps, int family, int type) {
354const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm) 367const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm)
355{ 368{
356 switch (family) { 369 switch (family) {
357 case PF_INET: { 370 case AF_INET: {
358 struct sockaddr_in sin; 371 struct sockaddr_in sin;
359 memset((char *) &sin, 0, sizeof(sin)); 372 memset((char *) &sin, 0, sizeof(sin));
360 sin.sin_family = AF_UNSPEC; 373 sin.sin_family = AF_UNSPEC;
361 sin.sin_addr.s_addr = INADDR_ANY; 374 sin.sin_addr.s_addr = INADDR_ANY;
362 return socket_strerror(socket_connect(ps, (SA *) &sin, 375 return socket_strerror(socket_connect(ps, (SA *) &sin,
363 sizeof(sin), tm)); 376 sizeof(sin), tm));
364 } 377 }
365 case PF_INET6: { 378 case AF_INET6: {
366 struct sockaddr_in6 sin6; 379 struct sockaddr_in6 sin6;
367 struct in6_addr addrany = IN6ADDR_ANY_INIT; 380 struct in6_addr addrany = IN6ADDR_ANY_INIT;
368 memset((char *) &sin6, 0, sizeof(sin6)); 381 memset((char *) &sin6, 0, sizeof(sin6));
369 sin6.sin6_family = AF_UNSPEC; 382 sin6.sin6_family = AF_UNSPEC;
370 sin6.sin6_addr = addrany; 383 sin6.sin6_addr = addrany;
371 return socket_strerror(socket_connect(ps, (SA *) &sin6, 384 return socket_strerror(socket_connect(ps, (SA *) &sin6,
372 sizeof(sin6), tm)); 385 sizeof(sin6), tm));
373 } 386 }
374 } 387 }
@@ -383,6 +396,7 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
383{ 396{
384 struct addrinfo *iterator = NULL, *resolved = NULL; 397 struct addrinfo *iterator = NULL, *resolved = NULL;
385 const char *err = NULL; 398 const char *err = NULL;
399 int current_family = *family;
386 /* try resolving */ 400 /* try resolving */
387 err = socket_gaistrerror(getaddrinfo(address, serv, 401 err = socket_gaistrerror(getaddrinfo(address, serv,
388 connecthints, &resolved)); 402 connecthints, &resolved));
@@ -397,23 +411,23 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
397 * that shows up while iterating. if there was a 411 * that shows up while iterating. if there was a
398 * bind, all families will be the same and we will 412 * bind, all families will be the same and we will
399 * not enter this branch. */ 413 * not enter this branch. */
400 if (*family != iterator->ai_family) { 414 if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
401 socket_destroy(ps); 415 socket_destroy(ps);
402 err = socket_strerror(socket_create(ps, iterator->ai_family, 416 err = inet_trycreate(ps, iterator->ai_family,
403 iterator->ai_socktype, iterator->ai_protocol)); 417 iterator->ai_socktype, iterator->ai_protocol);
404 if (err != NULL) { 418 if (err) continue;
405 freeaddrinfo(resolved); 419 current_family = iterator->ai_family;
406 return err; 420 /* set non-blocking before connect */
407 }
408 *family = iterator->ai_family;
409 /* all sockets initially non-blocking */
410 socket_setnonblocking(ps); 421 socket_setnonblocking(ps);
411 } 422 }
412 /* try connecting to remote address */ 423 /* try connecting to remote address */
413 err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, 424 err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr,
414 (socklen_t) iterator->ai_addrlen, tm)); 425 (socklen_t) iterator->ai_addrlen, tm));
415 /* if success, break out of loop */ 426 /* if success, break out of loop */
416 if (err == NULL) break; 427 if (err == NULL) {
428 *family = current_family;
429 break;
430 }
417 } 431 }
418 freeaddrinfo(resolved); 432 freeaddrinfo(resolved);
419 /* here, if err is set, we failed */ 433 /* here, if err is set, we failed */
@@ -423,29 +437,27 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
423/*-------------------------------------------------------------------------*\ 437/*-------------------------------------------------------------------------*\
424* Tries to accept a socket 438* Tries to accept a socket
425\*-------------------------------------------------------------------------*/ 439\*-------------------------------------------------------------------------*/
426const char *inet_tryaccept(p_socket server, int family, p_socket client, 440const char *inet_tryaccept(p_socket server, int family, p_socket client,
427 p_timeout tm) 441 p_timeout tm) {
428{
429 socklen_t len; 442 socklen_t len;
430 t_sockaddr_storage addr; 443 t_sockaddr_storage addr;
431 if (family == PF_INET6) { 444 switch (family) {
432 len = sizeof(struct sockaddr_in6); 445 case AF_INET6: len = sizeof(struct sockaddr_in6); break;
433 } else { 446 case AF_INET: len = sizeof(struct sockaddr_in); break;
434 len = sizeof(struct sockaddr_in); 447 default: len = sizeof(addr); break;
435 } 448 }
436 return socket_strerror(socket_accept(server, client, (SA *) &addr, 449 return socket_strerror(socket_accept(server, client, (SA *) &addr,
437 &len, tm)); 450 &len, tm));
438} 451}
439 452
440/*-------------------------------------------------------------------------*\ 453/*-------------------------------------------------------------------------*\
441* Tries to bind socket to (address, port) 454* Tries to bind socket to (address, port)
442\*-------------------------------------------------------------------------*/ 455\*-------------------------------------------------------------------------*/
443const char *inet_trybind(p_socket ps, const char *address, const char *serv, 456const char *inet_trybind(p_socket ps, int *family, const char *address,
444 struct addrinfo *bindhints) 457 const char *serv, struct addrinfo *bindhints) {
445{
446 struct addrinfo *iterator = NULL, *resolved = NULL; 458 struct addrinfo *iterator = NULL, *resolved = NULL;
447 const char *err = NULL; 459 const char *err = NULL;
448 t_socket sock = *ps; 460 int current_family = *family;
449 /* translate luasocket special values to C */ 461 /* translate luasocket special values to C */
450 if (strcmp(address, "*") == 0) address = NULL; 462 if (strcmp(address, "*") == 0) address = NULL;
451 if (!serv) serv = "0"; 463 if (!serv) serv = "0";
@@ -457,35 +469,32 @@ const char *inet_trybind(p_socket ps, const char *address, const char *serv,
457 } 469 }
458 /* iterate over resolved addresses until one is good */ 470 /* iterate over resolved addresses until one is good */
459 for (iterator = resolved; iterator; iterator = iterator->ai_next) { 471 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
460 if(sock == SOCKET_INVALID) { 472 if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
461 err = socket_strerror(socket_create(&sock, iterator->ai_family, 473 socket_destroy(ps);
462 iterator->ai_socktype, iterator->ai_protocol)); 474 err = inet_trycreate(ps, iterator->ai_family,
463 if(err) 475 iterator->ai_socktype, iterator->ai_protocol);
464 continue; 476 if (err) continue;
477 current_family = iterator->ai_family;
465 } 478 }
466 /* try binding to local address */ 479 /* try binding to local address */
467 err = socket_strerror(socket_bind(&sock, 480 err = socket_strerror(socket_bind(ps, (SA *) iterator->ai_addr,
468 (SA *) iterator->ai_addr,
469 (socklen_t) iterator->ai_addrlen)); 481 (socklen_t) iterator->ai_addrlen));
470
471 /* keep trying unless bind succeeded */ 482 /* keep trying unless bind succeeded */
472 if (err) { 483 if (err == NULL) {
473 if(sock != *ps) 484 *family = current_family;
474 socket_destroy(&sock); 485 /* set to non-blocking after bind */
475 } else { 486 socket_setnonblocking(ps);
476 /* remember what we connected to, particularly the family */
477 *bindhints = *iterator;
478 break; 487 break;
479 } 488 }
480 } 489 }
481 /* cleanup and return error */ 490 /* cleanup and return error */
482 freeaddrinfo(resolved); 491 freeaddrinfo(resolved);
483 *ps = sock; 492 /* here, if err is set, we failed */
484 return err; 493 return err;
485} 494}
486 495
487/*-------------------------------------------------------------------------*\ 496/*-------------------------------------------------------------------------*\
488* Some systems do not provide these so that we provide our own. 497* Some systems do not provide these so that we provide our own.
489\*-------------------------------------------------------------------------*/ 498\*-------------------------------------------------------------------------*/
490#ifdef LUASOCKET_INET_ATON 499#ifdef LUASOCKET_INET_ATON
491int inet_aton(const char *cp, struct in_addr *inp) 500int inet_aton(const char *cp, struct in_addr *inp)
@@ -510,7 +519,7 @@ int inet_aton(const char *cp, struct in_addr *inp)
510#endif 519#endif
511 520
512#ifdef LUASOCKET_INET_PTON 521#ifdef LUASOCKET_INET_PTON
513int inet_pton(int af, const char *src, void *dst) 522int inet_pton(int af, const char *src, void *dst)
514{ 523{
515 struct addrinfo hints, *res; 524 struct addrinfo hints, *res;
516 int ret = 1; 525 int ret = 1;
@@ -527,7 +536,7 @@ int inet_pton(int af, const char *src, void *dst)
527 } else { 536 } else {
528 ret = -1; 537 ret = -1;
529 } 538 }
530 freeaddrinfo(res); 539 freeaddrinfo(res);
531 return ret; 540 return ret;
532} 541}
533 542
diff --git a/src/inet.h b/src/inet.h
index 1f1a96a..feb3541 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
@@ -24,11 +24,11 @@
24 24
25int inet_open(lua_State *L); 25int inet_open(lua_State *L);
26 26
27const char *inet_trycreate(p_socket ps, int family, int type); 27const char *inet_trycreate(p_socket ps, int family, int type, int protocol);
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..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) {
diff --git a/src/udp.c b/src/udp.c
index 7ff00f5..17d932a 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};
@@ -183,7 +185,7 @@ static int meth_sendto(lua_State *L) {
183 return 2; 185 return 2;
184 } 186 }
185 timeout_markstart(tm); 187 timeout_markstart(tm);
186 err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, 188 err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr,
187 (socklen_t) ai->ai_addrlen, tm); 189 (socklen_t) ai->ai_addrlen, tm);
188 freeaddrinfo(ai); 190 freeaddrinfo(ai);
189 if (err != IO_DONE) { 191 if (err != IO_DONE) {
@@ -235,7 +237,7 @@ static int meth_receivefrom(lua_State *L)
235 char portstr[6]; 237 char portstr[6];
236 timeout_markstart(tm); 238 timeout_markstart(tm);
237 count = MIN(count, sizeof(buffer)); 239 count = MIN(count, sizeof(buffer));
238 err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr, 240 err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr,
239 &addr_len, tm); 241 &addr_len, tm);
240 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ 242 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
241 if (err == IO_CLOSED) 243 if (err == IO_CLOSED)
@@ -245,7 +247,7 @@ static int meth_receivefrom(lua_State *L)
245 lua_pushstring(L, udp_strerror(err)); 247 lua_pushstring(L, udp_strerror(err));
246 return 2; 248 return 2;
247 } 249 }
248 err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, 250 err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr,
249 INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); 251 INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV);
250 if (err) { 252 if (err) {
251 lua_pushnil(L); 253 lua_pushnil(L);
@@ -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 {
@@ -349,7 +351,7 @@ static int meth_setpeername(lua_State *L) {
349 /* make sure we try to connect only to the same family */ 351 /* make sure we try to connect only to the same family */
350 connecthints.ai_family = udp->family; 352 connecthints.ai_family = udp->family;
351 if (connecting) { 353 if (connecting) {
352 err = inet_tryconnect(&udp->sock, &udp->family, address, 354 err = inet_tryconnect(&udp->sock, &udp->family, address,
353 port, tm, &connecthints); 355 port, tm, &connecthints);
354 if (err) { 356 if (err) {
355 lua_pushnil(L); 357 lua_pushnil(L);
@@ -363,7 +365,6 @@ static int meth_setpeername(lua_State *L) {
363 inet_trydisconnect(&udp->sock, udp->family, tm); 365 inet_trydisconnect(&udp->sock, udp->family, tm);
364 auxiliar_setclass(L, "udp{unconnected}", 1); 366 auxiliar_setclass(L, "udp{unconnected}", 1);
365 } 367 }
366 /* change class to connected or unconnected depending on address */
367 lua_pushnumber(L, 1); 368 lua_pushnumber(L, 1);
368 return 1; 369 return 1;
369} 370}
@@ -391,7 +392,7 @@ static int meth_setsockname(lua_State *L) {
391 bindhints.ai_socktype = SOCK_DGRAM; 392 bindhints.ai_socktype = SOCK_DGRAM;
392 bindhints.ai_family = udp->family; 393 bindhints.ai_family = udp->family;
393 bindhints.ai_flags = AI_PASSIVE; 394 bindhints.ai_flags = AI_PASSIVE;
394 err = inet_trybind(&udp->sock, address, port, &bindhints); 395 err = inet_trybind(&udp->sock, &udp->family, address, port, &bindhints);
395 if (err) { 396 if (err) {
396 lua_pushnil(L); 397 lua_pushnil(L);
397 lua_pushstring(L, err); 398 lua_pushstring(L, err);
@@ -408,32 +409,32 @@ static int meth_setsockname(lua_State *L) {
408* Creates a master udp object 409* Creates a master udp object
409\*-------------------------------------------------------------------------*/ 410\*-------------------------------------------------------------------------*/
410static int udp_create(lua_State *L, int family) { 411static int udp_create(lua_State *L, int family) {
411 t_socket sock; 412 /* allocate udp object */
412 const char *err = inet_trycreate(&sock, family, SOCK_DGRAM); 413 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
413 /* try to allocate a system socket */ 414 auxiliar_setclass(L, "udp{unconnected}", -1);
414 if (!err) { 415 /* if family is AF_UNSPEC, we leave the socket invalid and
415 /* allocate udp object */ 416 * store AF_UNSPEC into family. This will allow it to later be
416 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); 417 * replaced with an AF_INET6 or AF_INET socket upon first use. */
417 auxiliar_setclass(L, "udp{unconnected}", -1); 418 udp->sock = SOCKET_INVALID;
418 /* initialize remaining structure fields */ 419 timeout_init(&udp->tm, -1, -1);
419 socket_setnonblocking(&sock); 420 udp->family = family;
420 if (family == PF_INET6) { 421 if (family != AF_UNSPEC) {
421 int yes = 1; 422 const char *err = inet_trycreate(&udp->sock, family, SOCK_DGRAM, 0);
422 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, 423 if (err != NULL) {
423 (void *)&yes, sizeof(yes)); 424 lua_pushnil(L);
425 lua_pushstring(L, err);
426 return 2;
424 } 427 }
425 udp->sock = sock; 428 socket_setnonblocking(&udp->sock);
426 timeout_init(&udp->tm, -1, -1);
427 udp->family = family;
428 return 1;
429 } else {
430 lua_pushnil(L);
431 lua_pushstring(L, err);
432 return 2;
433 } 429 }
430 return 1;
434} 431}
435 432
436static int global_create(lua_State *L) { 433static int global_create(lua_State *L) {
434 return udp_create(L, AF_UNSPEC);
435}
436
437static int global_create4(lua_State *L) {
437 return udp_create(L, AF_INET); 438 return udp_create(L, AF_INET);
438} 439}
439 440
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