diff options
| author | moteus <mimir@newmail.ru> | 2013-05-28 14:06:18 +0400 |
|---|---|---|
| committer | moteus <mimir@newmail.ru> | 2013-05-28 14:06:18 +0400 |
| commit | 5167ddaf499cf198b10208a2f76c27629e99ae1b (patch) | |
| tree | 193b3a7199ad5b0cfbe8a0d02e5fa469394608b6 /src | |
| parent | 45ff0e17753201f4c42c714fdc28898c73e59eb9 (diff) | |
| parent | 2d51d6168874cdb2b72ee4f56f414d9a9a9d92e5 (diff) | |
| download | luasocket-5167ddaf499cf198b10208a2f76c27629e99ae1b.tar.gz luasocket-5167ddaf499cf198b10208a2f76c27629e99ae1b.tar.bz2 luasocket-5167ddaf499cf198b10208a2f76c27629e99ae1b.zip | |
Merge branch 'unstable' of git://github.com/diegonehab/luasocket into moteus-lua52
Diffstat (limited to 'src')
| -rw-r--r-- | src/inet.c | 78 | ||||
| -rw-r--r-- | src/inet.h | 7 | ||||
| -rw-r--r-- | src/io.h | 2 | ||||
| -rw-r--r-- | src/makefile | 41 | ||||
| -rw-r--r-- | src/udp.c | 122 | ||||
| -rw-r--r-- | src/wsocket.c | 29 |
6 files changed, 145 insertions, 134 deletions
| @@ -79,24 +79,22 @@ static int inet_global_tohostname(lua_State *L) { | |||
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static int inet_global_getnameinfo(lua_State *L) { | 81 | static int inet_global_getnameinfo(lua_State *L) { |
| 82 | char hbuf[NI_MAXHOST]; | ||
| 83 | char sbuf[NI_MAXSERV]; | ||
| 82 | int i, ret; | 84 | int i, ret; |
| 83 | char host[1024]; | ||
| 84 | char serv[32]; | ||
| 85 | struct addrinfo hints; | 85 | struct addrinfo hints; |
| 86 | struct addrinfo *resolved, *iter; | 86 | struct addrinfo *resolved, *iter; |
| 87 | const char *node = luaL_optstring(L, 1, NULL); | 87 | const char *host = luaL_optstring(L, 1, NULL); |
| 88 | const char *service = luaL_optstring(L, 2, NULL); | 88 | const char *serv = luaL_optstring(L, 2, NULL); |
| 89 | 89 | ||
| 90 | if (!(node || service)) | 90 | if (!(host || serv)) |
| 91 | luaL_error(L, "You have to specify a hostname, a service, or both"); | 91 | luaL_error(L, "host and serv cannot be both nil"); |
| 92 | 92 | ||
| 93 | memset(&hints, 0, sizeof(hints)); | 93 | memset(&hints, 0, sizeof(hints)); |
| 94 | hints.ai_socktype = SOCK_STREAM; | 94 | hints.ai_socktype = SOCK_STREAM; |
| 95 | hints.ai_family = PF_UNSPEC; | 95 | hints.ai_family = PF_UNSPEC; |
| 96 | 96 | ||
| 97 | /* getaddrinfo must get a node and a service argument */ | 97 | ret = getaddrinfo(host, serv, &hints, &resolved); |
| 98 | ret = getaddrinfo(node ? node : "127.0.0.1", service ? service : "7", | ||
| 99 | &hints, &resolved); | ||
| 100 | if (ret != 0) { | 98 | if (ret != 0) { |
| 101 | lua_pushnil(L); | 99 | lua_pushnil(L); |
| 102 | lua_pushstring(L, socket_gaistrerror(ret)); | 100 | lua_pushstring(L, socket_gaistrerror(ret)); |
| @@ -105,19 +103,19 @@ static int inet_global_getnameinfo(lua_State *L) { | |||
| 105 | 103 | ||
| 106 | lua_newtable(L); | 104 | lua_newtable(L); |
| 107 | for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) { | 105 | for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) { |
| 108 | getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, host, | 106 | getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, |
| 109 | node ? (socklen_t) sizeof(host) : 0, serv, service ? (socklen_t) sizeof(serv) : 0, 0); | 107 | hbuf, host? (socklen_t) sizeof(hbuf): 0, |
| 110 | 108 | sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0); | |
| 111 | if (node) { | 109 | if (host) { |
| 112 | lua_pushnumber(L, i); | 110 | lua_pushnumber(L, i); |
| 113 | lua_pushstring(L, host); | 111 | lua_pushstring(L, hbuf); |
| 114 | lua_settable(L, -3); | 112 | lua_settable(L, -3); |
| 115 | } | 113 | } |
| 116 | } | 114 | } |
| 117 | freeaddrinfo(resolved); | 115 | freeaddrinfo(resolved); |
| 118 | 116 | ||
| 119 | if (service) { | 117 | if (serv) { |
| 120 | lua_pushstring(L, serv); | 118 | lua_pushstring(L, sbuf); |
| 121 | return 2; | 119 | return 2; |
| 122 | } else { | 120 | } else { |
| 123 | return 1; | 121 | return 1; |
| @@ -176,20 +174,10 @@ static int inet_global_getaddrinfo(lua_State *L) | |||
| 176 | } | 174 | } |
| 177 | lua_newtable(L); | 175 | lua_newtable(L); |
| 178 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { | 176 | for (iterator = resolved; iterator; iterator = iterator->ai_next) { |
| 179 | char hbuf[NI_MAXHOST] | 177 | char hbuf[NI_MAXHOST]; |
| 180 | #ifndef _WINDOWS | 178 | ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, |
| 181 | ,sbuf[NI_MAXSERV] | 179 | hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST); |
| 182 | #endif | 180 | if (ret){ |
| 183 | ; | ||
| 184 | ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, hbuf, | ||
| 185 | (socklen_t) sizeof(hbuf), | ||
| 186 | #ifdef _WINDOWS | ||
| 187 | NULL, 0, | ||
| 188 | #else | ||
| 189 | sbuf, 0, | ||
| 190 | #endif | ||
| 191 | NI_NUMERICHOST); | ||
| 192 | if(ret){ | ||
| 193 | lua_pushnil(L); | 181 | lua_pushnil(L); |
| 194 | lua_pushstring(L, socket_gaistrerror(ret)); | 182 | lua_pushstring(L, socket_gaistrerror(ret)); |
| 195 | return 2; | 183 | return 2; |
| @@ -218,7 +206,6 @@ static int inet_global_getaddrinfo(lua_State *L) | |||
| 218 | return 1; | 206 | return 1; |
| 219 | } | 207 | } |
| 220 | 208 | ||
| 221 | |||
| 222 | /*-------------------------------------------------------------------------*\ | 209 | /*-------------------------------------------------------------------------*\ |
| 223 | * Gets the host name | 210 | * Gets the host name |
| 224 | \*-------------------------------------------------------------------------*/ | 211 | \*-------------------------------------------------------------------------*/ |
| @@ -237,7 +224,6 @@ static int inet_global_gethostname(lua_State *L) | |||
| 237 | } | 224 | } |
| 238 | 225 | ||
| 239 | 226 | ||
| 240 | |||
| 241 | /*=========================================================================*\ | 227 | /*=========================================================================*\ |
| 242 | * Lua methods | 228 | * Lua methods |
| 243 | \*=========================================================================*/ | 229 | \*=========================================================================*/ |
| @@ -520,7 +506,7 @@ const char *inet_trybind(p_socket ps, const char *address, const char *serv, | |||
| 520 | * Some systems do not provide this so that we provide our own. It's not | 506 | * Some systems do not provide this so that we provide our own. It's not |
| 521 | * marvelously fast, but it works just fine. | 507 | * marvelously fast, but it works just fine. |
| 522 | \*-------------------------------------------------------------------------*/ | 508 | \*-------------------------------------------------------------------------*/ |
| 523 | #ifdef INET_ATON | 509 | #ifdef LUASOCKET_INET_ATON |
| 524 | int inet_aton(const char *cp, struct in_addr *inp) | 510 | int inet_aton(const char *cp, struct in_addr *inp) |
| 525 | { | 511 | { |
| 526 | unsigned int a = 0, b = 0, c = 0, d = 0; | 512 | unsigned int a = 0, b = 0, c = 0, d = 0; |
| @@ -547,7 +533,7 @@ int inet_aton(const char *cp, struct in_addr *inp) | |||
| 547 | * http://mingw-users.1079350.n2.nabble.com/IPv6-getaddrinfo-amp-inet-ntop-td5891996.html | 533 | * http://mingw-users.1079350.n2.nabble.com/IPv6-getaddrinfo-amp-inet-ntop-td5891996.html |
| 548 | \*-------------------------------------------------------------------------*/ | 534 | \*-------------------------------------------------------------------------*/ |
| 549 | 535 | ||
| 550 | #ifdef INET_PTON | 536 | #ifdef LUASOCKET_INET_PTON |
| 551 | const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) | 537 | const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) |
| 552 | { | 538 | { |
| 553 | if (af == AF_INET) { | 539 | if (af == AF_INET) { |
| @@ -572,19 +558,23 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) | |||
| 572 | 558 | ||
| 573 | int inet_pton(int af, const char *src, void *dst) | 559 | int inet_pton(int af, const char *src, void *dst) |
| 574 | { | 560 | { |
| 575 | struct addrinfo hints, *res, *ressave; | 561 | struct addrinfo hints, *res; |
| 562 | int ret = 1; | ||
| 576 | memset(&hints, 0, sizeof(struct addrinfo)); | 563 | memset(&hints, 0, sizeof(struct addrinfo)); |
| 577 | hints.ai_family = af; | 564 | hints.ai_family = af; |
| 578 | if (getaddrinfo(src, NULL, &hints, &res) != 0) { | 565 | hints.ai_flags = AI_NUMERICHOST; |
| 579 | return -1; | 566 | if (getaddrinfo(src, NULL, &hints, &res) != 0) return -1; |
| 580 | } | 567 | if (af == AF_INET) { |
| 581 | ressave = res; | 568 | struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr; |
| 582 | while (res) { | 569 | memcpy(dst, &in->sin_addr, sizeof(in->sin_addr)); |
| 583 | memcpy(dst, res->ai_addr, res->ai_addrlen); | 570 | } else if (af == AF_INET6) { |
| 584 | res = res->ai_next; | 571 | struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr; |
| 572 | memcpy(dst, &in->sin6_addr, sizeof(in->sin6_addr)); | ||
| 573 | } else { | ||
| 574 | ret = -1; | ||
| 585 | } | 575 | } |
| 586 | freeaddrinfo(ressave); | 576 | freeaddrinfo(res); |
| 587 | return 0; | 577 | return ret; |
| 588 | } | 578 | } |
| 589 | 579 | ||
| 590 | #endif | 580 | #endif |
| @@ -19,8 +19,7 @@ | |||
| 19 | #include "timeout.h" | 19 | #include "timeout.h" |
| 20 | 20 | ||
| 21 | #ifdef _WIN32 | 21 | #ifdef _WIN32 |
| 22 | #define INET_ATON | 22 | #define LUASOCKET_INET_ATON |
| 23 | #define INET_PTON | ||
| 24 | #endif | 23 | #endif |
| 25 | 24 | ||
| 26 | int inet_open(lua_State *L); | 25 | int inet_open(lua_State *L); |
| @@ -39,11 +38,11 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family); | |||
| 39 | int inet_optfamily(lua_State* L, int narg, const char* def); | 38 | int inet_optfamily(lua_State* L, int narg, const char* def); |
| 40 | int inet_optsocktype(lua_State* L, int narg, const char* def); | 39 | int inet_optsocktype(lua_State* L, int narg, const char* def); |
| 41 | 40 | ||
| 42 | #ifdef INET_ATON | 41 | #ifdef LUASOCKET_INET_ATON |
| 43 | int inet_aton(const char *cp, struct in_addr *inp); | 42 | int inet_aton(const char *cp, struct in_addr *inp); |
| 44 | #endif | 43 | #endif |
| 45 | 44 | ||
| 46 | #ifdef INET_PTON | 45 | #ifdef LUASOCKET_INET_PTON |
| 47 | const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt); | 46 | const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt); |
| 48 | int inet_pton(int af, const char *src, void *dst); | 47 | int inet_pton(int af, const char *src, void *dst); |
| 49 | #endif | 48 | #endif |
| @@ -22,7 +22,7 @@ enum { | |||
| 22 | IO_DONE = 0, /* operation completed successfully */ | 22 | IO_DONE = 0, /* operation completed successfully */ |
| 23 | IO_TIMEOUT = -1, /* operation timed out */ | 23 | IO_TIMEOUT = -1, /* operation timed out */ |
| 24 | IO_CLOSED = -2, /* the connection has been closed */ | 24 | IO_CLOSED = -2, /* the connection has been closed */ |
| 25 | IO_UNKNOWN = -3 | 25 | IO_UNKNOWN = -3 |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | /* interface to error message function */ | 28 | /* interface to error message function */ |
diff --git a/src/makefile b/src/makefile index fbb26a0..94a2f9f 100644 --- a/src/makefile +++ b/src/makefile | |||
| @@ -63,12 +63,13 @@ LDIR_mingw?=lua/$(LUAV)/lua | |||
| 63 | # LUAINC_win32: | 63 | # LUAINC_win32: |
| 64 | # LUALIB_win32: | 64 | # LUALIB_win32: |
| 65 | # where lua headers and libraries are found for win32 builds | 65 | # where lua headers and libraries are found for win32 builds |
| 66 | LUAINC_win32?="../../lua-5.1.3/src" | 66 | LUAINC_win32_base?= |
| 67 | LUALIB_win32?=/LIBPATH:"../../lua-5.1.3" lua$(LUAV).lib | 67 | LUAINC_win32?=$(LUAINC_win32_base)/lua/$(LUAV) |
| 68 | 68 | PLATFORM_win32?=Release | |
| 69 | LUAPREFIX_win32?= | 69 | LUAPREFIX_win32?= |
| 70 | CDIR_win32?=lua/$(LUAV) | 70 | CDIR_win32?=lua/$(LUAV)/$(PLATFORM_win32) |
| 71 | LDIR_win32?=lua/$(LUAV)/lua | 71 | LDIR_win32?=lua/$(LUAV)/$(PLATFORM_win32)/lua |
| 72 | LUALIB_win32?=$(LUAPREFIX_win32)/lua/$(LUAV)/$(PLATFORM_win32) | ||
| 72 | 73 | ||
| 73 | # prefix: /usr/local /usr /opt/local /sw | 74 | # prefix: /usr/local /usr /opt/local /sw |
| 74 | # the top of the default install tree | 75 | # the top of the default install tree |
| @@ -154,12 +155,12 @@ SOCKET_linux=usocket.o | |||
| 154 | SO_mingw=dll | 155 | SO_mingw=dll |
| 155 | O_mingw=o | 156 | O_mingw=o |
| 156 | CC_mingw=gcc | 157 | CC_mingw=gcc |
| 157 | DEF_mingw= -DLUASOCKET_$(DEBUG) -DLUA_COMPAT_MODULE -DWINVER=0x0501 \ | 158 | DEF_mingw= -DLUASOCKET_INET_PTON -DLUASOCKET_$(DEBUG) -DLUA_COMPAT_MODULE \ |
| 158 | -DLUASOCKET_API='__declspec(dllexport)' \ | 159 | -DWINVER=0x0501 -DLUASOCKET_API='__declspec(dllexport)' \ |
| 159 | -DMIME_API='__declspec(dllexport)' | 160 | -DMIME_API='__declspec(dllexport)' |
| 160 | CFLAGS_mingw= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fno-common \ | 161 | CFLAGS_mingw= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fno-common \ |
| 161 | -fvisibility=hidden | 162 | -fvisibility=hidden |
| 162 | LDFLAGS_mingw= $(LUALIB) -shared -Wl,-s -lwsock32 -lws2_32 -o | 163 | LDFLAGS_mingw= $(LUALIB) -shared -Wl,-s -lws2_32 -o |
| 163 | LD_mingw=gcc | 164 | LD_mingw=gcc |
| 164 | SOCKET_mingw=wsocket.o | 165 | SOCKET_mingw=wsocket.o |
| 165 | 166 | ||
| @@ -170,23 +171,25 @@ SOCKET_mingw=wsocket.o | |||
| 170 | SO_win32=dll | 171 | SO_win32=dll |
| 171 | O_win32=obj | 172 | O_win32=obj |
| 172 | CC_win32=cl | 173 | CC_win32=cl |
| 173 | DEF_win32= /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" \ | 174 | DEF_win32= //D "WIN32" //D "NDEBUG" //D "_WINDOWS" //D "_USRDLL" \ |
| 174 | /D "LUASOCKET_API=__declspec(dllexport)" /D "_CRT_SECURE_NO_WARNINGS" \ | 175 | //D "LUASOCKET_API=__declspec(dllexport)" //D "_CRT_SECURE_NO_WARNINGS" \ |
| 175 | /D "_WINDLL" /D "LUA_COMPAT_MODULE" /D "MIME_API=__declspec(dllexport)" \ | 176 | //D "_WINDLL" //D "LUA_COMPAT_MODULE" \ |
| 176 | /D "LUASOCKET_$(DEBUG)" | 177 | //D "MIME_API=__declspec(dllexport)" \ |
| 177 | CFLAGS_win32=/I "$(LUAINC)" $(DEF) /O2 /Ot /MD /W3 /nologo | 178 | //D "LUASOCKET_$(DEBUG)" |
| 178 | LDFLAGS_win32= /nologo /link /NOLOGO /DLL /INCREMENTAL:NO \ | 179 | CFLAGS_win32=//I "$(LUAINC)" $(DEF) //O2 //Ot //MD //W3 //nologo |
| 179 | /MANIFEST /MANIFESTFILE:"intermediate.manifest" \ | 180 | LDFLAGS_win32= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \ |
| 180 | /MANIFESTUAC:"level='asInvoker' uiAccess='false'" \ | 181 | //MANIFEST //MANIFESTFILE:"intermediate.manifest" \ |
| 181 | /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /DYNAMICBASE:NO \ | 182 | //MANIFESTUAC:"level='asInvoker' uiAccess='false'" \ |
| 182 | /MACHINE:X86 $(LUALIB) ws2_32.lib /OUT: | 183 | //SUBSYSTEM:WINDOWS //OPT:REF //OPT:ICF //DYNAMICBASE:NO \ |
| 184 | //MACHINE:X86 /LIBPATH:"$(shell cmd //c echo $(LUALIB))" \ | ||
| 185 | lua$(subst .,,$(LUAV)).lib ws2_32.lib //OUT: | ||
| 183 | LD_win32=cl | 186 | LD_win32=cl |
| 184 | SOCKET_win32=wsocket.obj | 187 | SOCKET_win32=wsocket.obj |
| 185 | 188 | ||
| 186 | .SUFFIXES: .obj | 189 | .SUFFIXES: .obj |
| 187 | 190 | ||
| 188 | .c.obj: | 191 | .c.obj: |
| 189 | $(CC) $(CFLAGS) /Fo"$@" /c $< | 192 | $(CC) $(CFLAGS) //Fo"$@" //c $< |
| 190 | 193 | ||
| 191 | #------ | 194 | #------ |
| 192 | # Output file names | 195 | # Output file names |
| @@ -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)) | 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)) | 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 | } |
diff --git a/src/wsocket.c b/src/wsocket.c index 65f76bc..b4a4384 100644 --- a/src/wsocket.c +++ b/src/wsocket.c | |||
| @@ -238,8 +238,10 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, | |||
| 238 | /*-------------------------------------------------------------------------*\ | 238 | /*-------------------------------------------------------------------------*\ |
| 239 | * Receive with timeout | 239 | * Receive with timeout |
| 240 | \*-------------------------------------------------------------------------*/ | 240 | \*-------------------------------------------------------------------------*/ |
| 241 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) { | 241 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, |
| 242 | int err; | 242 | p_timeout tm) |
| 243 | { | ||
| 244 | int err, prev = IO_DONE; | ||
| 243 | *got = 0; | 245 | *got = 0; |
| 244 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | 246 | if (*ps == SOCKET_INVALID) return IO_CLOSED; |
| 245 | for ( ;; ) { | 247 | for ( ;; ) { |
| @@ -250,7 +252,14 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm | |||
| 250 | } | 252 | } |
| 251 | if (taken == 0) return IO_CLOSED; | 253 | if (taken == 0) return IO_CLOSED; |
| 252 | err = WSAGetLastError(); | 254 | err = WSAGetLastError(); |
| 253 | if (err != WSAEWOULDBLOCK) return err; | 255 | /* On UDP, a connreset simply means the previous send failed. |
| 256 | * So we try again. | ||
| 257 | * On TCP, it means our socket is now useless, so the error passes. | ||
| 258 | * (We will loop again, exiting because the same error will happen) */ | ||
| 259 | if (err != WSAEWOULDBLOCK) { | ||
| 260 | if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; | ||
| 261 | prev = err; | ||
| 262 | } | ||
| 254 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | 263 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; |
| 255 | } | 264 | } |
| 256 | } | 265 | } |
| @@ -259,8 +268,9 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm | |||
| 259 | * Recvfrom with timeout | 268 | * Recvfrom with timeout |
| 260 | \*-------------------------------------------------------------------------*/ | 269 | \*-------------------------------------------------------------------------*/ |
| 261 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, | 270 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, |
| 262 | SA *addr, socklen_t *len, p_timeout tm) { | 271 | SA *addr, socklen_t *len, p_timeout tm) |
| 263 | int err; | 272 | { |
| 273 | int err, prev = IO_DONE; | ||
| 264 | *got = 0; | 274 | *got = 0; |
| 265 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | 275 | if (*ps == SOCKET_INVALID) return IO_CLOSED; |
| 266 | for ( ;; ) { | 276 | for ( ;; ) { |
| @@ -271,7 +281,14 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, | |||
| 271 | } | 281 | } |
| 272 | if (taken == 0) return IO_CLOSED; | 282 | if (taken == 0) return IO_CLOSED; |
| 273 | err = WSAGetLastError(); | 283 | err = WSAGetLastError(); |
| 274 | if (err != WSAEWOULDBLOCK) return err; | 284 | /* On UDP, a connreset simply means the previous send failed. |
| 285 | * So we try again. | ||
| 286 | * On TCP, it means our socket is now useless, so the error passes. | ||
| 287 | * (We will loop again, exiting because the same error will happen) */ | ||
| 288 | if (err != WSAEWOULDBLOCK) { | ||
| 289 | if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; | ||
| 290 | prev = err; | ||
| 291 | } | ||
| 275 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | 292 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; |
| 276 | } | 293 | } |
| 277 | } | 294 | } |
