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 dpsnprintf(string, stringbuffersize, "local:%d", address->port);
562 if (stringbuffersize >= 6)
564 memcpy(string, "local", 6);
569 case LHNETADDRESSTYPE_INET4:
570 a = (const unsigned char *)(&address->addr.in.sin_addr);
573 if (stringbuffersize >= 22)
575 dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d:%d", a[0], a[1], a[2], a[3], address->port);
581 if (stringbuffersize >= 16)
583 dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
588 #ifndef NOSUPPORTIPV6
589 case LHNETADDRESSTYPE_INET6:
590 a = (const unsigned char *)(&address->addr.in6.sin6_addr);
593 if (stringbuffersize >= 88)
595 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);
601 if (stringbuffersize >= 80)
603 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]);
613 const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress, char *ifname, size_t ifnamelength)
615 #ifndef NOSUPPORTIPV6
616 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
618 if (address && address->addresstype == LHNETADDRESSTYPE_INET6)
622 if (if_indextoname(address->addr.in6.sin6_scope_id, ifname) == ifname)
627 // The Win32 API doesn't have if_indextoname() until Windows Vista,
628 // but luckily it just uses the interface ID as the interface name
630 if (dpsnprintf(ifname, ifnamelength, "%lu", address->addr.in6.sin6_scope_id) > 0)
640 int LHNETADDRESS_GetPort(const lhnetaddress_t *address)
644 return address->port;
647 int LHNETADDRESS_SetPort(lhnetaddress_t *vaddress, int port)
649 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
652 address->port = port;
653 switch(address->addresstype)
655 case LHNETADDRESSTYPE_LOOP:
657 case LHNETADDRESSTYPE_INET4:
658 address->addr.in.sin_port = htons((unsigned short)port);
660 #ifndef NOSUPPORTIPV6
661 case LHNETADDRESSTYPE_INET6:
662 address->addr.in6.sin6_port = htons((unsigned short)port);
670 int LHNETADDRESS_Compare(const lhnetaddress_t *vaddress1, const lhnetaddress_t *vaddress2)
672 lhnetaddressnative_t *address1 = (lhnetaddressnative_t *)vaddress1;
673 lhnetaddressnative_t *address2 = (lhnetaddressnative_t *)vaddress2;
674 if (!address1 || !address2)
676 if (address1->addresstype != address2->addresstype)
678 switch(address1->addresstype)
680 case LHNETADDRESSTYPE_LOOP:
681 if (address1->port != address2->port)
684 case LHNETADDRESSTYPE_INET4:
685 if (address1->addr.in.sin_family != address2->addr.in.sin_family)
687 if (memcmp(&address1->addr.in.sin_addr, &address2->addr.in.sin_addr, sizeof(address1->addr.in.sin_addr)))
689 if (address1->port != address2->port)
692 #ifndef NOSUPPORTIPV6
693 case LHNETADDRESSTYPE_INET6:
694 if (address1->addr.in6.sin6_family != address2->addr.in6.sin6_family)
696 if (memcmp(&address1->addr.in6.sin6_addr, &address2->addr.in6.sin6_addr, sizeof(address1->addr.in6.sin6_addr)))
698 if (address1->port != address2->port)
707 typedef struct lhnetpacket_s
714 #ifndef STANDALONETEST
715 double sentdoubletime;
721 static int lhnet_active;
722 lhnetsocket_t lhnet_socketlist;
723 static lhnetpacket_t lhnet_packetlist;
724 static int lhnet_default_dscp = 0;
726 static int lhnet_didWSAStartup = 0;
727 static WSADATA lhnet_winsockdata;
730 void LHNET_Init(void)
734 List_Create(&lhnet_socketlist.list);
735 List_Create(&lhnet_packetlist.list);
738 lhnet_didWSAStartup = !WSAStartup(MAKEWORD(1, 1), &lhnet_winsockdata);
739 if (!lhnet_didWSAStartup)
740 Con_Print("LHNET_Init: WSAStartup failed, networking disabled\n");
744 int LHNET_DefaultDSCP(int dscp)
747 int prev = lhnet_default_dscp;
749 lhnet_default_dscp = dscp;
756 void LHNET_Shutdown(void)
758 lhnetsocket_t *s, *snext;
759 lhnetpacket_t *p, *pnext;
762 List_For_Each_Entry_Safe(s, snext, &lhnet_socketlist.list, lhnetsocket_t, list)
763 LHNET_CloseSocket(s);
764 List_For_Each_Entry_Safe(p, pnext, &lhnet_packetlist.list, lhnetpacket_t, list)
766 List_Delete(&p->list);
770 if (lhnet_didWSAStartup)
772 lhnet_didWSAStartup = 0;
779 static const char *LHNETPRIVATE_StrError(void)
782 int i = WSAGetLastError();
785 case WSAEINTR: return "WSAEINTR";
786 case WSAEBADF: return "WSAEBADF";
787 case WSAEACCES: return "WSAEACCES";
788 case WSAEFAULT: return "WSAEFAULT";
789 case WSAEINVAL: return "WSAEINVAL";
790 case WSAEMFILE: return "WSAEMFILE";
791 case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
792 case WSAEINPROGRESS: return "WSAEINPROGRESS";
793 case WSAEALREADY: return "WSAEALREADY";
794 case WSAENOTSOCK: return "WSAENOTSOCK";
795 case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
796 case WSAEMSGSIZE: return "WSAEMSGSIZE";
797 case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
798 case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
799 case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
800 case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
801 case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
802 case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
803 case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
804 case WSAEADDRINUSE: return "WSAEADDRINUSE";
805 case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
806 case WSAENETDOWN: return "WSAENETDOWN";
807 case WSAENETUNREACH: return "WSAENETUNREACH";
808 case WSAENETRESET: return "WSAENETRESET";
809 case WSAECONNABORTED: return "WSAECONNABORTED";
810 case WSAECONNRESET: return "WSAECONNRESET";
811 case WSAENOBUFS: return "WSAENOBUFS";
812 case WSAEISCONN: return "WSAEISCONN";
813 case WSAENOTCONN: return "WSAENOTCONN";
814 case WSAESHUTDOWN: return "WSAESHUTDOWN";
815 case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
816 case WSAETIMEDOUT: return "WSAETIMEDOUT";
817 case WSAECONNREFUSED: return "WSAECONNREFUSED";
818 case WSAELOOP: return "WSAELOOP";
819 case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
820 case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
821 case WSAEHOSTUNREACH: return "WSAEHOSTUNREACH";
822 case WSAENOTEMPTY: return "WSAENOTEMPTY";
823 case WSAEPROCLIM: return "WSAEPROCLIM";
824 case WSAEUSERS: return "WSAEUSERS";
825 case WSAEDQUOT: return "WSAEDQUOT";
826 case WSAESTALE: return "WSAESTALE";
827 case WSAEREMOTE: return "WSAEREMOTE";
828 case WSAEDISCON: return "WSAEDISCON";
829 case 0: return "no error";
830 default: return "unknown WSAE error";
833 return strerror(errno);
837 lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address)
839 lhnetsocket_t *lhnetsocket, *s;
842 lhnetsocket = (lhnetsocket_t *)Z_Malloc(sizeof(*lhnetsocket));
845 memset(lhnetsocket, 0, sizeof(*lhnetsocket));
846 lhnetsocket->address = *address;
847 switch(lhnetsocket->address.addresstype)
849 case LHNETADDRESSTYPE_LOOP:
850 if (lhnetsocket->address.port == 0)
852 // allocate a port dynamically
853 // this search will always terminate because there is never
854 // an allocated socket with port 0, so if the number wraps it
855 // will find the port is unused, and then refuse to use port
856 // 0, causing an intentional failure condition
857 lhnetsocket->address.port = 1024;
860 List_For_Each_Entry(s, &lhnet_socketlist.list, lhnetsocket_t, list)
861 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
863 if (s == &lhnet_socketlist)
865 lhnetsocket->address.port++;
868 // check if the port is available
869 List_For_Each_Entry(s, &lhnet_socketlist.list, lhnetsocket_t, list)
870 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
872 if (s == &lhnet_socketlist && lhnetsocket->address.port != 0)
874 List_Add_Tail(&lhnetsocket->list, &lhnet_socketlist.list);
878 case LHNETADDRESSTYPE_INET4:
879 #ifndef NOSUPPORTIPV6
880 case LHNETADDRESSTYPE_INET6:
883 if (lhnet_didWSAStartup)
886 #ifndef NOSUPPORTIPV6
887 if ((lhnetsocket->inetsocket = socket(address->addresstype == LHNETADDRESSTYPE_INET6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
889 if ((lhnetsocket->inetsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
903 if (ioctlsocket(lhnetsocket->inetsocket, FIONBIO, &_true) != -1)
907 // We need to set this flag to tell the OS that we only listen on IPv6. If we don't
908 // most OSes will create a dual-protocol socket that also listens on IPv4. In this case
909 // if an IPv4 socket is already bound to the port we want, our bind() call will fail.
911 if (address->addresstype != LHNETADDRESSTYPE_INET6
912 || setsockopt (lhnetsocket->inetsocket, IPPROTO_IPV6, IPV6_V6ONLY,
913 (const char *)&ipv6_only, sizeof(ipv6_only)) == 0
915 // The Win32 API only supports IPV6_V6ONLY since Windows Vista, but fortunately
916 // the default value is what we want on Win32 anyway (IPV6_V6ONLY = true)
917 || SOCKETERRNO == WSAENOPROTOOPT
922 lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
926 #if defined(SOL_RFC1149) && defined(RFC1149_1149ONLY)
927 // we got reports of massive lags when this protocol was chosen as transport
928 // so better turn it off
931 int rfc1149enabled = 0;
932 if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_1149ONLY, &rfc1149only))
933 Con_Printf(CON_ERROR "LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_1149ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
934 if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_ENABLED, &rfc1149enabled))
935 Con_Printf(CON_ERROR "LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_ENABLED) returned error: %s\n", LHNETPRIVATE_StrError());
939 #ifndef NOSUPPORTIPV6
940 if (address->addresstype == LHNETADDRESSTYPE_INET6)
942 namelen = sizeof(localaddress->addr.in6);
943 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
944 if (bindresult != -1)
946 if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen))
948 // If getsockname failed, we can assume the bound socket is useless.
956 namelen = sizeof(localaddress->addr.in);
957 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
958 if (bindresult != -1)
960 if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen))
962 // If getsockname failed, we can assume the bound socket is useless.
967 if (bindresult != -1)
970 // enable broadcast on this socket
971 setsockopt(lhnetsocket->inetsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i));
974 // enable DSCP for ToS support
975 int tos = lhnet_default_dscp << 2;
976 if (setsockopt(lhnetsocket->inetsocket, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos)))
978 // Error in setsockopt - fine, we'll simply set no TOS then.
982 List_Add_Tail(&lhnetsocket->list, &lhnet_socketlist.list);
984 if (ioctlsocket(lhnetsocket->inetsocket, SIO_UDP_CONNRESET, &_false) == -1)
985 Con_DPrintf("LHNET_OpenSocket_Connectionless: ioctlsocket SIO_UDP_CONNRESET returned error: %s\n", LHNETPRIVATE_StrError());
990 Con_Printf("LHNET_OpenSocket_Connectionless: bind returned error: %s\n", LHNETPRIVATE_StrError());
994 Con_Printf("LHNET_OpenSocket_Connectionless: setsockopt(IPV6_V6ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
998 Con_Printf("LHNET_OpenSocket_Connectionless: ioctlsocket returned error: %s\n", LHNETPRIVATE_StrError());
999 closesocket(lhnetsocket->inetsocket);
1002 Con_Printf("LHNET_OpenSocket_Connectionless: socket returned error: %s\n", LHNETPRIVATE_StrError());
1006 Con_Print("LHNET_OpenSocket_Connectionless: can't open a socket (WSAStartup failed during LHNET_Init)\n");
1012 Z_Free(lhnetsocket);
1017 void LHNET_CloseSocket(lhnetsocket_t *lhnetsocket)
1021 List_Delete(&lhnetsocket->list);
1022 // no special close code for loopback, just inet
1023 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4 || lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1025 closesocket(lhnetsocket->inetsocket);
1027 Z_Free(lhnetsocket);
1031 lhnetaddress_t *LHNET_AddressFromSocket(lhnetsocket_t *sock)
1034 return &sock->address;
1039 int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, lhnetaddress_t *vaddress)
1041 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
1043 if (!lhnetsocket || !address || !content || maxcontentlength < 1)
1045 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
1048 lhnetpacket_t *p, *pnext;
1049 // scan for any old packets to timeout while searching for a packet
1050 // that is waiting to be delivered to this socket
1051 currenttime = time(NULL);
1052 List_For_Each_Entry_Safe(p, pnext, &lhnet_packetlist.list, lhnetpacket_t, list)
1054 if (p->timeout < currenttime)
1057 List_Delete(&p->list);
1061 #ifndef STANDALONETEST
1062 if (net_fakelag.value && (host.realtime - net_fakelag.value * (1.0 / 2000.0)) < p->sentdoubletime)
1065 if (value == 0 && p->destinationport == lhnetsocket->address.port)
1067 if (p->length <= maxcontentlength)
1069 lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
1070 *address = *localaddress;
1071 address->port = p->sourceport;
1072 memcpy(content, p->data, p->length);
1078 List_Delete(&p->list);
1083 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
1085 SOCKLEN_T inetaddresslength;
1086 address->addresstype = LHNETADDRESSTYPE_NONE;
1087 inetaddresslength = sizeof(address->addr.in);
1088 value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength);
1091 address->addresstype = LHNETADDRESSTYPE_INET4;
1092 address->port = ntohs(address->addr.in.sin_port);
1097 int e = SOCKETERRNO;
1098 if (e == EWOULDBLOCK)
1103 Con_Print("Connection refused\n");
1106 Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
1109 #ifndef NOSUPPORTIPV6
1110 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1112 SOCKLEN_T inetaddresslength;
1113 address->addresstype = LHNETADDRESSTYPE_NONE;
1114 inetaddresslength = sizeof(address->addr.in6);
1115 value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength);
1118 address->addresstype = LHNETADDRESSTYPE_INET6;
1119 address->port = ntohs(address->addr.in6.sin6_port);
1122 else if (value == -1)
1124 int e = SOCKETERRNO;
1125 if (e == EWOULDBLOCK)
1130 Con_Print("Connection refused\n");
1133 Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
1140 int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *vaddress)
1142 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
1144 if (!lhnetsocket || !address || !content || contentlength < 1)
1146 if (lhnetsocket->address.addresstype != address->addresstype)
1148 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
1151 p = (lhnetpacket_t *)Z_Malloc(sizeof(*p) + contentlength);
1152 p->data = (void *)(p + 1);
1153 memcpy(p->data, content, contentlength);
1154 p->length = contentlength;
1155 p->sourceport = lhnetsocket->address.port;
1156 p->destinationport = address->port;
1157 p->timeout = time(NULL) + 10;
1158 List_Add_Tail(&p->list, &lhnet_packetlist.list);
1160 #ifndef STANDALONETEST
1161 p->sentdoubletime = host.realtime;
1163 value = contentlength;
1165 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
1167 value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, LHNET_SENDTO_FLAGS, (struct sockaddr *)&address->addr.in, sizeof(struct sockaddr_in));
1170 if (SOCKETERRNO == EWOULDBLOCK)
1172 Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
1175 #ifndef NOSUPPORTIPV6
1176 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1178 value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, 0, (struct sockaddr *)&address->addr.in6, sizeof(struct sockaddr_in6));
1181 if (SOCKETERRNO == EWOULDBLOCK)
1183 Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
1190 #ifdef STANDALONETEST
1191 int main(int argc, char **argv)
1194 char *buffer = "test", buffer2[1024];
1195 int blen = strlen(buffer);
1197 lhnetsocket_t *sock1;
1198 lhnetsocket_t *sock2;
1199 lhnetaddress_t myaddy1;
1200 lhnetaddress_t myaddy2;
1201 lhnetaddress_t myaddy3;
1202 lhnetaddress_t localhostaddy1;
1203 lhnetaddress_t localhostaddy2;
1207 printf("calling LHNET_Init\n");
1210 printf("calling LHNET_FromPort twice to create two local addresses\n");
1211 LHNETADDRESS_FromPort(&myaddy1, LHNETADDRESSTYPE_INET4, 4000);
1212 LHNETADDRESS_FromPort(&myaddy2, LHNETADDRESSTYPE_INET4, 4001);
1213 LHNETADDRESS_FromString(&localhostaddy1, "127.0.0.1", 4000);
1214 LHNETADDRESS_FromString(&localhostaddy2, "127.0.0.1", 4001);
1216 printf("calling LHNET_OpenSocket_Connectionless twice to create two local sockets\n");
1217 sock1 = LHNET_OpenSocket_Connectionless(&myaddy1);
1218 sock2 = LHNET_OpenSocket_Connectionless(&myaddy2);
1220 printf("calling LHNET_Write to send a packet from the first socket to the second socket\n");
1221 test1 = LHNET_Write(sock1, buffer, blen, &localhostaddy2);
1222 printf("sleeping briefly\n");
1228 printf("calling LHNET_Read on the second socket to read the packet sent from the first socket\n");
1229 test2 = LHNET_Read(sock2, buffer2, b2len - 1, &myaddy3);
1231 Con_Printf("socket to socket test succeeded\n");
1233 Con_Printf("socket to socket test failed\n");
1236 printf("press any key to exit\n");
1240 printf("calling LHNET_Shutdown\n");
1242 printf("exiting\n");
1245 lhnetsocket_t *sock[16], *sendsock;
1254 int sendmessagelength;
1255 lhnetaddress_t destaddress;
1256 lhnetaddress_t receiveaddress;
1257 lhnetaddress_t sockaddress[16];
1258 char buffer[1536], addressstring[128], addressstring2[128];
1259 if ((argc == 2 || argc == 5) && (port = atoi(argv[1])) >= 1 && port < 65535)
1261 printf("calling LHNET_Init()\n");
1265 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_LOOP, port);
1266 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET4, port);
1267 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET6, port+1);
1271 sendmessagelength = 0;
1273 for (i = 0;i < numsockets;i++)
1275 LHNETADDRESS_ToString(&sockaddress[i], addressstring, sizeof(addressstring), 1);
1276 printf("calling LHNET_OpenSocket_Connectionless(<%s>)\n", addressstring);
1277 if ((sock[i] = LHNET_OpenSocket_Connectionless(&sockaddress[i])))
1279 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1280 printf("opened socket successfully (address \"%s\")\n", addressstring2);
1284 printf("failed to open socket\n");
1295 count = atoi(argv[2]);
1296 if (LHNETADDRESS_FromString(&destaddress, argv[3], -1))
1298 sendmessage = argv[4];
1299 sendmessagelength = strlen(sendmessage);
1301 for (i = 0;i < numsockets;i++)
1302 if (sock[i] && LHNETADDRESS_GetAddressType(&destaddress) == LHNETADDRESS_GetAddressType(&sockaddress[i]))
1304 if (sendsock == NULL)
1306 printf("Could not find an open socket matching the addresstype (%i) of destination address, switching to listen only mode\n", LHNETADDRESS_GetAddressType(&destaddress));
1312 printf("LHNETADDRESS_FromString did not like the address \"%s\", switching to listen only mode\n", argv[3]);
1316 printf("started, now listening for \"exit\" on the opened sockets\n");
1317 oldtime = time(NULL);
1325 for (i = 0;i < numsockets;i++)
1329 length = LHNET_Read(sock[i], buffer, sizeof(buffer), &receiveaddress);
1331 printf("localsock read error: length < 0");
1332 else if (length > 0 && length < (int)sizeof(buffer))
1335 LHNETADDRESS_ToString(&receiveaddress, addressstring, sizeof(addressstring), 1);
1336 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1337 printf("received message \"%s\" from \"%s\" on socket \"%s\"\n", buffer, addressstring, addressstring2);
1338 if (!strcmp(buffer, "exit"))
1345 if (argc == 5 && count > 0)
1347 newtime = time(NULL);
1348 if (newtime != oldtime)
1350 LHNETADDRESS_ToString(&destaddress, addressstring, sizeof(addressstring), 1);
1351 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sendsock), addressstring2, sizeof(addressstring2), 1);
1352 printf("calling LHNET_Write(<%s>, \"%s\", %i, <%s>)\n", addressstring2, sendmessage, sendmessagelength, addressstring);
1353 length = LHNET_Write(sendsock, sendmessage, sendmessagelength, &destaddress);
1354 if (length == sendmessagelength)
1355 printf("sent successfully\n");
1357 printf("LH_Write failed, returned %i (length of message was %i)\n", length, strlen(argv[4]));
1361 printf("Done sending, still listening for \"exit\"\n");
1365 for (i = 0;i < numsockets;i++)
1369 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1370 printf("calling LHNET_CloseSocket(<%s>)\n", addressstring2);
1371 LHNET_CloseSocket(sock[i]);
1374 printf("calling LHNET_Shutdown()\n");
1378 printf("Testing code for lhnet.c\nusage: lhnettest <localportnumber> [<sendnumberoftimes> <sendaddress:port> <sendmessage>]\n");