Fixes suggested by @Florob in #147.

This commit is contained in:
Diego Nehab 2015-08-25 15:41:40 -03:00
parent 96965b179c
commit 77bba625d7
7 changed files with 78 additions and 76 deletions

View File

@ -65,6 +65,12 @@ href=#bind><tt>connect</tt></a>, depending on the address
family obtained from the resolver. family obtained from the resolver.
</p> </p>
<p class=note>
Note: Before the choice between IPv4 and IPv6 happens,
the internal socket object is invalid and therefore <a
href=#setoption><tt>setoption</tt></a> will fail.
</p>
<!-- socket.tcp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> <!-- socket.tcp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<p class=name id="socket.tcp4"> <p class=name id="socket.tcp4">

View File

@ -76,6 +76,12 @@ href=#setsockname><tt>sockname</tt></a>, depending on the address
family obtained from the resolver. family obtained from the resolver.
</p> </p>
<p class=note>
Note: Before the choice between IPv4 and IPv6 happens,
the internal socket object is invalid and therefore <a
href=#setoption><tt>setoption</tt></a> will fail.
</p>
<!-- socket.udp4 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> <!-- socket.udp4 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<p class="name" id="socket.udp"> <p class="name" id="socket.udp">

View File

@ -352,8 +352,13 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp)
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\
* Tries to create a new inet socket * Tries to create a new inet socket
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
const char *inet_trycreate(p_socket ps, int family, int type) { const char *inet_trycreate(p_socket ps, int family, int type, int protocol) {
return socket_strerror(socket_create(ps, family, type, 0)); const char *err = socket_strerror(socket_create(ps, family, type, protocol));
if (err == NULL && family == AF_INET6) {
int yes = 1;
setsockopt(*ps, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes));
}
return err;
} }
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\
@ -408,8 +413,8 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address,
* not enter this branch. */ * not enter this branch. */
if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) { if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
socket_destroy(ps); socket_destroy(ps);
err = socket_strerror(socket_create(ps, iterator->ai_family, err = inet_trycreate(ps, iterator->ai_family,
iterator->ai_socktype, iterator->ai_protocol)); iterator->ai_socktype, iterator->ai_protocol);
if (err) continue; if (err) continue;
current_family = iterator->ai_family; current_family = iterator->ai_family;
/* set non-blocking before connect */ /* set non-blocking before connect */
@ -466,8 +471,8 @@ const char *inet_trybind(p_socket ps, int *family, const char *address,
for (iterator = resolved; iterator; iterator = iterator->ai_next) { for (iterator = resolved; iterator; iterator = iterator->ai_next) {
if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) { if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
socket_destroy(ps); socket_destroy(ps);
err = socket_strerror(socket_create(ps, iterator->ai_family, err = inet_trycreate(ps, iterator->ai_family,
iterator->ai_socktype, iterator->ai_protocol)); iterator->ai_socktype, iterator->ai_protocol);
if (err) continue; if (err) continue;
current_family = iterator->ai_family; current_family = iterator->ai_family;
} }

View File

@ -24,7 +24,7 @@
int inet_open(lua_State *L); int inet_open(lua_State *L);
const char *inet_trycreate(p_socket ps, int family, int type); const char *inet_trycreate(p_socket ps, int family, int type, int protocol);
const char *inet_tryconnect(p_socket ps, int *family, const char *address, const char *inet_tryconnect(p_socket ps, int *family, const char *address,
const char *serv, p_timeout tm, struct addrinfo *connecthints); const char *serv, p_timeout tm, struct addrinfo *connecthints);
const char *inet_trybind(p_socket ps, int *family, const char *address, const char *inet_trybind(p_socket ps, int *family, const char *address,

View File

@ -355,39 +355,29 @@ static int meth_settimeout(lua_State *L)
* Creates a master tcp object * Creates a master tcp object
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
static int tcp_create(lua_State *L, int family) { static int tcp_create(lua_State *L, int family) {
t_socket sock; p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
/* if family is AF_UNSPEC, we create an AF_INET socket memset(tcp, 0, sizeof(t_tcp));
* but store AF_UNSPEC into tcp-family. This will allow it /* set its type as master object */
* later be replaced with an AF_INET6 socket if auxiliar_setclass(L, "tcp{master}", -1);
* trybind or tryconnect prefer it instead. */ /* if family is AF_UNSPEC, we leave the socket invalid and
const char *err = inet_trycreate(&sock, family == AF_UNSPEC? * store AF_UNSPEC into family. This will allow it to later be
AF_INET: family, SOCK_STREAM); * replaced with an AF_INET6 or AF_INET socket upon first use. */
/* try to allocate a system socket */ tcp->sock = SOCKET_INVALID;
if (!err) { tcp->family = family;
/* allocate tcp object */ io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); (p_error) socket_ioerror, &tcp->sock);
memset(tcp, 0, sizeof(t_tcp)); timeout_init(&tcp->tm, -1, -1);
/* set its type as master object */ buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
auxiliar_setclass(L, "tcp{master}", -1); if (family != AF_UNSPEC) {
/* initialize remaining structure fields */ const char *err = inet_trycreate(&tcp->sock, family, SOCK_STREAM, 0);
socket_setnonblocking(&sock); if (err != NULL) {
if (family == AF_INET6) { lua_pushnil(L);
int yes = 1; lua_pushstring(L, err);
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, return 2;
(void *)&yes, sizeof(yes));
} }
tcp->sock = sock; socket_setnonblocking(&tcp->sock);
io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
(p_error) socket_ioerror, &tcp->sock);
timeout_init(&tcp->tm, -1, -1);
buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
tcp->family = family;
return 1;
} else {
lua_pushnil(L);
lua_pushstring(L, err);
return 2;
} }
return 1;
} }
static int global_create(lua_State *L) { static int global_create(lua_State *L) {

View File

@ -185,7 +185,7 @@ static int meth_sendto(lua_State *L) {
return 2; return 2;
} }
timeout_markstart(tm); timeout_markstart(tm);
err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr,
(socklen_t) ai->ai_addrlen, tm); (socklen_t) ai->ai_addrlen, tm);
freeaddrinfo(ai); freeaddrinfo(ai);
if (err != IO_DONE) { if (err != IO_DONE) {
@ -237,7 +237,7 @@ static int meth_receivefrom(lua_State *L)
char portstr[6]; char portstr[6];
timeout_markstart(tm); timeout_markstart(tm);
count = MIN(count, sizeof(buffer)); count = MIN(count, sizeof(buffer));
err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr, err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr,
&addr_len, tm); &addr_len, tm);
/* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
if (err == IO_CLOSED) if (err == IO_CLOSED)
@ -247,7 +247,7 @@ static int meth_receivefrom(lua_State *L)
lua_pushstring(L, udp_strerror(err)); lua_pushstring(L, udp_strerror(err));
return 2; return 2;
} }
err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr,
INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV);
if (err) { if (err) {
lua_pushnil(L); lua_pushnil(L);
@ -351,7 +351,7 @@ static int meth_setpeername(lua_State *L) {
/* make sure we try to connect only to the same family */ /* make sure we try to connect only to the same family */
connecthints.ai_family = udp->family; connecthints.ai_family = udp->family;
if (connecting) { if (connecting) {
err = inet_tryconnect(&udp->sock, &udp->family, address, err = inet_tryconnect(&udp->sock, &udp->family, address,
port, tm, &connecthints); port, tm, &connecthints);
if (err) { if (err) {
lua_pushnil(L); lua_pushnil(L);
@ -365,7 +365,6 @@ static int meth_setpeername(lua_State *L) {
inet_trydisconnect(&udp->sock, udp->family, tm); inet_trydisconnect(&udp->sock, udp->family, tm);
auxiliar_setclass(L, "udp{unconnected}", 1); auxiliar_setclass(L, "udp{unconnected}", 1);
} }
/* change class to connected or unconnected depending on address */
lua_pushnumber(L, 1); lua_pushnumber(L, 1);
return 1; return 1;
} }
@ -410,34 +409,25 @@ static int meth_setsockname(lua_State *L) {
* Creates a master udp object * Creates a master udp object
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
static int udp_create(lua_State *L, int family) { static int udp_create(lua_State *L, int family) {
t_socket sock; /* allocate udp object */
/* if family is AF_UNSPEC, we create an AF_INET socket p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
* but store AF_UNSPEC into tcp-family. This will allow it auxiliar_setclass(L, "udp{unconnected}", -1);
* later be replaced with an AF_INET6 socket if /* if family is AF_UNSPEC, we leave the socket invalid and
* trybind or tryconnect prefer it instead. */ * store AF_UNSPEC into family. This will allow it to later be
const char *err = inet_trycreate(&sock, family == AF_UNSPEC? * replaced with an AF_INET6 or AF_INET socket upon first use. */
AF_INET: family, SOCK_DGRAM); udp->sock = SOCKET_INVALID;
/* try to allocate a system socket */ timeout_init(&udp->tm, -1, -1);
if (!err) { udp->family = family;
/* allocate udp object */ if (family != AF_UNSPEC) {
p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); const char *err = inet_trycreate(&udp->sock, family, SOCK_DGRAM, 0);
auxiliar_setclass(L, "udp{unconnected}", -1); if (err != NULL) {
/* initialize remaining structure fields */ lua_pushnil(L);
socket_setnonblocking(&sock); lua_pushstring(L, err);
if (family == AF_INET6) { return 2;
int yes = 1;
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
(void *)&yes, sizeof(yes));
} }
udp->sock = sock; socket_setnonblocking(&udp->sock);
timeout_init(&udp->tm, -1, -1);
udp->family = family;
return 1;
} else {
lua_pushnil(L);
lua_pushstring(L, err);
return 2;
} }
return 1;
} }
static int global_create(lua_State *L) { static int global_create(lua_State *L) {

View File

@ -304,15 +304,20 @@ function isclosed(c)
end end
function active_close() function active_close()
reconnect() local tcp = socket.tcp4()
if isclosed(data) then fail("should not be closed") end if isclosed(tcp) then fail("should not be closed") end
data:close() tcp:close()
if not isclosed(data) then fail("should be closed") end if not isclosed(tcp) then fail("should be closed") end
data = nil tcp = socket.tcp()
local udp = socket.udp() if not isclosed(tcp) then fail("should be closed") end
tcp = nil
local udp = socket.udp4()
if isclosed(udp) then fail("should not be closed") end if isclosed(udp) then fail("should not be closed") end
udp:close() udp:close()
if not isclosed(udp) then fail("should be closed") end if not isclosed(udp) then fail("should be closed") end
udp = socket.udp()
if not isclosed(udp) then fail("should be closed") end
udp = nil
pass("ok") pass("ok")
end end
@ -368,7 +373,7 @@ function test_selectbugs()
pass("invalid input: ok") pass("invalid input: ok")
local toomany = {} local toomany = {}
for i = 1, socket._SETSIZE+1 do for i = 1, socket._SETSIZE+1 do
toomany[#toomany+1] = socket.udp() toomany[#toomany+1] = socket.udp4()
end end
if #toomany > socket._SETSIZE then if #toomany > socket._SETSIZE then
local e = pcall(socket.select, toomany, nil, 0.1) local e = pcall(socket.select, toomany, nil, 0.1)