2 // Written by Ashley Rose Hale (LadyHavoc) 2003-06-15 and placed into public domain.
6 # pragma comment(lib, "ws2_32.lib")
9 // Windows XP or higher is required for getaddrinfo, but the inclusion of wspiapi provides fallbacks for older versions
10 # define _WIN32_WINNT 0x0501
12 // To increase FD_SETSIZE (defaults to 64 on Windows)
13 // it must be defined before the first inclusion of winsock2.h
14 # define FD_SETSIZE 1024 // Matches Linux and BSD defaults
15 # include <winsock2.h>
16 # include <ws2tcpip.h>
22 #ifndef STANDALONETEST
23 #include "darkplaces.h"
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/ioctl.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
45 #include <proto/socket.h>
48 // for Z_Malloc/Z_Free in quake
49 #ifndef STANDALONETEST
54 #define Con_Print printf
55 #define Con_Printf printf
56 #define Z_Malloc malloc
63 // as of Visual Studio 2015, EWOULDBLOCK and ECONNREFUSED are real things, with different values than we want when talking to WinSock, so we have to undef them here or change the rest of the code.
66 #define EWOULDBLOCK WSAEWOULDBLOCK
67 #define ECONNREFUSED WSAECONNREFUSED
69 #define SOCKETERRNO WSAGetLastError()
71 #define IOC_VENDOR 0x18000000
72 #define _WSAIOW(x,y) (IOC_IN|(x)|(y))
73 #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
76 #elif defined(__MORPHOS__)
77 #define ioctlsocket IoctlSocket
78 #define closesocket CloseSocket
79 #define SOCKETERRNO Errno()
83 #define ioctlsocket ioctl
84 #define closesocket close
85 #define SOCKETERRNO errno
87 #define SOCKLEN_T socklen_t
91 #define LHNET_RECVFROM_FLAGS MSG_DONTWAIT
92 #define LHNET_SENDTO_FLAGS 0
94 #define LHNET_RECVFROM_FLAGS 0
95 #define LHNET_SENDTO_FLAGS 0
98 typedef struct lhnetaddressnative_s
100 lhnetaddresstype_t addresstype;
104 struct sockaddr sock;
105 struct sockaddr_in in;
106 #ifndef NOSUPPORTIPV6
107 struct sockaddr_in6 in6;
112 lhnetaddressnative_t;
114 // to make LHNETADDRESS_FromString resolve repeated hostnames faster, cache them
115 #define MAX_NAMECACHE 64
116 static struct namecache_s
118 lhnetaddressnative_t address;
119 double expirationtime;
122 namecache[MAX_NAMECACHE];
123 static int namecacheposition = 0;
125 int LHNETADDRESS_FromPort(lhnetaddress_t *vaddress, lhnetaddresstype_t addresstype, int port)
127 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
134 case LHNETADDRESSTYPE_LOOP:
135 // local:port (loopback)
136 memset(address, 0, sizeof(*address));
137 address->addresstype = LHNETADDRESSTYPE_LOOP;
138 address->port = port;
140 case LHNETADDRESSTYPE_INET4:
141 // 0.0.0.0:port (INADDR_ANY, binds to all interfaces)
142 memset(address, 0, sizeof(*address));
143 address->addresstype = LHNETADDRESSTYPE_INET4;
144 address->port = port;
145 address->addr.in.sin_family = AF_INET;
146 address->addr.in.sin_port = htons((unsigned short)port);
148 #ifndef NOSUPPORTIPV6
149 case LHNETADDRESSTYPE_INET6:
150 // [0:0:0:0:0:0:0:0]:port (IN6ADDR_ANY, binds to all interfaces)
151 memset(address, 0, sizeof(*address));
152 address->addresstype = LHNETADDRESSTYPE_INET6;
153 address->port = port;
154 address->addr.in6.sin6_family = AF_INET6;
155 address->addr.in6.sin6_port = htons((unsigned short)port);
162 #ifndef NOSUPPORTIPV6
163 static int LHNETADDRESS_Resolve(lhnetaddressnative_t *address, const char *name, int port)
166 struct addrinfo hints;
167 struct addrinfo* addrinf;
170 dpsnprintf (port_buff, sizeof (port_buff), "%d", port);
171 port_buff[sizeof (port_buff) - 1] = '\0';
173 memset(&hints, 0, sizeof (hints));
174 hints.ai_family = AF_UNSPEC;
175 hints.ai_socktype = SOCK_DGRAM;
176 //hints.ai_flags = AI_PASSIVE;
178 err = getaddrinfo(name, port_buff, &hints, &addrinf);
179 if (err != 0 || addrinf == NULL)
181 if (addrinf->ai_addr->sa_family != AF_INET6 && addrinf->ai_addr->sa_family != AF_INET)
183 freeaddrinfo (addrinf);
188 if (addrinf->ai_addr->sa_family == AF_INET6)
190 address->addresstype = LHNETADDRESSTYPE_INET6;
191 memcpy(&address->addr.in6, addrinf->ai_addr, sizeof(address->addr.in6));
195 address->addresstype = LHNETADDRESSTYPE_INET4;
196 memcpy(&address->addr.in, addrinf->ai_addr, sizeof(address->addr.in));
198 address->port = port;
200 freeaddrinfo (addrinf);
204 int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
206 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
207 int i, port, d1, d2, d3, d4, resolved;
211 #ifdef STANDALONETEST
214 const char* addr_start;
215 const char* addr_end = NULL;
216 const char* port_name = NULL;
217 int addr_family = AF_UNSPEC;
219 if (!address || !string || !*string)
221 memset(address, 0, sizeof(*address));
222 address->addresstype = LHNETADDRESSTYPE_NONE;
225 // If it's a bracketed IPv6 address
226 if (string[0] == '[')
228 const char* end_bracket = strchr(string, ']');
230 if (end_bracket == NULL)
233 if (end_bracket[1] == ':')
234 port_name = end_bracket + 2;
235 else if (end_bracket[1] != '\0')
238 addr_family = AF_INET6;
239 addr_start = &string[1];
240 addr_end = end_bracket;
244 const char* first_colon;
248 // If it's a numeric non-bracket IPv6 address (-> no port),
249 // or it's a numeric IPv4 address, or a name, with a port
250 first_colon = strchr(string, ':');
251 if (first_colon != NULL)
253 const char* last_colon = strrchr(first_colon + 1, ':');
255 // If it's an numeric IPv4 address, or a name, with a port
256 if (last_colon == NULL)
258 addr_end = first_colon;
259 port_name = first_colon + 1;
262 addr_family = AF_INET6;
266 if (addr_end != NULL)
267 namelen = addr_end - addr_start;
269 namelen = strlen (addr_start);
271 if (namelen >= sizeof(name))
272 namelen = sizeof(name) - 1;
273 memcpy (name, addr_start, namelen);
277 port = atoi(port_name);
283 if (!strcmp(name, "local"))
285 address->addresstype = LHNETADDRESSTYPE_LOOP;
286 address->port = port;
289 // try to parse as dotted decimal ipv4 address first
290 // note this supports partial ip addresses
291 d1 = d2 = d3 = d4 = 0;
293 #define sscanf sscanf_s
295 if (addr_family != AF_INET6 &&
296 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)
298 // parsed a valid ipv4 address
299 address->addresstype = LHNETADDRESSTYPE_INET4;
300 address->port = port;
301 address->addr.in.sin_family = AF_INET;
302 address->addr.in.sin_port = htons((unsigned short)port);
303 a = (unsigned char *)&address->addr.in.sin_addr;
308 #ifdef STANDALONETEST
309 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
310 printf("manual parsing of ipv4 dotted decimal address \"%s\" successful: %s\n", string, string2);
314 for (i = 0;i < MAX_NAMECACHE;i++)
315 if (!strcmp(namecache[i].name, name))
317 #ifdef STANDALONETEST
318 if (i < MAX_NAMECACHE)
320 if (i < MAX_NAMECACHE && host.realtime < namecache[i].expirationtime)
323 *address = namecache[i].address;
324 address->port = port;
325 if (address->addresstype == LHNETADDRESSTYPE_INET6)
327 address->addr.in6.sin6_port = htons((unsigned short)port);
330 else if (address->addresstype == LHNETADDRESSTYPE_INET4)
332 address->addr.in.sin_port = htons((unsigned short)port);
338 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
339 namecache[namecacheposition].name[i] = name[i];
340 namecache[namecacheposition].name[i] = 0;
341 #ifndef STANDALONETEST
342 namecache[namecacheposition].expirationtime = host.realtime + 12 * 3600; // 12 hours
345 // try resolving the address (handles dns and other ip formats)
346 resolved = LHNETADDRESS_Resolve(address, name, port);
349 #ifdef STANDALONETEST
350 const char *protoname;
352 switch (address->addresstype)
354 case LHNETADDRESSTYPE_INET6:
357 case LHNETADDRESSTYPE_INET4:
361 protoname = "UNKNOWN";
364 LHNETADDRESS_ToString(vaddress, string2, sizeof(string2), 1);
365 Con_Printf("LHNETADDRESS_Resolve(\"%s\") returned %s address %s\n", string, protoname, string2);
367 namecache[namecacheposition].address = *address;
371 #ifdef STANDALONETEST
372 printf("name resolution failed on address \"%s\"\n", name);
374 namecache[namecacheposition].address.addresstype = LHNETADDRESSTYPE_NONE;
377 namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
381 int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
383 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
384 int i, port, namelen, d1, d2, d3, d4;
385 struct hostent *hostentry;
389 #ifdef STANDALONETEST
392 if (!address || !string || !*string)
394 memset(address, 0, sizeof(*address));
395 address->addresstype = LHNETADDRESSTYPE_NONE;
397 colon = strrchr(string, ':');
398 if (colon && (colon == strchr(string, ':') || (string[0] == '[' && colon - string > 0 && colon[-1] == ']')))
399 // EITHER: colon is the ONLY colon OR: colon comes after [...] delimited IPv6 address
400 // fixes misparsing of IPv6 addresses without port
402 port = atoi(colon + 1);
405 colon = string + strlen(string);
408 namelen = colon - string;
411 if (string[0] == '[' && namelen > 0 && string[namelen-1] == ']') // ipv6
416 memcpy(name, string, namelen);
419 if (!strcmp(name, "local"))
421 address->addresstype = LHNETADDRESSTYPE_LOOP;
422 address->port = port;
425 // try to parse as dotted decimal ipv4 address first
426 // note this supports partial ip addresses
427 d1 = d2 = d3 = d4 = 0;
429 #define sscanf sscanf_s
431 if (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)
433 // parsed a valid ipv4 address
434 address->addresstype = LHNETADDRESSTYPE_INET4;
435 address->port = port;
436 address->addr.in.sin_family = AF_INET;
437 address->addr.in.sin_port = htons((unsigned short)port);
438 a = (unsigned char *)&address->addr.in.sin_addr;
443 #ifdef STANDALONETEST
444 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
445 printf("manual parsing of ipv4 dotted decimal address \"%s\" successful: %s\n", string, string2);
449 for (i = 0;i < MAX_NAMECACHE;i++)
450 if (!strcmp(namecache[i].name, name))
452 #ifdef STANDALONETEST
453 if (i < MAX_NAMECACHE)
455 if (i < MAX_NAMECACHE && host.realtime < namecache[i].expirationtime)
458 *address = namecache[i].address;
459 address->port = port;
460 if (address->addresstype == LHNETADDRESSTYPE_INET6)
462 #ifndef NOSUPPORTIPV6
463 address->addr.in6.sin6_port = htons((unsigned short)port);
467 else if (address->addresstype == LHNETADDRESSTYPE_INET4)
469 address->addr.in.sin_port = htons((unsigned short)port);
474 // try gethostbyname (handles dns and other ip formats)
475 hostentry = gethostbyname(name);
478 if (hostentry->h_addrtype == AF_INET6)
480 #ifndef NOSUPPORTIPV6
482 address->addresstype = LHNETADDRESSTYPE_INET6;
483 address->port = port;
484 address->addr.in6.sin6_family = hostentry->h_addrtype;
485 address->addr.in6.sin6_port = htons((unsigned short)port);
486 memcpy(&address->addr.in6.sin6_addr, hostentry->h_addr_list[0], sizeof(address->addr.in6.sin6_addr));
487 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
488 namecache[namecacheposition].name[i] = name[i];
489 namecache[namecacheposition].name[i] = 0;
490 #ifndef STANDALONETEST
491 namecache[namecacheposition].expirationtime = host.realtime + 12 * 3600; // 12 hours
493 namecache[namecacheposition].address = *address;
494 namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
495 #ifdef STANDALONETEST
496 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
497 printf("gethostbyname(\"%s\") returned ipv6 address %s\n", string, string2);
502 else if (hostentry->h_addrtype == AF_INET)
505 address->addresstype = LHNETADDRESSTYPE_INET4;
506 address->port = port;
507 address->addr.in.sin_family = hostentry->h_addrtype;
508 address->addr.in.sin_port = htons((unsigned short)port);
509 memcpy(&address->addr.in.sin_addr, hostentry->h_addr_list[0], sizeof(address->addr.in.sin_addr));
510 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
511 namecache[namecacheposition].name[i] = name[i];
512 namecache[namecacheposition].name[i] = 0;
513 #ifndef STANDALONETEST
514 namecache[namecacheposition].expirationtime = host.realtime + 12 * 3600; // 12 hours
516 namecache[namecacheposition].address = *address;
517 namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
518 #ifdef STANDALONETEST
519 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
520 printf("gethostbyname(\"%s\") returned ipv4 address %s\n", string, string2);
525 #ifdef STANDALONETEST
526 printf("gethostbyname failed on address \"%s\"\n", name);
528 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
529 namecache[namecacheposition].name[i] = name[i];
530 namecache[namecacheposition].name[i] = 0;
531 #ifndef STANDALONETEST
532 namecache[namecacheposition].expirationtime = host.realtime + 12 * 3600; // 12 hours
534 namecache[namecacheposition].address.addresstype = LHNETADDRESSTYPE_NONE;
535 namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
540 int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stringbuffersize, int includeport)
542 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
543 const unsigned char *a;
544 if (!address || !string || stringbuffersize < 1)
547 switch(address->addresstype)
551 case LHNETADDRESSTYPE_LOOP:
554 if (stringbuffersize >= 12)
556 return dpsnprintf(string, stringbuffersize, "local:%d", address->port);
561 if (stringbuffersize >= 6)
563 memcpy(string, "local", 6);
568 case LHNETADDRESSTYPE_INET4:
569 a = (const unsigned char *)(&address->addr.in.sin_addr);
572 if (stringbuffersize >= 22)
574 return dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d:%d", a[0], a[1], a[2], a[3], address->port);
579 if (stringbuffersize >= 16)
581 return dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
585 #ifndef NOSUPPORTIPV6
586 case LHNETADDRESSTYPE_INET6:
587 a = (const unsigned char *)(&address->addr.in6.sin6_addr);
590 if (stringbuffersize >= 88)
592 return 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);
597 if (stringbuffersize >= 80)
599 return 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]);
608 const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress, char *ifname, size_t ifnamelength)
610 #ifndef NOSUPPORTIPV6
611 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
613 if (address && address->addresstype == LHNETADDRESSTYPE_INET6)
617 if (if_indextoname(address->addr.in6.sin6_scope_id, ifname) == ifname)
622 // The Win32 API doesn't have if_indextoname() until Windows Vista,
623 // but luckily it just uses the interface ID as the interface name
625 if (dpsnprintf(ifname, ifnamelength, "%lu", address->addr.in6.sin6_scope_id) > 0)
635 int LHNETADDRESS_GetPort(const lhnetaddress_t *address)
639 return address->port;
642 int LHNETADDRESS_SetPort(lhnetaddress_t *vaddress, int port)
644 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
647 address->port = port;
648 switch(address->addresstype)
650 case LHNETADDRESSTYPE_LOOP:
652 case LHNETADDRESSTYPE_INET4:
653 address->addr.in.sin_port = htons((unsigned short)port);
655 #ifndef NOSUPPORTIPV6
656 case LHNETADDRESSTYPE_INET6:
657 address->addr.in6.sin6_port = htons((unsigned short)port);
665 int LHNETADDRESS_Compare(const lhnetaddress_t *vaddress1, const lhnetaddress_t *vaddress2)
667 lhnetaddressnative_t *address1 = (lhnetaddressnative_t *)vaddress1;
668 lhnetaddressnative_t *address2 = (lhnetaddressnative_t *)vaddress2;
669 if (!address1 || !address2)
671 if (address1->addresstype != address2->addresstype)
673 switch(address1->addresstype)
675 case LHNETADDRESSTYPE_LOOP:
676 if (address1->port != address2->port)
679 case LHNETADDRESSTYPE_INET4:
680 if (address1->addr.in.sin_family != address2->addr.in.sin_family)
682 if (memcmp(&address1->addr.in.sin_addr, &address2->addr.in.sin_addr, sizeof(address1->addr.in.sin_addr)))
684 if (address1->port != address2->port)
687 #ifndef NOSUPPORTIPV6
688 case LHNETADDRESSTYPE_INET6:
689 if (address1->addr.in6.sin6_family != address2->addr.in6.sin6_family)
691 if (memcmp(&address1->addr.in6.sin6_addr, &address2->addr.in6.sin6_addr, sizeof(address1->addr.in6.sin6_addr)))
693 if (address1->port != address2->port)
702 typedef struct lhnetpacket_s
709 #ifndef STANDALONETEST
710 double sentdoubletime;
716 static int lhnet_active;
717 lhnetsocket_t lhnet_socketlist;
718 static lhnetpacket_t lhnet_packetlist;
719 static int lhnet_default_dscp = 0;
721 static int lhnet_didWSAStartup = 0;
722 static WSADATA lhnet_winsockdata;
725 void LHNET_Init(void)
729 List_Create(&lhnet_socketlist.list);
730 List_Create(&lhnet_packetlist.list);
733 lhnet_didWSAStartup = !WSAStartup(MAKEWORD(1, 1), &lhnet_winsockdata);
734 if (!lhnet_didWSAStartup)
735 Con_Print("LHNET_Init: WSAStartup failed, networking disabled\n");
739 int LHNET_DefaultDSCP(int dscp)
742 int prev = lhnet_default_dscp;
744 lhnet_default_dscp = dscp;
751 void LHNET_Shutdown(void)
753 lhnetsocket_t *s, *snext;
754 lhnetpacket_t *p, *pnext;
757 List_For_Each_Entry_Safe(s, snext, &lhnet_socketlist.list, lhnetsocket_t, list)
758 LHNET_CloseSocket(s);
759 List_For_Each_Entry_Safe(p, pnext, &lhnet_packetlist.list, lhnetpacket_t, list)
761 List_Delete(&p->list);
765 if (lhnet_didWSAStartup)
767 lhnet_didWSAStartup = 0;
774 static const char *LHNETPRIVATE_StrError(void)
777 int i = WSAGetLastError();
780 case WSAEINTR: return "WSAEINTR";
781 case WSAEBADF: return "WSAEBADF";
782 case WSAEACCES: return "WSAEACCES";
783 case WSAEFAULT: return "WSAEFAULT";
784 case WSAEINVAL: return "WSAEINVAL";
785 case WSAEMFILE: return "WSAEMFILE";
786 case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
787 case WSAEINPROGRESS: return "WSAEINPROGRESS";
788 case WSAEALREADY: return "WSAEALREADY";
789 case WSAENOTSOCK: return "WSAENOTSOCK";
790 case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
791 case WSAEMSGSIZE: return "WSAEMSGSIZE";
792 case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
793 case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
794 case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
795 case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
796 case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
797 case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
798 case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
799 case WSAEADDRINUSE: return "WSAEADDRINUSE";
800 case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
801 case WSAENETDOWN: return "WSAENETDOWN";
802 case WSAENETUNREACH: return "WSAENETUNREACH";
803 case WSAENETRESET: return "WSAENETRESET";
804 case WSAECONNABORTED: return "WSAECONNABORTED";
805 case WSAECONNRESET: return "WSAECONNRESET";
806 case WSAENOBUFS: return "WSAENOBUFS";
807 case WSAEISCONN: return "WSAEISCONN";
808 case WSAENOTCONN: return "WSAENOTCONN";
809 case WSAESHUTDOWN: return "WSAESHUTDOWN";
810 case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
811 case WSAETIMEDOUT: return "WSAETIMEDOUT";
812 case WSAECONNREFUSED: return "WSAECONNREFUSED";
813 case WSAELOOP: return "WSAELOOP";
814 case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
815 case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
816 case WSAEHOSTUNREACH: return "WSAEHOSTUNREACH";
817 case WSAENOTEMPTY: return "WSAENOTEMPTY";
818 case WSAEPROCLIM: return "WSAEPROCLIM";
819 case WSAEUSERS: return "WSAEUSERS";
820 case WSAEDQUOT: return "WSAEDQUOT";
821 case WSAESTALE: return "WSAESTALE";
822 case WSAEREMOTE: return "WSAEREMOTE";
823 case WSAEDISCON: return "WSAEDISCON";
824 case 0: return "no error";
825 default: return "unknown WSAE error";
828 return strerror(errno);
832 lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address)
834 lhnetsocket_t *lhnetsocket, *s;
837 lhnetsocket = (lhnetsocket_t *)Z_Malloc(sizeof(*lhnetsocket));
840 memset(lhnetsocket, 0, sizeof(*lhnetsocket));
841 lhnetsocket->address = *address;
842 switch(lhnetsocket->address.addresstype)
844 case LHNETADDRESSTYPE_LOOP:
845 if (lhnetsocket->address.port == 0)
847 // allocate a port dynamically
848 // this search will always terminate because there is never
849 // an allocated socket with port 0, so if the number wraps it
850 // will find the port is unused, and then refuse to use port
851 // 0, causing an intentional failure condition
852 lhnetsocket->address.port = 1024;
855 List_For_Each_Entry(s, &lhnet_socketlist.list, lhnetsocket_t, list)
856 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
858 if (s == &lhnet_socketlist)
860 lhnetsocket->address.port++;
863 // check if the port is available
864 List_For_Each_Entry(s, &lhnet_socketlist.list, lhnetsocket_t, list)
865 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
867 if (s == &lhnet_socketlist && lhnetsocket->address.port != 0)
869 List_Add_Tail(&lhnetsocket->list, &lhnet_socketlist.list);
873 case LHNETADDRESSTYPE_INET4:
874 #ifndef NOSUPPORTIPV6
875 case LHNETADDRESSTYPE_INET6:
878 if (lhnet_didWSAStartup)
881 #ifndef NOSUPPORTIPV6
882 if ((lhnetsocket->inetsocket = socket(address->addresstype == LHNETADDRESSTYPE_INET6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
884 if ((lhnetsocket->inetsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
898 if (ioctlsocket(lhnetsocket->inetsocket, FIONBIO, &_true) != -1)
902 // We need to set this flag to tell the OS that we only listen on IPv6. If we don't
903 // most OSes will create a dual-protocol socket that also listens on IPv4. In this case
904 // if an IPv4 socket is already bound to the port we want, our bind() call will fail.
906 if (address->addresstype != LHNETADDRESSTYPE_INET6
907 || setsockopt (lhnetsocket->inetsocket, IPPROTO_IPV6, IPV6_V6ONLY,
908 (const char *)&ipv6_only, sizeof(ipv6_only)) == 0
910 // The Win32 API only supports IPV6_V6ONLY since Windows Vista, but fortunately
911 // the default value is what we want on Win32 anyway (IPV6_V6ONLY = true)
912 || SOCKETERRNO == WSAENOPROTOOPT
917 lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
921 #if defined(SOL_RFC1149) && defined(RFC1149_1149ONLY)
922 // we got reports of massive lags when this protocol was chosen as transport
923 // so better turn it off
926 int rfc1149enabled = 0;
927 if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_1149ONLY, &rfc1149only))
928 Con_Printf(CON_ERROR "LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_1149ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
929 if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_ENABLED, &rfc1149enabled))
930 Con_Printf(CON_ERROR "LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_ENABLED) returned error: %s\n", LHNETPRIVATE_StrError());
934 #ifndef NOSUPPORTIPV6
935 if (address->addresstype == LHNETADDRESSTYPE_INET6)
937 namelen = sizeof(localaddress->addr.in6);
938 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
939 if (bindresult != -1)
941 if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen))
943 // If getsockname failed, we can assume the bound socket is useless.
951 namelen = sizeof(localaddress->addr.in);
952 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
953 if (bindresult != -1)
955 if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen))
957 // If getsockname failed, we can assume the bound socket is useless.
962 if (bindresult != -1)
965 // enable broadcast on this socket
966 setsockopt(lhnetsocket->inetsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i));
969 // enable DSCP for ToS support
970 int tos = lhnet_default_dscp << 2;
971 if (setsockopt(lhnetsocket->inetsocket, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos)))
973 // Error in setsockopt - fine, we'll simply set no TOS then.
977 List_Add_Tail(&lhnetsocket->list, &lhnet_socketlist.list);
979 if (ioctlsocket(lhnetsocket->inetsocket, SIO_UDP_CONNRESET, &_false) == -1)
980 Con_DPrintf("LHNET_OpenSocket_Connectionless: ioctlsocket SIO_UDP_CONNRESET returned error: %s\n", LHNETPRIVATE_StrError());
985 Con_Printf("LHNET_OpenSocket_Connectionless: bind returned error: %s\n", LHNETPRIVATE_StrError());
989 Con_Printf("LHNET_OpenSocket_Connectionless: setsockopt(IPV6_V6ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
993 Con_Printf("LHNET_OpenSocket_Connectionless: ioctlsocket returned error: %s\n", LHNETPRIVATE_StrError());
994 closesocket(lhnetsocket->inetsocket);
997 Con_Printf("LHNET_OpenSocket_Connectionless: socket returned error: %s\n", LHNETPRIVATE_StrError());
1001 Con_Print("LHNET_OpenSocket_Connectionless: can't open a socket (WSAStartup failed during LHNET_Init)\n");
1007 Z_Free(lhnetsocket);
1012 void LHNET_CloseSocket(lhnetsocket_t *lhnetsocket)
1016 List_Delete(&lhnetsocket->list);
1017 // no special close code for loopback, just inet
1018 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4 || lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1020 closesocket(lhnetsocket->inetsocket);
1022 Z_Free(lhnetsocket);
1026 lhnetaddress_t *LHNET_AddressFromSocket(lhnetsocket_t *sock)
1029 return &sock->address;
1034 int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, lhnetaddress_t *vaddress)
1036 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
1038 if (!lhnetsocket || !address || !content || maxcontentlength < 1)
1040 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
1043 lhnetpacket_t *p, *pnext;
1044 // scan for any old packets to timeout while searching for a packet
1045 // that is waiting to be delivered to this socket
1046 currenttime = time(NULL);
1047 List_For_Each_Entry_Safe(p, pnext, &lhnet_packetlist.list, lhnetpacket_t, list)
1049 if (p->timeout < currenttime)
1052 List_Delete(&p->list);
1056 #ifndef STANDALONETEST
1057 if (net_fakelag.value && (host.realtime - net_fakelag.value * (1.0 / 2000.0)) < p->sentdoubletime)
1060 if (value == 0 && p->destinationport == lhnetsocket->address.port)
1062 if (p->length <= maxcontentlength)
1064 lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
1065 *address = *localaddress;
1066 address->port = p->sourceport;
1067 memcpy(content, p->data, p->length);
1073 List_Delete(&p->list);
1078 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
1080 SOCKLEN_T inetaddresslength;
1081 address->addresstype = LHNETADDRESSTYPE_NONE;
1082 inetaddresslength = sizeof(address->addr.in);
1083 value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength);
1086 address->addresstype = LHNETADDRESSTYPE_INET4;
1087 address->port = ntohs(address->addr.in.sin_port);
1092 int e = SOCKETERRNO;
1093 if (e == EWOULDBLOCK)
1098 Con_Print("Connection refused\n");
1101 Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
1104 #ifndef NOSUPPORTIPV6
1105 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1107 SOCKLEN_T inetaddresslength;
1108 address->addresstype = LHNETADDRESSTYPE_NONE;
1109 inetaddresslength = sizeof(address->addr.in6);
1110 value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength);
1113 address->addresstype = LHNETADDRESSTYPE_INET6;
1114 address->port = ntohs(address->addr.in6.sin6_port);
1117 else if (value == -1)
1119 int e = SOCKETERRNO;
1120 if (e == EWOULDBLOCK)
1125 Con_Print("Connection refused\n");
1128 Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
1135 int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *vaddress)
1137 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
1139 if (!lhnetsocket || !address || !content || contentlength < 1)
1141 if (lhnetsocket->address.addresstype != address->addresstype)
1143 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
1146 p = (lhnetpacket_t *)Z_Malloc(sizeof(*p) + contentlength);
1147 p->data = (void *)(p + 1);
1148 memcpy(p->data, content, contentlength);
1149 p->length = contentlength;
1150 p->sourceport = lhnetsocket->address.port;
1151 p->destinationport = address->port;
1152 p->timeout = time(NULL) + 10;
1153 List_Add_Tail(&p->list, &lhnet_packetlist.list);
1155 #ifndef STANDALONETEST
1156 p->sentdoubletime = host.realtime;
1158 value = contentlength;
1160 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
1162 value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, LHNET_SENDTO_FLAGS, (struct sockaddr *)&address->addr.in, sizeof(struct sockaddr_in));
1165 if (SOCKETERRNO == EWOULDBLOCK)
1167 Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
1170 #ifndef NOSUPPORTIPV6
1171 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1173 value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, 0, (struct sockaddr *)&address->addr.in6, sizeof(struct sockaddr_in6));
1176 if (SOCKETERRNO == EWOULDBLOCK)
1178 Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
1185 #ifdef STANDALONETEST
1186 int main(int argc, char **argv)
1189 char *buffer = "test", buffer2[1024];
1190 int blen = strlen(buffer);
1192 lhnetsocket_t *sock1;
1193 lhnetsocket_t *sock2;
1194 lhnetaddress_t myaddy1;
1195 lhnetaddress_t myaddy2;
1196 lhnetaddress_t myaddy3;
1197 lhnetaddress_t localhostaddy1;
1198 lhnetaddress_t localhostaddy2;
1202 printf("calling LHNET_Init\n");
1205 printf("calling LHNET_FromPort twice to create two local addresses\n");
1206 LHNETADDRESS_FromPort(&myaddy1, LHNETADDRESSTYPE_INET4, 4000);
1207 LHNETADDRESS_FromPort(&myaddy2, LHNETADDRESSTYPE_INET4, 4001);
1208 LHNETADDRESS_FromString(&localhostaddy1, "127.0.0.1", 4000);
1209 LHNETADDRESS_FromString(&localhostaddy2, "127.0.0.1", 4001);
1211 printf("calling LHNET_OpenSocket_Connectionless twice to create two local sockets\n");
1212 sock1 = LHNET_OpenSocket_Connectionless(&myaddy1);
1213 sock2 = LHNET_OpenSocket_Connectionless(&myaddy2);
1215 printf("calling LHNET_Write to send a packet from the first socket to the second socket\n");
1216 test1 = LHNET_Write(sock1, buffer, blen, &localhostaddy2);
1217 printf("sleeping briefly\n");
1223 printf("calling LHNET_Read on the second socket to read the packet sent from the first socket\n");
1224 test2 = LHNET_Read(sock2, buffer2, b2len - 1, &myaddy3);
1226 Con_Printf("socket to socket test succeeded\n");
1228 Con_Printf("socket to socket test failed\n");
1231 printf("press any key to exit\n");
1235 printf("calling LHNET_Shutdown\n");
1237 printf("exiting\n");
1240 lhnetsocket_t *sock[16], *sendsock;
1249 int sendmessagelength;
1250 lhnetaddress_t destaddress;
1251 lhnetaddress_t receiveaddress;
1252 lhnetaddress_t sockaddress[16];
1253 char buffer[1536], addressstring[128], addressstring2[128];
1254 if ((argc == 2 || argc == 5) && (port = atoi(argv[1])) >= 1 && port < 65535)
1256 printf("calling LHNET_Init()\n");
1260 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_LOOP, port);
1261 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET4, port);
1262 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET6, port+1);
1266 sendmessagelength = 0;
1268 for (i = 0;i < numsockets;i++)
1270 LHNETADDRESS_ToString(&sockaddress[i], addressstring, sizeof(addressstring), 1);
1271 printf("calling LHNET_OpenSocket_Connectionless(<%s>)\n", addressstring);
1272 if ((sock[i] = LHNET_OpenSocket_Connectionless(&sockaddress[i])))
1274 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1275 printf("opened socket successfully (address \"%s\")\n", addressstring2);
1279 printf("failed to open socket\n");
1290 count = atoi(argv[2]);
1291 if (LHNETADDRESS_FromString(&destaddress, argv[3], -1))
1293 sendmessage = argv[4];
1294 sendmessagelength = strlen(sendmessage);
1296 for (i = 0;i < numsockets;i++)
1297 if (sock[i] && LHNETADDRESS_GetAddressType(&destaddress) == LHNETADDRESS_GetAddressType(&sockaddress[i]))
1299 if (sendsock == NULL)
1301 printf("Could not find an open socket matching the addresstype (%i) of destination address, switching to listen only mode\n", LHNETADDRESS_GetAddressType(&destaddress));
1307 printf("LHNETADDRESS_FromString did not like the address \"%s\", switching to listen only mode\n", argv[3]);
1311 printf("started, now listening for \"exit\" on the opened sockets\n");
1312 oldtime = time(NULL);
1320 for (i = 0;i < numsockets;i++)
1324 length = LHNET_Read(sock[i], buffer, sizeof(buffer), &receiveaddress);
1326 printf("localsock read error: length < 0");
1327 else if (length > 0 && length < (int)sizeof(buffer))
1330 LHNETADDRESS_ToString(&receiveaddress, addressstring, sizeof(addressstring), 1);
1331 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1332 printf("received message \"%s\" from \"%s\" on socket \"%s\"\n", buffer, addressstring, addressstring2);
1333 if (!strcmp(buffer, "exit"))
1340 if (argc == 5 && count > 0)
1342 newtime = time(NULL);
1343 if (newtime != oldtime)
1345 LHNETADDRESS_ToString(&destaddress, addressstring, sizeof(addressstring), 1);
1346 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sendsock), addressstring2, sizeof(addressstring2), 1);
1347 printf("calling LHNET_Write(<%s>, \"%s\", %i, <%s>)\n", addressstring2, sendmessage, sendmessagelength, addressstring);
1348 length = LHNET_Write(sendsock, sendmessage, sendmessagelength, &destaddress);
1349 if (length == sendmessagelength)
1350 printf("sent successfully\n");
1352 printf("LH_Write failed, returned %i (length of message was %i)\n", length, strlen(argv[4]));
1356 printf("Done sending, still listening for \"exit\"\n");
1360 for (i = 0;i < numsockets;i++)
1364 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1365 printf("calling LHNET_CloseSocket(<%s>)\n", addressstring2);
1366 LHNET_CloseSocket(sock[i]);
1369 printf("calling LHNET_Shutdown()\n");
1373 printf("Testing code for lhnet.c\nusage: lhnettest <localportnumber> [<sendnumberoftimes> <sendaddress:port> <sendmessage>]\n");