1 /*
2 * file w32_socket.c - true bsd sockets for xblast
3 *
4 * $Id: w32_socket.c,v 1.13 2006/02/19 13:33:01 lodott Exp $
5 *
6 * Program XBLAST
7 * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2; or (at your option)
12 * any later version
13 *
14 * This program is distributed in the hope that it will be entertaining,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23 #include "xblast.h"
24 #define __USE_W32_SOCKETS
25 #include <winsock2.h>
26 #include <ws2tcpip.h>
27 #include "socket.h"
28 #include "w32_socket.h"
29 #include "w32_event.h"
30 #include "str_util.h"
31 #include "com.h"
32 #include "gui.h"
33
34 /*
35 * local constants
36 */
37 #define LISTENQ 5
38 /* needed winsock version */
39 #define WINSOCK_VERSION (MAKEWORD (2, 0))
40 /* maximum number of sockets in map */
41 #define MAX_SOCKET 64
42 /* interface detection modes */
43 #define XBIF_MS 0x01
44 #define XBIF_MOD 0x02
45
46 /*
47 * type definitions
48 */
49
50 /* socket address */
51 typedef struct _xb_socket_address
52 {
53 int len; /* allocated length */
54 struct sockaddr *addr; /* protocol dependent data */
55 } XBSocketAddress;
56
57 /* socket data */
58 struct _xb_socket
59 {
60 SOCKET fd; /* file descriptor */
61 XBSocketAddress sock; /* local address */
62 XBSocketAddress peer; /* remote address */
63 XBBool read; /* read flag */
64 XBBool write; /* write flag */
65 XBBool shutdown; /* shutdown flag */
66 };
67
68 /* list of all sockets */
69 typedef struct
70 {
71 size_t num;
72 SOCKET fd[MAX_SOCKET];
73 const XBSocket *socket[MAX_SOCKET];
74 } XBSocketMap;
75
76 /* modified sockaddr_gen, to deal with winsock bug */
77 typedef union sockaddr_genk
78 {
79 struct sockaddr address;
80 struct sockaddr_in addressIn;
81 struct sockaddr_in6 addressIn6;
82 } sockaddr_genk;
83
84 /* modified INTERFACE_INFO using the modified sockaddr_gen */
85 typedef struct _interface_info_mod
86 {
87 u_long iiFlags; /* Interface flags */
88 sockaddr_genk iiAddress; /* Interface address */
89 sockaddr_genk iiBroadcastAddress; /* Broadcast address */
90 sockaddr_genk iiNetmask; /* Network mask */
91 } INTERFACE_INFO_MOD;
92
93 /* both INTERFACE_INFO versions */
94 typedef union
95 {
96 INTERFACE_INFO ms;
97 INTERFACE_INFO_MOD mod;
98 } XB_INTERFACE_INFO;
99
100 /*
101 * local variables
102 */
103 static XBSocketMap socketMap; /* socket list */
104 static XBSocketInterface *inter = NULL; /* interface list */
105 static size_t numInter = 0; /* number of interfaces */
106 static short modeflags = 0; /* interface detection mode */
107
108 /***************
109 * local stuff *
110 ***************/
111
112 /**/ static void AsyncSelect (const XBSocket * pSocket);
113
114 /*
115 * delete list with all interfaces
116 */
117 static void
DeleteInterfaces(void)118 DeleteInterfaces (void)
119 {
120 if (NULL != inter) {
121 size_t i;
122 for (i = 0; i < numInter; i++) {
123 if (NULL != inter[i].name) {
124 free (inter[i].name);
125 }
126 if (NULL != inter[i].addrDevice) {
127 free (inter[i].addrDevice);
128 }
129 if (NULL != inter[i].addrBroadcast) {
130 free (inter[i].addrBroadcast);
131 }
132 }
133 free (inter);
134 }
135 inter = NULL;
136 numInter = 0;
137 } /* DeleteInterfaces */
138
139 /*
140 * get inet address from string, host byte order
141 */
142 static unsigned long
GetAddressInet(const char * hostName)143 GetAddressInet (const char *hostName)
144 {
145 long addr;
146 struct hostent *serverEnt;
147 assert (hostName != NULL);
148 /* check if ip string */
149 if (-1L != (addr = inet_addr (hostName))) {
150 return ntohl (addr);
151 }
152 /* lookup hostname if not an ip string */
153 if (NULL != (serverEnt = gethostbyname (hostName))) {
154 return ntohl (*(long *)serverEnt->h_addr_list[0]);
155 }
156 /* lookup failed */
157 return 0L;
158 } /* GetAddressInet */
159
160 /***************************
161 * general socket managing *
162 ***************************/
163
164 /*
165 * initialize winsock
166 */
167 XBBool
Socket_Init(void)168 Socket_Init (void)
169 {
170 WSADATA wsaData;
171 memset (&socketMap, 0, sizeof (XBSocketMap));
172 if (0 != WSAStartup (WINSOCK_VERSION, &wsaData)) {
173 GUI_ErrorMessage ("winsock startup failed - unknown version\n");
174 return XBFalse;
175 }
176 if (wsaData.wVersion != WINSOCK_VERSION) {
177 GUI_ErrorMessage ("winsock startup failed - wrong version (2.0 required)\n");
178 WSACleanup ();
179 return XBFalse;
180 }
181 return XBTrue;
182 } /* Socket_Init */
183
184 /*
185 * add socket to list
186 */
187 static void
SocketMapAdd(XBSocketMap * map,const XBSocket * pSocket)188 SocketMapAdd (XBSocketMap * map, const XBSocket * pSocket)
189 {
190 assert (NULL != socket);
191 assert (NULL != map);
192 assert (map->num < MAX_SOCKET);
193 Dbg_Socket ("add fd=%u at map position #%u\n", pSocket->fd, map->num);
194 map->fd[map->num] = pSocket->fd;
195 map->socket[map->num] = pSocket;
196 map->num++;
197 } /* SocketMapAdd */
198
199 /*
200 * subtract socket from set
201 */
202 static void
SocketMapSubtract(XBSocketMap * map,const XBSocket * pSocket)203 SocketMapSubtract (XBSocketMap * map, const XBSocket * pSocket)
204 {
205 size_t i;
206
207 assert (NULL != socket);
208 assert (NULL != map);
209 assert (map->num > 0);
210 for (i = 0; i < map->num; i++) {
211 if (map->socket[i] == pSocket) {
212 Dbg_Socket ("sub fd=%u from map pos #%u (total %u)\n", pSocket->fd, i, map->num);
213 map->num--;
214 if (i < map->num) {
215 map->fd[i] = map->fd[map->num];
216 map->socket[i] = map->socket[map->num];
217 }
218 }
219 }
220 } /* SocketMapSubtract */
221
222 /*
223 * find socket to fd
224 */
225 static const XBSocket *
SocketMapFind(XBSocketMap * map,SOCKET fd)226 SocketMapFind (XBSocketMap * map, SOCKET fd)
227 {
228 size_t i;
229
230 assert (NULL != socket);
231 assert (NULL != map);
232 for (i = 0; i < map->num; i++) {
233 if (map->fd[i] == fd) {
234 return map->socket[i];
235 }
236 }
237 return NULL;
238 } /* SocketMapFind */
239
240 /*
241 * shutdown winsock
242 */
243 void
Socket_Finish(void)244 Socket_Finish (void)
245 {
246 Dbg_Socket ("shutting down winsock\n");
247 DeleteInterfaces ();
248 WSACleanup ();
249 } /* Socket_Finish */
250
251 /***************
252 * socket data *
253 ***************/
254
255 /*
256 * return file descriptor for socket
257 */
258 int
Socket_Fd(const XBSocket * pSocket)259 Socket_Fd (const XBSocket * pSocket)
260 {
261 assert (NULL != pSocket);
262 return pSocket->fd;
263 } /* Socket_Fd */
264
265 /*
266 * return adress family for socket
267 */
268 int
Socket_Family(const XBSocket * pSocket)269 Socket_Family (const XBSocket * pSocket)
270 {
271 assert (NULL != pSocket);
272
273 return pSocket->sock.addr->sa_family;
274 } /* Socket_Family */
275
276 /*
277 * get host name of client
278 */
279 const char *
Socket_HostName(const XBSocket * pSocket,XBBool peer)280 Socket_HostName (const XBSocket * pSocket, XBBool peer)
281 {
282 const XBSocketAddress *sa;
283 struct sockaddr_in *inetAddr;
284 assert (NULL != pSocket);
285 /* determine address struct */
286 sa = peer ? &pSocket->peer : &pSocket->sock;
287 assert (NULL != sa);
288 assert (NULL != sa->addr);
289 /* reconstruct address */
290 inetAddr = (struct sockaddr_in *)sa->addr;
291 return inet_ntoa (inetAddr->sin_addr);
292 } /* Socket_HostName */
293
294 /*
295 * get port of host
296 */
297 unsigned
Socket_HostPort(const XBSocket * pSocket,XBBool peer)298 Socket_HostPort (const XBSocket * pSocket, XBBool peer)
299 {
300 const XBSocketAddress *sa;
301 struct sockaddr_in *inetAddr;
302 assert (NULL != pSocket);
303 /* determine address struct */
304 sa = peer ? &pSocket->peer : &pSocket->sock;
305 assert (NULL != sa);
306 assert (NULL != sa->addr);
307 /* reconstruct port */
308 inetAddr = (struct sockaddr_in *)sa->addr;
309 return ntohs (inetAddr->sin_port);
310 } /* Socket_HostPort */
311
312 /*******************
313 * socket creation *
314 *******************
315
316 /*
317 * create socket structure
318 */
319 XBSocket *
Socket_Alloc(int family)320 Socket_Alloc (int family)
321 {
322 int len;
323 XBSocket *pSocket;
324 /* require AF_INET family */
325 switch (family) {
326 case AF_INET:
327 len = sizeof (struct sockaddr_in);
328 break;
329 default:
330 Dbg_Socket ("AF_INET family required, socket not created\n");
331 return NULL;
332 }
333 /* alloc socket data structure */
334 pSocket = calloc (1, sizeof (XBSocket));
335 assert (NULL != pSocket);
336 pSocket->fd = -1;
337 pSocket->read = XBFalse;
338 pSocket->write = XBFalse;
339 pSocket->shutdown = XBFalse;
340 /* out address */
341 pSocket->sock.len = len;
342 pSocket->sock.addr = calloc (1, len);
343 assert (NULL != pSocket->sock.addr);
344 pSocket->sock.addr->sa_family = family;
345 /* other addresse */
346 pSocket->peer.len = len;
347 pSocket->peer.addr = calloc (1, len);
348 assert (NULL != pSocket->peer.addr);
349 pSocket->peer.addr->sa_family = family;
350 /* that's all */
351 return pSocket;
352 } /* Socket_Alloc */
353
354 /*
355 * free socket structure memory
356 */
357 void
Socket_Free(XBSocket * pSocket)358 Socket_Free (XBSocket * pSocket)
359 {
360 assert (NULL != pSocket);
361 if (NULL != pSocket->sock.addr) {
362 free (pSocket->sock.addr);
363 }
364 if (NULL != pSocket->peer.addr) {
365 free (pSocket->peer.addr);
366 }
367 free (pSocket);
368 } /* Socket_Free */
369
370 /*
371 * set socket adress
372 */
373 XBBool
Socket_SetAddressInet(XBSocket * pSocket,XBBool peer,const char * hostName,unsigned short port)374 Socket_SetAddressInet (XBSocket * pSocket, XBBool peer, const char *hostName, unsigned short port)
375 {
376 XBSocketAddress *sa;
377 unsigned long addr;
378 struct sockaddr_in *serverAddr;
379 assert (NULL != pSocket);
380 /* determine address structure to set */
381 sa = peer ? &pSocket->peer : &pSocket->sock;
382 /* get address in host byte order */
383 if (NULL != hostName) {
384 if (0 == (addr = GetAddressInet (hostName))) {
385 Dbg_Socket ("failed to set address %s:%u for fd=%u\n", hostName, port, pSocket->fd);
386 return XBFalse;
387 }
388 }
389 else {
390 addr = INADDR_ANY;
391 }
392 /* now set the address */
393 assert (NULL != sa);
394 memset (sa->addr, 0, sa->len);
395 serverAddr = (struct sockaddr_in *)sa->addr;
396 serverAddr->sin_family = AF_INET;
397 serverAddr->sin_addr.s_addr = htonl (addr);
398 serverAddr->sin_port = htons (port);
399 Dbg_Socket ("set %s address %s:%u for fd=%u\n", peer ? "remote" : "local", hostName, port,
400 pSocket->fd);
401 return XBTrue;
402 } /* Socket_SetAddressInet */
403
404 /*
405 * set broadcast option for socket
406 */
407 XBBool
Socket_SetBroadcast(XBSocket * pSocket,XBBool enable)408 Socket_SetBroadcast (XBSocket * pSocket, XBBool enable)
409 {
410 BOOL flag = enable ? TRUE : FALSE;
411 assert (NULL != pSocket);
412 return (0 == setsockopt (pSocket->fd, SOL_SOCKET, SO_BROADCAST, (void *)&flag, sizeof (flag)));
413 } /* Socket_SetBroadcast */
414
415 /*
416 * set socket option reuse
417 */
418 XBBool
Socket_SetReuse(XBSocket * pSocket)419 Socket_SetReuse (XBSocket * pSocket)
420 {
421 #if 0
422 /* TODO: implement for windows */
423 int so_reuseaddr = 1;
424 if (-1 ==
425 setsockopt (pSocket->fd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof (so_reuseaddr))) {
426 return XBFalse;
427 }
428 /* that's all */
429 #endif
430 return XBTrue;
431 } /* Socket_SetReuse */
432
433 /*
434 * register read socket for event handling
435 */
436 void
Socket_RegisterRead(XBSocket * pSocket)437 Socket_RegisterRead (XBSocket * pSocket)
438 {
439 assert (NULL != pSocket);
440 if (!pSocket->read) {
441 pSocket->read = XBTrue;
442 AsyncSelect (pSocket);
443 }
444 } /* Socket_RegisterRead */
445
446 /*
447 * register read socket for event handling
448 */
449 void
Socket_RegisterWrite(XBSocket * pSocket)450 Socket_RegisterWrite (XBSocket * pSocket)
451 {
452 assert (NULL != pSocket);
453 if (!pSocket->write) {
454 pSocket->write = XBTrue;
455 AsyncSelect (pSocket);
456 }
457 } /* Socket_RegisterWrite */
458
459 /*
460 * register read socket for event handling
461 */
462 void
Socket_UnregisterRead(XBSocket * pSocket)463 Socket_UnregisterRead (XBSocket * pSocket)
464 {
465 assert (NULL != pSocket);
466 if (pSocket->read) {
467 pSocket->read = XBFalse;
468 AsyncSelect (pSocket);
469 }
470 } /* Socket_UnregisterRead */
471
472 /*
473 * register read socket for event handling
474 */
475 void
Socket_UnregisterWrite(XBSocket * pSocket)476 Socket_UnregisterWrite (XBSocket * pSocket)
477 {
478 assert (NULL != pSocket);
479 if (pSocket->write) {
480 pSocket->write = XBFalse;
481 AsyncSelect (pSocket);
482 }
483 } /* Socket_UnregisterWrite */
484
485 /*************
486 * BSD calls *
487 *************
488
489 /*
490 * open socket
491 */
492 XBBool
Socket_Open(XBSocket * pSocket,int type)493 Socket_Open (XBSocket * pSocket, int type)
494 {
495 assert (pSocket != NULL);
496 /* request a socket from system */
497 if (-1 == (pSocket->fd = socket (pSocket->sock.addr->sa_family, type, 0))) {
498 #ifndef WMS
499 Dbg_Socket ("failed to open socket of type=%i, err=%u\n", type, WSAGetLastError ());
500 #endif
501 pSocket->shutdown = XBTrue;
502 return XBFalse;
503 }
504 SocketMapAdd (&socketMap, pSocket);
505 Dbg_Socket ("open socket fd=%u (type=%i)\n", pSocket->fd, type);
506 return XBTrue;
507 } /* Socket_Open */
508
509 /*
510 * close socket
511 */
512 void
Socket_Close(XBSocket * pSocket)513 Socket_Close (XBSocket * pSocket)
514 {
515 assert (NULL != pSocket);
516 if (pSocket->fd >= 0) {
517 if (!pSocket->shutdown) {
518 SocketMapSubtract (&socketMap, pSocket);
519 pSocket->shutdown = XBTrue;
520 }
521 closesocket (pSocket->fd);
522 Dbg_Socket ("socket fd=%u closed\n", pSocket->fd);
523 }
524 } /* Socket_Close */
525
526 /*
527 * close write access
528 */
529 void
Socket_ShutdownWrite(XBSocket * pSocket)530 Socket_ShutdownWrite (XBSocket * pSocket)
531 {
532 assert (NULL != pSocket);
533
534 if (pSocket->fd >= 0) {
535 if (!pSocket->shutdown) {
536 SocketMapSubtract (&socketMap, pSocket);
537 pSocket->shutdown = XBTrue;
538 }
539 shutdown (pSocket->fd, SD_SEND);
540 Dbg_Socket ("socket fd=%u shutdown write\n", pSocket->fd);
541 }
542 } /* Socket_ShutdownWrite */
543
544 /*
545 * connect a socket
546 */
547 XBBool
Socket_Connect(XBSocket * pSocket)548 Socket_Connect (XBSocket * pSocket)
549 {
550 assert (pSocket != NULL);
551 /* connect */
552 if (-1 == connect (pSocket->fd, pSocket->peer.addr, pSocket->peer.len)) {
553 #ifndef WMS
554 Dbg_Socket ("failed to connect socket fd=%u to %s:%u, err=%u\n", pSocket->fd,
555 Socket_HostName (pSocket, XBTrue), Socket_HostPort (pSocket, XBTrue),
556 WSAGetLastError ());
557 #endif
558 return XBFalse;
559 }
560 /* now get adress assigned by kernel. the cast to void* is needed since not all systems know socklen_t */
561 if (-1 == getsockname (pSocket->fd, pSocket->sock.addr, (void *)&pSocket->sock.len)) {
562 #ifndef WMS
563 Dbg_Socket ("failed to get local address of socket fd=%u after connecting, err=%u\n",
564 pSocket->fd, WSAGetLastError ());
565 #endif
566 return XBFalse;
567 }
568 Dbg_Socket ("socket fd=%u connected to %s:%u\n", pSocket->fd, Socket_HostName (pSocket, XBTrue),
569 Socket_HostPort (pSocket, XBTrue));
570 return XBTrue;
571 } /* Socket_Connect */
572
573 /*
574 * bind a socket
575 */
576 XBBool
Socket_Bind(XBSocket * pSocket)577 Socket_Bind (XBSocket * pSocket)
578 {
579 /* bind to port */
580 if (-1 == bind (pSocket->fd, pSocket->sock.addr, pSocket->sock.len)) {
581 #ifndef WMS
582 Dbg_Socket ("failed to bind socket fd=%u, err=%u\n", pSocket->fd, WSAGetLastError ());
583 #endif
584 return XBFalse;
585 }
586 /* now get adress assigned by kernel. the cast to void* is needed since not all systems know socklen_t */
587 if (-1 == getsockname (pSocket->fd, pSocket->sock.addr, (void *)&pSocket->sock.len)) {
588 #ifndef WMS
589 Dbg_Socket ("failed to get local address of socket fd=%u after binding, err=%u\n",
590 pSocket->fd, WSAGetLastError ());
591 #endif
592 return XBFalse;
593 }
594 Dbg_Socket ("socket fd=%u bound to %s:%u\n", pSocket->fd, Socket_HostName (pSocket, XBFalse),
595 Socket_HostPort (pSocket, XBFalse));
596 /* that's all */
597 return XBTrue;
598 } /* Socket_Bind */
599
600 /*
601 * accept a socket
602 */
603 XBBool
Socket_Accept(XBSocket * pSocket,const XBSocket * pListen)604 Socket_Accept (XBSocket * pSocket, const XBSocket * pListen)
605 {
606 assert (pSocket != NULL);
607 assert (pListen != NULL);
608 /* try to accept */
609 if (-1 == (pSocket->fd = accept (pListen->fd, pSocket->peer.addr, (void *)&pSocket->peer.len))) {
610 #ifndef WMS
611 Dbg_Socket ("failed to accept from socket fd=%u, err=%u\n", pListen->fd,
612 WSAGetLastError ());
613 #endif
614 return XBFalse;
615 }
616 /* now retrieve local adress */
617 if (-1 == getsockname (pSocket->fd, pSocket->sock.addr, (void *)&pSocket->sock.len)) {
618 #ifndef WMS
619 Dbg_Socket ("failed to get local address from accepted socket fd=%u, err=%u\n", pListen->fd,
620 WSAGetLastError ());
621 #endif
622 return XBFalse;
623 }
624 /* add the new socket */
625 SocketMapAdd (&socketMap, pSocket);
626 Dbg_Out ("accepted socket %d from socket fd=%u\n", pSocket->fd, pListen->fd);
627 /* that's all */
628 return XBTrue;
629 } /* Socket_Accept */
630
631 /*
632 * create listen socket
633 */
634 XBBool
Socket_Listen(XBSocket * pSocket)635 Socket_Listen (XBSocket * pSocket)
636 {
637 assert (pSocket != NULL);
638 /* now listen for client to connect */
639 if (0 != listen (pSocket->fd, LISTENQ)) {
640 #ifndef WMS
641 Dbg_Socket ("failed to listen on socket fd=%u (%s:%u), err=%u\n", pSocket->fd,
642 Socket_HostName (pSocket, XBFalse), Socket_HostPort (pSocket, XBFalse),
643 WSAGetLastError ());
644 #endif
645 return XBFalse;
646 }
647 Dbg_Socket ("listening on socket fd=%u (%s:%u)\n", pSocket->fd,
648 Socket_HostName (pSocket, XBFalse), Socket_HostPort (pSocket, XBFalse));
649 return XBTrue;
650 } /* Socket_Listen */
651
652 /*
653 * write to socket, non blocking i/o assumed
654 */
655 int
Socket_Send(const XBSocket * pSocket,const void * buf,size_t len)656 Socket_Send (const XBSocket * pSocket, const void *buf, size_t len)
657 {
658 int result;
659 assert (NULL != pSocket);
660 assert (NULL != buf);
661 /* try to write */
662 result = send (pSocket->fd, buf, len, 0);
663 if (result < 0) {
664 int err = WSAGetLastError ();
665 if (err == WSAEWOULDBLOCK) {
666 Dbg_Socket ("send on fd=%d would block\n", pSocket->fd);
667 return XB_SOCKET_WOULD_BLOCK;
668 }
669 else {
670 Dbg_Out ("send error %d on fd=%u\n", err, pSocket->fd);
671 return XB_SOCKET_ERROR;
672 }
673 }
674 Dbg_Socket ("sent %u bytes on fd=%u\n", result, pSocket->fd);
675 return result;
676 } /* Socket_Send */
677
678 /*
679 * write to socket, given target, non blocking i/o assumed
680 */
681 int
Socket_SendTo(XBSocket * pSocket,const void * buf,size_t len,const char * host,unsigned short port)682 Socket_SendTo (XBSocket * pSocket, const void *buf, size_t len, const char *host,
683 unsigned short port)
684 {
685 int result;
686 assert (NULL != pSocket);
687 assert (NULL != buf);
688 assert (NULL != host);
689 /* convert destination adress */
690 if (!Socket_SetAddressInet (pSocket, XBTrue, host, port)) {
691 Dbg_Socket ("failed to send on fd=%u - failed to resolve %s:%u", pSocket->fd, host, port);
692 return -1;
693 }
694 /* now try to write data */
695 result = sendto (pSocket->fd, buf, len, 0, pSocket->peer.addr, pSocket->peer.len);
696 if (result < 0) {
697 int err = WSAGetLastError ();
698 if (err == WSAEWOULDBLOCK) {
699 Dbg_Socket ("sendto on fd=%u would block\n", pSocket->fd);
700 return XB_SOCKET_WOULD_BLOCK;
701 }
702 else {
703 Dbg_Out ("sendto error on fd=%u\n", err);
704 return XB_SOCKET_ERROR;
705 }
706 }
707 Dbg_Socket ("sent %u bytes on fd=%u to %s:%u\n", result, pSocket->fd, host, port);
708 return result;
709 } /* Socket_SendTo */
710
711 /*
712 * read from socket
713 */
714 int
Socket_Receive(const XBSocket * pSocket,void * buf,size_t len)715 Socket_Receive (const XBSocket * pSocket, void *buf, size_t len)
716 {
717 int result;
718 assert (NULL != pSocket);
719 assert (NULL != buf);
720 /* try to read */
721 result = recv (pSocket->fd, buf, len, 0);
722 if (result < 0) {
723 int err = WSAGetLastError ();
724 if (err == WSAEWOULDBLOCK) {
725 Dbg_Out ("receive on fd=%u would block\n", pSocket->fd);
726 if (pSocket->read) {
727 AsyncSelect (pSocket);
728 }
729 return XB_SOCKET_WOULD_BLOCK;
730 }
731 else {
732 Dbg_Socket ("receive error %u on fd=%u\n", err, pSocket->fd);
733 return XB_SOCKET_ERROR;
734 }
735 }
736 Dbg_Socket ("received %u bytes on fd=%u\n", result, pSocket->fd);
737 return result;
738 } /* Socket_Receive */
739
740 /*
741 * read from socket, get sender
742 */
743 int
Socket_ReceiveFrom(XBSocket * pSocket,void * buf,size_t len,const char ** host,unsigned short * port)744 Socket_ReceiveFrom (XBSocket * pSocket, void *buf, size_t len, const char **host,
745 unsigned short *port)
746 {
747 long numRead;
748 assert (NULL != pSocket);
749 assert (NULL != buf);
750 assert (NULL != host);
751 /* try to read */
752 numRead = recvfrom (pSocket->fd, buf, len, 0, pSocket->peer.addr, &pSocket->peer.len);
753 if (numRead >= 0) {
754 *host = Socket_HostName (pSocket, XBTrue);
755 *port = Socket_HostPort (pSocket, XBTrue);
756 }
757 else {
758 int err = WSAGetLastError ();
759 *host = NULL;
760 *port = 0;
761 if (err == WSAEWOULDBLOCK) {
762 Dbg_Socket ("socket receivefrom on fd=%u would block\n", pSocket->fd);
763 return XB_SOCKET_WOULD_BLOCK;
764 }
765 else {
766 Dbg_Socket ("receivefrom error %u on fd=%u\n", err, pSocket->fd);
767 return XB_SOCKET_ERROR;
768 }
769 }
770 Dbg_Socket ("received %u bytes on fd=%u from %s:%u\n", numRead, pSocket->fd, *host, *port);
771 return numRead;
772 } /* Net_ReceiveFrom */
773
774 /*****************
775 * socket events *
776 *****************/
777
778 /*
779 * handle selection events, needed in w32_event.c
780 */
781 void
HandleSelect(UINT wParam,LONG lParam)782 HandleSelect (UINT wParam, LONG lParam)
783 {
784 SOCKET fd = wParam;
785 UINT event = WSAGETSELECTEVENT (lParam);
786 const XBSocket *pSocket;
787
788 switch (event) {
789 case FD_READ:
790 case FD_ACCEPT:
791 case FD_CLOSE:
792 Dbg_Socket ("socket fd=%u readable\n", fd);
793 CommReadable (fd);
794 break;
795 case FD_WRITE:
796 Dbg_Socket ("socket fd=%u writeable\n", fd);
797 CommWriteable (fd);
798 if (NULL != (pSocket = SocketMapFind (&socketMap, fd)) && pSocket->write) {
799 AsyncSelect (pSocket);
800 }
801 break;
802 default:
803 Dbg_Socket ("unknown select event %04x\n", event);
804 break;
805 }
806 } /* HandleSelect */
807
808 /*
809 * trigger async select
810 */
811 static void
AsyncSelect(const XBSocket * pSocket)812 AsyncSelect (const XBSocket * pSocket)
813 {
814 long event = 0;
815 assert (NULL != pSocket);
816 Dbg_Socket ("async select on fd=%u, flags=%c%c\n", pSocket->fd, pSocket->read ? 'R' : '-',
817 pSocket->write ? 'W' : '-');
818 if (pSocket->read) {
819 event |= (FD_READ | FD_ACCEPT | FD_CLOSE);
820 }
821 if (pSocket->write) {
822 event |= FD_WRITE;
823 }
824 WSAAsyncSelect (pSocket->fd, window, MSG_XBLAST_SELECT, event);
825 } /* AsyncSelect */
826
827 /**************
828 * interfaces *
829 **************/
830
831 /*
832 * get all available interfaces
833 */
834 const XBSocketInterface *
Socket_GetInterfaces(size_t * num)835 Socket_GetInterfaces (size_t * num)
836 {
837 SOCKET fd = SOCKET_ERROR;
838 DWORD nr, len;
839 SOCKADDR_IN *pAddrInet = NULL;
840 SOCKADDR_IN *pAddrNetmask = NULL;
841 SOCKADDR_IN *pAddrBroadcast = NULL;
842 u_long iFlags = 0;
843 void *info = NULL;
844 INTERFACE_INFO *ii = NULL;
845 INTERFACE_INFO_MOD *iimod = NULL;
846 DWORD iLen = 10;
847
848 /* clean up */
849 DeleteInterfaces ();
850 /* get test udp socket for interface detection */
851 if (SOCKET_ERROR == (fd = socket (AF_INET, SOCK_DGRAM, 0))) {
852 Dbg_Socket ("failed to open udp socket for interface detection\n");
853 goto Error;
854 }
855 /* allocate space for iLen interfaces */
856 info = calloc (iLen, sizeof (XB_INTERFACE_INFO));
857 assert (NULL != info);
858 /* start scanning */
859 Dbg_Socket ("guessing %u interfaces\n", iLen);
860 while (SOCKET_ERROR ==
861 WSAIoctl (fd, SIO_GET_INTERFACE_LIST, NULL, 0, info, iLen * sizeof (XB_INTERFACE_INFO),
862 &len, NULL, NULL)) {
863 if (WSAEFAULT != WSAGetLastError ()) {
864 Dbg_Socket ("ioctl failed, err=%u\n", WSAGetLastError ());
865 goto Error;
866 }
867 /* more space needed */
868 free (info);
869 iLen += 10;
870 info = calloc (iLen, sizeof (XB_INTERFACE_INFO));
871 assert (NULL != info);
872 Dbg_Socket ("increasing guess to %u\n", iLen);
873 }
874 /* determine interface count */
875 modeflags |= XBIF_MS & (len % sizeof (INTERFACE_INFO) == 0);
876 modeflags |= XBIF_MOD & (len % sizeof (INTERFACE_INFO_MOD) == 0);
877 switch (modeflags) {
878 case XBIF_MS:
879 len /= sizeof (INTERFACE_INFO);
880 Dbg_Socket ("using MS mode!\n");
881 break;
882 case XBIF_MOD:
883 len /= sizeof (INTERFACE_INFO_MOD);
884 Dbg_Socket ("using modified MS mode!\n");
885 break;
886 default:
887 *num = 0;
888 Dbg_Socket ("no matching mode, interface detection unreliable!\n");
889 goto Error;
890 }
891 Dbg_Socket ("interfaces detected = %u\n", len);
892 /* allocate output buffer */
893 inter = calloc (len, sizeof (XBSocketInterface));
894 assert (NULL != inter);
895 Dbg_Socket ("allocated %u interface descriptions\n", len);
896 /* create interface list */
897 numInter = 0;
898 for (nr = 0; nr < len; nr++) {
899 Dbg_Out ("### interface %u ###\n", nr);
900 /* get flags and addresses */
901 switch (modeflags) {
902 case XBIF_MS:
903 ii = (INTERFACE_INFO *) info;
904 pAddrInet = (SOCKADDR_IN *) & ii[nr].iiAddress;
905 pAddrNetmask = (SOCKADDR_IN *) & ii[nr].iiNetmask;
906 pAddrBroadcast = (SOCKADDR_IN *) & ii[nr].iiBroadcastAddress;
907 iFlags = ii[nr].iiFlags;
908 break;
909 case XBIF_MOD:
910 iimod = (INTERFACE_INFO_MOD *) info;
911 pAddrInet = (SOCKADDR_IN *) & iimod[nr].iiAddress;
912 pAddrNetmask = (SOCKADDR_IN *) & iimod[nr].iiNetmask;
913 pAddrBroadcast = (SOCKADDR_IN *) & iimod[nr].iiBroadcastAddress;
914 iFlags = iimod[nr].iiFlags;
915 break;
916 default:
917 break;
918 }
919 /* require INET family, up and broadcast */
920 if (pAddrInet->sin_family == AF_INET &&
921 pAddrInet->sin_addr.s_addr != INADDR_ANY && (iFlags & (IFF_UP | IFF_BROADCAST))) {
922 struct in_addr bcAddr = pAddrInet->sin_addr;
923 bcAddr.s_addr |= ~pAddrNetmask->sin_addr.s_addr;
924 /* set interface data */
925 inter[numInter].name = DupString ("net");
926 inter[numInter].addrDevice = DupString (inet_ntoa (pAddrInet->sin_addr));
927 inter[numInter].addrBroadcast = DupString (inet_ntoa (bcAddr));
928 /* output data */
929 Dbg_Out ("IP = %s\n", inter[numInter].addrDevice);
930 Dbg_Out ("NET= %s\n", inet_ntoa (pAddrNetmask->sin_addr));
931 Dbg_Out ("GBC= %s\n", inet_ntoa (pAddrBroadcast->sin_addr));
932 Dbg_Out ("BC = %s\n", inter[numInter].addrBroadcast);
933 numInter++;
934 }
935 else {
936 /* output interface data */
937 Dbg_Out ("IP = %s\n", inet_ntoa (pAddrInet->sin_addr));
938 Dbg_Out ("NET= %s\n", inet_ntoa (pAddrNetmask->sin_addr));
939 Dbg_Out ("GBC= %s\n", inet_ntoa (pAddrBroadcast->sin_addr));
940 Dbg_Out ("skipping interface\n");
941 }
942 }
943 /* clean up */
944 free (info);
945 closesocket (fd);
946 /* that's all */
947 *num = numInter;
948 return inter;
949
950 Error:
951 if (NULL != info) {
952 free (info);
953 }
954 if (SOCKET_ERROR != fd) {
955 closesocket (fd);
956 }
957 return NULL;
958 } /* Socket_GetInterfaces */
959
960 /*
961 * return auto interface for given target and socket
962 */
963 const char *
Socket_GetAutoInterface(XBSocket * pSocket,const char * trg)964 Socket_GetAutoInterface (XBSocket * pSocket, const char *trg)
965 {
966 SOCKADDR_IN inaddr_trg;
967 SOCKADDR_IN inaddr_if;
968 DWORD ret = 0;
969 const char *ifname;
970 /* construct target address */
971 inaddr_trg.sin_family = AF_INET;
972 inaddr_trg.sin_addr.s_addr = inet_addr (trg);
973 /* ioctl to get interface address */
974 if (SOCKET_ERROR == WSAIoctl (pSocket->fd, SIO_ROUTING_INTERFACE_QUERY,
975 &inaddr_trg, sizeof (SOCKADDR_IN),
976 &inaddr_if, sizeof (SOCKADDR_IN), &ret, NULL, NULL)) {
977 Dbg_Socket ("failed to find auto-interface, ioctl error %u\n", WSAGetLastError ());
978 ifname = NULL;
979 }
980 else {
981 ifname = inet_ntoa (inaddr_if.sin_addr);
982 }
983 return ifname;
984 } /* Socket_GetAutoInterface */
985
986 /*
987 * end of file w32_socket.c
988 */
989