1 #ifdef _WIN32
2
3 /*=========================================================================*\
4 * Socket compatibilization module for Win32
5 * LuaSocket toolkit
6 *
7 * The penalty of calling select to avoid busy-wait is only paid when
8 * the I/O call fail in the first place.
9 \*=========================================================================*/
10 #include <string.h>
11
12 #include "socket.h"
13 #include "pierror.h"
14
15 /* WinSock doesn't have a strerror... */
16 static const char *wstrerror(int err);
17
18 /*-------------------------------------------------------------------------*\
19 * Initializes module
20 \*-------------------------------------------------------------------------*/
socket_open(void)21 int socket_open(void) {
22 WSADATA wsaData;
23 WORD wVersionRequested = MAKEWORD(2, 0);
24 int err = WSAStartup(wVersionRequested, &wsaData );
25 if (err != 0) return 0;
26 if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) &&
27 (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) {
28 WSACleanup();
29 return 0;
30 }
31 return 1;
32 }
33
34 /*-------------------------------------------------------------------------*\
35 * Close module
36 \*-------------------------------------------------------------------------*/
socket_close(void)37 int socket_close(void) {
38 WSACleanup();
39 return 1;
40 }
41
42 /*-------------------------------------------------------------------------*\
43 * Wait for readable/writable/connected socket with timeout
44 \*-------------------------------------------------------------------------*/
45 #define WAITFD_R 1
46 #define WAITFD_W 2
47 #define WAITFD_E 4
48 #define WAITFD_C (WAITFD_E|WAITFD_W)
49
socket_waitfd(p_socket ps,int sw,p_timeout tm)50 int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
51 int ret;
52 fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL;
53 struct timeval tv, *tp = NULL;
54 double t;
55 if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
56 if (sw & WAITFD_R) {
57 FD_ZERO(&rfds);
58 FD_SET(*ps, &rfds);
59 rp = &rfds;
60 }
61 if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
62 if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; }
63 if ((t = timeout_get(tm)) >= 0.0) {
64 tv.tv_sec = (int) t;
65 tv.tv_usec = (int) ((t-tv.tv_sec)*1.0e6);
66 tp = &tv;
67 }
68 ret = select(0, rp, wp, ep, tp);
69 if (ret == -1) return WSAGetLastError();
70 if (ret == 0) return IO_TIMEOUT;
71 if (sw == WAITFD_C && FD_ISSET(*ps, &efds)) return IO_CLOSED;
72 return IO_DONE;
73 }
74
75 /*-------------------------------------------------------------------------*\
76 * Select with int timeout in ms
77 \*-------------------------------------------------------------------------*/
socket_select(t_socket n,fd_set * rfds,fd_set * wfds,fd_set * efds,p_timeout tm)78 int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds,
79 p_timeout tm) {
80 struct timeval tv;
81 double t = timeout_get(tm);
82 tv.tv_sec = (int) t;
83 tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
84 if (n <= 0) {
85 Sleep((DWORD) (1000*t));
86 return 0;
87 } else return select(0, rfds, wfds, efds, t >= 0.0? &tv: NULL);
88 }
89
90 /*-------------------------------------------------------------------------*\
91 * Close and inutilize socket
92 \*-------------------------------------------------------------------------*/
socket_destroy(p_socket ps)93 void socket_destroy(p_socket ps) {
94 if (*ps != SOCKET_INVALID) {
95 socket_setblocking(ps); /* close can take a long time on WIN32 */
96 closesocket(*ps);
97 *ps = SOCKET_INVALID;
98 }
99 }
100
101 /*-------------------------------------------------------------------------*\
102 *
103 \*-------------------------------------------------------------------------*/
socket_shutdown(p_socket ps,int how)104 void socket_shutdown(p_socket ps, int how) {
105 socket_setblocking(ps);
106 shutdown(*ps, how);
107 socket_setnonblocking(ps);
108 }
109
110 /*-------------------------------------------------------------------------*\
111 * Creates and sets up a socket
112 \*-------------------------------------------------------------------------*/
socket_create(p_socket ps,int domain,int type,int protocol)113 int socket_create(p_socket ps, int domain, int type, int protocol) {
114 *ps = socket(domain, type, protocol);
115 if (*ps != SOCKET_INVALID) return IO_DONE;
116 else return WSAGetLastError();
117 }
118
119 /*-------------------------------------------------------------------------*\
120 * Connects or returns error message
121 \*-------------------------------------------------------------------------*/
socket_connect(p_socket ps,SA * addr,socklen_t len,p_timeout tm)122 int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) {
123 int err;
124 /* don't call on closed socket */
125 if (*ps == SOCKET_INVALID) return IO_CLOSED;
126 /* ask system to connect */
127 if (connect(*ps, addr, len) == 0) return IO_DONE;
128 /* make sure the system is trying to connect */
129 err = WSAGetLastError();
130 if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS) return err;
131 /* zero timeout case optimization */
132 if (timeout_iszero(tm)) return IO_TIMEOUT;
133 /* we wait until something happens */
134 err = socket_waitfd(ps, WAITFD_C, tm);
135 if (err == IO_CLOSED) {
136 int elen = sizeof(err);
137 /* give windows time to set the error (yes, disgusting) */
138 Sleep(10);
139 /* find out why we failed */
140 getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &elen);
141 /* we KNOW there was an error. if 'why' is 0, we will return
142 * "unknown error", but it's not really our fault */
143 return err > 0? err: IO_UNKNOWN;
144 } else return err;
145
146 }
147
148 /*-------------------------------------------------------------------------*\
149 * Binds or returns error message
150 \*-------------------------------------------------------------------------*/
socket_bind(p_socket ps,SA * addr,socklen_t len)151 int socket_bind(p_socket ps, SA *addr, socklen_t len) {
152 int err = IO_DONE;
153 socket_setblocking(ps);
154 if (bind(*ps, addr, len) < 0) err = WSAGetLastError();
155 socket_setnonblocking(ps);
156 return err;
157 }
158
159 /*-------------------------------------------------------------------------*\
160 *
161 \*-------------------------------------------------------------------------*/
socket_listen(p_socket ps,int backlog)162 int socket_listen(p_socket ps, int backlog) {
163 int err = IO_DONE;
164 socket_setblocking(ps);
165 if (listen(*ps, backlog) < 0) err = WSAGetLastError();
166 socket_setnonblocking(ps);
167 return err;
168 }
169
170 /*-------------------------------------------------------------------------*\
171 * Accept with timeout
172 \*-------------------------------------------------------------------------*/
socket_accept(p_socket ps,p_socket pa,SA * addr,socklen_t * len,p_timeout tm)173 int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len,
174 p_timeout tm) {
175 if (*ps == SOCKET_INVALID) return IO_CLOSED;
176 for ( ;; ) {
177 int err;
178 /* try to get client socket */
179 if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE;
180 /* find out why we failed */
181 err = WSAGetLastError();
182 /* if we failed because there was no connectoin, keep trying */
183 if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err;
184 /* call select to avoid busy wait */
185 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
186 }
187 }
188
189 /*-------------------------------------------------------------------------*\
190 * Send with timeout
191 * On windows, if you try to send 10MB, the OS will buffer EVERYTHING
192 * this can take an awful lot of time and we will end up blocked.
193 * Therefore, whoever calls this function should not pass a huge buffer.
194 \*-------------------------------------------------------------------------*/
socket_send(p_socket ps,const char * data,size_t count,size_t * sent,p_timeout tm)195 int socket_send(p_socket ps, const char *data, size_t count,
196 size_t *sent, p_timeout tm)
197 {
198 int err;
199 *sent = 0;
200 /* avoid making system calls on closed sockets */
201 if (*ps == SOCKET_INVALID) return IO_CLOSED;
202 /* loop until we send something or we give up on error */
203 for ( ;; ) {
204 /* try to send something */
205 int put = send(*ps, data, (int) count, 0);
206 /* if we sent something, we are done */
207 if (put > 0) {
208 *sent = put;
209 return IO_DONE;
210 }
211 /* deal with failure */
212 err = WSAGetLastError();
213 /* we can only proceed if there was no serious error */
214 if (err != WSAEWOULDBLOCK) return err;
215 /* avoid busy wait */
216 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
217 }
218 }
219
220 /*-------------------------------------------------------------------------*\
221 * Sendto with timeout
222 \*-------------------------------------------------------------------------*/
socket_sendto(p_socket ps,const char * data,size_t count,size_t * sent,SA * addr,socklen_t len,p_timeout tm)223 int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent,
224 SA *addr, socklen_t len, p_timeout tm)
225 {
226 int err;
227 *sent = 0;
228 if (*ps == SOCKET_INVALID) return IO_CLOSED;
229 for ( ;; ) {
230 int put = sendto(*ps, data, (int) count, 0, addr, len);
231 if (put > 0) {
232 *sent = put;
233 return IO_DONE;
234 }
235 err = WSAGetLastError();
236 if (err != WSAEWOULDBLOCK) return err;
237 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
238 }
239 }
240
241 /*-------------------------------------------------------------------------*\
242 * Receive with timeout
243 \*-------------------------------------------------------------------------*/
socket_recv(p_socket ps,char * data,size_t count,size_t * got,p_timeout tm)244 int socket_recv(p_socket ps, char *data, size_t count, size_t *got,
245 p_timeout tm)
246 {
247 int err, prev = IO_DONE;
248 *got = 0;
249 if (*ps == SOCKET_INVALID) return IO_CLOSED;
250 for ( ;; ) {
251 int taken = recv(*ps, data, (int) count, 0);
252 if (taken > 0) {
253 *got = taken;
254 return IO_DONE;
255 }
256 if (taken == 0) return IO_CLOSED;
257 err = WSAGetLastError();
258 /* On UDP, a connreset simply means the previous send failed.
259 * So we try again.
260 * On TCP, it means our socket is now useless, so the error passes.
261 * (We will loop again, exiting because the same error will happen) */
262 if (err != WSAEWOULDBLOCK) {
263 if (err != WSAECONNRESET || prev == WSAECONNRESET) return err;
264 prev = err;
265 }
266 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
267 }
268 }
269
270 /*-------------------------------------------------------------------------*\
271 * Recvfrom with timeout
272 \*-------------------------------------------------------------------------*/
socket_recvfrom(p_socket ps,char * data,size_t count,size_t * got,SA * addr,socklen_t * len,p_timeout tm)273 int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
274 SA *addr, socklen_t *len, p_timeout tm)
275 {
276 int err, prev = IO_DONE;
277 *got = 0;
278 if (*ps == SOCKET_INVALID) return IO_CLOSED;
279 for ( ;; ) {
280 int taken = recvfrom(*ps, data, (int) count, 0, addr, len);
281 if (taken > 0) {
282 *got = taken;
283 return IO_DONE;
284 }
285 if (taken == 0) return IO_CLOSED;
286 err = WSAGetLastError();
287 /* On UDP, a connreset simply means the previous send failed.
288 * So we try again.
289 * On TCP, it means our socket is now useless, so the error passes.
290 * (We will loop again, exiting because the same error will happen) */
291 if (err != WSAEWOULDBLOCK) {
292 if (err != WSAECONNRESET || prev == WSAECONNRESET) return err;
293 prev = err;
294 }
295 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
296 }
297 }
298
299 /*-------------------------------------------------------------------------*\
300 * Put socket into blocking mode
301 \*-------------------------------------------------------------------------*/
socket_setblocking(p_socket ps)302 void socket_setblocking(p_socket ps) {
303 u_long argp = 0;
304 ioctlsocket(*ps, FIONBIO, &argp);
305 }
306
307 /*-------------------------------------------------------------------------*\
308 * Put socket into non-blocking mode
309 \*-------------------------------------------------------------------------*/
socket_setnonblocking(p_socket ps)310 void socket_setnonblocking(p_socket ps) {
311 u_long argp = 1;
312 ioctlsocket(*ps, FIONBIO, &argp);
313 }
314
315 /*-------------------------------------------------------------------------*\
316 * DNS helpers
317 \*-------------------------------------------------------------------------*/
socket_gethostbyaddr(const char * addr,socklen_t len,struct hostent ** hp)318 int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) {
319 *hp = gethostbyaddr(addr, len, AF_INET);
320 if (*hp) return IO_DONE;
321 else return WSAGetLastError();
322 }
323
socket_gethostbyname(const char * addr,struct hostent ** hp)324 int socket_gethostbyname(const char *addr, struct hostent **hp) {
325 *hp = gethostbyname(addr);
326 if (*hp) return IO_DONE;
327 else return WSAGetLastError();
328 }
329
330 /*-------------------------------------------------------------------------*\
331 * Error translation functions
332 \*-------------------------------------------------------------------------*/
socket_hoststrerror(int err)333 const char *socket_hoststrerror(int err) {
334 if (err <= 0) return io_strerror(err);
335 switch (err) {
336 case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND;
337 default: return wstrerror(err);
338 }
339 }
340
socket_strerror(int err)341 const char *socket_strerror(int err) {
342 if (err <= 0) return io_strerror(err);
343 switch (err) {
344 case WSAEADDRINUSE: return PIE_ADDRINUSE;
345 case WSAECONNREFUSED : return PIE_CONNREFUSED;
346 case WSAEISCONN: return PIE_ISCONN;
347 case WSAEACCES: return PIE_ACCESS;
348 case WSAECONNABORTED: return PIE_CONNABORTED;
349 case WSAECONNRESET: return PIE_CONNRESET;
350 case WSAETIMEDOUT: return PIE_TIMEDOUT;
351 default: return wstrerror(err);
352 }
353 }
354
socket_ioerror(p_socket ps,int err)355 const char *socket_ioerror(p_socket ps, int err) {
356 (void) ps;
357 return socket_strerror(err);
358 }
359
wstrerror(int err)360 static const char *wstrerror(int err) {
361 switch (err) {
362 case WSAEINTR: return "Interrupted function call";
363 case WSAEACCES: return PIE_ACCESS; // "Permission denied";
364 case WSAEFAULT: return "Bad address";
365 case WSAEINVAL: return "Invalid argument";
366 case WSAEMFILE: return "Too many open files";
367 case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
368 case WSAEINPROGRESS: return "Operation now in progress";
369 case WSAEALREADY: return "Operation already in progress";
370 case WSAENOTSOCK: return "Socket operation on nonsocket";
371 case WSAEDESTADDRREQ: return "Destination address required";
372 case WSAEMSGSIZE: return "Message too long";
373 case WSAEPROTOTYPE: return "Protocol wrong type for socket";
374 case WSAENOPROTOOPT: return "Bad protocol option";
375 case WSAEPROTONOSUPPORT: return "Protocol not supported";
376 case WSAESOCKTNOSUPPORT: return PIE_SOCKTYPE; // "Socket type not supported";
377 case WSAEOPNOTSUPP: return "Operation not supported";
378 case WSAEPFNOSUPPORT: return "Protocol family not supported";
379 case WSAEAFNOSUPPORT: return PIE_FAMILY; // "Address family not supported by protocol family";
380 case WSAEADDRINUSE: return PIE_ADDRINUSE; // "Address already in use";
381 case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
382 case WSAENETDOWN: return "Network is down";
383 case WSAENETUNREACH: return "Network is unreachable";
384 case WSAENETRESET: return "Network dropped connection on reset";
385 case WSAECONNABORTED: return "Software caused connection abort";
386 case WSAECONNRESET: return PIE_CONNRESET; // "Connection reset by peer";
387 case WSAENOBUFS: return "No buffer space available";
388 case WSAEISCONN: return PIE_ISCONN; // "Socket is already connected";
389 case WSAENOTCONN: return "Socket is not connected";
390 case WSAESHUTDOWN: return "Cannot send after socket shutdown";
391 case WSAETIMEDOUT: return PIE_TIMEDOUT; // "Connection timed out";
392 case WSAECONNREFUSED: return PIE_CONNREFUSED; // "Connection refused";
393 case WSAEHOSTDOWN: return "Host is down";
394 case WSAEHOSTUNREACH: return "No route to host";
395 case WSAEPROCLIM: return "Too many processes";
396 case WSASYSNOTREADY: return "Network subsystem is unavailable";
397 case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range";
398 case WSANOTINITIALISED:
399 return "Successful WSAStartup not yet performed";
400 case WSAEDISCON: return "Graceful shutdown in progress";
401 case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; // "Host not found";
402 case WSATRY_AGAIN: return "Nonauthoritative host not found";
403 case WSANO_RECOVERY: return PIE_FAIL; // "Nonrecoverable name lookup error";
404 case WSANO_DATA: return "Valid name, no data record of requested type";
405 default: return "Unknown error";
406 }
407 }
408
socket_gaistrerror(int err)409 const char *socket_gaistrerror(int err) {
410 if (err == 0) return NULL;
411 switch (err) {
412 case EAI_AGAIN: return PIE_AGAIN;
413 case EAI_BADFLAGS: return PIE_BADFLAGS;
414 #ifdef EAI_BADHINTS
415 case EAI_BADHINTS: return PIE_BADHINTS;
416 #endif
417 case EAI_FAIL: return PIE_FAIL;
418 case EAI_FAMILY: return PIE_FAMILY;
419 case EAI_MEMORY: return PIE_MEMORY;
420 case EAI_NONAME: return PIE_NONAME;
421 #ifdef EAI_OVERFLOW
422 case EAI_OVERFLOW: return PIE_OVERFLOW;
423 #endif
424 #ifdef EAI_PROTOCOL
425 case EAI_PROTOCOL: return PIE_PROTOCOL;
426 #endif
427 case EAI_SERVICE: return PIE_SERVICE;
428 case EAI_SOCKTYPE: return PIE_SOCKTYPE;
429 #ifdef EAI_SYSTEM
430 case EAI_SYSTEM: return strerror(errno);
431 #endif
432 default: return gai_strerrorA(err);
433 }
434 }
435
436 #endif