aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/tcp.html6
-rw-r--r--doc/udp.html6
-rw-r--r--src/inet.c17
-rw-r--r--src/inet.h2
-rw-r--r--src/tcp.c52
-rw-r--r--src/udp.c52
-rw-r--r--test/testclnt.lua19
7 files changed, 78 insertions, 76 deletions
diff --git a/doc/tcp.html b/doc/tcp.html
index 6fc9900..fb627a1 100644
--- a/doc/tcp.html
+++ b/doc/tcp.html
@@ -65,6 +65,12 @@ href=#bind><tt>connect</tt></a>, depending on the address
65family obtained from the resolver. 65family obtained from the resolver.
66</p> 66</p>
67 67
68<p class=note>
69Note: Before the choice between IPv4 and IPv6 happens,
70the internal socket object is invalid and therefore <a
71href=#setoption><tt>setoption</tt></a> will fail.
72</p>
73
68<!-- socket.tcp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 74<!-- socket.tcp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
69 75
70<p class=name id="socket.tcp4"> 76<p class=name id="socket.tcp4">
diff --git a/doc/udp.html b/doc/udp.html
index e313af4..a300f2f 100644
--- a/doc/udp.html
+++ b/doc/udp.html
@@ -76,6 +76,12 @@ href=#setsockname><tt>sockname</tt></a>, depending on the address
76family obtained from the resolver. 76family obtained from the resolver.
77</p> 77</p>
78 78
79<p class=note>
80Note: Before the choice between IPv4 and IPv6 happens,
81the internal socket object is invalid and therefore <a
82href=#setoption><tt>setoption</tt></a> will fail.
83</p>
84
79<!-- socket.udp4 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 85<!-- socket.udp4 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
80 86
81<p class="name" id="socket.udp"> 87<p class="name" id="socket.udp">
diff --git a/src/inet.c b/src/inet.c
index 8f0fac2..331b800 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -352,8 +352,13 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp)
352/*-------------------------------------------------------------------------*\ 352/*-------------------------------------------------------------------------*\
353* Tries to create a new inet socket 353* Tries to create a new inet socket
354\*-------------------------------------------------------------------------*/ 354\*-------------------------------------------------------------------------*/
355const char *inet_trycreate(p_socket ps, int family, int type) { 355const char *inet_trycreate(p_socket ps, int family, int type, int protocol) {
356 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;
357} 362}
358 363
359/*-------------------------------------------------------------------------*\ 364/*-------------------------------------------------------------------------*\
@@ -408,8 +413,8 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
408 * not enter this branch. */ 413 * not enter this branch. */
409 if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) { 414 if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
410 socket_destroy(ps); 415 socket_destroy(ps);
411 err = socket_strerror(socket_create(ps, iterator->ai_family, 416 err = inet_trycreate(ps, iterator->ai_family,
412 iterator->ai_socktype, iterator->ai_protocol)); 417 iterator->ai_socktype, iterator->ai_protocol);
413 if (err) continue; 418 if (err) continue;
414 current_family = iterator->ai_family; 419 current_family = iterator->ai_family;
415 /* set non-blocking before connect */ 420 /* set non-blocking before connect */
@@ -466,8 +471,8 @@ const char *inet_trybind(p_socket ps, int *family, const char *address,
466 for (iterator = resolved; iterator; iterator = iterator->ai_next) { 471 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
467 if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) { 472 if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
468 socket_destroy(ps); 473 socket_destroy(ps);
469 err = socket_strerror(socket_create(ps, iterator->ai_family, 474 err = inet_trycreate(ps, iterator->ai_family,
470 iterator->ai_socktype, iterator->ai_protocol)); 475 iterator->ai_socktype, iterator->ai_protocol);
471 if (err) continue; 476 if (err) continue;
472 current_family = iterator->ai_family; 477 current_family = iterator->ai_family;
473 } 478 }
diff --git a/src/inet.h b/src/inet.h
index b85c20e..feb3541 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -24,7 +24,7 @@
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, int *family, const char *address, 30const char *inet_trybind(p_socket ps, int *family, const char *address,
diff --git a/src/tcp.c b/src/tcp.c
index 4d12f08..7bf1af5 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -355,39 +355,29 @@ static int meth_settimeout(lua_State *L)
355* Creates a master tcp object 355* Creates a master tcp object
356\*-------------------------------------------------------------------------*/ 356\*-------------------------------------------------------------------------*/
357static int tcp_create(lua_State *L, int family) { 357static int tcp_create(lua_State *L, int family) {
358 t_socket sock; 358 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
359 /* if family is AF_UNSPEC, we create an AF_INET socket 359 memset(tcp, 0, sizeof(t_tcp));
360 * but store AF_UNSPEC into tcp-family. This will allow it 360 /* set its type as master object */
361 * later be replaced with an AF_INET6 socket if 361 auxiliar_setclass(L, "tcp{master}", -1);
362 * trybind or tryconnect prefer it instead. */ 362 /* if family is AF_UNSPEC, we leave the socket invalid and
363 const char *err = inet_trycreate(&sock, family == AF_UNSPEC? 363 * store AF_UNSPEC into family. This will allow it to later be
364 AF_INET: family, SOCK_STREAM); 364 * replaced with an AF_INET6 or AF_INET socket upon first use. */
365 /* try to allocate a system socket */ 365 tcp->sock = SOCKET_INVALID;
366 if (!err) { 366 tcp->family = family;
367 /* allocate tcp object */ 367 io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
368 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); 368 (p_error) socket_ioerror, &tcp->sock);
369 memset(tcp, 0, sizeof(t_tcp)); 369 timeout_init(&tcp->tm, -1, -1);
370 /* set its type as master object */ 370 buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
371 auxiliar_setclass(L, "tcp{master}", -1); 371 if (family != AF_UNSPEC) {
372 /* initialize remaining structure fields */ 372 const char *err = inet_trycreate(&tcp->sock, family, SOCK_STREAM, 0);
373 socket_setnonblocking(&sock); 373 if (err != NULL) {
374 if (family == AF_INET6) { 374 lua_pushnil(L);
375 int yes = 1; 375 lua_pushstring(L, err);
376 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, 376 return 2;
377 (void *)&yes, sizeof(yes));
378 } 377 }
379 tcp->sock = sock; 378 socket_setnonblocking(&tcp->sock);
380 io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
381 (p_error) socket_ioerror, &tcp->sock);
382 timeout_init(&tcp->tm, -1, -1);
383 buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
384 tcp->family = family;
385 return 1;
386 } else {
387 lua_pushnil(L);
388 lua_pushstring(L, err);
389 return 2;
390 } 379 }
380 return 1;
391} 381}
392 382
393static int global_create(lua_State *L) { 383static int global_create(lua_State *L) {
diff --git a/src/udp.c b/src/udp.c
index 6600859..17d932a 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -185,7 +185,7 @@ static int meth_sendto(lua_State *L) {
185 return 2; 185 return 2;
186 } 186 }
187 timeout_markstart(tm); 187 timeout_markstart(tm);
188 err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, 188 err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr,
189 (socklen_t) ai->ai_addrlen, tm); 189 (socklen_t) ai->ai_addrlen, tm);
190 freeaddrinfo(ai); 190 freeaddrinfo(ai);
191 if (err != IO_DONE) { 191 if (err != IO_DONE) {
@@ -237,7 +237,7 @@ static int meth_receivefrom(lua_State *L)
237 char portstr[6]; 237 char portstr[6];
238 timeout_markstart(tm); 238 timeout_markstart(tm);
239 count = MIN(count, sizeof(buffer)); 239 count = MIN(count, sizeof(buffer));
240 err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr, 240 err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr,
241 &addr_len, tm); 241 &addr_len, tm);
242 /* 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. */
243 if (err == IO_CLOSED) 243 if (err == IO_CLOSED)
@@ -247,7 +247,7 @@ static int meth_receivefrom(lua_State *L)
247 lua_pushstring(L, udp_strerror(err)); 247 lua_pushstring(L, udp_strerror(err));
248 return 2; 248 return 2;
249 } 249 }
250 err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, 250 err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr,
251 INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); 251 INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV);
252 if (err) { 252 if (err) {
253 lua_pushnil(L); 253 lua_pushnil(L);
@@ -351,7 +351,7 @@ static int meth_setpeername(lua_State *L) {
351 /* make sure we try to connect only to the same family */ 351 /* make sure we try to connect only to the same family */
352 connecthints.ai_family = udp->family; 352 connecthints.ai_family = udp->family;
353 if (connecting) { 353 if (connecting) {
354 err = inet_tryconnect(&udp->sock, &udp->family, address, 354 err = inet_tryconnect(&udp->sock, &udp->family, address,
355 port, tm, &connecthints); 355 port, tm, &connecthints);
356 if (err) { 356 if (err) {
357 lua_pushnil(L); 357 lua_pushnil(L);
@@ -365,7 +365,6 @@ static int meth_setpeername(lua_State *L) {
365 inet_trydisconnect(&udp->sock, udp->family, tm); 365 inet_trydisconnect(&udp->sock, udp->family, tm);
366 auxiliar_setclass(L, "udp{unconnected}", 1); 366 auxiliar_setclass(L, "udp{unconnected}", 1);
367 } 367 }
368 /* change class to connected or unconnected depending on address */
369 lua_pushnumber(L, 1); 368 lua_pushnumber(L, 1);
370 return 1; 369 return 1;
371} 370}
@@ -410,34 +409,25 @@ static int meth_setsockname(lua_State *L) {
410* Creates a master udp object 409* Creates a master udp object
411\*-------------------------------------------------------------------------*/ 410\*-------------------------------------------------------------------------*/
412static int udp_create(lua_State *L, int family) { 411static int udp_create(lua_State *L, int family) {
413 t_socket sock; 412 /* allocate udp object */
414 /* if family is AF_UNSPEC, we create an AF_INET socket 413 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
415 * but store AF_UNSPEC into tcp-family. This will allow it 414 auxiliar_setclass(L, "udp{unconnected}", -1);
416 * later be replaced with an AF_INET6 socket if 415 /* if family is AF_UNSPEC, we leave the socket invalid and
417 * trybind or tryconnect prefer it instead. */ 416 * store AF_UNSPEC into family. This will allow it to later be
418 const char *err = inet_trycreate(&sock, family == AF_UNSPEC? 417 * replaced with an AF_INET6 or AF_INET socket upon first use. */
419 AF_INET: family, SOCK_DGRAM); 418 udp->sock = SOCKET_INVALID;
420 /* try to allocate a system socket */ 419 timeout_init(&udp->tm, -1, -1);
421 if (!err) { 420 udp->family = family;
422 /* allocate udp object */ 421 if (family != AF_UNSPEC) {
423 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); 422 const char *err = inet_trycreate(&udp->sock, family, SOCK_DGRAM, 0);
424 auxiliar_setclass(L, "udp{unconnected}", -1); 423 if (err != NULL) {
425 /* initialize remaining structure fields */ 424 lua_pushnil(L);
426 socket_setnonblocking(&sock); 425 lua_pushstring(L, err);
427 if (family == AF_INET6) { 426 return 2;
428 int yes = 1;
429 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
430 (void *)&yes, sizeof(yes));
431 } 427 }
432 udp->sock = sock; 428 socket_setnonblocking(&udp->sock);
433 timeout_init(&udp->tm, -1, -1);
434 udp->family = family;
435 return 1;
436 } else {
437 lua_pushnil(L);
438 lua_pushstring(L, err);
439 return 2;
440 } 429 }
430 return 1;
441} 431}
442 432
443static int global_create(lua_State *L) { 433static int global_create(lua_State *L) {
diff --git a/test/testclnt.lua b/test/testclnt.lua
index abf9608..ee1201f 100644
--- a/test/testclnt.lua
+++ b/test/testclnt.lua
@@ -304,15 +304,20 @@ function isclosed(c)
304end 304end
305 305
306function active_close() 306function active_close()
307 reconnect() 307 local tcp = socket.tcp4()
308 if isclosed(data) then fail("should not be closed") end 308 if isclosed(tcp) then fail("should not be closed") end
309 data:close() 309 tcp:close()
310 if not isclosed(data) then fail("should be closed") end 310 if not isclosed(tcp) then fail("should be closed") end
311 data = nil 311 tcp = socket.tcp()
312 local udp = socket.udp() 312 if not isclosed(tcp) then fail("should be closed") end
313 tcp = nil
314 local udp = socket.udp4()
313 if isclosed(udp) then fail("should not be closed") end 315 if isclosed(udp) then fail("should not be closed") end
314 udp:close() 316 udp:close()
315 if not isclosed(udp) then fail("should be closed") end 317 if not isclosed(udp) then fail("should be closed") end
318 udp = socket.udp()
319 if not isclosed(udp) then fail("should be closed") end
320 udp = nil
316 pass("ok") 321 pass("ok")
317end 322end
318 323
@@ -368,7 +373,7 @@ function test_selectbugs()
368 pass("invalid input: ok") 373 pass("invalid input: ok")
369 local toomany = {} 374 local toomany = {}
370 for i = 1, socket._SETSIZE+1 do 375 for i = 1, socket._SETSIZE+1 do
371 toomany[#toomany+1] = socket.udp() 376 toomany[#toomany+1] = socket.udp4()
372 end 377 end
373 if #toomany > socket._SETSIZE then 378 if #toomany > socket._SETSIZE then
374 local e = pcall(socket.select, toomany, nil, 0.1) 379 local e = pcall(socket.select, toomany, nil, 0.1)