diff options
author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-01-17 00:17:46 +0000 |
---|---|---|
committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-01-17 00:17:46 +0000 |
commit | 076451c75336b30e6152bd5c02f355db39107f7d (patch) | |
tree | 785a6c71ca1e5246f2ce09a9b91f98eb902ac2a0 /src | |
parent | 89f3ecf7820857f91c4039536d2bbe3cf12d5f95 (diff) | |
download | luasocket-076451c75336b30e6152bd5c02f355db39107f7d.tar.gz luasocket-076451c75336b30e6152bd5c02f355db39107f7d.tar.bz2 luasocket-076451c75336b30e6152bd5c02f355db39107f7d.zip |
Tested in windows. Still needs more testing, but progress has been made.
Diffstat (limited to 'src')
-rw-r--r-- | src/inet.h | 4 | ||||
-rw-r--r-- | src/luasocket.h | 2 | ||||
-rw-r--r-- | src/tcp.c | 18 | ||||
-rw-r--r-- | src/timeout.c | 1 | ||||
-rw-r--r-- | src/udp.c | 75 | ||||
-rw-r--r-- | src/usocket.c | 92 | ||||
-rw-r--r-- | src/wsocket.c | 180 |
7 files changed, 224 insertions, 148 deletions
@@ -19,6 +19,10 @@ | |||
19 | #include <lua.h> | 19 | #include <lua.h> |
20 | #include "socket.h" | 20 | #include "socket.h" |
21 | 21 | ||
22 | #ifdef WIN32 | ||
23 | #define INET_ATON | ||
24 | #endif | ||
25 | |||
22 | void inet_open(lua_State *L); | 26 | void inet_open(lua_State *L); |
23 | const char *inet_tryconnect(p_sock ps, const char *address, | 27 | const char *inet_tryconnect(p_sock ps, const char *address, |
24 | unsigned short port); | 28 | unsigned short port); |
diff --git a/src/luasocket.h b/src/luasocket.h index 7756605..ac26824 100644 --- a/src/luasocket.h +++ b/src/luasocket.h | |||
@@ -18,7 +18,9 @@ | |||
18 | /*-------------------------------------------------------------------------*\ | 18 | /*-------------------------------------------------------------------------*\ |
19 | * Library's namespace | 19 | * Library's namespace |
20 | \*-------------------------------------------------------------------------*/ | 20 | \*-------------------------------------------------------------------------*/ |
21 | #ifndef LUASOCKET_LIBNAME | ||
21 | #define LUASOCKET_LIBNAME "socket" | 22 | #define LUASOCKET_LIBNAME "socket" |
23 | #endif | ||
22 | 24 | ||
23 | /*-------------------------------------------------------------------------*\ | 25 | /*-------------------------------------------------------------------------*\ |
24 | * This macro prefixes all exported API functions | 26 | * This macro prefixes all exported API functions |
@@ -36,6 +36,7 @@ static int meth_dirty(lua_State *L); | |||
36 | static int opt_tcp_nodelay(lua_State *L); | 36 | static int opt_tcp_nodelay(lua_State *L); |
37 | static int opt_keepalive(lua_State *L); | 37 | static int opt_keepalive(lua_State *L); |
38 | static int opt_linger(lua_State *L); | 38 | static int opt_linger(lua_State *L); |
39 | static int opt_reuseaddr(lua_State *L); | ||
39 | 40 | ||
40 | /* tcp object methods */ | 41 | /* tcp object methods */ |
41 | static luaL_reg tcp[] = { | 42 | static luaL_reg tcp[] = { |
@@ -61,6 +62,7 @@ static luaL_reg tcp[] = { | |||
61 | /* socket option handlers */ | 62 | /* socket option handlers */ |
62 | static luaL_reg opt[] = { | 63 | static luaL_reg opt[] = { |
63 | {"keepalive", opt_keepalive}, | 64 | {"keepalive", opt_keepalive}, |
65 | {"reuseaddr", opt_reuseaddr}, | ||
64 | {"tcp-nodelay", opt_tcp_nodelay}, | 66 | {"tcp-nodelay", opt_tcp_nodelay}, |
65 | {"linger", opt_linger}, | 67 | {"linger", opt_linger}, |
66 | {NULL, NULL} | 68 | {NULL, NULL} |
@@ -123,7 +125,7 @@ static int meth_setoption(lua_State *L) | |||
123 | 125 | ||
124 | static int opt_boolean(lua_State *L, int level, int name) | 126 | static int opt_boolean(lua_State *L, int level, int name) |
125 | { | 127 | { |
126 | p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1); | 128 | p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); |
127 | int val = aux_checkboolean(L, 2); | 129 | int val = aux_checkboolean(L, 2); |
128 | if (setsockopt(tcp->sock, level, name, (char *) &val, sizeof(val)) < 0) { | 130 | if (setsockopt(tcp->sock, level, name, (char *) &val, sizeof(val)) < 0) { |
129 | lua_pushnil(L); | 131 | lua_pushnil(L); |
@@ -134,16 +136,16 @@ static int opt_boolean(lua_State *L, int level, int name) | |||
134 | return 1; | 136 | return 1; |
135 | } | 137 | } |
136 | 138 | ||
139 | /* enables reuse of local address */ | ||
140 | static int opt_reuseaddr(lua_State *L) | ||
141 | { | ||
142 | return opt_boolean(L, SOL_SOCKET, SO_REUSEADDR); | ||
143 | } | ||
144 | |||
137 | /* disables the Naggle algorithm */ | 145 | /* disables the Naggle algorithm */ |
138 | static int opt_tcp_nodelay(lua_State *L) | 146 | static int opt_tcp_nodelay(lua_State *L) |
139 | { | 147 | { |
140 | struct protoent *pe = getprotobyname("TCP"); | 148 | return opt_boolean(L, IPPROTO_TCP, TCP_NODELAY); |
141 | if (!pe) { | ||
142 | lua_pushnil(L); | ||
143 | lua_pushstring(L, "getprotobyname"); | ||
144 | return 2; | ||
145 | } | ||
146 | return opt_boolean(L, pe->p_proto, TCP_NODELAY); | ||
147 | } | 149 | } |
148 | 150 | ||
149 | static int opt_keepalive(lua_State *L) | 151 | static int opt_keepalive(lua_State *L) |
diff --git a/src/timeout.c b/src/timeout.c index 5d6de99..2d88ded 100644 --- a/src/timeout.c +++ b/src/timeout.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #ifdef WIN32 | 16 | #ifdef WIN32 |
17 | #include <windows.h> | 17 | #include <windows.h> |
18 | #else | 18 | #else |
19 | #include <time.h> | ||
19 | #include <sys/time.h> | 20 | #include <sys/time.h> |
20 | #include <sys/times.h> | 21 | #include <sys/times.h> |
21 | #include <unistd.h> | 22 | #include <unistd.h> |
@@ -35,6 +35,11 @@ static int meth_fd(lua_State *L); | |||
35 | static int meth_dirty(lua_State *L); | 35 | static int meth_dirty(lua_State *L); |
36 | static int opt_dontroute(lua_State *L); | 36 | static int opt_dontroute(lua_State *L); |
37 | static int opt_broadcast(lua_State *L); | 37 | static int opt_broadcast(lua_State *L); |
38 | static int opt_reuseaddr(lua_State *L); | ||
39 | static int opt_ip_multicast_ttl(lua_State *L); | ||
40 | static int opt_ip_multicast_loop(lua_State *L); | ||
41 | static int opt_ip_add_membership(lua_State *L); | ||
42 | static int opt_ip_drop_membersip(lua_State *L); | ||
38 | 43 | ||
39 | /* udp object methods */ | 44 | /* udp object methods */ |
40 | static luaL_reg udp[] = { | 45 | static luaL_reg udp[] = { |
@@ -57,8 +62,13 @@ static luaL_reg udp[] = { | |||
57 | 62 | ||
58 | /* socket options */ | 63 | /* socket options */ |
59 | static luaL_reg opt[] = { | 64 | static luaL_reg opt[] = { |
60 | {"dontroute", opt_dontroute}, | 65 | {"dontroute", opt_dontroute}, |
61 | {"broadcast", opt_broadcast}, | 66 | {"broadcast", opt_broadcast}, |
67 | {"reuseaddr", opt_reuseaddr}, | ||
68 | {"ip-multicast-ttl", opt_ip_multicast_ttl}, | ||
69 | {"ip-multicast-loop", opt_ip_multicast_loop}, | ||
70 | {"ip-add-membership", opt_ip_add_membership}, | ||
71 | {"ip-drop-membership", opt_ip_drop_membersip}, | ||
62 | {NULL, NULL} | 72 | {NULL, NULL} |
63 | }; | 73 | }; |
64 | 74 | ||
@@ -244,11 +254,72 @@ static int opt_dontroute(lua_State *L) | |||
244 | return opt_boolean(L, SOL_SOCKET, SO_DONTROUTE); | 254 | return opt_boolean(L, SOL_SOCKET, SO_DONTROUTE); |
245 | } | 255 | } |
246 | 256 | ||
257 | static int opt_reuseaddr(lua_State *L) | ||
258 | { | ||
259 | return opt_boolean(L, SOL_SOCKET, SO_REUSEADDR); | ||
260 | } | ||
261 | |||
247 | static int opt_broadcast(lua_State *L) | 262 | static int opt_broadcast(lua_State *L) |
248 | { | 263 | { |
249 | return opt_boolean(L, SOL_SOCKET, SO_BROADCAST); | 264 | return opt_boolean(L, SOL_SOCKET, SO_BROADCAST); |
250 | } | 265 | } |
251 | 266 | ||
267 | static int opt_ip_multicast_loop(lua_State *L) | ||
268 | { | ||
269 | return opt_boolean(L, IPPROTO_IP, IP_MULTICAST_LOOP); | ||
270 | } | ||
271 | |||
272 | static int opt_ip_multicast_ttl(lua_State *L) | ||
273 | { | ||
274 | p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); | ||
275 | int val = (int) luaL_checknumber(L, 2); | ||
276 | if (setsockopt(udp->sock, IPPROTO_IP, IP_MULTICAST_TTL, | ||
277 | (char *) &val, sizeof(val)) < 0) { | ||
278 | lua_pushnil(L); | ||
279 | lua_pushstring(L, "setsockopt failed"); | ||
280 | return 2; | ||
281 | } | ||
282 | lua_pushnumber(L, 1); | ||
283 | return 1; | ||
284 | } | ||
285 | |||
286 | static int opt_membership(lua_State *L, int level, int name) | ||
287 | { | ||
288 | p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); | ||
289 | struct ip_mreq val; | ||
290 | if (!lua_istable(L, 2)) | ||
291 | luaL_typerror(L, 2, lua_typename(L, LUA_TTABLE)); | ||
292 | lua_pushstring(L, "multiaddr"); | ||
293 | lua_gettable(L, 2); | ||
294 | if (!lua_isstring(L, -1)) luaL_argerror(L, 2, "invalid 'group' field"); | ||
295 | if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr)) | ||
296 | luaL_argerror(L, 3, "invalid 'multiaddr' ip address"); | ||
297 | lua_pushstring(L, "interface"); | ||
298 | lua_gettable(L, 2); | ||
299 | if (!lua_isstring(L, -1)) luaL_argerror(L, 2, "invalid 'interface' field"); | ||
300 | val.imr_interface.s_addr = htonl(INADDR_ANY); | ||
301 | if (strcmp(lua_tostring(L, -1), "*") && | ||
302 | !inet_aton(lua_tostring(L, -1), &val.imr_interface)) | ||
303 | luaL_argerror(L, 3, "invalid 'interface' ip address"); | ||
304 | if (setsockopt(udp->sock, level, name, (char *) &val, sizeof(val)) < 0) { | ||
305 | lua_pushnil(L); | ||
306 | lua_pushstring(L, "setsockopt failed"); | ||
307 | return 2; | ||
308 | } | ||
309 | lua_pushnumber(L, 1); | ||
310 | return 1; | ||
311 | } | ||
312 | |||
313 | static int opt_ip_add_membership(lua_State *L) | ||
314 | { | ||
315 | return opt_membership(L, IPPROTO_IP, IP_ADD_MEMBERSHIP); | ||
316 | } | ||
317 | |||
318 | static int opt_ip_drop_membersip(lua_State *L) | ||
319 | { | ||
320 | return opt_membership(L, IPPROTO_IP, IP_DROP_MEMBERSHIP); | ||
321 | } | ||
322 | |||
252 | /*-------------------------------------------------------------------------*\ | 323 | /*-------------------------------------------------------------------------*\ |
253 | * Just call tm methods | 324 | * Just call tm methods |
254 | \*-------------------------------------------------------------------------*/ | 325 | \*-------------------------------------------------------------------------*/ |
diff --git a/src/usocket.c b/src/usocket.c index f2d9f01..89be85e 100644 --- a/src/usocket.c +++ b/src/usocket.c | |||
@@ -145,7 +145,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | |||
145 | else return IO_TIMEOUT; | 145 | else return IO_TIMEOUT; |
146 | /* here we know the connection has been closed */ | 146 | /* here we know the connection has been closed */ |
147 | } else return IO_CLOSED; | 147 | } else return IO_CLOSED; |
148 | /* here we sent successfully sent something */ | 148 | /* here we successfully sent something */ |
149 | } else { | 149 | } else { |
150 | *sent = put; | 150 | *sent = put; |
151 | return IO_DONE; | 151 | return IO_DONE; |
@@ -159,34 +159,36 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
159 | SA *addr, socklen_t addr_len, int timeout) | 159 | SA *addr, socklen_t addr_len, int timeout) |
160 | { | 160 | { |
161 | t_sock sock = *ps; | 161 | t_sock sock = *ps; |
162 | struct timeval tv; | 162 | ssize_t put; |
163 | fd_set fds; | ||
164 | ssize_t put = 0; | ||
165 | int err; | ||
166 | int ret; | 163 | int ret; |
164 | /* avoid making system calls on closed sockets */ | ||
167 | if (sock == SOCK_INVALID) return IO_CLOSED; | 165 | if (sock == SOCK_INVALID) return IO_CLOSED; |
168 | tv.tv_sec = timeout / 1000; | 166 | /* make sure we repeat in case the call was interrupted */ |
169 | tv.tv_usec = (timeout % 1000) * 1000; | 167 | do put = sendto(sock, data, count, 0, addr, addr_len); |
170 | FD_ZERO(&fds); | 168 | while (put <= 0 && errno == EINTR); |
171 | FD_SET(sock, &fds); | 169 | /* deal with failure */ |
172 | ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | 170 | if (put <= 0) { |
173 | if (ret > 0) { | 171 | /* in any case, nothing has been sent */ |
174 | put = sendto(sock, data, count, 0, addr, addr_len); | ||
175 | if (put <= 0) { | ||
176 | err = IO_CLOSED; | ||
177 | #ifdef __CYGWIN__ | ||
178 | /* this is for CYGWIN, which is like Unix but has Win32 bugs */ | ||
179 | if (sent < 0 && errno == EWOULDBLOCK) err = IO_DONE; | ||
180 | #endif | ||
181 | *sent = 0; | ||
182 | } else { | ||
183 | *sent = put; | ||
184 | err = IO_DONE; | ||
185 | } | ||
186 | return err; | ||
187 | } else { | ||
188 | *sent = 0; | 172 | *sent = 0; |
189 | return IO_TIMEOUT; | 173 | /* run select to avoid busy wait */ |
174 | if (errno != EPIPE) { | ||
175 | struct timeval tv; | ||
176 | fd_set fds; | ||
177 | tv.tv_sec = timeout / 1000; | ||
178 | tv.tv_usec = (timeout % 1000) * 1000; | ||
179 | FD_ZERO(&fds); | ||
180 | FD_SET(sock, &fds); | ||
181 | ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | ||
182 | /* tell the caller to call us again because there is more data */ | ||
183 | if (ret > 0) return IO_DONE; | ||
184 | /* tell the caller there was no data before timeout */ | ||
185 | else return IO_TIMEOUT; | ||
186 | /* here we know the connection has been closed */ | ||
187 | } else return IO_CLOSED; | ||
188 | /* here we successfully sent something */ | ||
189 | } else { | ||
190 | *sent = put; | ||
191 | return IO_DONE; | ||
190 | } | 192 | } |
191 | } | 193 | } |
192 | 194 | ||
@@ -232,28 +234,26 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, | |||
232 | SA *addr, socklen_t *addr_len, int timeout) | 234 | SA *addr, socklen_t *addr_len, int timeout) |
233 | { | 235 | { |
234 | t_sock sock = *ps; | 236 | t_sock sock = *ps; |
235 | struct timeval tv; | 237 | ssize_t taken; |
236 | fd_set fds; | ||
237 | int ret; | ||
238 | if (sock == SOCK_INVALID) return IO_CLOSED; | 238 | if (sock == SOCK_INVALID) return IO_CLOSED; |
239 | ssize_t taken = 0; | 239 | do taken = recvfrom(sock, data, count, 0, addr, addr_len); |
240 | tv.tv_sec = timeout / 1000; | 240 | while (taken <= 0 && errno == EINTR); |
241 | tv.tv_usec = (timeout % 1000) * 1000; | 241 | if (taken <= 0) { |
242 | FD_ZERO(&fds); | 242 | struct timeval tv; |
243 | FD_SET(sock, &fds); | 243 | fd_set fds; |
244 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | 244 | int ret; |
245 | if (ret > 0) { | ||
246 | taken = recvfrom(sock, data, count, 0, addr, addr_len); | ||
247 | if (taken <= 0) { | ||
248 | *got = 0; | ||
249 | return IO_CLOSED; | ||
250 | } else { | ||
251 | *got = taken; | ||
252 | return IO_DONE; | ||
253 | } | ||
254 | } else { | ||
255 | *got = 0; | 245 | *got = 0; |
256 | return IO_TIMEOUT; | 246 | if (taken == 0) return IO_CLOSED; |
247 | tv.tv_sec = timeout / 1000; | ||
248 | tv.tv_usec = (timeout % 1000) * 1000; | ||
249 | FD_ZERO(&fds); | ||
250 | FD_SET(sock, &fds); | ||
251 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | ||
252 | if (ret > 0) return IO_DONE; | ||
253 | else return IO_TIMEOUT; | ||
254 | } else { | ||
255 | *got = taken; | ||
256 | return IO_DONE; | ||
257 | } | 257 | } |
258 | } | 258 | } |
259 | 259 | ||
diff --git a/src/wsocket.c b/src/wsocket.c index 59d88df..30208b9 100644 --- a/src/wsocket.c +++ b/src/wsocket.c | |||
@@ -100,7 +100,7 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | |||
100 | FD_ZERO(&fds); | 100 | FD_ZERO(&fds); |
101 | FD_SET(sock, &fds); | 101 | FD_SET(sock, &fds); |
102 | *pa = SOCK_INVALID; | 102 | *pa = SOCK_INVALID; |
103 | if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0) | 103 | if (select(0, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0) |
104 | return IO_TIMEOUT; | 104 | return IO_TIMEOUT; |
105 | if (!addr) addr = &dummy_addr; | 105 | if (!addr) addr = &dummy_addr; |
106 | if (!addr_len) addr_len = &dummy_len; | 106 | if (!addr_len) addr_len = &dummy_len; |
@@ -116,34 +116,35 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | |||
116 | int timeout) | 116 | int timeout) |
117 | { | 117 | { |
118 | t_sock sock = *ps; | 118 | t_sock sock = *ps; |
119 | struct timeval tv; | 119 | ssize_t put; |
120 | fd_set fds; | ||
121 | ssize_t put = 0; | ||
122 | if (sock == SOCK_INVALID) return IO_CLOSED; | ||
123 | int err; | ||
124 | int ret; | 120 | int ret; |
125 | tv.tv_sec = timeout / 1000; | 121 | /* avoid making system calls on closed sockets */ |
126 | tv.tv_usec = (timeout % 1000) * 1000; | 122 | if (sock == SOCK_INVALID) return IO_CLOSED; |
127 | FD_ZERO(&fds); | 123 | /* try to send something */ |
128 | FD_SET(sock, &fds); | 124 | put = send(sock, data, (int) count, 0); |
129 | ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | 125 | /* deal with failure */ |
130 | if (ret > 0) { | 126 | if (put <= 0) { |
131 | put = send(sock, data, count, 0); | 127 | /* in any case, nothing has been sent */ |
132 | if (put <= 0) { | ||
133 | /* a bug in WinSock forces us to do a busy wait until we manage | ||
134 | ** to write, because select returns immediately even though it | ||
135 | ** should have blocked us until we could write... */ | ||
136 | if (WSAGetLastError() == WSAEWOULDBLOCK) err = IO_DONE; | ||
137 | else err = IO_CLOSED; | ||
138 | *sent = 0; | ||
139 | } else { | ||
140 | *sent = put; | ||
141 | err = IO_DONE; | ||
142 | } | ||
143 | return err; | ||
144 | } else { | ||
145 | *sent = 0; | 128 | *sent = 0; |
146 | return IO_TIMEOUT; | 129 | /* run select to avoid busy wait */ |
130 | if (WSAGetLastError() == WSAEWOULDBLOCK) { | ||
131 | struct timeval tv; | ||
132 | fd_set fds; | ||
133 | tv.tv_sec = timeout / 1000; | ||
134 | tv.tv_usec = (timeout % 1000) * 1000; | ||
135 | FD_ZERO(&fds); | ||
136 | FD_SET(sock, &fds); | ||
137 | ret = select(0, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | ||
138 | /* tell the caller to call us again because there is more data */ | ||
139 | if (ret > 0) return IO_DONE; | ||
140 | /* tell the caller there was no data before timeout */ | ||
141 | else return IO_TIMEOUT; | ||
142 | /* here we know the connection has been closed */ | ||
143 | } else return IO_CLOSED; | ||
144 | /* here we successfully sent something */ | ||
145 | } else { | ||
146 | *sent = put; | ||
147 | return IO_DONE; | ||
147 | } | 148 | } |
148 | } | 149 | } |
149 | 150 | ||
@@ -154,34 +155,35 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
154 | SA *addr, socklen_t addr_len, int timeout) | 155 | SA *addr, socklen_t addr_len, int timeout) |
155 | { | 156 | { |
156 | t_sock sock = *ps; | 157 | t_sock sock = *ps; |
157 | struct timeval tv; | 158 | ssize_t put; |
158 | fd_set fds; | ||
159 | ssize_t put = 0; | ||
160 | int err; | ||
161 | int ret; | 159 | int ret; |
160 | /* avoid making system calls on closed sockets */ | ||
162 | if (sock == SOCK_INVALID) return IO_CLOSED; | 161 | if (sock == SOCK_INVALID) return IO_CLOSED; |
163 | tv.tv_sec = timeout / 1000; | 162 | /* try to send something */ |
164 | tv.tv_usec = (timeout % 1000) * 1000; | 163 | put = sendto(sock, data, (int) count, 0, addr, addr_len); |
165 | FD_ZERO(&fds); | 164 | /* deal with failure */ |
166 | FD_SET(sock, &fds); | 165 | if (put <= 0) { |
167 | ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | 166 | /* in any case, nothing has been sent */ |
168 | if (ret > 0) { | ||
169 | put = sendto(sock, data, count, 0, addr, addr_len); | ||
170 | if (put <= 0) { | ||
171 | /* a bug in WinSock forces us to do a busy wait until we manage | ||
172 | ** to write, because select returns immediately even though it | ||
173 | ** should have blocked us until we could write... */ | ||
174 | if (WSAGetLastError() == WSAEWOULDBLOCK) err = IO_DONE; | ||
175 | else err = IO_CLOSED; | ||
176 | *sent = 0; | ||
177 | } else { | ||
178 | *sent = put; | ||
179 | err = IO_DONE; | ||
180 | } | ||
181 | return err; | ||
182 | } else { | ||
183 | *sent = 0; | 167 | *sent = 0; |
184 | return IO_TIMEOUT; | 168 | /* run select to avoid busy wait */ |
169 | if (WSAGetLastError() == WSAEWOULDBLOCK) { | ||
170 | struct timeval tv; | ||
171 | fd_set fds; | ||
172 | tv.tv_sec = timeout / 1000; | ||
173 | tv.tv_usec = (timeout % 1000) * 1000; | ||
174 | FD_ZERO(&fds); | ||
175 | FD_SET(sock, &fds); | ||
176 | ret = select(0, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | ||
177 | /* tell the caller to call us again because there is more data */ | ||
178 | if (ret > 0) return IO_DONE; | ||
179 | /* tell the caller there was no data before timeout */ | ||
180 | else return IO_TIMEOUT; | ||
181 | /* here we know the connection has been closed */ | ||
182 | } else return IO_CLOSED; | ||
183 | /* here we successfully sent something */ | ||
184 | } else { | ||
185 | *sent = put; | ||
186 | return IO_DONE; | ||
185 | } | 187 | } |
186 | } | 188 | } |
187 | 189 | ||
@@ -191,28 +193,25 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
191 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) | 193 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) |
192 | { | 194 | { |
193 | t_sock sock = *ps; | 195 | t_sock sock = *ps; |
194 | struct timeval tv; | 196 | ssize_t taken; |
195 | fd_set fds; | ||
196 | int ret; | ||
197 | ssize_t taken = 0; | ||
198 | if (sock == SOCK_INVALID) return IO_CLOSED; | 197 | if (sock == SOCK_INVALID) return IO_CLOSED; |
199 | tv.tv_sec = timeout / 1000; | 198 | taken = recv(sock, data, (int) count, 0); |
200 | tv.tv_usec = (timeout % 1000) * 1000; | 199 | if (taken <= 0) { |
201 | FD_ZERO(&fds); | 200 | struct timeval tv; |
202 | FD_SET(sock, &fds); | 201 | fd_set fds; |
203 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | 202 | int ret; |
204 | if (ret > 0) { | ||
205 | taken = recv(sock, data, count, 0); | ||
206 | if (taken <= 0) { | ||
207 | *got = 0; | ||
208 | return IO_CLOSED; | ||
209 | } else { | ||
210 | *got = taken; | ||
211 | return IO_DONE; | ||
212 | } | ||
213 | } else { | ||
214 | *got = 0; | 203 | *got = 0; |
215 | return IO_TIMEOUT; | 204 | if (taken == 0) return IO_CLOSED; |
205 | tv.tv_sec = timeout / 1000; | ||
206 | tv.tv_usec = (timeout % 1000) * 1000; | ||
207 | FD_ZERO(&fds); | ||
208 | FD_SET(sock, &fds); | ||
209 | ret = select(0, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | ||
210 | if (ret > 0) return IO_DONE; | ||
211 | else return IO_TIMEOUT; | ||
212 | } else { | ||
213 | *got = taken; | ||
214 | return IO_DONE; | ||
216 | } | 215 | } |
217 | } | 216 | } |
218 | 217 | ||
@@ -223,28 +222,25 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, | |||
223 | SA *addr, socklen_t *addr_len, int timeout) | 222 | SA *addr, socklen_t *addr_len, int timeout) |
224 | { | 223 | { |
225 | t_sock sock = *ps; | 224 | t_sock sock = *ps; |
226 | struct timeval tv; | 225 | ssize_t taken; |
227 | fd_set fds; | ||
228 | int ret; | ||
229 | ssize_t taken = 0; | ||
230 | if (sock == SOCK_INVALID) return IO_CLOSED; | 226 | if (sock == SOCK_INVALID) return IO_CLOSED; |
231 | tv.tv_sec = timeout / 1000; | 227 | taken = recvfrom(sock, data, (int) count, 0, addr, addr_len); |
232 | tv.tv_usec = (timeout % 1000) * 1000; | 228 | if (taken <= 0) { |
233 | FD_ZERO(&fds); | 229 | struct timeval tv; |
234 | FD_SET(sock, &fds); | 230 | fd_set fds; |
235 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | 231 | int ret; |
236 | if (ret > 0) { | ||
237 | taken = recvfrom(sock, data, count, 0, addr, addr_len); | ||
238 | if (taken <= 0) { | ||
239 | *got = 0; | ||
240 | return IO_CLOSED; | ||
241 | } else { | ||
242 | *got = taken; | ||
243 | return IO_DONE; | ||
244 | } | ||
245 | } else { | ||
246 | *got = 0; | 232 | *got = 0; |
247 | return IO_TIMEOUT; | 233 | if (taken == 0) return IO_CLOSED; |
234 | tv.tv_sec = timeout / 1000; | ||
235 | tv.tv_usec = (timeout % 1000) * 1000; | ||
236 | FD_ZERO(&fds); | ||
237 | FD_SET(sock, &fds); | ||
238 | ret = select(0, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | ||
239 | if (ret > 0) return IO_DONE; | ||
240 | else return IO_TIMEOUT; | ||
241 | } else { | ||
242 | *got = taken; | ||
243 | return IO_DONE; | ||
248 | } | 244 | } |
249 | } | 245 | } |
250 | 246 | ||