mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-11-19 11:48:21 +01:00
Fixed inet_pton and a new Winsock UDP bug.
inet_pton was copying the entire sockaddr_in struct, rather than just the sin_addr field... I am a bit unsure about the UDP fix, because it may affect TCP as well. On UDP sockets, when a sendto fails, the next receive/receivefrom fails with CONNRESET. I changed sock_recv/sock_recvfrom in wsocket.c to skip the CONNRESET from the recv/recvfrom, hoping that if the socket is TCP, sock_waitfd will get the CONNRESET again. The tests pass, but this should be tested more thoroughly.
This commit is contained in:
parent
66cd8cfcee
commit
734cc23e1f
17
src/inet.c
17
src/inet.c
@ -558,18 +558,23 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
|
||||
|
||||
int inet_pton(int af, const char *src, void *dst)
|
||||
{
|
||||
struct addrinfo hints, *res, *ressave;
|
||||
struct addrinfo hints, *res;
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = af;
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
if (getaddrinfo(src, NULL, &hints, &res) != 0) {
|
||||
return -1;
|
||||
}
|
||||
ressave = res;
|
||||
while (res) {
|
||||
memcpy(dst, res->ai_addr, res->ai_addrlen);
|
||||
res = res->ai_next;
|
||||
if (af == AF_INET) {
|
||||
struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr;
|
||||
memcpy(dst, &in->sin_addr, sizeof(in->sin_addr));
|
||||
} else if (af == AF_INET6) {
|
||||
struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr;
|
||||
memcpy(dst, &in->sin6_addr, sizeof(in->sin6_addr));
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
freeaddrinfo(ressave);
|
||||
freeaddrinfo(res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,8 @@ static int meth_receivefrom(lua_State *L) {
|
||||
socklen_t addr_len = sizeof(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. */
|
||||
/* Unlike TCP, recv() of zero is not closed,
|
||||
* but a zero-length packet. */
|
||||
if (err == IO_CLOSED)
|
||||
err = IO_DONE;
|
||||
if (err == IO_DONE) {
|
||||
@ -257,7 +258,8 @@ static int meth_receivefrom(lua_State *L) {
|
||||
socklen_t addr_len = sizeof(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. */
|
||||
/* Unlike TCP, recv() of zero is not closed,
|
||||
* but a zero-length packet. */
|
||||
if (err == IO_CLOSED)
|
||||
err = IO_DONE;
|
||||
if (err == IO_DONE) {
|
||||
|
@ -250,7 +250,11 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm
|
||||
}
|
||||
if (taken == 0) return IO_CLOSED;
|
||||
err = WSAGetLastError();
|
||||
if (err != WSAEWOULDBLOCK) return err;
|
||||
/* On Windows, and on UDP, a connreset simply means the
|
||||
* previous send failed. On TCP, it means our socket
|
||||
* is now useless, so the error must pass. I am
|
||||
* hoping waitfd will still get the error. */
|
||||
if (err != WSAEWOULDBLOCK && err != WSAECONNRESET) return err;
|
||||
if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
|
||||
}
|
||||
}
|
||||
@ -271,7 +275,11 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
|
||||
}
|
||||
if (taken == 0) return IO_CLOSED;
|
||||
err = WSAGetLastError();
|
||||
if (err != WSAEWOULDBLOCK) return err;
|
||||
/* On Windows, and on UDP, a connreset simply means the
|
||||
* previous send failed. On TCP, it means our socket
|
||||
* is now useless, so the error must pass. I am
|
||||
* hoping waitfd will still get the error. */
|
||||
if (err != WSAEWOULDBLOCK && err != WSAECONNRESET) return err;
|
||||
if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user