Quake II RTX doxygen  1.0 dev
win.h
Go to the documentation of this file.
1 /*
2 Copyright (C) 2012 Andrey Nazarov
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 //
20 // net_win.h -- Windows sockets wrapper
21 //
22 
23 static const struct {
24  int err;
25  const char *msg;
26 } wsa_error_table[] = {
27  { S_OK, "Success" },
28  { WSAEINTR, "Interrupted function call" },
29  { WSAEBADF, "File handle is not valid" },
30  { WSAEACCES, "Permission denied" },
31  { WSAEFAULT, "Bad address" },
32  { WSAEINVAL, "Invalid argument" },
33  { WSAEMFILE, "Too many open files" },
34  { WSAEWOULDBLOCK, "Resource temporarily unavailable" },
35  { WSAEINPROGRESS, "Operation now in progress" },
36  { WSAEALREADY, "Operation already in progress" },
37  { WSAENOTSOCK, "Socket operation on nonsocket" },
38  { WSAEDESTADDRREQ, "Destination address required" },
39  { WSAEMSGSIZE, "Message too long" },
40  { WSAEPROTOTYPE, "Protocol wrong type for socket" },
41  { WSAENOPROTOOPT, "Bad protocol option" },
42  { WSAEPROTONOSUPPORT, "Protocol not supported" },
43  { WSAESOCKTNOSUPPORT, "Socket type not supported" },
44  { WSAEOPNOTSUPP, "Operation not supported" },
45  { WSAEPFNOSUPPORT, "Protocol family not supported" },
46  { WSAEAFNOSUPPORT, "Address family not supported by protocol family" },
47  { WSAEADDRINUSE, "Address already in use" },
48  { WSAEADDRNOTAVAIL, "Cannot assign requested address" },
49  { WSAENETDOWN, "Network is down" },
50  { WSAENETUNREACH, "Network is unreachable" },
51  { WSAENETRESET, "Network dropped connection on reset" },
52  { WSAECONNABORTED, "Software caused connection abort" },
53  { WSAECONNRESET, "Connection reset by peer" },
54  { WSAENOBUFS, "No buffer space available" },
55  { WSAEISCONN, "Socket is already connected" },
56  { WSAENOTCONN, "Socket is not connected" },
57  { WSAESHUTDOWN, "Cannot send after socket shutdown" },
58  { WSAETOOMANYREFS, "Too many references" },
59  { WSAETIMEDOUT, "Connection timed out" },
60  { WSAECONNREFUSED, "Connection refused" },
61  { WSAELOOP, "Cannot translate name" },
62  { WSAENAMETOOLONG, "Name too long" },
63  { WSAEHOSTDOWN, "Host is down" },
64  { WSAEHOSTUNREACH, "No route to host" },
65  { WSAENOTEMPTY, "Directory not empty" },
66  { WSAEPROCLIM, "Too many processes" },
67  { WSAEUSERS, "User quota exceeded" },
68  { WSAEDQUOT, "Disk quota exceeded" },
69  { WSAESTALE, "Stale file handle reference" },
70  { WSAEREMOTE, "Item is remote" },
71  { WSASYSNOTREADY, "Network subsystem is unavailable" },
72  { WSAVERNOTSUPPORTED, "Winsock.dll version out of range" },
73  { WSANOTINITIALISED, "Successful WSAStartup not yet performed" },
74  { WSAEDISCON, "Graceful shutdown in progress" },
75  { WSAENOMORE, "No more results" },
76  { WSAECANCELLED, "Call has been canceled" },
77  { WSAEINVALIDPROCTABLE, "Procedure call table is invalid" },
78  { WSAEINVALIDPROVIDER, "Service provider is invalid" },
79  { WSAEPROVIDERFAILEDINIT, "Service provider failed to initialize" },
80  { WSASYSCALLFAILURE, "System call failure" },
81  { WSASERVICE_NOT_FOUND, "Service not found" },
82  { WSATYPE_NOT_FOUND, "Class type not found" },
83  { WSA_E_NO_MORE, "No more results" },
84  { WSA_E_CANCELLED, "Call was canceled" },
85  { WSAEREFUSED, "Database query was refused" },
86  { WSAHOST_NOT_FOUND, "Host not found" },
87  { WSATRY_AGAIN, "Nonauthoritative host not found" },
88  { WSANO_RECOVERY, "This is a nonrecoverable error" },
89  { WSANO_DATA, "Valid name, no data record of requested type" },
90  { -1, "Unknown error" }
91 };
92 
93 static const char *os_error_string(int err)
94 {
95  int i;
96 
97  for (i = 0; wsa_error_table[i].err != -1; i++) {
98  if (wsa_error_table[i].err == err)
99  break;
100  }
101 
102  return wsa_error_table[i].msg;
103 }
104 
105 static ssize_t os_udp_recv(qsocket_t sock, void *data,
106  size_t len, netadr_t *from)
107 {
108  struct sockaddr_storage addr;
109  int addrlen;
110  int ret;
111  int tries;
112 
113  for (tries = 0; tries < MAX_ERROR_RETRIES; tries++) {
114  memset(&addr, 0, sizeof(addr));
115  addrlen = sizeof(addr);
116  ret = recvfrom(sock, data, len, 0,
117  (struct sockaddr *)&addr, &addrlen);
118 
119  NET_SockadrToNetadr(&addr, from);
120 
121  if (ret != SOCKET_ERROR)
122  return ret;
123 
124  net_error = WSAGetLastError();
125 
126  // wouldblock is silent
127  if (net_error == WSAEWOULDBLOCK)
128  return NET_AGAIN;
129 
130 #if USE_ICMP
131  if (net_error == WSAECONNRESET || net_error == WSAENETRESET) {
132  // winsock has already provided us with
133  // a valid address from ICMP error packet
134  NET_ErrorEvent(sock, from, net_error, 0);
135  continue;
136  }
137 #endif
138 
139  break;
140  }
141 
142  return NET_ERROR;
143 }
144 
145 static ssize_t os_udp_send(qsocket_t sock, const void *data,
146  size_t len, const netadr_t *to)
147 {
148  struct sockaddr_storage addr;
149  int addrlen;
150  int ret;
151 
152  addrlen = NET_NetadrToSockadr(to, &addr);
153 
154  ret = sendto(sock, data, len, 0,
155  (struct sockaddr *)&addr, addrlen);
156 
157  if (ret != SOCKET_ERROR)
158  return ret;
159 
160  net_error = WSAGetLastError();
161 
162  // wouldblock is silent
163  if (net_error == WSAEWOULDBLOCK || net_error == WSAEINTR)
164  return NET_AGAIN;
165 
166  // some PPP links do not allow broadcasts
167  if (net_error == WSAEADDRNOTAVAIL && to->type == NA_BROADCAST)
168  return NET_AGAIN;
169 
170  return NET_ERROR;
171 }
172 
173 static neterr_t os_get_error(void)
174 {
175  net_error = WSAGetLastError();
176  if (net_error == WSAEWOULDBLOCK)
177  return NET_AGAIN;
178 
179  return NET_ERROR;
180 }
181 
182 static ssize_t os_recv(qsocket_t sock, void *data, size_t len, int flags)
183 {
184  int ret = recv(sock, data, len, flags);
185 
186  if (ret == SOCKET_ERROR)
187  return os_get_error();
188 
189  return ret;
190 }
191 
192 static ssize_t os_send(qsocket_t sock, const void *data, size_t len, int flags)
193 {
194  int ret = send(sock, data, len, flags);
195 
196  if (ret == SOCKET_ERROR)
197  return os_get_error();
198 
199  return ret;
200 }
201 
202 static neterr_t os_listen(qsocket_t sock, int backlog)
203 {
204  if (listen(sock, backlog) == SOCKET_ERROR) {
205  net_error = WSAGetLastError();
206  return NET_ERROR;
207  }
208 
209  return NET_OK;
210 }
211 
212 static neterr_t os_accept(qsocket_t sock, qsocket_t *newsock, netadr_t *from)
213 {
214  struct sockaddr_storage addr;
215  int addrlen;
216  SOCKET s;
217 
218  memset(&addr, 0, sizeof(addr));
219  addrlen = sizeof(addr);
220  s = accept(sock, (struct sockaddr *)&addr, &addrlen);
221 
222  NET_SockadrToNetadr(&addr, from);
223 
224  if (s == INVALID_SOCKET) {
225  *newsock = -1;
226  return os_get_error();
227  }
228 
229  *newsock = s;
230  return NET_OK;
231 }
232 
233 static neterr_t os_connect(qsocket_t sock, const netadr_t *to)
234 {
235  struct sockaddr_storage addr;
236  int addrlen;
237 
238  addrlen = NET_NetadrToSockadr(to, &addr);
239 
240  if (connect(sock, (struct sockaddr *)&addr, addrlen) == SOCKET_ERROR) {
241  net_error = WSAGetLastError();
242  if (net_error == WSAEWOULDBLOCK)
243  return NET_OK;
244 
245  return NET_ERROR;
246  }
247 
248  return NET_OK;
249 }
250 
251 static neterr_t os_make_nonblock(qsocket_t sock, int val)
252 {
253  u_long _val = val;
254 
255  if (ioctlsocket(sock, FIONBIO, &_val) == SOCKET_ERROR) {
256  net_error = WSAGetLastError();
257  return NET_ERROR;
258  }
259 
260  return NET_OK;
261 }
262 
263 static neterr_t os_setsockopt(qsocket_t sock, int level, int name, int val)
264 {
265  u_long _val = val;
266 
267  if (setsockopt(sock, level, name, (char *)&_val, sizeof(_val)) == SOCKET_ERROR) {
268  net_error = WSAGetLastError();
269  return NET_ERROR;
270  }
271 
272  return NET_OK;
273 }
274 
275 static neterr_t os_getsockopt(qsocket_t sock, int level, int name, int *val)
276 {
277  u_long _val;
278  int optlen = sizeof(_val);
279 
280  if (getsockopt(sock, level, name, (char *)&_val, &optlen) == SOCKET_ERROR) {
281  net_error = WSAGetLastError();
282  return NET_ERROR;
283  }
284 
285  *val = _val;
286  return NET_OK;
287 }
288 
289 static neterr_t os_bind(qsocket_t sock, const struct sockaddr *addr, size_t addrlen)
290 {
291  if (bind(sock, addr, addrlen) == SOCKET_ERROR) {
292  net_error = WSAGetLastError();
293  return NET_ERROR;
294  }
295 
296  return NET_OK;
297 }
298 
299 static neterr_t os_getsockname(qsocket_t sock, netadr_t *name)
300 {
301  struct sockaddr_storage addr;
302  int addrlen;
303 
304  memset(&addr, 0, sizeof(addr));
305  addrlen = sizeof(addr);
306  if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) == SOCKET_ERROR) {
307  net_error = WSAGetLastError();
308  return NET_ERROR;
309  }
310 
311  NET_SockadrToNetadr(&addr, name);
312  return NET_OK;
313 }
314 
315 static void os_closesocket(qsocket_t sock)
316 {
317  closesocket(sock);
318 }
319 
320 static qsocket_t os_socket(int domain, int type, int protocol)
321 {
322  SOCKET s = socket(domain, type, protocol);
323 
324  if (s == INVALID_SOCKET) {
325  net_error = WSAGetLastError();
326  return -1;
327  }
328 
329  return s;
330 }
331 
332 static ioentry_t *os_add_io(qsocket_t fd)
333 {
334  ioentry_t *e;
335  int i;
336 
337  for (i = 0, e = io_entries; i < io_numfds; i++, e++) {
338  if (!e->inuse)
339  break;
340  }
341 
342  if (i == io_numfds) {
343  if (++io_numfds > FD_SETSIZE)
344  Com_Error(ERR_FATAL, "%s: no more space for fd: %Id", __func__, fd);
345  }
346 
347  e->fd = fd;
348  return e;
349 }
350 
351 static ioentry_t *os_get_io(qsocket_t fd)
352 {
353  ioentry_t *e;
354  int i;
355 
356  for (i = 0, e = io_entries; i < io_numfds; i++, e++) {
357  if (!e->inuse)
358  continue;
359  if (e->fd == fd)
360  return e;
361  }
362 
363  Com_Error(ERR_FATAL, "%s: fd not found: %Id", __func__, fd);
364  return NULL;
365 }
366 
367 static qsocket_t os_get_fd(ioentry_t *e)
368 {
369  return e->fd;
370 }
371 
372 static int os_select(int nfds, fd_set *rfds, fd_set *wfds,
373  fd_set *efds, struct timeval *tv)
374 {
375  int ret = select(nfds, rfds, wfds, efds, tv);
376 
377  if (ret == SOCKET_ERROR)
378  net_error = WSAGetLastError();
379 
380  return ret;
381 }
382 
383 static void os_net_init(void)
384 {
385  WSADATA ws;
386  int ret;
387 
388  ret = WSAStartup(MAKEWORD(1, 1), &ws);
389  if (ret) {
390  Com_Error(ERR_FATAL, "Winsock initialization failed: %s (%d)",
391  os_error_string(ret), ret);
392  }
393 
394  Com_DPrintf("Winsock initialized\n");
395 }
396 
397 static void os_net_shutdown(void)
398 {
399  WSACleanup();
400 }
401 
os_bind
static neterr_t os_bind(qsocket_t sock, const struct sockaddr *addr, size_t addrlen)
Definition: win.h:289
os_getsockname
static neterr_t os_getsockname(qsocket_t sock, netadr_t *name)
Definition: win.h:299
os_net_init
static void os_net_init(void)
Definition: win.h:383
os_udp_recv
static ssize_t os_udp_recv(qsocket_t sock, void *data, size_t len, netadr_t *from)
Definition: win.h:105
MAX_ERROR_RETRIES
#define MAX_ERROR_RETRIES
Definition: net.c:65
net_error
static int net_error
Definition: net.c:110
os_setsockopt
static neterr_t os_setsockopt(qsocket_t sock, int level, int name, int val)
Definition: win.h:263
os_make_nonblock
static neterr_t os_make_nonblock(qsocket_t sock, int val)
Definition: win.h:251
tv
float * tv(float x, float y, float z)
Definition: g_utils.c:248
os_get_io
static ioentry_t * os_get_io(qsocket_t fd)
Definition: win.h:351
os_getsockopt
static neterr_t os_getsockopt(qsocket_t sock, int level, int name, int *val)
Definition: win.h:275
os_add_io
static ioentry_t * os_add_io(qsocket_t fd)
Definition: win.h:332
os_error_string
static const char * os_error_string(int err)
Definition: win.h:93
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
io_numfds
static int io_numfds
Definition: net.c:123
os_closesocket
static void os_closesocket(qsocket_t sock)
Definition: win.h:315
os_socket
static qsocket_t os_socket(int domain, int type, int protocol)
Definition: win.h:320
NET_SockadrToNetadr
static void NET_SockadrToNetadr(const struct sockaddr_storage *s, netadr_t *a)
Definition: net.c:176
os_listen
static neterr_t os_listen(qsocket_t sock, int backlog)
Definition: win.h:202
NET_NetadrToSockadr
static size_t NET_NetadrToSockadr(const netadr_t *a, struct sockaddr_storage *s)
Definition: net.c:145
os_udp_send
static ssize_t os_udp_send(qsocket_t sock, const void *data, size_t len, const netadr_t *to)
Definition: win.h:145
os_accept
static neterr_t os_accept(qsocket_t sock, qsocket_t *newsock, netadr_t *from)
Definition: win.h:212
os_get_fd
static qsocket_t os_get_fd(ioentry_t *e)
Definition: win.h:367
io_entries
static ioentry_t io_entries[FD_SETSIZE]
Definition: net.c:122
os_send
static ssize_t os_send(qsocket_t sock, const void *data, size_t len, int flags)
Definition: win.h:192
os_recv
static ssize_t os_recv(qsocket_t sock, void *data, size_t len, int flags)
Definition: win.h:182
level
level_locals_t level
Definition: g_main.c:22
err
int err
Definition: win.h:24
msg
const char * msg
Definition: win.h:25
os_get_error
static neterr_t os_get_error(void)
Definition: win.h:173
os_net_shutdown
static void os_net_shutdown(void)
Definition: win.h:397
os_connect
static neterr_t os_connect(qsocket_t sock, const netadr_t *to)
Definition: win.h:233
wsa_error_table
static const struct @10 wsa_error_table[]
os_select
static int os_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
Definition: win.h:372