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