mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-12-25 20:18:21 +01:00
Fixes suggested by @Florob in #147.
This commit is contained in:
parent
96965b179c
commit
77bba625d7
@ -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">
|
||||||
|
@ -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">
|
||||||
|
17
src/inet.c
17
src/inet.c
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
52
src/tcp.c
52
src/tcp.c
@ -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) {
|
||||||
|
52
src/udp.c
52
src/udp.c
@ -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) {
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user