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