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

View File

@ -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;
/* if family is AF_UNSPEC, we create an AF_INET socket
* but store AF_UNSPEC into tcp-family. This will allow it
* later be replaced with an AF_INET6 socket if
* trybind or tryconnect prefer it instead. */
const char *err = inet_trycreate(&sock, family == AF_UNSPEC?
AF_INET: family, SOCK_DGRAM);
/* try to allocate a system socket */
if (!err) {
/* allocate udp object */ /* allocate udp object */
p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
auxiliar_setclass(L, "udp{unconnected}", -1); auxiliar_setclass(L, "udp{unconnected}", -1);
/* initialize remaining structure fields */ /* if family is AF_UNSPEC, we leave the socket invalid and
socket_setnonblocking(&sock); * store AF_UNSPEC into family. This will allow it to later be
if (family == AF_INET6) { * replaced with an AF_INET6 or AF_INET socket upon first use. */
int yes = 1; udp->sock = SOCKET_INVALID;
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
(void *)&yes, sizeof(yes));
}
udp->sock = sock;
timeout_init(&udp->tm, -1, -1); timeout_init(&udp->tm, -1, -1);
udp->family = family; udp->family = family;
return 1; if (family != AF_UNSPEC) {
} else { const char *err = inet_trycreate(&udp->sock, family, SOCK_DGRAM, 0);
if (err != NULL) {
lua_pushnil(L); lua_pushnil(L);
lua_pushstring(L, err); lua_pushstring(L, err);
return 2; return 2;
} }
socket_setnonblocking(&udp->sock);
}
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)