diff options
author | Diego Nehab <diego.nehab@gmail.com> | 2015-08-21 15:39:34 -0300 |
---|---|---|
committer | Diego Nehab <diego.nehab@gmail.com> | 2015-08-21 15:39:34 -0300 |
commit | e75444ccd1f30a3b5fbc7cec4a85e831bd0560ed (patch) | |
tree | 71475c18fee070c770fc0fe25d0859b7d54c8fbb /src/wsocket.c | |
parent | 321c0c9b1f7b6b83cd83b58e7e259f53eca69373 (diff) | |
download | luasocket-e75444ccd1f30a3b5fbc7cec4a85e831bd0560ed.tar.gz luasocket-e75444ccd1f30a3b5fbc7cec4a85e831bd0560ed.tar.bz2 luasocket-e75444ccd1f30a3b5fbc7cec4a85e831bd0560ed.zip |
New compat.h module implements luaL_setfuncs.
Makes initialization code simpler everywhere.
Diffstat (limited to 'src/wsocket.c')
-rw-r--r-- | src/wsocket.c | 82 |
1 files changed, 41 insertions, 41 deletions
diff --git a/src/wsocket.c b/src/wsocket.c index 10800e3..8ecb0fc 100644 --- a/src/wsocket.c +++ b/src/wsocket.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
4 | * | 4 | * |
5 | * The penalty of calling select to avoid busy-wait is only paid when | 5 | * The penalty of calling select to avoid busy-wait is only paid when |
6 | * the I/O call fail in the first place. | 6 | * the I/O call fail in the first place. |
7 | \*=========================================================================*/ | 7 | \*=========================================================================*/ |
8 | #include <string.h> | 8 | #include <string.h> |
9 | 9 | ||
@@ -14,23 +14,23 @@ | |||
14 | static const char *wstrerror(int err); | 14 | static const char *wstrerror(int err); |
15 | 15 | ||
16 | /*-------------------------------------------------------------------------*\ | 16 | /*-------------------------------------------------------------------------*\ |
17 | * Initializes module | 17 | * Initializes module |
18 | \*-------------------------------------------------------------------------*/ | 18 | \*-------------------------------------------------------------------------*/ |
19 | int socket_open(void) { | 19 | int socket_open(void) { |
20 | WSADATA wsaData; | 20 | WSADATA wsaData; |
21 | WORD wVersionRequested = MAKEWORD(2, 0); | 21 | WORD wVersionRequested = MAKEWORD(2, 0); |
22 | int err = WSAStartup(wVersionRequested, &wsaData ); | 22 | int err = WSAStartup(wVersionRequested, &wsaData ); |
23 | if (err != 0) return 0; | 23 | if (err != 0) return 0; |
24 | if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) && | 24 | if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) && |
25 | (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) { | 25 | (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) { |
26 | WSACleanup(); | 26 | WSACleanup(); |
27 | return 0; | 27 | return 0; |
28 | } | 28 | } |
29 | return 1; | 29 | return 1; |
30 | } | 30 | } |
31 | 31 | ||
32 | /*-------------------------------------------------------------------------*\ | 32 | /*-------------------------------------------------------------------------*\ |
33 | * Close module | 33 | * Close module |
34 | \*-------------------------------------------------------------------------*/ | 34 | \*-------------------------------------------------------------------------*/ |
35 | int socket_close(void) { | 35 | int socket_close(void) { |
36 | WSACleanup(); | 36 | WSACleanup(); |
@@ -51,10 +51,10 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | |||
51 | struct timeval tv, *tp = NULL; | 51 | struct timeval tv, *tp = NULL; |
52 | double t; | 52 | double t; |
53 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ | 53 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ |
54 | if (sw & WAITFD_R) { | 54 | if (sw & WAITFD_R) { |
55 | FD_ZERO(&rfds); | 55 | FD_ZERO(&rfds); |
56 | FD_SET(*ps, &rfds); | 56 | FD_SET(*ps, &rfds); |
57 | rp = &rfds; | 57 | rp = &rfds; |
58 | } | 58 | } |
59 | if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } | 59 | if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } |
60 | if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; } | 60 | if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; } |
@@ -73,9 +73,9 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | |||
73 | /*-------------------------------------------------------------------------*\ | 73 | /*-------------------------------------------------------------------------*\ |
74 | * Select with int timeout in ms | 74 | * Select with int timeout in ms |
75 | \*-------------------------------------------------------------------------*/ | 75 | \*-------------------------------------------------------------------------*/ |
76 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, | 76 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, |
77 | p_timeout tm) { | 77 | p_timeout tm) { |
78 | struct timeval tv; | 78 | struct timeval tv; |
79 | double t = timeout_get(tm); | 79 | double t = timeout_get(tm); |
80 | tv.tv_sec = (int) t; | 80 | tv.tv_sec = (int) t; |
81 | tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); | 81 | tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); |
@@ -97,7 +97,7 @@ void socket_destroy(p_socket ps) { | |||
97 | } | 97 | } |
98 | 98 | ||
99 | /*-------------------------------------------------------------------------*\ | 99 | /*-------------------------------------------------------------------------*\ |
100 | * | 100 | * |
101 | \*-------------------------------------------------------------------------*/ | 101 | \*-------------------------------------------------------------------------*/ |
102 | void socket_shutdown(p_socket ps, int how) { | 102 | void socket_shutdown(p_socket ps, int how) { |
103 | socket_setblocking(ps); | 103 | socket_setblocking(ps); |
@@ -135,10 +135,10 @@ int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { | |||
135 | /* give windows time to set the error (yes, disgusting) */ | 135 | /* give windows time to set the error (yes, disgusting) */ |
136 | Sleep(10); | 136 | Sleep(10); |
137 | /* find out why we failed */ | 137 | /* find out why we failed */ |
138 | getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len); | 138 | getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len); |
139 | /* we KNOW there was an error. if 'why' is 0, we will return | 139 | /* we KNOW there was an error. if 'why' is 0, we will return |
140 | * "unknown error", but it's not really our fault */ | 140 | * "unknown error", but it's not really our fault */ |
141 | return err > 0? err: IO_UNKNOWN; | 141 | return err > 0? err: IO_UNKNOWN; |
142 | } else return err; | 142 | } else return err; |
143 | 143 | ||
144 | } | 144 | } |
@@ -155,7 +155,7 @@ int socket_bind(p_socket ps, SA *addr, socklen_t len) { | |||
155 | } | 155 | } |
156 | 156 | ||
157 | /*-------------------------------------------------------------------------*\ | 157 | /*-------------------------------------------------------------------------*\ |
158 | * | 158 | * |
159 | \*-------------------------------------------------------------------------*/ | 159 | \*-------------------------------------------------------------------------*/ |
160 | int socket_listen(p_socket ps, int backlog) { | 160 | int socket_listen(p_socket ps, int backlog) { |
161 | int err = IO_DONE; | 161 | int err = IO_DONE; |
@@ -168,7 +168,7 @@ int socket_listen(p_socket ps, int backlog) { | |||
168 | /*-------------------------------------------------------------------------*\ | 168 | /*-------------------------------------------------------------------------*\ |
169 | * Accept with timeout | 169 | * Accept with timeout |
170 | \*-------------------------------------------------------------------------*/ | 170 | \*-------------------------------------------------------------------------*/ |
171 | int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, | 171 | int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, |
172 | p_timeout tm) { | 172 | p_timeout tm) { |
173 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | 173 | if (*ps == SOCKET_INVALID) return IO_CLOSED; |
174 | for ( ;; ) { | 174 | for ( ;; ) { |
@@ -176,21 +176,21 @@ int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, | |||
176 | /* try to get client socket */ | 176 | /* try to get client socket */ |
177 | if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; | 177 | if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; |
178 | /* find out why we failed */ | 178 | /* find out why we failed */ |
179 | err = WSAGetLastError(); | 179 | err = WSAGetLastError(); |
180 | /* if we failed because there was no connectoin, keep trying */ | 180 | /* if we failed because there was no connectoin, keep trying */ |
181 | if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err; | 181 | if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err; |
182 | /* call select to avoid busy wait */ | 182 | /* call select to avoid busy wait */ |
183 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | 183 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; |
184 | } | 184 | } |
185 | } | 185 | } |
186 | 186 | ||
187 | /*-------------------------------------------------------------------------*\ | 187 | /*-------------------------------------------------------------------------*\ |
188 | * Send with timeout | 188 | * Send with timeout |
189 | * On windows, if you try to send 10MB, the OS will buffer EVERYTHING | 189 | * On windows, if you try to send 10MB, the OS will buffer EVERYTHING |
190 | * this can take an awful lot of time and we will end up blocked. | 190 | * this can take an awful lot of time and we will end up blocked. |
191 | * Therefore, whoever calls this function should not pass a huge buffer. | 191 | * Therefore, whoever calls this function should not pass a huge buffer. |
192 | \*-------------------------------------------------------------------------*/ | 192 | \*-------------------------------------------------------------------------*/ |
193 | int socket_send(p_socket ps, const char *data, size_t count, | 193 | int socket_send(p_socket ps, const char *data, size_t count, |
194 | size_t *sent, p_timeout tm) | 194 | size_t *sent, p_timeout tm) |
195 | { | 195 | { |
196 | int err; | 196 | int err; |
@@ -207,18 +207,18 @@ int socket_send(p_socket ps, const char *data, size_t count, | |||
207 | return IO_DONE; | 207 | return IO_DONE; |
208 | } | 208 | } |
209 | /* deal with failure */ | 209 | /* deal with failure */ |
210 | err = WSAGetLastError(); | 210 | err = WSAGetLastError(); |
211 | /* we can only proceed if there was no serious error */ | 211 | /* we can only proceed if there was no serious error */ |
212 | if (err != WSAEWOULDBLOCK) return err; | 212 | if (err != WSAEWOULDBLOCK) return err; |
213 | /* avoid busy wait */ | 213 | /* avoid busy wait */ |
214 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | 214 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; |
215 | } | 215 | } |
216 | } | 216 | } |
217 | 217 | ||
218 | /*-------------------------------------------------------------------------*\ | 218 | /*-------------------------------------------------------------------------*\ |
219 | * Sendto with timeout | 219 | * Sendto with timeout |
220 | \*-------------------------------------------------------------------------*/ | 220 | \*-------------------------------------------------------------------------*/ |
221 | int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, | 221 | int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, |
222 | SA *addr, socklen_t len, p_timeout tm) | 222 | SA *addr, socklen_t len, p_timeout tm) |
223 | { | 223 | { |
224 | int err; | 224 | int err; |
@@ -230,17 +230,17 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, | |||
230 | *sent = put; | 230 | *sent = put; |
231 | return IO_DONE; | 231 | return IO_DONE; |
232 | } | 232 | } |
233 | err = WSAGetLastError(); | 233 | err = WSAGetLastError(); |
234 | if (err != WSAEWOULDBLOCK) return err; | 234 | if (err != WSAEWOULDBLOCK) return err; |
235 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | 235 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; |
236 | } | 236 | } |
237 | } | 237 | } |
238 | 238 | ||
239 | /*-------------------------------------------------------------------------*\ | 239 | /*-------------------------------------------------------------------------*\ |
240 | * Receive with timeout | 240 | * Receive with timeout |
241 | \*-------------------------------------------------------------------------*/ | 241 | \*-------------------------------------------------------------------------*/ |
242 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, | 242 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, |
243 | p_timeout tm) | 243 | p_timeout tm) |
244 | { | 244 | { |
245 | int err, prev = IO_DONE; | 245 | int err, prev = IO_DONE; |
246 | *got = 0; | 246 | *got = 0; |
@@ -253,9 +253,9 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, | |||
253 | } | 253 | } |
254 | if (taken == 0) return IO_CLOSED; | 254 | if (taken == 0) return IO_CLOSED; |
255 | err = WSAGetLastError(); | 255 | err = WSAGetLastError(); |
256 | /* On UDP, a connreset simply means the previous send failed. | 256 | /* On UDP, a connreset simply means the previous send failed. |
257 | * So we try again. | 257 | * So we try again. |
258 | * On TCP, it means our socket is now useless, so the error passes. | 258 | * On TCP, it means our socket is now useless, so the error passes. |
259 | * (We will loop again, exiting because the same error will happen) */ | 259 | * (We will loop again, exiting because the same error will happen) */ |
260 | if (err != WSAEWOULDBLOCK) { | 260 | if (err != WSAEWOULDBLOCK) { |
261 | if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; | 261 | if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; |
@@ -268,8 +268,8 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, | |||
268 | /*-------------------------------------------------------------------------*\ | 268 | /*-------------------------------------------------------------------------*\ |
269 | * Recvfrom with timeout | 269 | * Recvfrom with timeout |
270 | \*-------------------------------------------------------------------------*/ | 270 | \*-------------------------------------------------------------------------*/ |
271 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, | 271 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, |
272 | SA *addr, socklen_t *len, p_timeout tm) | 272 | SA *addr, socklen_t *len, p_timeout tm) |
273 | { | 273 | { |
274 | int err, prev = IO_DONE; | 274 | int err, prev = IO_DONE; |
275 | *got = 0; | 275 | *got = 0; |
@@ -282,8 +282,8 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, | |||
282 | } | 282 | } |
283 | if (taken == 0) return IO_CLOSED; | 283 | if (taken == 0) return IO_CLOSED; |
284 | err = WSAGetLastError(); | 284 | err = WSAGetLastError(); |
285 | /* On UDP, a connreset simply means the previous send failed. | 285 | /* On UDP, a connreset simply means the previous send failed. |
286 | * So we try again. | 286 | * So we try again. |
287 | * On TCP, it means our socket is now useless, so the error passes. | 287 | * On TCP, it means our socket is now useless, so the error passes. |
288 | * (We will loop again, exiting because the same error will happen) */ | 288 | * (We will loop again, exiting because the same error will happen) */ |
289 | if (err != WSAEWOULDBLOCK) { | 289 | if (err != WSAEWOULDBLOCK) { |
@@ -311,7 +311,7 @@ void socket_setnonblocking(p_socket ps) { | |||
311 | } | 311 | } |
312 | 312 | ||
313 | /*-------------------------------------------------------------------------*\ | 313 | /*-------------------------------------------------------------------------*\ |
314 | * DNS helpers | 314 | * DNS helpers |
315 | \*-------------------------------------------------------------------------*/ | 315 | \*-------------------------------------------------------------------------*/ |
316 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { | 316 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { |
317 | *hp = gethostbyaddr(addr, len, AF_INET); | 317 | *hp = gethostbyaddr(addr, len, AF_INET); |
@@ -332,7 +332,7 @@ const char *socket_hoststrerror(int err) { | |||
332 | if (err <= 0) return io_strerror(err); | 332 | if (err <= 0) return io_strerror(err); |
333 | switch (err) { | 333 | switch (err) { |
334 | case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; | 334 | case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; |
335 | default: return wstrerror(err); | 335 | default: return wstrerror(err); |
336 | } | 336 | } |
337 | } | 337 | } |
338 | 338 | ||
@@ -374,7 +374,7 @@ static const char *wstrerror(int err) { | |||
374 | case WSAESOCKTNOSUPPORT: return PIE_SOCKTYPE; // "Socket type not supported"; | 374 | case WSAESOCKTNOSUPPORT: return PIE_SOCKTYPE; // "Socket type not supported"; |
375 | case WSAEOPNOTSUPP: return "Operation not supported"; | 375 | case WSAEOPNOTSUPP: return "Operation not supported"; |
376 | case WSAEPFNOSUPPORT: return "Protocol family not supported"; | 376 | case WSAEPFNOSUPPORT: return "Protocol family not supported"; |
377 | case WSAEAFNOSUPPORT: return PIE_FAMILY; // "Address family not supported by protocol family"; | 377 | case WSAEAFNOSUPPORT: return PIE_FAMILY; // "Address family not supported by protocol family"; |
378 | case WSAEADDRINUSE: return PIE_ADDRINUSE; // "Address already in use"; | 378 | case WSAEADDRINUSE: return PIE_ADDRINUSE; // "Address already in use"; |
379 | case WSAEADDRNOTAVAIL: return "Cannot assign requested address"; | 379 | case WSAEADDRNOTAVAIL: return "Cannot assign requested address"; |
380 | case WSAENETDOWN: return "Network is down"; | 380 | case WSAENETDOWN: return "Network is down"; |
@@ -393,19 +393,19 @@ static const char *wstrerror(int err) { | |||
393 | case WSAEPROCLIM: return "Too many processes"; | 393 | case WSAEPROCLIM: return "Too many processes"; |
394 | case WSASYSNOTREADY: return "Network subsystem is unavailable"; | 394 | case WSASYSNOTREADY: return "Network subsystem is unavailable"; |
395 | case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range"; | 395 | case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range"; |
396 | case WSANOTINITIALISED: | 396 | case WSANOTINITIALISED: |
397 | return "Successful WSAStartup not yet performed"; | 397 | return "Successful WSAStartup not yet performed"; |
398 | case WSAEDISCON: return "Graceful shutdown in progress"; | 398 | case WSAEDISCON: return "Graceful shutdown in progress"; |
399 | case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; // "Host not found"; | 399 | case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; // "Host not found"; |
400 | case WSATRY_AGAIN: return "Nonauthoritative host not found"; | 400 | case WSATRY_AGAIN: return "Nonauthoritative host not found"; |
401 | case WSANO_RECOVERY: return PIE_FAIL; // "Nonrecoverable name lookup error"; | 401 | case WSANO_RECOVERY: return PIE_FAIL; // "Nonrecoverable name lookup error"; |
402 | case WSANO_DATA: return "Valid name, no data record of requested type"; | 402 | case WSANO_DATA: return "Valid name, no data record of requested type"; |
403 | default: return "Unknown error"; | 403 | default: return "Unknown error"; |
404 | } | 404 | } |
405 | } | 405 | } |
406 | 406 | ||
407 | const char *socket_gaistrerror(int err) { | 407 | const char *socket_gaistrerror(int err) { |
408 | if (err == 0) return NULL; | 408 | if (err == 0) return NULL; |
409 | switch (err) { | 409 | switch (err) { |
410 | case EAI_AGAIN: return PIE_AGAIN; | 410 | case EAI_AGAIN: return PIE_AGAIN; |
411 | case EAI_BADFLAGS: return PIE_BADFLAGS; | 411 | case EAI_BADFLAGS: return PIE_BADFLAGS; |
@@ -425,7 +425,7 @@ const char *socket_gaistrerror(int err) { | |||
425 | case EAI_SERVICE: return PIE_SERVICE; | 425 | case EAI_SERVICE: return PIE_SERVICE; |
426 | case EAI_SOCKTYPE: return PIE_SOCKTYPE; | 426 | case EAI_SOCKTYPE: return PIE_SOCKTYPE; |
427 | #ifdef EAI_SYSTEM | 427 | #ifdef EAI_SYSTEM |
428 | case EAI_SYSTEM: return strerror(errno); | 428 | case EAI_SYSTEM: return strerror(errno); |
429 | #endif | 429 | #endif |
430 | default: return gai_strerror(err); | 430 | default: return gai_strerror(err); |
431 | } | 431 | } |