mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-11-08 14:28: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.
|
||||
</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 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<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.
|
||||
</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 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<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
|
||||
\*-------------------------------------------------------------------------*/
|
||||
const char *inet_trycreate(p_socket ps, int family, int type) {
|
||||
return socket_strerror(socket_create(ps, family, type, 0));
|
||||
const char *inet_trycreate(p_socket ps, int family, int type, int protocol) {
|
||||
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. */
|
||||
if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
|
||||
socket_destroy(ps);
|
||||
err = socket_strerror(socket_create(ps, iterator->ai_family,
|
||||
iterator->ai_socktype, iterator->ai_protocol));
|
||||
err = inet_trycreate(ps, iterator->ai_family,
|
||||
iterator->ai_socktype, iterator->ai_protocol);
|
||||
if (err) continue;
|
||||
current_family = iterator->ai_family;
|
||||
/* 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) {
|
||||
if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
|
||||
socket_destroy(ps);
|
||||
err = socket_strerror(socket_create(ps, iterator->ai_family,
|
||||
iterator->ai_socktype, iterator->ai_protocol));
|
||||
err = inet_trycreate(ps, iterator->ai_family,
|
||||
iterator->ai_socktype, iterator->ai_protocol);
|
||||
if (err) continue;
|
||||
current_family = iterator->ai_family;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
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 *serv, p_timeout tm, struct addrinfo *connecthints);
|
||||
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
|
||||
\*-------------------------------------------------------------------------*/
|
||||
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));
|
||||
memset(tcp, 0, sizeof(t_tcp));
|
||||
/* set its type as master object */
|
||||
auxiliar_setclass(L, "tcp{master}", -1);
|
||||
/* initialize remaining structure fields */
|
||||
socket_setnonblocking(&sock);
|
||||
if (family == AF_INET6) {
|
||||
int yes = 1;
|
||||
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||
(void *)&yes, sizeof(yes));
|
||||
p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
|
||||
memset(tcp, 0, sizeof(t_tcp));
|
||||
/* set its type as master object */
|
||||
auxiliar_setclass(L, "tcp{master}", -1);
|
||||
/* if family is AF_UNSPEC, we leave the socket invalid and
|
||||
* store AF_UNSPEC into family. This will allow it to later be
|
||||
* replaced with an AF_INET6 or AF_INET socket upon first use. */
|
||||
tcp->sock = SOCKET_INVALID;
|
||||
tcp->family = family;
|
||||
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);
|
||||
if (family != AF_UNSPEC) {
|
||||
const char *err = inet_trycreate(&tcp->sock, family, SOCK_STREAM, 0);
|
||||
if (err != NULL) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, err);
|
||||
return 2;
|
||||
}
|
||||
tcp->sock = 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;
|
||||
socket_setnonblocking(&tcp->sock);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
freeaddrinfo(ai);
|
||||
if (err != IO_DONE) {
|
||||
@ -237,7 +237,7 @@ static int meth_receivefrom(lua_State *L)
|
||||
char portstr[6];
|
||||
timeout_markstart(tm);
|
||||
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);
|
||||
/* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
|
||||
if (err == IO_CLOSED)
|
||||
@ -247,7 +247,7 @@ static int meth_receivefrom(lua_State *L)
|
||||
lua_pushstring(L, udp_strerror(err));
|
||||
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);
|
||||
if (err) {
|
||||
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 */
|
||||
connecthints.ai_family = udp->family;
|
||||
if (connecting) {
|
||||
err = inet_tryconnect(&udp->sock, &udp->family, address,
|
||||
err = inet_tryconnect(&udp->sock, &udp->family, address,
|
||||
port, tm, &connecthints);
|
||||
if (err) {
|
||||
lua_pushnil(L);
|
||||
@ -365,7 +365,6 @@ static int meth_setpeername(lua_State *L) {
|
||||
inet_trydisconnect(&udp->sock, udp->family, tm);
|
||||
auxiliar_setclass(L, "udp{unconnected}", 1);
|
||||
}
|
||||
/* change class to connected or unconnected depending on address */
|
||||
lua_pushnumber(L, 1);
|
||||
return 1;
|
||||
}
|
||||
@ -410,34 +409,25 @@ static int meth_setsockname(lua_State *L) {
|
||||
* Creates a master udp object
|
||||
\*-------------------------------------------------------------------------*/
|
||||
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 */
|
||||
p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
|
||||
auxiliar_setclass(L, "udp{unconnected}", -1);
|
||||
/* initialize remaining structure fields */
|
||||
socket_setnonblocking(&sock);
|
||||
if (family == AF_INET6) {
|
||||
int yes = 1;
|
||||
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||
(void *)&yes, sizeof(yes));
|
||||
/* allocate udp object */
|
||||
p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
|
||||
auxiliar_setclass(L, "udp{unconnected}", -1);
|
||||
/* if family is AF_UNSPEC, we leave the socket invalid and
|
||||
* store AF_UNSPEC into family. This will allow it to later be
|
||||
* replaced with an AF_INET6 or AF_INET socket upon first use. */
|
||||
udp->sock = SOCKET_INVALID;
|
||||
timeout_init(&udp->tm, -1, -1);
|
||||
udp->family = family;
|
||||
if (family != AF_UNSPEC) {
|
||||
const char *err = inet_trycreate(&udp->sock, family, SOCK_DGRAM, 0);
|
||||
if (err != NULL) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, err);
|
||||
return 2;
|
||||
}
|
||||
udp->sock = sock;
|
||||
timeout_init(&udp->tm, -1, -1);
|
||||
udp->family = family;
|
||||
return 1;
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, err);
|
||||
return 2;
|
||||
socket_setnonblocking(&udp->sock);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int global_create(lua_State *L) {
|
||||
|
@ -304,15 +304,20 @@ function isclosed(c)
|
||||
end
|
||||
|
||||
function active_close()
|
||||
reconnect()
|
||||
if isclosed(data) then fail("should not be closed") end
|
||||
data:close()
|
||||
if not isclosed(data) then fail("should be closed") end
|
||||
data = nil
|
||||
local udp = socket.udp()
|
||||
local tcp = socket.tcp4()
|
||||
if isclosed(tcp) then fail("should not be closed") end
|
||||
tcp:close()
|
||||
if not isclosed(tcp) then fail("should be closed") end
|
||||
tcp = socket.tcp()
|
||||
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
|
||||
udp:close()
|
||||
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")
|
||||
end
|
||||
|
||||
@ -368,7 +373,7 @@ function test_selectbugs()
|
||||
pass("invalid input: ok")
|
||||
local toomany = {}
|
||||
for i = 1, socket._SETSIZE+1 do
|
||||
toomany[#toomany+1] = socket.udp()
|
||||
toomany[#toomany+1] = socket.udp4()
|
||||
end
|
||||
if #toomany > socket._SETSIZE then
|
||||
local e = pcall(socket.select, toomany, nil, 0.1)
|
||||
|
Loading…
Reference in New Issue
Block a user