src/wsocket.c

changeset 0
f7d2d78eb424
equal deleted inserted replaced
-1:000000000000 0:f7d2d78eb424
1 /*=========================================================================*\
2 * LuaSocket 2.0.2
3 * Copyright (C) 2004-2007 Diego Nehab
4 *
5 * Socket compatibilization module for Win32
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 * RCS ID: $Id: wsocket.c,v 1.36 2007/06/11 23:44:54 diego Exp $
11 \*=========================================================================*/
12 #include <string.h>
13
14 #include "socket.h"
15
16 /*-------------------------------------------------------------------------*\
17 * Initializes module
18 \*-------------------------------------------------------------------------*/
19 int socket_open(void) {
20 WSADATA wsaData;
21 WORD wVersionRequested = MAKEWORD(2, 0);
22 int err = WSAStartup(wVersionRequested, &wsaData );
23 if (err != 0) return 0;
24 if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) &&
25 (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) {
26 WSACleanup();
27 return 0;
28 }
29 return 1;
30 }
31
32 /*-------------------------------------------------------------------------*\
33 * Close module
34 \*-------------------------------------------------------------------------*/
35 int socket_close(void) {
36 WSACleanup();
37 return 1;
38 }
39
40 /*-------------------------------------------------------------------------*\
41 * Wait for readable/writable/connected socket with timeout
42 \*-------------------------------------------------------------------------*/
43 int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
44 int ret;
45 fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL;
46 struct timeval tv, *tp = NULL;
47 double t;
48 if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
49 if (sw & WAITFD_R) {
50 FD_ZERO(&rfds);
51 FD_SET(*ps, &rfds);
52 rp = &rfds;
53 }
54 if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
55 if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; }
56 if ((t = timeout_get(tm)) >= 0.0) {
57 tv.tv_sec = (int) t;
58 tv.tv_usec = (int) ((t-tv.tv_sec)*1.0e6);
59 tp = &tv;
60 }
61 ret = select(0, rp, wp, ep, tp);
62 if (ret == -1) return WSAGetLastError();
63 if (ret == 0) return IO_TIMEOUT;
64 if (sw == WAITFD_C && FD_ISSET(*ps, &efds)) return IO_CLOSED;
65 return IO_DONE;
66 }
67
68 /*-------------------------------------------------------------------------*\
69 * Close and inutilize socket
70 \*-------------------------------------------------------------------------*/
71 void socket_destroy(p_socket ps) {
72 if (*ps != SOCKET_INVALID) {
73 socket_setblocking(ps); /* close can take a long time on WIN32 */
74 closesocket(*ps);
75 *ps = SOCKET_INVALID;
76 }
77 }
78
79 /*-------------------------------------------------------------------------*\
80 * Put socket into blocking mode
81 \*-------------------------------------------------------------------------*/
82 void socket_setblocking(p_socket ps) {
83 u_long argp = 0;
84 ioctlsocket(*ps, FIONBIO, &argp);
85 }
86
87 /*-------------------------------------------------------------------------*\
88 * Put socket into non-blocking mode
89 \*-------------------------------------------------------------------------*/
90 void socket_setnonblocking(p_socket ps) {
91 u_long argp = 1;
92 ioctlsocket(*ps, FIONBIO, &argp);
93 }
94
95 /*-------------------------------------------------------------------------*\
96 * Error translation functions
97 \*-------------------------------------------------------------------------*/
98
99 /* WinSock doesn't have a strerror... */
100 static const char *wstrerror(int err) {
101 switch (err) {
102 case WSAEINTR: return "Interrupted function call";
103 case WSAEACCES: return "Permission denied";
104 case WSAEFAULT: return "Bad address";
105 case WSAEINVAL: return "Invalid argument";
106 case WSAEMFILE: return "Too many open files";
107 case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
108 case WSAEINPROGRESS: return "Operation now in progress";
109 case WSAEALREADY: return "Operation already in progress";
110 case WSAENOTSOCK: return "Socket operation on nonsocket";
111 case WSAEDESTADDRREQ: return "Destination address required";
112 case WSAEMSGSIZE: return "Message too long";
113 case WSAEPROTOTYPE: return "Protocol wrong type for socket";
114 case WSAENOPROTOOPT: return "Bad protocol option";
115 case WSAEPROTONOSUPPORT: return "Protocol not supported";
116 case WSAESOCKTNOSUPPORT: return "Socket type not supported";
117 case WSAEOPNOTSUPP: return "Operation not supported";
118 case WSAEPFNOSUPPORT: return "Protocol family not supported";
119 case WSAEAFNOSUPPORT:
120 return "Address family not supported by protocol family";
121 case WSAEADDRINUSE: return "Address already in use";
122 case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
123 case WSAENETDOWN: return "Network is down";
124 case WSAENETUNREACH: return "Network is unreachable";
125 case WSAENETRESET: return "Network dropped connection on reset";
126 case WSAECONNABORTED: return "Software caused connection abort";
127 case WSAECONNRESET: return "Connection reset by peer";
128 case WSAENOBUFS: return "No buffer space available";
129 case WSAEISCONN: return "Socket is already connected";
130 case WSAENOTCONN: return "Socket is not connected";
131 case WSAESHUTDOWN: return "Cannot send after socket shutdown";
132 case WSAETIMEDOUT: return "Connection timed out";
133 case WSAECONNREFUSED: return "Connection refused";
134 case WSAEHOSTDOWN: return "Host is down";
135 case WSAEHOSTUNREACH: return "No route to host";
136 case WSAEPROCLIM: return "Too many processes";
137 case WSASYSNOTREADY: return "Network subsystem is unavailable";
138 case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range";
139 case WSANOTINITIALISED:
140 return "Successful WSAStartup not yet performed";
141 case WSAEDISCON: return "Graceful shutdown in progress";
142 case WSAHOST_NOT_FOUND: return "Host not found";
143 case WSATRY_AGAIN: return "Nonauthoritative host not found";
144 case WSANO_RECOVERY: return "Nonrecoverable name lookup error";
145 case WSANO_DATA: return "Valid name, no data record of requested type";
146 default: return "Unknown error";
147 }
148 }
149
150 const char *socket_strerror(int err) {
151 if (err <= 0) return io_strerror(err);
152 switch (err) {
153 case WSAEADDRINUSE: return "address already in use";
154 case WSAECONNREFUSED: return "connection refused";
155 case WSAEISCONN: return "already connected";
156 case WSAEACCES: return "permission denied";
157 case WSAECONNABORTED: return "closed";
158 case WSAECONNRESET: return "closed";
159 case WSAETIMEDOUT: return "timeout";
160 default: return wstrerror(err);
161 }
162 }
163
164 /* Socket error code */
165 int socket_error()
166 {
167 return WSAGetLastError();
168 }
169

mercurial