diff options
| author | unknown <diego.nehab@gmail.com> | 2013-05-28 00:09:30 +0800 |
|---|---|---|
| committer | unknown <diego.nehab@gmail.com> | 2013-05-28 00:09:30 +0800 |
| commit | 734cc23e1f03372314ebad07ffd35117c152afcd (patch) | |
| tree | 808531d9c0c84aae57657aff353b08d466a3dcfb /src/udp.c | |
| parent | 66cd8cfcee1f14b59450147c16a6bc44ef298edc (diff) | |
| download | luasocket-734cc23e1f03372314ebad07ffd35117c152afcd.tar.gz luasocket-734cc23e1f03372314ebad07ffd35117c152afcd.tar.bz2 luasocket-734cc23e1f03372314ebad07ffd35117c152afcd.zip | |
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.
Diffstat (limited to 'src/udp.c')
| -rw-r--r-- | src/udp.c | 122 |
1 files changed, 62 insertions, 60 deletions
| @@ -155,31 +155,31 @@ static int meth_sendto(lua_State *L) { | |||
| 155 | p_timeout tm = &udp->tm; | 155 | p_timeout tm = &udp->tm; |
| 156 | int err; | 156 | int err; |
| 157 | switch (udp->family) { | 157 | switch (udp->family) { |
| 158 | case PF_INET: { | 158 | case PF_INET: { |
| 159 | struct sockaddr_in addr; | 159 | struct sockaddr_in addr; |
| 160 | memset(&addr, 0, sizeof(addr)); | 160 | memset(&addr, 0, sizeof(addr)); |
| 161 | if (inet_pton(AF_INET, ip, &addr.sin_addr) != 1) | 161 | if (inet_pton(AF_INET, ip, &addr.sin_addr) != 1) |
| 162 | luaL_argerror(L, 3, "invalid ip address"); | 162 | luaL_argerror(L, 3, "invalid ip address"); |
| 163 | addr.sin_family = AF_INET; | 163 | addr.sin_family = AF_INET; |
| 164 | addr.sin_port = htons(port); | 164 | addr.sin_port = htons(port); |
| 165 | timeout_markstart(tm); | 165 | timeout_markstart(tm); |
| 166 | err = socket_sendto(&udp->sock, data, count, &sent, | 166 | err = socket_sendto(&udp->sock, data, count, &sent, |
| 167 | (SA *) &addr, sizeof(addr), tm); | 167 | (SA *) &addr, sizeof(addr), tm); |
| 168 | break; | 168 | break; |
| 169 | } | 169 | } |
| 170 | case PF_INET6: { | 170 | case PF_INET6: { |
| 171 | struct sockaddr_in6 addr; | 171 | struct sockaddr_in6 addr; |
| 172 | memset(&addr, 0, sizeof(addr)); | 172 | memset(&addr, 0, sizeof(addr)); |
| 173 | if (!inet_pton(AF_INET6, ip, &addr.sin6_addr) != 1) | 173 | if (!inet_pton(AF_INET6, ip, &addr.sin6_addr) != 1) |
| 174 | luaL_argerror(L, 3, "invalid ip address"); | 174 | luaL_argerror(L, 3, "invalid ip address"); |
| 175 | addr.sin6_family = AF_INET6; | 175 | addr.sin6_family = AF_INET6; |
| 176 | addr.sin6_port = htons(port); | 176 | addr.sin6_port = htons(port); |
| 177 | timeout_markstart(tm); | 177 | timeout_markstart(tm); |
| 178 | err = socket_sendto(&udp->sock, data, count, &sent, | 178 | err = socket_sendto(&udp->sock, data, count, &sent, |
| 179 | (SA *) &addr, sizeof(addr), tm); | 179 | (SA *) &addr, sizeof(addr), tm); |
| 180 | break; | 180 | break; |
| 181 | } | 181 | } |
| 182 | default: | 182 | default: |
| 183 | lua_pushnil(L); | 183 | lua_pushnil(L); |
| 184 | lua_pushfstring(L, "unknown family %d", udp->family); | 184 | lua_pushfstring(L, "unknown family %d", udp->family); |
| 185 | return 2; | 185 | return 2; |
| @@ -229,38 +229,40 @@ static int meth_receivefrom(lua_State *L) { | |||
| 229 | timeout_markstart(tm); | 229 | timeout_markstart(tm); |
| 230 | count = MIN(count, sizeof(buffer)); | 230 | count = MIN(count, sizeof(buffer)); |
| 231 | switch (udp->family) { | 231 | switch (udp->family) { |
| 232 | case PF_INET: { | 232 | case PF_INET: { |
| 233 | struct sockaddr_in addr; | 233 | struct sockaddr_in addr; |
| 234 | socklen_t addr_len = sizeof(addr); | 234 | socklen_t addr_len = sizeof(addr); |
| 235 | err = socket_recvfrom(&udp->sock, buffer, count, &got, | 235 | err = socket_recvfrom(&udp->sock, buffer, count, &got, |
| 236 | (SA *) &addr, &addr_len, tm); | 236 | (SA *) &addr, &addr_len, tm); |
| 237 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ | 237 | /* Unlike TCP, recv() of zero is not closed, |
| 238 | if (err == IO_CLOSED) | 238 | * but a zero-length packet. */ |
| 239 | err = IO_DONE; | 239 | if (err == IO_CLOSED) |
| 240 | if (err == IO_DONE) { | 240 | err = IO_DONE; |
| 241 | char addrstr[INET_ADDRSTRLEN]; | 241 | if (err == IO_DONE) { |
| 242 | lua_pushlstring(L, buffer, got); | 242 | char addrstr[INET_ADDRSTRLEN]; |
| 243 | if (!inet_ntop(AF_INET, &addr.sin_addr, | 243 | lua_pushlstring(L, buffer, got); |
| 244 | addrstr, sizeof(addrstr))) { | 244 | if (!inet_ntop(AF_INET, &addr.sin_addr, |
| 245 | lua_pushnil(L); | 245 | addrstr, sizeof(addrstr))) { |
| 246 | lua_pushstring(L, "invalid source address"); | 246 | lua_pushnil(L); |
| 247 | return 2; | 247 | lua_pushstring(L, "invalid source address"); |
| 248 | } | 248 | return 2; |
| 249 | lua_pushstring(L, addrstr); | 249 | } |
| 250 | lua_pushnumber(L, ntohs(addr.sin_port)); | 250 | lua_pushstring(L, addrstr); |
| 251 | return 3; | 251 | lua_pushnumber(L, ntohs(addr.sin_port)); |
| 252 | } | 252 | return 3; |
| 253 | break; | 253 | } |
| 254 | } | 254 | break; |
| 255 | case PF_INET6: { | 255 | } |
| 256 | struct sockaddr_in6 addr; | 256 | case PF_INET6: { |
| 257 | socklen_t addr_len = sizeof(addr); | 257 | struct sockaddr_in6 addr; |
| 258 | err = socket_recvfrom(&udp->sock, buffer, count, &got, | 258 | socklen_t addr_len = sizeof(addr); |
| 259 | (SA *) &addr, &addr_len, tm); | 259 | err = socket_recvfrom(&udp->sock, buffer, count, &got, |
| 260 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ | 260 | (SA *) &addr, &addr_len, tm); |
| 261 | if (err == IO_CLOSED) | 261 | /* Unlike TCP, recv() of zero is not closed, |
| 262 | * but a zero-length packet. */ | ||
| 263 | if (err == IO_CLOSED) | ||
| 262 | err = IO_DONE; | 264 | err = IO_DONE; |
| 263 | if (err == IO_DONE) { | 265 | if (err == IO_DONE) { |
| 264 | char addrstr[INET6_ADDRSTRLEN]; | 266 | char addrstr[INET6_ADDRSTRLEN]; |
| 265 | lua_pushlstring(L, buffer, got); | 267 | lua_pushlstring(L, buffer, got); |
| 266 | if (!inet_ntop(AF_INET6, &addr.sin6_addr, | 268 | if (!inet_ntop(AF_INET6, &addr.sin6_addr, |
| @@ -272,9 +274,9 @@ static int meth_receivefrom(lua_State *L) { | |||
| 272 | lua_pushstring(L, addrstr); | 274 | lua_pushstring(L, addrstr); |
| 273 | lua_pushnumber(L, ntohs(addr.sin6_port)); | 275 | lua_pushnumber(L, ntohs(addr.sin6_port)); |
| 274 | return 3; | 276 | return 3; |
| 275 | } | 277 | } |
| 276 | break; | 278 | break; |
| 277 | } | 279 | } |
| 278 | default: | 280 | default: |
| 279 | lua_pushnil(L); | 281 | lua_pushnil(L); |
| 280 | lua_pushfstring(L, "unknown family %d", udp->family); | 282 | lua_pushfstring(L, "unknown family %d", udp->family); |
| @@ -413,7 +415,7 @@ static int meth_setsockname(lua_State *L) { | |||
| 413 | const char *address = luaL_checkstring(L, 2); | 415 | const char *address = luaL_checkstring(L, 2); |
| 414 | const char *port = luaL_checkstring(L, 3); | 416 | const char *port = luaL_checkstring(L, 3); |
| 415 | const char *err; | 417 | const char *err; |
| 416 | struct addrinfo bindhints; | 418 | struct addrinfo bindhints; |
| 417 | memset(&bindhints, 0, sizeof(bindhints)); | 419 | memset(&bindhints, 0, sizeof(bindhints)); |
| 418 | bindhints.ai_socktype = SOCK_DGRAM; | 420 | bindhints.ai_socktype = SOCK_DGRAM; |
| 419 | bindhints.ai_family = udp->family; | 421 | bindhints.ai_family = udp->family; |
| @@ -461,9 +463,9 @@ static int udp_create(lua_State *L, int family) { | |||
| 461 | } | 463 | } |
| 462 | 464 | ||
| 463 | static int global_create(lua_State *L) { | 465 | static int global_create(lua_State *L) { |
| 464 | return udp_create(L, AF_INET); | 466 | return udp_create(L, AF_INET); |
| 465 | } | 467 | } |
| 466 | 468 | ||
| 467 | static int global_create6(lua_State *L) { | 469 | static int global_create6(lua_State *L) { |
| 468 | return udp_create(L, AF_INET6); | 470 | return udp_create(L, AF_INET6); |
| 469 | } | 471 | } |
