]> git.xonotic.org Git - xonotic/darkplaces.git/blob - lhnet.c
fix USE_WSPIAPI_H
[xonotic/darkplaces.git] / lhnet.c
1
2 // Written by Forest Hale 2003-06-15 and placed into public domain.
3
4 #ifdef WIN32
5 // Windows XP or higher is required for getaddrinfo, but the inclusion of wspiapi provides fallbacks for older versions
6 # define _WIN32_WINNT 0x0501
7 # include <winsock2.h>
8 # include <ws2tcpip.h>
9 # ifdef USE_WSPIAPI_H
10 #  include <wspiapi.h>
11 # endif
12 #endif
13
14 #ifndef STANDALONETEST
15 #include "quakedef.h"
16 #endif
17
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <time.h>
21 #include <string.h>
22 #ifndef WIN32
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <sys/ioctl.h>
27 #include <errno.h>
28 #include <netdb.h>
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
31 #include <net/if.h>
32 #endif
33
34 #ifdef __MORPHOS__
35 #include <proto/socket.h>
36 #endif
37
38 // for Z_Malloc/Z_Free in quake
39 #ifndef STANDALONETEST
40 #include "zone.h"
41 #include "sys.h"
42 #include "netconn.h"
43 #else
44 #define Con_Print printf
45 #define Con_Printf printf
46 #define Z_Malloc malloc
47 #define Z_Free free
48 #endif
49
50 #include "lhnet.h"
51
52 #if defined(WIN32)
53 #define EWOULDBLOCK WSAEWOULDBLOCK
54 #define ECONNREFUSED WSAECONNREFUSED
55
56 #define SOCKETERRNO WSAGetLastError()
57
58 #define IOC_VENDOR 0x18000000
59 #define _WSAIOW(x,y) (IOC_IN|(x)|(y))
60 #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
61
62 #define SOCKLEN_T int
63 #elif defined(__MORPHOS__)
64 #define ioctlsocket IoctlSocket
65 #define closesocket CloseSocket
66 #define SOCKETERRNO Errno()
67
68 #define SOCKLEN_T int
69 #else
70 #define ioctlsocket ioctl
71 #define closesocket close
72 #define SOCKETERRNO errno
73
74 #define SOCKLEN_T socklen_t
75 #endif
76
77 typedef struct lhnetaddressnative_s
78 {
79         lhnetaddresstype_t addresstype;
80         int port;
81         union
82         {
83                 struct sockaddr sock;
84                 struct sockaddr_in in;
85                 struct sockaddr_in6 in6;
86         }
87         addr;
88 }
89 lhnetaddressnative_t;
90
91 // to make LHNETADDRESS_FromString resolve repeated hostnames faster, cache them
92 #define MAX_NAMECACHE 64
93 static struct namecache_s
94 {
95         lhnetaddressnative_t address;
96         double expirationtime;
97         char name[64];
98 }
99 namecache[MAX_NAMECACHE];
100 static int namecacheposition = 0;
101
102 int LHNETADDRESS_FromPort(lhnetaddress_t *vaddress, lhnetaddresstype_t addresstype, int port)
103 {
104         lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
105         if (!address)
106                 return 0;
107         switch(addresstype)
108         {
109         default:
110                 return 0;
111         case LHNETADDRESSTYPE_LOOP:
112                 // local:port  (loopback)
113                 memset(address, 0, sizeof(*address));
114                 address->addresstype = LHNETADDRESSTYPE_LOOP;
115                 address->port = port;
116                 return 1;
117         case LHNETADDRESSTYPE_INET4:
118                 // 0.0.0.0:port  (INADDR_ANY, binds to all interfaces)
119                 memset(address, 0, sizeof(*address));
120                 address->addresstype = LHNETADDRESSTYPE_INET4;
121                 address->port = port;
122                 address->addr.in.sin_family = AF_INET;
123                 address->addr.in.sin_port = htons((unsigned short)port);
124                 return 1;
125         case LHNETADDRESSTYPE_INET6:
126                 // [0:0:0:0:0:0:0:0]:port  (IN6ADDR_ANY, binds to all interfaces)
127                 memset(address, 0, sizeof(*address));
128                 address->addresstype = LHNETADDRESSTYPE_INET6;
129                 address->port = port;
130                 address->addr.in6.sin6_family = AF_INET6;
131                 address->addr.in6.sin6_port = htons((unsigned short)port);
132                 return 1;
133         }
134         return 0;
135 }
136
137 int LHNETADDRESS_Resolve(lhnetaddressnative_t *address, const char *name, int port)
138 {
139         char port_buff [16];
140         struct addrinfo hints;
141         struct addrinfo* addrinf;
142         int err;
143
144         dpsnprintf (port_buff, sizeof (port_buff), "%d", port);
145         port_buff[sizeof (port_buff) - 1] = '\0';
146
147         memset(&hints, 0, sizeof (hints));
148         hints.ai_family = AF_UNSPEC;
149         hints.ai_socktype = SOCK_DGRAM;
150         //hints.ai_flags = AI_PASSIVE;
151
152         err = getaddrinfo(name, port_buff, &hints, &addrinf);
153         if (err != 0 || addrinf == NULL)
154                 return 0;
155         if (addrinf->ai_addr->sa_family != AF_INET6 && addrinf->ai_addr->sa_family != AF_INET)
156         {
157                 freeaddrinfo (addrinf);
158                 return 0;
159         }
160
161         // great it worked
162         if (addrinf->ai_addr->sa_family == AF_INET6)
163         {
164                 address->addresstype = LHNETADDRESSTYPE_INET6;
165                 memcpy(&address->addr.in6, addrinf->ai_addr, sizeof(address->addr.in6));
166         }
167         else
168         {
169                 address->addresstype = LHNETADDRESSTYPE_INET4;
170                 memcpy(&address->addr.in, addrinf->ai_addr, sizeof(address->addr.in));
171         }
172         address->port = port;
173         
174         freeaddrinfo (addrinf);
175         return 1;
176 }
177
178 int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
179 {
180         lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
181         int i, port, d1, d2, d3, d4, resolved;
182         size_t namelen;
183         unsigned char *a;
184         char name[128];
185 #ifdef STANDALONETEST
186         char string2[128];
187 #endif
188         const char* addr_start;
189         const char* addr_end = NULL;
190         const char* port_name = NULL;
191         int addr_family = AF_UNSPEC;
192
193         if (!address || !string || !*string)
194                 return 0;
195         memset(address, 0, sizeof(*address));
196         address->addresstype = LHNETADDRESSTYPE_NONE;
197         port = 0;
198
199         // If it's a bracketed IPv6 address
200         if (string[0] == '[')
201         {
202                 const char* end_bracket = strchr(string, ']');
203
204                 if (end_bracket == NULL)
205                         return 0;
206
207                 if (end_bracket[1] == ':')
208                         port_name = end_bracket + 2;
209                 else if (end_bracket[1] != '\0')
210                         return 0;
211
212                 addr_family = AF_INET6;
213                 addr_start = &string[1];
214                 addr_end = end_bracket;
215         }
216         else
217         {
218                 const char* first_colon;
219
220                 addr_start = string;
221
222                 // If it's a numeric non-bracket IPv6 address (-> no port),
223                 // or it's a numeric IPv4 address, or a name, with a port
224                 first_colon = strchr(string, ':');
225                 if (first_colon != NULL)
226                 {
227                         const char* last_colon = strrchr(first_colon + 1, ':');
228
229                         // If it's an numeric IPv4 address, or a name, with a port
230                         if (last_colon == NULL)
231                         {
232                                 addr_end = first_colon;
233                                 port_name = first_colon + 1;
234                         }
235                         else
236                                 addr_family = AF_INET6;
237                 }
238         }
239
240         if (addr_end != NULL)
241                 namelen = addr_end - addr_start;
242         else
243                 namelen = strlen (addr_start);
244
245         if (namelen >= sizeof(name))
246                 namelen = sizeof(name) - 1;
247         memcpy (name, addr_start, namelen);
248         name[namelen] = 0;
249
250         if (port_name)
251                 port = atoi(port_name);
252
253         if (port == 0)
254                 port = defaultport;
255
256         // handle loopback
257         if (!strcmp(name, "local"))
258         {
259                 address->addresstype = LHNETADDRESSTYPE_LOOP;
260                 address->port = port;
261                 return 1;
262         }
263         // try to parse as dotted decimal ipv4 address first
264         // note this supports partial ip addresses
265         d1 = d2 = d3 = d4 = 0;
266 #if _MSC_VER >= 1400
267 #define sscanf sscanf_s
268 #endif
269         if (addr_family != AF_INET6 &&
270                 sscanf(name, "%d.%d.%d.%d", &d1, &d2, &d3, &d4) >= 1 && (unsigned int)d1 < 256 && (unsigned int)d2 < 256 && (unsigned int)d3 < 256 && (unsigned int)d4 < 256)
271         {
272                 // parsed a valid ipv4 address
273                 address->addresstype = LHNETADDRESSTYPE_INET4;
274                 address->port = port;
275                 address->addr.in.sin_family = AF_INET;
276                 address->addr.in.sin_port = htons((unsigned short)port);
277                 a = (unsigned char *)&address->addr.in.sin_addr;
278                 a[0] = d1;
279                 a[1] = d2;
280                 a[2] = d3;
281                 a[3] = d4;
282 #ifdef STANDALONETEST
283                 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
284                 printf("manual parsing of ipv4 dotted decimal address \"%s\" successful: %s\n", string, string2);
285 #endif
286                 return 1;
287         }
288         for (i = 0;i < MAX_NAMECACHE;i++)
289                 if (!strcmp(namecache[i].name, name))
290                         break;
291 #ifdef STANDALONETEST
292         if (i < MAX_NAMECACHE)
293 #else
294         if (i < MAX_NAMECACHE && realtime < namecache[i].expirationtime)
295 #endif
296         {
297                 *address = namecache[i].address;
298                 address->port = port;
299                 if (address->addresstype == LHNETADDRESSTYPE_INET6)
300                 {
301                         address->addr.in6.sin6_port = htons((unsigned short)port);
302                         return 1;
303                 }
304                 else if (address->addresstype == LHNETADDRESSTYPE_INET4)
305                 {
306                         address->addr.in.sin_port = htons((unsigned short)port);
307                         return 1;
308                 }
309                 return 0;
310         }
311
312         for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
313                 namecache[namecacheposition].name[i] = name[i];
314         namecache[namecacheposition].name[i] = 0;
315 #ifndef STANDALONETEST
316         namecache[namecacheposition].expirationtime = realtime + 12 * 3600; // 12 hours
317 #endif
318
319         // try resolving the address (handles dns and other ip formats)
320         resolved = LHNETADDRESS_Resolve(address, name, port);
321         if (resolved)
322         {
323 #ifdef STANDALONETEST
324                 const char *protoname;
325
326                 switch (address->addresstype)
327                 {
328                         case LHNETADDRESSTYPE_INET6:
329                                 protoname = "ipv6";
330                                 break;
331                         case LHNETADDRESSTYPE_INET4:
332                                 protoname = "ipv4";
333                                 break;
334                         default:
335                                 protoname = "UNKNOWN";
336                                 break;
337                 }
338                 LHNETADDRESS_ToString(vaddress, string2, sizeof(string2), 1);
339                 Con_Printf("LHNETADDRESS_Resolve(\"%s\") returned %s address %s\n", string, protoname, string2);
340 #endif
341                 namecache[namecacheposition].address = *address;
342         }
343         else
344         {
345 #ifdef STANDALONETEST
346                 printf("name resolution failed on address \"%s\"\n", name);
347 #endif
348                 namecache[namecacheposition].address.addresstype = LHNETADDRESSTYPE_NONE;
349         }
350         
351         namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
352         return resolved;
353 }
354
355 int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stringbuffersize, int includeport)
356 {
357         lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
358         const unsigned char *a;
359         *string = 0;
360         if (!address || !string || stringbuffersize < 1)
361                 return 0;
362         switch(address->addresstype)
363         {
364         default:
365                 break;
366         case LHNETADDRESSTYPE_LOOP:
367                 if (includeport)
368                 {
369                         if (stringbuffersize >= 12)
370                         {
371                                 dpsnprintf(string, stringbuffersize, "local:%d", address->port);
372                                 return 1;
373                         }
374                 }
375                 else
376                 {
377                         if (stringbuffersize >= 6)
378                         {
379                                 memcpy(string, "local", 6);
380                                 return 1;
381                         }
382                 }
383                 break;
384         case LHNETADDRESSTYPE_INET4:
385                 a = (const unsigned char *)(&address->addr.in.sin_addr);
386                 if (includeport)
387                 {
388                         if (stringbuffersize >= 22)
389                         {
390                                 dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d:%d", a[0], a[1], a[2], a[3], address->port);
391                                 return 1;
392                         }
393                 }
394                 else
395                 {
396                         if (stringbuffersize >= 16)
397                         {
398                                 dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
399                                 return 1;
400                         }
401                 }
402                 break;
403         case LHNETADDRESSTYPE_INET6:
404                 a = (const unsigned char *)(&address->addr.in6.sin6_addr);
405                 if (includeport)
406                 {
407                         if (stringbuffersize >= 88)
408                         {
409                                 dpsnprintf(string, stringbuffersize, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d", a[0] * 256 + a[1], a[2] * 256 + a[3], a[4] * 256 + a[5], a[6] * 256 + a[7], a[8] * 256 + a[9], a[10] * 256 + a[11], a[12] * 256 + a[13], a[14] * 256 + a[15], address->port);
410                                 return 1;
411                         }
412                 }
413                 else
414                 {
415                         if (stringbuffersize >= 80)
416                         {
417                                 dpsnprintf(string, stringbuffersize, "%x:%x:%x:%x:%x:%x:%x:%x", a[0] * 256 + a[1], a[2] * 256 + a[3], a[4] * 256 + a[5], a[6] * 256 + a[7], a[8] * 256 + a[9], a[10] * 256 + a[11], a[12] * 256 + a[13], a[14] * 256 + a[15]);
418                                 return 1;
419                         }
420                 }
421                 break;
422         }
423         return 0;
424 }
425
426 int LHNETADDRESS_GetAddressType(const lhnetaddress_t *address)
427 {
428         if (address)
429                 return address->addresstype;
430         else
431                 return LHNETADDRESSTYPE_NONE;
432 }
433
434 const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress)
435 {
436         lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
437
438         if (address && address->addresstype == LHNETADDRESSTYPE_INET6)
439         {
440 #ifndef _WIN32
441
442                 static char ifname [IF_NAMESIZE];
443                 
444                 if (if_indextoname(address->addr.in6.sin6_scope_id, ifname) == ifname)
445                         return ifname;
446
447 #else
448
449                 // The Win32 API doesn't have if_indextoname() until Windows Vista,
450                 // but luckily it just uses the interface ID as the interface name
451
452                 static char ifname [16];
453
454                 if (dpsnprintf(ifname, sizeof(ifname), "%lu", address->addr.in6.sin6_scope_id) > 0)
455                         return ifname;
456
457 #endif
458         }
459
460         return NULL;
461 }
462
463 int LHNETADDRESS_GetPort(const lhnetaddress_t *address)
464 {
465         if (!address)
466                 return -1;
467         return address->port;
468 }
469
470 int LHNETADDRESS_SetPort(lhnetaddress_t *vaddress, int port)
471 {
472         lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
473         if (!address)
474                 return 0;
475         address->port = port;
476         switch(address->addresstype)
477         {
478         case LHNETADDRESSTYPE_LOOP:
479                 return 1;
480         case LHNETADDRESSTYPE_INET4:
481                 address->addr.in.sin_port = htons((unsigned short)port);
482                 return 1;
483         case LHNETADDRESSTYPE_INET6:
484                 address->addr.in6.sin6_port = htons((unsigned short)port);
485                 return 1;
486         default:
487                 return 0;
488         }
489 }
490
491 int LHNETADDRESS_Compare(const lhnetaddress_t *vaddress1, const lhnetaddress_t *vaddress2)
492 {
493         lhnetaddressnative_t *address1 = (lhnetaddressnative_t *)vaddress1;
494         lhnetaddressnative_t *address2 = (lhnetaddressnative_t *)vaddress2;
495         if (!address1 || !address2)
496                 return 1;
497         if (address1->addresstype != address2->addresstype)
498                 return 1;
499         switch(address1->addresstype)
500         {
501         case LHNETADDRESSTYPE_LOOP:
502                 if (address1->port != address2->port)
503                         return -1;
504                 return 0;
505         case LHNETADDRESSTYPE_INET4:
506                 if (address1->addr.in.sin_family != address2->addr.in.sin_family)
507                         return 1;
508                 if (memcmp(&address1->addr.in.sin_addr, &address2->addr.in.sin_addr, sizeof(address1->addr.in.sin_addr)))
509                         return 1;
510                 if (address1->port != address2->port)
511                         return -1;
512                 return 0;
513         case LHNETADDRESSTYPE_INET6:
514                 if (address1->addr.in6.sin6_family != address2->addr.in6.sin6_family)
515                         return 1;
516                 if (memcmp(&address1->addr.in6.sin6_addr, &address2->addr.in6.sin6_addr, sizeof(address1->addr.in6.sin6_addr)))
517                         return 1;
518                 if (address1->port != address2->port)
519                         return -1;
520                 return 0;
521         default:
522                 return 1;
523         }
524 }
525
526 typedef struct lhnetpacket_s
527 {
528         void *data;
529         int length;
530         int sourceport;
531         int destinationport;
532         time_t timeout;
533 #ifndef STANDALONETEST
534         double sentdoubletime;
535 #endif
536         struct lhnetpacket_s *next, *prev;
537 }
538 lhnetpacket_t;
539
540 static int lhnet_active;
541 static lhnetsocket_t lhnet_socketlist;
542 static lhnetpacket_t lhnet_packetlist;
543 #ifdef WIN32
544 static int lhnet_didWSAStartup = 0;
545 static WSADATA lhnet_winsockdata;
546 #endif
547
548 void LHNET_Init(void)
549 {
550         if (lhnet_active)
551                 return;
552         lhnet_socketlist.next = lhnet_socketlist.prev = &lhnet_socketlist;
553         lhnet_packetlist.next = lhnet_packetlist.prev = &lhnet_packetlist;
554         lhnet_active = 1;
555 #ifdef WIN32
556         lhnet_didWSAStartup = !WSAStartup(MAKEWORD(1, 1), &lhnet_winsockdata);
557         if (!lhnet_didWSAStartup)
558                 Con_Print("LHNET_Init: WSAStartup failed, networking disabled\n");
559 #endif
560 }
561
562 void LHNET_Shutdown(void)
563 {
564         lhnetpacket_t *p;
565         if (!lhnet_active)
566                 return;
567         while (lhnet_socketlist.next != &lhnet_socketlist)
568                 LHNET_CloseSocket(lhnet_socketlist.next);
569         while (lhnet_packetlist.next != &lhnet_packetlist)
570         {
571                 p = lhnet_packetlist.next;
572                 p->prev->next = p->next;
573                 p->next->prev = p->prev;
574                 Z_Free(p);
575         }
576 #ifdef WIN32
577         if (lhnet_didWSAStartup)
578         {
579                 lhnet_didWSAStartup = 0;
580                 WSACleanup();
581         }
582 #endif
583         lhnet_active = 0;
584 }
585
586 static const char *LHNETPRIVATE_StrError(void)
587 {
588 #ifdef WIN32
589         int i = WSAGetLastError();
590         switch (i)
591         {
592                 case WSAEINTR:           return "WSAEINTR";
593                 case WSAEBADF:           return "WSAEBADF";
594                 case WSAEACCES:          return "WSAEACCES";
595                 case WSAEFAULT:          return "WSAEFAULT";
596                 case WSAEINVAL:          return "WSAEINVAL";
597                 case WSAEMFILE:          return "WSAEMFILE";
598                 case WSAEWOULDBLOCK:     return "WSAEWOULDBLOCK";
599                 case WSAEINPROGRESS:     return "WSAEINPROGRESS";
600                 case WSAEALREADY:        return "WSAEALREADY";
601                 case WSAENOTSOCK:        return "WSAENOTSOCK";
602                 case WSAEDESTADDRREQ:    return "WSAEDESTADDRREQ";
603                 case WSAEMSGSIZE:        return "WSAEMSGSIZE";
604                 case WSAEPROTOTYPE:      return "WSAEPROTOTYPE";
605                 case WSAENOPROTOOPT:     return "WSAENOPROTOOPT";
606                 case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
607                 case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
608                 case WSAEOPNOTSUPP:      return "WSAEOPNOTSUPP";
609                 case WSAEPFNOSUPPORT:    return "WSAEPFNOSUPPORT";
610                 case WSAEAFNOSUPPORT:    return "WSAEAFNOSUPPORT";
611                 case WSAEADDRINUSE:      return "WSAEADDRINUSE";
612                 case WSAEADDRNOTAVAIL:   return "WSAEADDRNOTAVAIL";
613                 case WSAENETDOWN:        return "WSAENETDOWN";
614                 case WSAENETUNREACH:     return "WSAENETUNREACH";
615                 case WSAENETRESET:       return "WSAENETRESET";
616                 case WSAECONNABORTED:    return "WSAECONNABORTED";
617                 case WSAECONNRESET:      return "WSAECONNRESET";
618                 case WSAENOBUFS:         return "WSAENOBUFS";
619                 case WSAEISCONN:         return "WSAEISCONN";
620                 case WSAENOTCONN:        return "WSAENOTCONN";
621                 case WSAESHUTDOWN:       return "WSAESHUTDOWN";
622                 case WSAETOOMANYREFS:    return "WSAETOOMANYREFS";
623                 case WSAETIMEDOUT:       return "WSAETIMEDOUT";
624                 case WSAECONNREFUSED:    return "WSAECONNREFUSED";
625                 case WSAELOOP:           return "WSAELOOP";
626                 case WSAENAMETOOLONG:    return "WSAENAMETOOLONG";
627                 case WSAEHOSTDOWN:       return "WSAEHOSTDOWN";
628                 case WSAEHOSTUNREACH:    return "WSAEHOSTUNREACH";
629                 case WSAENOTEMPTY:       return "WSAENOTEMPTY";
630                 case WSAEPROCLIM:        return "WSAEPROCLIM";
631                 case WSAEUSERS:          return "WSAEUSERS";
632                 case WSAEDQUOT:          return "WSAEDQUOT";
633                 case WSAESTALE:          return "WSAESTALE";
634                 case WSAEREMOTE:         return "WSAEREMOTE";
635                 case WSAEDISCON:         return "WSAEDISCON";
636                 case 0:                  return "no error";
637                 default:                 return "unknown WSAE error";
638         }
639 #else
640         return strerror(errno);
641 #endif
642 }
643
644 void LHNET_SleepUntilPacket_Microseconds(int microseconds)
645 {
646         fd_set fdreadset;
647         struct timeval tv;
648         int lastfd;
649         lhnetsocket_t *s;
650         FD_ZERO(&fdreadset);
651         lastfd = 0;
652         for (s = lhnet_socketlist.next;s != &lhnet_socketlist;s = s->next)
653         {
654                 if (s->address.addresstype == LHNETADDRESSTYPE_INET4 || s->address.addresstype == LHNETADDRESSTYPE_INET6)
655                 {
656                         if (lastfd < s->inetsocket)
657                                 lastfd = s->inetsocket;
658                         FD_SET((unsigned int)s->inetsocket, &fdreadset);
659                 }
660         }
661         tv.tv_sec = microseconds / 1000000;
662         tv.tv_usec = microseconds % 1000000;
663         select(lastfd + 1, &fdreadset, NULL, NULL, &tv);
664 }
665
666 lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address)
667 {
668         lhnetsocket_t *lhnetsocket, *s;
669         if (!address)
670                 return NULL;
671         lhnetsocket = (lhnetsocket_t *)Z_Malloc(sizeof(*lhnetsocket));
672         if (lhnetsocket)
673         {
674                 memset(lhnetsocket, 0, sizeof(*lhnetsocket));
675                 lhnetsocket->address = *address;
676                 switch(lhnetsocket->address.addresstype)
677                 {
678                 case LHNETADDRESSTYPE_LOOP:
679                         if (lhnetsocket->address.port == 0)
680                         {
681                                 // allocate a port dynamically
682                                 // this search will always terminate because there is never
683                                 // an allocated socket with port 0, so if the number wraps it
684                                 // will find the port is unused, and then refuse to use port
685                                 // 0, causing an intentional failure condition
686                                 lhnetsocket->address.port = 1024;
687                                 for (;;)
688                                 {
689                                         for (s = lhnet_socketlist.next;s != &lhnet_socketlist;s = s->next)
690                                                 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
691                                                         break;
692                                         if (s == &lhnet_socketlist)
693                                                 break;
694                                         lhnetsocket->address.port++;
695                                 }
696                         }
697                         // check if the port is available
698                         for (s = lhnet_socketlist.next;s != &lhnet_socketlist;s = s->next)
699                                 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
700                                         break;
701                         if (s == &lhnet_socketlist && lhnetsocket->address.port != 0)
702                         {
703                                 lhnetsocket->next = &lhnet_socketlist;
704                                 lhnetsocket->prev = lhnetsocket->next->prev;
705                                 lhnetsocket->next->prev = lhnetsocket;
706                                 lhnetsocket->prev->next = lhnetsocket;
707                                 return lhnetsocket;
708                         }
709                         break;
710                 case LHNETADDRESSTYPE_INET4:
711                 case LHNETADDRESSTYPE_INET6:
712 #ifdef WIN32
713                         if (lhnet_didWSAStartup)
714                         {
715 #endif
716                                 if ((lhnetsocket->inetsocket = socket(address->addresstype == LHNETADDRESSTYPE_INET6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
717                                 {
718 #ifdef WIN32
719                                         u_long _true = 1;
720                                         u_long _false = 0;
721 #else
722                                         char _true = 1;
723 #endif
724                                         if (ioctlsocket(lhnetsocket->inetsocket, FIONBIO, &_true) != -1)
725                                         {
726 #ifdef IPV6_V6ONLY
727                                                 // We need to set this flag to tell the OS that we only listen on IPv6. If we don't
728                                                 // most OSes will create a dual-protocol socket that also listens on IPv4. In this case
729                                                 // if an IPv4 socket is already bound to the port we want, our bind() call will fail.
730                                                 int ipv6_only = 1;
731                                                 if (address->addresstype != LHNETADDRESSTYPE_INET6
732                                                         || setsockopt (lhnetsocket->inetsocket, IPPROTO_IPV6, IPV6_V6ONLY,
733                                                                                    (const char *)&ipv6_only, sizeof(ipv6_only)) == 0
734 #ifdef WIN32
735                                                         // The Win32 API only supports IPV6_V6ONLY since Windows Vista, but fortunately
736                                                         // the default value is what we want on Win32 anyway (IPV6_V6ONLY = true)
737                                                         || SOCKETERRNO == WSAENOPROTOOPT
738 #endif
739                                                         )
740 #endif
741                                                 {
742                                                         lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
743                                                         SOCKLEN_T namelen;
744                                                         int bindresult;
745                                                         if (address->addresstype == LHNETADDRESSTYPE_INET6)
746                                                         {
747                                                                 namelen = sizeof(localaddress->addr.in6);
748                                                                 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
749                                                                 if (bindresult != -1)
750                                                                         getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen);
751                                                         }
752                                                         else
753                                                         {
754                                                                 namelen = sizeof(localaddress->addr.in);
755                                                                 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
756                                                                 if (bindresult != -1)
757                                                                         getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen);
758                                                         }
759                                                         if (bindresult != -1)
760                                                         {
761                                                                 int i = 1;
762                                                                 // enable broadcast on this socket
763                                                                 setsockopt(lhnetsocket->inetsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i));
764                                                                 lhnetsocket->next = &lhnet_socketlist;
765                                                                 lhnetsocket->prev = lhnetsocket->next->prev;
766                                                                 lhnetsocket->next->prev = lhnetsocket;
767                                                                 lhnetsocket->prev->next = lhnetsocket;
768 #ifdef WIN32
769                                                                 if (ioctlsocket(lhnetsocket->inetsocket, SIO_UDP_CONNRESET, &_false) == -1)
770                                                                         Con_DPrintf("LHNET_OpenSocket_Connectionless: ioctlsocket SIO_UDP_CONNRESET returned error: %s\n", LHNETPRIVATE_StrError());
771 #endif
772                                                                 return lhnetsocket;
773                                                         }
774                                                         else
775                                                                 Con_Printf("LHNET_OpenSocket_Connectionless: bind returned error: %s\n", LHNETPRIVATE_StrError());
776                                                 }
777 #ifdef IPV6_V6ONLY
778                                                 else
779                                                         Con_Printf("LHNET_OpenSocket_Connectionless: setsockopt(IPV6_V6ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
780 #endif
781                                         }
782                                         else
783                                                 Con_Printf("LHNET_OpenSocket_Connectionless: ioctlsocket returned error: %s\n", LHNETPRIVATE_StrError());
784                                         closesocket(lhnetsocket->inetsocket);
785                                 }
786                                 else
787                                         Con_Printf("LHNET_OpenSocket_Connectionless: socket returned error: %s\n", LHNETPRIVATE_StrError());
788 #ifdef WIN32
789                         }
790                         else
791                                 Con_Print("LHNET_OpenSocket_Connectionless: can't open a socket (WSAStartup failed during LHNET_Init)\n");
792 #endif
793                         break;
794                 default:
795                         break;
796                 }
797                 Z_Free(lhnetsocket);
798         }
799         return NULL;
800 }
801
802 void LHNET_CloseSocket(lhnetsocket_t *lhnetsocket)
803 {
804         if (lhnetsocket)
805         {
806                 // unlink from socket list
807                 if (lhnetsocket->next == NULL)
808                         return; // invalid!
809                 lhnetsocket->next->prev = lhnetsocket->prev;
810                 lhnetsocket->prev->next = lhnetsocket->next;
811                 lhnetsocket->next = NULL;
812                 lhnetsocket->prev = NULL;
813
814                 // no special close code for loopback, just inet
815                 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4 || lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
816                 {
817                         closesocket(lhnetsocket->inetsocket);
818                 }
819                 Z_Free(lhnetsocket);
820         }
821 }
822
823 lhnetaddress_t *LHNET_AddressFromSocket(lhnetsocket_t *sock)
824 {
825         if (sock)
826                 return &sock->address;
827         else
828                 return NULL;
829 }
830
831 int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, lhnetaddress_t *vaddress)
832 {
833         lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
834         int value = 0;
835         if (!lhnetsocket || !address || !content || maxcontentlength < 1)
836                 return -1;
837         if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
838         {
839                 time_t currenttime;
840                 lhnetpacket_t *p, *pnext;
841                 // scan for any old packets to timeout while searching for a packet
842                 // that is waiting to be delivered to this socket
843                 currenttime = time(NULL);
844                 for (p = lhnet_packetlist.next;p != &lhnet_packetlist;p = pnext)
845                 {
846                         pnext = p->next;
847                         if (p->timeout < currenttime)
848                         {
849                                 // unlink and free
850                                 p->next->prev = p->prev;
851                                 p->prev->next = p->next;
852                                 Z_Free(p);
853                                 continue;
854                         }
855 #ifndef STANDALONETEST
856                         if (cl_netlocalping.value && (realtime - cl_netlocalping.value * (1.0 / 2000.0)) < p->sentdoubletime)
857                                 continue;
858 #endif
859                         if (value == 0 && p->destinationport == lhnetsocket->address.port)
860                         {
861                                 if (p->length <= maxcontentlength)
862                                 {
863                                         lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
864                                         *address = *localaddress;
865                                         address->port = p->sourceport;
866                                         memcpy(content, p->data, p->length);
867                                         value = p->length;
868                                 }
869                                 else
870                                         value = -1;
871                                 // unlink and free
872                                 p->next->prev = p->prev;
873                                 p->prev->next = p->next;
874                                 Z_Free(p);
875                         }
876                 }
877         }
878         else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
879         {
880                 SOCKLEN_T inetaddresslength;
881                 address->addresstype = LHNETADDRESSTYPE_NONE;
882                 inetaddresslength = sizeof(address->addr.in);
883                 value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, 0, &address->addr.sock, &inetaddresslength);
884                 if (value > 0)
885                 {
886                         address->addresstype = LHNETADDRESSTYPE_INET4;
887                         address->port = ntohs(address->addr.in.sin_port);
888                         return value;
889                 }
890                 else if (value == -1)
891                 {
892                         int e = SOCKETERRNO;
893                         if (e == EWOULDBLOCK)
894                                 return 0;
895                         switch (e)
896                         {
897                                 case ECONNREFUSED:
898                                         Con_Print("Connection refused\n");
899                                         return 0;
900                         }
901                         Con_Printf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
902                 }
903         }
904         else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
905         {
906                 SOCKLEN_T inetaddresslength;
907                 address->addresstype = LHNETADDRESSTYPE_NONE;
908                 inetaddresslength = sizeof(address->addr.in6);
909                 value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, 0, &address->addr.sock, &inetaddresslength);
910                 if (value > 0)
911                 {
912                         address->addresstype = LHNETADDRESSTYPE_INET6;
913                         address->port = ntohs(address->addr.in6.sin6_port);
914                         return value;
915                 }
916                 else if (value == -1)
917                 {
918                         int e = SOCKETERRNO;
919                         if (e == EWOULDBLOCK)
920                                 return 0;
921                         switch (e)
922                         {
923                                 case ECONNREFUSED:
924                                         Con_Print("Connection refused\n");
925                                         return 0;
926                         }
927                         Con_Printf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
928                 }
929         }
930         return value;
931 }
932
933 int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *vaddress)
934 {
935         lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
936         int value = -1;
937         if (!lhnetsocket || !address || !content || contentlength < 1)
938                 return -1;
939         if (lhnetsocket->address.addresstype != address->addresstype)
940                 return -1;
941         if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
942         {
943                 lhnetpacket_t *p;
944                 p = (lhnetpacket_t *)Z_Malloc(sizeof(*p) + contentlength);
945                 p->data = (void *)(p + 1);
946                 memcpy(p->data, content, contentlength);
947                 p->length = contentlength;
948                 p->sourceport = lhnetsocket->address.port;
949                 p->destinationport = address->port;
950                 p->timeout = time(NULL) + 10;
951                 p->next = &lhnet_packetlist;
952                 p->prev = p->next->prev;
953                 p->next->prev = p;
954                 p->prev->next = p;
955 #ifndef STANDALONETEST
956                 p->sentdoubletime = realtime;
957 #endif
958                 value = contentlength;
959         }
960         else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
961         {
962                 value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, 0, (struct sockaddr *)&address->addr.in, sizeof(struct sockaddr_in));
963                 if (value == -1)
964                 {
965                         if (SOCKETERRNO == EWOULDBLOCK)
966                                 return 0;
967                         Con_Printf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
968                 }
969         }
970         else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
971         {
972                 value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, 0, (struct sockaddr *)&address->addr.in6, sizeof(struct sockaddr_in6));
973                 if (value == -1)
974                 {
975                         if (SOCKETERRNO == EWOULDBLOCK)
976                                 return 0;
977                         Con_Printf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
978                 }
979         }
980         return value;
981 }
982
983 #ifdef STANDALONETEST
984 int main(int argc, char **argv)
985 {
986 #if 1
987         char *buffer = "test", buffer2[1024];
988         int blen = strlen(buffer);
989         int b2len = 1024;
990         lhnetsocket_t *sock1;
991         lhnetsocket_t *sock2;
992         lhnetaddress_t myaddy1;
993         lhnetaddress_t myaddy2;
994         lhnetaddress_t myaddy3;
995         lhnetaddress_t localhostaddy1;
996         lhnetaddress_t localhostaddy2;
997         int test1;
998         int test2;
999
1000         printf("calling LHNET_Init\n");
1001         LHNET_Init();
1002
1003         printf("calling LHNET_FromPort twice to create two local addresses\n");
1004         LHNETADDRESS_FromPort(&myaddy1, LHNETADDRESSTYPE_INET4, 4000);
1005         LHNETADDRESS_FromPort(&myaddy2, LHNETADDRESSTYPE_INET4, 4001);
1006         LHNETADDRESS_FromString(&localhostaddy1, "127.0.0.1", 4000);
1007         LHNETADDRESS_FromString(&localhostaddy2, "127.0.0.1", 4001);
1008
1009         printf("calling LHNET_OpenSocket_Connectionless twice to create two local sockets\n");
1010         sock1 = LHNET_OpenSocket_Connectionless(&myaddy1);
1011         sock2 = LHNET_OpenSocket_Connectionless(&myaddy2);
1012
1013         printf("calling LHNET_Write to send a packet from the first socket to the second socket\n");
1014         test1 = LHNET_Write(sock1, buffer, blen, &localhostaddy2);
1015         printf("sleeping briefly\n");
1016 #ifdef WIN32
1017         Sleep (100);
1018 #else
1019         usleep (100000);
1020 #endif
1021         printf("calling LHNET_Read on the second socket to read the packet sent from the first socket\n");
1022         test2 = LHNET_Read(sock2, buffer2, b2len - 1, &myaddy3);
1023         if (test2 > 0)
1024                 Con_Printf("socket to socket test succeeded\n");
1025         else
1026                 Con_Printf("socket to socket test failed\n");
1027
1028 #ifdef WIN32
1029         printf("press any key to exit\n");
1030         getchar();
1031 #endif
1032
1033         printf("calling LHNET_Shutdown\n");
1034         LHNET_Shutdown();
1035         printf("exiting\n");
1036         return 0;
1037 #else
1038         lhnetsocket_t *sock[16], *sendsock;
1039         int i;
1040         int numsockets;
1041         int count;
1042         int length;
1043         int port;
1044         time_t oldtime;
1045         time_t newtime;
1046         char *sendmessage;
1047         int sendmessagelength;
1048         lhnetaddress_t destaddress;
1049         lhnetaddress_t receiveaddress;
1050         lhnetaddress_t sockaddress[16];
1051         char buffer[1536], addressstring[128], addressstring2[128];
1052         if ((argc == 2 || argc == 5) && (port = atoi(argv[1])) >= 1 && port < 65535)
1053         {
1054                 printf("calling LHNET_Init()\n");
1055                 LHNET_Init();
1056
1057                 numsockets = 0;
1058                 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_LOOP, port);
1059                 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET4, port);
1060                 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET6, port+1);
1061
1062                 sendsock = NULL;
1063                 sendmessage = NULL;
1064                 sendmessagelength = 0;
1065
1066                 for (i = 0;i < numsockets;i++)
1067                 {
1068                         LHNETADDRESS_ToString(&sockaddress[i], addressstring, sizeof(addressstring), 1);
1069                         printf("calling LHNET_OpenSocket_Connectionless(<%s>)\n", addressstring);
1070                         if ((sock[i] = LHNET_OpenSocket_Connectionless(&sockaddress[i])))
1071                         {
1072                                 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1073                                 printf("opened socket successfully (address \"%s\")\n", addressstring2);
1074                         }
1075                         else
1076                         {
1077                                 printf("failed to open socket\n");
1078                                 if (i == 0)
1079                                 {
1080                                         LHNET_Shutdown();
1081                                         return -1;
1082                                 }
1083                         }
1084                 }
1085                 count = 0;
1086                 if (argc == 5)
1087                 {
1088                         count = atoi(argv[2]);
1089                         if (LHNETADDRESS_FromString(&destaddress, argv[3], -1))
1090                         {
1091                                 sendmessage = argv[4];
1092                                 sendmessagelength = strlen(sendmessage);
1093                                 sendsock = NULL;
1094                                 for (i = 0;i < numsockets;i++)
1095                                         if (sock[i] && LHNETADDRESS_GetAddressType(&destaddress) == LHNETADDRESS_GetAddressType(&sockaddress[i]))
1096                                                 sendsock = sock[i];
1097                                 if (sendsock == NULL)
1098                                 {
1099                                         printf("Could not find an open socket matching the addresstype (%i) of destination address, switching to listen only mode\n", LHNETADDRESS_GetAddressType(&destaddress));
1100                                         argc = 2;
1101                                 }
1102                         }
1103                         else
1104                         {
1105                                 printf("LHNETADDRESS_FromString did not like the address \"%s\", switching to listen only mode\n", argv[3]);
1106                                 argc = 2;
1107                         }
1108                 }
1109                 printf("started, now listening for \"exit\" on the opened sockets\n");
1110                 oldtime = time(NULL);
1111                 for(;;)
1112                 {
1113 #ifdef WIN32
1114                         Sleep(1);
1115 #else
1116                         usleep(1);
1117 #endif
1118                         for (i = 0;i < numsockets;i++)
1119                         {
1120                                 if (sock[i])
1121                                 {
1122                                         length = LHNET_Read(sock[i], buffer, sizeof(buffer), &receiveaddress);
1123                                         if (length < 0)
1124                                                 printf("localsock read error: length < 0");
1125                                         else if (length > 0 && length < (int)sizeof(buffer))
1126                                         {
1127                                                 buffer[length] = 0;
1128                                                 LHNETADDRESS_ToString(&receiveaddress, addressstring, sizeof(addressstring), 1);
1129                                                 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1130                                                 printf("received message \"%s\" from \"%s\" on socket \"%s\"\n", buffer, addressstring, addressstring2);
1131                                                 if (!strcmp(buffer, "exit"))
1132                                                         break;
1133                                         }
1134                                 }
1135                         }
1136                         if (i < numsockets)
1137                                 break;
1138                         if (argc == 5 && count > 0)
1139                         {
1140                                 newtime = time(NULL);
1141                                 if (newtime != oldtime)
1142                                 {
1143                                         LHNETADDRESS_ToString(&destaddress, addressstring, sizeof(addressstring), 1);
1144                                         LHNETADDRESS_ToString(LHNET_AddressFromSocket(sendsock), addressstring2, sizeof(addressstring2), 1);
1145                                         printf("calling LHNET_Write(<%s>, \"%s\", %i, <%s>)\n", addressstring2, sendmessage, sendmessagelength, addressstring);
1146                                         length = LHNET_Write(sendsock, sendmessage, sendmessagelength, &destaddress);
1147                                         if (length == sendmessagelength)
1148                                                 printf("sent successfully\n");
1149                                         else
1150                                                 printf("LH_Write failed, returned %i (length of message was %i)\n", length, strlen(argv[4]));
1151                                         oldtime = newtime;
1152                                         count--;
1153                                         if (count <= 0)
1154                                                 printf("Done sending, still listening for \"exit\"\n");
1155                                 }
1156                         }
1157                 }
1158                 for (i = 0;i < numsockets;i++)
1159                 {
1160                         if (sock[i])
1161                         {
1162                                 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1163                                 printf("calling LHNET_CloseSocket(<%s>)\n", addressstring2);
1164                                 LHNET_CloseSocket(sock[i]);
1165                         }
1166                 }
1167                 printf("calling LHNET_Shutdown()\n");
1168                 LHNET_Shutdown();
1169                 return 0;
1170         }
1171         printf("Testing code for lhnet.c\nusage: lhnettest <localportnumber> [<sendnumberoftimes> <sendaddress:port> <sendmessage>]\n");
1172         return -1;
1173 #endif
1174 }
1175 #endif
1176