aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-01-17 00:17:46 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-01-17 00:17:46 +0000
commit076451c75336b30e6152bd5c02f355db39107f7d (patch)
tree785a6c71ca1e5246f2ce09a9b91f98eb902ac2a0 /src
parent89f3ecf7820857f91c4039536d2bbe3cf12d5f95 (diff)
downloadluasocket-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.h4
-rw-r--r--src/luasocket.h2
-rw-r--r--src/tcp.c18
-rw-r--r--src/timeout.c1
-rw-r--r--src/udp.c75
-rw-r--r--src/usocket.c92
-rw-r--r--src/wsocket.c180
7 files changed, 224 insertions, 148 deletions
diff --git a/src/inet.h b/src/inet.h
index 244a310..b69e82d 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -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
22void inet_open(lua_State *L); 26void inet_open(lua_State *L);
23const char *inet_tryconnect(p_sock ps, const char *address, 27const 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
diff --git a/src/tcp.c b/src/tcp.c
index afa0477..a67b44a 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -36,6 +36,7 @@ static int meth_dirty(lua_State *L);
36static int opt_tcp_nodelay(lua_State *L); 36static int opt_tcp_nodelay(lua_State *L);
37static int opt_keepalive(lua_State *L); 37static int opt_keepalive(lua_State *L);
38static int opt_linger(lua_State *L); 38static int opt_linger(lua_State *L);
39static int opt_reuseaddr(lua_State *L);
39 40
40/* tcp object methods */ 41/* tcp object methods */
41static luaL_reg tcp[] = { 42static luaL_reg tcp[] = {
@@ -61,6 +62,7 @@ static luaL_reg tcp[] = {
61/* socket option handlers */ 62/* socket option handlers */
62static luaL_reg opt[] = { 63static 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
124static int opt_boolean(lua_State *L, int level, int name) 126static 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 */
140static 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 */
138static int opt_tcp_nodelay(lua_State *L) 146static 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
149static int opt_keepalive(lua_State *L) 151static 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>
diff --git a/src/udp.c b/src/udp.c
index 58119cd..21730ab 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -35,6 +35,11 @@ static int meth_fd(lua_State *L);
35static int meth_dirty(lua_State *L); 35static int meth_dirty(lua_State *L);
36static int opt_dontroute(lua_State *L); 36static int opt_dontroute(lua_State *L);
37static int opt_broadcast(lua_State *L); 37static int opt_broadcast(lua_State *L);
38static int opt_reuseaddr(lua_State *L);
39static int opt_ip_multicast_ttl(lua_State *L);
40static int opt_ip_multicast_loop(lua_State *L);
41static int opt_ip_add_membership(lua_State *L);
42static int opt_ip_drop_membersip(lua_State *L);
38 43
39/* udp object methods */ 44/* udp object methods */
40static luaL_reg udp[] = { 45static luaL_reg udp[] = {
@@ -57,8 +62,13 @@ static luaL_reg udp[] = {
57 62
58/* socket options */ 63/* socket options */
59static luaL_reg opt[] = { 64static 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
257static int opt_reuseaddr(lua_State *L)
258{
259 return opt_boolean(L, SOL_SOCKET, SO_REUSEADDR);
260}
261
247static int opt_broadcast(lua_State *L) 262static 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
267static int opt_ip_multicast_loop(lua_State *L)
268{
269 return opt_boolean(L, IPPROTO_IP, IP_MULTICAST_LOOP);
270}
271
272static 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
286static 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
313static int opt_ip_add_membership(lua_State *L)
314{
315 return opt_membership(L, IPPROTO_IP, IP_ADD_MEMBERSHIP);
316}
317
318static 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,
191int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) 193int 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