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 # include <winsock2.h>
13 # include <ws2tcpip.h>
19 #ifndef STANDALONETEST
20 #include "darkplaces.h"
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <sys/ioctl.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
42 #include <proto/socket.h>
45 // for Z_Malloc/Z_Free in quake
46 #ifndef STANDALONETEST
51 #define Con_Print printf
52 #define Con_Printf printf
53 #define Z_Malloc malloc
60 // 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.
63 #define EWOULDBLOCK WSAEWOULDBLOCK
64 #define ECONNREFUSED WSAECONNREFUSED
66 #define SOCKETERRNO WSAGetLastError()
68 #define IOC_VENDOR 0x18000000
69 #define _WSAIOW(x,y) (IOC_IN|(x)|(y))
70 #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
73 #elif defined(__MORPHOS__)
74 #define ioctlsocket IoctlSocket
75 #define closesocket CloseSocket
76 #define SOCKETERRNO Errno()
80 #define ioctlsocket ioctl
81 #define closesocket close
82 #define SOCKETERRNO errno
84 #define SOCKLEN_T socklen_t
88 #define LHNET_RECVFROM_FLAGS MSG_DONTWAIT
89 #define LHNET_SENDTO_FLAGS 0
91 #define LHNET_RECVFROM_FLAGS 0
92 #define LHNET_SENDTO_FLAGS 0
95 typedef struct lhnetaddressnative_s
97 lhnetaddresstype_t addresstype;
101 struct sockaddr sock;
102 struct sockaddr_in in;
103 #ifndef NOSUPPORTIPV6
104 struct sockaddr_in6 in6;
109 lhnetaddressnative_t;
111 // to make LHNETADDRESS_FromString resolve repeated hostnames faster, cache them
112 #define MAX_NAMECACHE 64
113 static struct namecache_s
115 lhnetaddressnative_t address;
116 double expirationtime;
119 namecache[MAX_NAMECACHE];
120 static int namecacheposition = 0;
122 int LHNETADDRESS_FromPort(lhnetaddress_t *vaddress, lhnetaddresstype_t addresstype, int port)
124 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
131 case LHNETADDRESSTYPE_LOOP:
132 // local:port (loopback)
133 memset(address, 0, sizeof(*address));
134 address->addresstype = LHNETADDRESSTYPE_LOOP;
135 address->port = port;
137 case LHNETADDRESSTYPE_INET4:
138 // 0.0.0.0:port (INADDR_ANY, binds to all interfaces)
139 memset(address, 0, sizeof(*address));
140 address->addresstype = LHNETADDRESSTYPE_INET4;
141 address->port = port;
142 address->addr.in.sin_family = AF_INET;
143 address->addr.in.sin_port = htons((unsigned short)port);
145 #ifndef NOSUPPORTIPV6
146 case LHNETADDRESSTYPE_INET6:
147 // [0:0:0:0:0:0:0:0]:port (IN6ADDR_ANY, binds to all interfaces)
148 memset(address, 0, sizeof(*address));
149 address->addresstype = LHNETADDRESSTYPE_INET6;
150 address->port = port;
151 address->addr.in6.sin6_family = AF_INET6;
152 address->addr.in6.sin6_port = htons((unsigned short)port);
159 #ifndef NOSUPPORTIPV6
160 static int LHNETADDRESS_Resolve(lhnetaddressnative_t *address, const char *name, int port)
163 struct addrinfo hints;
164 struct addrinfo* addrinf;
167 dpsnprintf (port_buff, sizeof (port_buff), "%d", port);
168 port_buff[sizeof (port_buff) - 1] = '\0';
170 memset(&hints, 0, sizeof (hints));
171 hints.ai_family = AF_UNSPEC;
172 hints.ai_socktype = SOCK_DGRAM;
173 //hints.ai_flags = AI_PASSIVE;
175 err = getaddrinfo(name, port_buff, &hints, &addrinf);
176 if (err != 0 || addrinf == NULL)
178 if (addrinf->ai_addr->sa_family != AF_INET6 && addrinf->ai_addr->sa_family != AF_INET)
180 freeaddrinfo (addrinf);
185 if (addrinf->ai_addr->sa_family == AF_INET6)
187 address->addresstype = LHNETADDRESSTYPE_INET6;
188 memcpy(&address->addr.in6, addrinf->ai_addr, sizeof(address->addr.in6));
192 address->addresstype = LHNETADDRESSTYPE_INET4;
193 memcpy(&address->addr.in, addrinf->ai_addr, sizeof(address->addr.in));
195 address->port = port;
197 freeaddrinfo (addrinf);
201 int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
203 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
204 int i, port, d1, d2, d3, d4, resolved;
208 #ifdef STANDALONETEST
211 const char* addr_start;
212 const char* addr_end = NULL;
213 const char* port_name = NULL;
214 int addr_family = AF_UNSPEC;
216 if (!address || !string || !*string)
218 memset(address, 0, sizeof(*address));
219 address->addresstype = LHNETADDRESSTYPE_NONE;
222 // If it's a bracketed IPv6 address
223 if (string[0] == '[')
225 const char* end_bracket = strchr(string, ']');
227 if (end_bracket == NULL)
230 if (end_bracket[1] == ':')
231 port_name = end_bracket + 2;
232 else if (end_bracket[1] != '\0')
235 addr_family = AF_INET6;
236 addr_start = &string[1];
237 addr_end = end_bracket;
241 const char* first_colon;
245 // If it's a numeric non-bracket IPv6 address (-> no port),
246 // or it's a numeric IPv4 address, or a name, with a port
247 first_colon = strchr(string, ':');
248 if (first_colon != NULL)
250 const char* last_colon = strrchr(first_colon + 1, ':');
252 // If it's an numeric IPv4 address, or a name, with a port
253 if (last_colon == NULL)
255 addr_end = first_colon;
256 port_name = first_colon + 1;
259 addr_family = AF_INET6;
263 if (addr_end != NULL)
264 namelen = addr_end - addr_start;
266 namelen = strlen (addr_start);
268 if (namelen >= sizeof(name))
269 namelen = sizeof(name) - 1;
270 memcpy (name, addr_start, namelen);
274 port = atoi(port_name);
280 if (!strcmp(name, "local"))
282 address->addresstype = LHNETADDRESSTYPE_LOOP;
283 address->port = port;
286 // try to parse as dotted decimal ipv4 address first
287 // note this supports partial ip addresses
288 d1 = d2 = d3 = d4 = 0;
290 #define sscanf sscanf_s
292 if (addr_family != AF_INET6 &&
293 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)
295 // parsed a valid ipv4 address
296 address->addresstype = LHNETADDRESSTYPE_INET4;
297 address->port = port;
298 address->addr.in.sin_family = AF_INET;
299 address->addr.in.sin_port = htons((unsigned short)port);
300 a = (unsigned char *)&address->addr.in.sin_addr;
305 #ifdef STANDALONETEST
306 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
307 printf("manual parsing of ipv4 dotted decimal address \"%s\" successful: %s\n", string, string2);
311 for (i = 0;i < MAX_NAMECACHE;i++)
312 if (!strcmp(namecache[i].name, name))
314 #ifdef STANDALONETEST
315 if (i < MAX_NAMECACHE)
317 if (i < MAX_NAMECACHE && host.realtime < namecache[i].expirationtime)
320 *address = namecache[i].address;
321 address->port = port;
322 if (address->addresstype == LHNETADDRESSTYPE_INET6)
324 address->addr.in6.sin6_port = htons((unsigned short)port);
327 else if (address->addresstype == LHNETADDRESSTYPE_INET4)
329 address->addr.in.sin_port = htons((unsigned short)port);
335 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
336 namecache[namecacheposition].name[i] = name[i];
337 namecache[namecacheposition].name[i] = 0;
338 #ifndef STANDALONETEST
339 namecache[namecacheposition].expirationtime = host.realtime + 12 * 3600; // 12 hours
342 // try resolving the address (handles dns and other ip formats)
343 resolved = LHNETADDRESS_Resolve(address, name, port);
346 #ifdef STANDALONETEST
347 const char *protoname;
349 switch (address->addresstype)
351 case LHNETADDRESSTYPE_INET6:
354 case LHNETADDRESSTYPE_INET4:
358 protoname = "UNKNOWN";
361 LHNETADDRESS_ToString(vaddress, string2, sizeof(string2), 1);
362 Con_Printf("LHNETADDRESS_Resolve(\"%s\") returned %s address %s\n", string, protoname, string2);
364 namecache[namecacheposition].address = *address;
368 #ifdef STANDALONETEST
369 printf("name resolution failed on address \"%s\"\n", name);
371 namecache[namecacheposition].address.addresstype = LHNETADDRESSTYPE_NONE;
374 namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
378 int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
380 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
381 int i, port, namelen, d1, d2, d3, d4;
382 struct hostent *hostentry;
386 #ifdef STANDALONETEST
389 if (!address || !string || !*string)
391 memset(address, 0, sizeof(*address));
392 address->addresstype = LHNETADDRESSTYPE_NONE;
394 colon = strrchr(string, ':');
395 if (colon && (colon == strchr(string, ':') || (string[0] == '[' && colon - string > 0 && colon[-1] == ']')))
396 // EITHER: colon is the ONLY colon OR: colon comes after [...] delimited IPv6 address
397 // fixes misparsing of IPv6 addresses without port
399 port = atoi(colon + 1);
402 colon = string + strlen(string);
405 namelen = colon - string;
408 if (string[0] == '[' && namelen > 0 && string[namelen-1] == ']') // ipv6
413 memcpy(name, string, namelen);
416 if (!strcmp(name, "local"))
418 address->addresstype = LHNETADDRESSTYPE_LOOP;
419 address->port = port;
422 // try to parse as dotted decimal ipv4 address first
423 // note this supports partial ip addresses
424 d1 = d2 = d3 = d4 = 0;
426 #define sscanf sscanf_s
428 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)
430 // parsed a valid ipv4 address
431 address->addresstype = LHNETADDRESSTYPE_INET4;
432 address->port = port;
433 address->addr.in.sin_family = AF_INET;
434 address->addr.in.sin_port = htons((unsigned short)port);
435 a = (unsigned char *)&address->addr.in.sin_addr;
440 #ifdef STANDALONETEST
441 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
442 printf("manual parsing of ipv4 dotted decimal address \"%s\" successful: %s\n", string, string2);
446 for (i = 0;i < MAX_NAMECACHE;i++)
447 if (!strcmp(namecache[i].name, name))
449 #ifdef STANDALONETEST
450 if (i < MAX_NAMECACHE)
452 if (i < MAX_NAMECACHE && host.realtime < namecache[i].expirationtime)
455 *address = namecache[i].address;
456 address->port = port;
457 if (address->addresstype == LHNETADDRESSTYPE_INET6)
459 #ifndef NOSUPPORTIPV6
460 address->addr.in6.sin6_port = htons((unsigned short)port);
464 else if (address->addresstype == LHNETADDRESSTYPE_INET4)
466 address->addr.in.sin_port = htons((unsigned short)port);
471 // try gethostbyname (handles dns and other ip formats)
472 hostentry = gethostbyname(name);
475 if (hostentry->h_addrtype == AF_INET6)
477 #ifndef NOSUPPORTIPV6
479 address->addresstype = LHNETADDRESSTYPE_INET6;
480 address->port = port;
481 address->addr.in6.sin6_family = hostentry->h_addrtype;
482 address->addr.in6.sin6_port = htons((unsigned short)port);
483 memcpy(&address->addr.in6.sin6_addr, hostentry->h_addr_list[0], sizeof(address->addr.in6.sin6_addr));
484 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
485 namecache[namecacheposition].name[i] = name[i];
486 namecache[namecacheposition].name[i] = 0;
487 #ifndef STANDALONETEST
488 namecache[namecacheposition].expirationtime = host.realtime + 12 * 3600; // 12 hours
490 namecache[namecacheposition].address = *address;
491 namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
492 #ifdef STANDALONETEST
493 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
494 printf("gethostbyname(\"%s\") returned ipv6 address %s\n", string, string2);
499 else if (hostentry->h_addrtype == AF_INET)
502 address->addresstype = LHNETADDRESSTYPE_INET4;
503 address->port = port;
504 address->addr.in.sin_family = hostentry->h_addrtype;
505 address->addr.in.sin_port = htons((unsigned short)port);
506 memcpy(&address->addr.in.sin_addr, hostentry->h_addr_list[0], sizeof(address->addr.in.sin_addr));
507 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
508 namecache[namecacheposition].name[i] = name[i];
509 namecache[namecacheposition].name[i] = 0;
510 #ifndef STANDALONETEST
511 namecache[namecacheposition].expirationtime = host.realtime + 12 * 3600; // 12 hours
513 namecache[namecacheposition].address = *address;
514 namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
515 #ifdef STANDALONETEST
516 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
517 printf("gethostbyname(\"%s\") returned ipv4 address %s\n", string, string2);
522 #ifdef STANDALONETEST
523 printf("gethostbyname failed on address \"%s\"\n", name);
525 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
526 namecache[namecacheposition].name[i] = name[i];
527 namecache[namecacheposition].name[i] = 0;
528 #ifndef STANDALONETEST
529 namecache[namecacheposition].expirationtime = host.realtime + 12 * 3600; // 12 hours
531 namecache[namecacheposition].address.addresstype = LHNETADDRESSTYPE_NONE;
532 namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
537 int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stringbuffersize, int includeport)
539 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
540 const unsigned char *a;
541 if (!address || !string || stringbuffersize < 1)
544 switch(address->addresstype)
548 case LHNETADDRESSTYPE_LOOP:
551 if (stringbuffersize >= 12)
553 dpsnprintf(string, stringbuffersize, "local:%d", address->port);
559 if (stringbuffersize >= 6)
561 memcpy(string, "local", 6);
566 case LHNETADDRESSTYPE_INET4:
567 a = (const unsigned char *)(&address->addr.in.sin_addr);
570 if (stringbuffersize >= 22)
572 dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d:%d", a[0], a[1], a[2], a[3], address->port);
578 if (stringbuffersize >= 16)
580 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 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);
598 if (stringbuffersize >= 80)
600 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]);
610 int LHNETADDRESS_GetAddressType(const lhnetaddress_t *address)
613 return address->addresstype;
615 return LHNETADDRESSTYPE_NONE;
618 const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress, char *ifname, size_t ifnamelength)
620 #ifndef NOSUPPORTIPV6
621 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
623 if (address && address->addresstype == LHNETADDRESSTYPE_INET6)
627 if (if_indextoname(address->addr.in6.sin6_scope_id, ifname) == ifname)
632 // The Win32 API doesn't have if_indextoname() until Windows Vista,
633 // but luckily it just uses the interface ID as the interface name
635 if (dpsnprintf(ifname, ifnamelength, "%lu", address->addr.in6.sin6_scope_id) > 0)
645 int LHNETADDRESS_GetPort(const lhnetaddress_t *address)
649 return address->port;
652 int LHNETADDRESS_SetPort(lhnetaddress_t *vaddress, int port)
654 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
657 address->port = port;
658 switch(address->addresstype)
660 case LHNETADDRESSTYPE_LOOP:
662 case LHNETADDRESSTYPE_INET4:
663 address->addr.in.sin_port = htons((unsigned short)port);
665 #ifndef NOSUPPORTIPV6
666 case LHNETADDRESSTYPE_INET6:
667 address->addr.in6.sin6_port = htons((unsigned short)port);
675 int LHNETADDRESS_Compare(const lhnetaddress_t *vaddress1, const lhnetaddress_t *vaddress2)
677 lhnetaddressnative_t *address1 = (lhnetaddressnative_t *)vaddress1;
678 lhnetaddressnative_t *address2 = (lhnetaddressnative_t *)vaddress2;
679 if (!address1 || !address2)
681 if (address1->addresstype != address2->addresstype)
683 switch(address1->addresstype)
685 case LHNETADDRESSTYPE_LOOP:
686 if (address1->port != address2->port)
689 case LHNETADDRESSTYPE_INET4:
690 if (address1->addr.in.sin_family != address2->addr.in.sin_family)
692 if (memcmp(&address1->addr.in.sin_addr, &address2->addr.in.sin_addr, sizeof(address1->addr.in.sin_addr)))
694 if (address1->port != address2->port)
697 #ifndef NOSUPPORTIPV6
698 case LHNETADDRESSTYPE_INET6:
699 if (address1->addr.in6.sin6_family != address2->addr.in6.sin6_family)
701 if (memcmp(&address1->addr.in6.sin6_addr, &address2->addr.in6.sin6_addr, sizeof(address1->addr.in6.sin6_addr)))
703 if (address1->port != address2->port)
712 typedef struct lhnetpacket_s
719 #ifndef STANDALONETEST
720 double sentdoubletime;
726 static int lhnet_active;
727 static lhnetsocket_t lhnet_socketlist;
728 static lhnetpacket_t lhnet_packetlist;
729 static int lhnet_default_dscp = 0;
731 static int lhnet_didWSAStartup = 0;
732 static WSADATA lhnet_winsockdata;
735 void LHNET_Init(void)
739 List_Create(&lhnet_socketlist.list);
740 List_Create(&lhnet_packetlist.list);
743 lhnet_didWSAStartup = !WSAStartup(MAKEWORD(1, 1), &lhnet_winsockdata);
744 if (!lhnet_didWSAStartup)
745 Con_Print("LHNET_Init: WSAStartup failed, networking disabled\n");
749 int LHNET_DefaultDSCP(int dscp)
752 int prev = lhnet_default_dscp;
754 lhnet_default_dscp = dscp;
761 void LHNET_Shutdown(void)
763 lhnetsocket_t *s, *snext;
764 lhnetpacket_t *p, *pnext;
767 List_For_Each_Entry_Safe(s, snext, &lhnet_socketlist.list, lhnetsocket_t, list)
768 LHNET_CloseSocket(s);
769 List_For_Each_Entry_Safe(p, pnext, &lhnet_packetlist.list, lhnetpacket_t, list)
771 List_Delete(&p->list);
775 if (lhnet_didWSAStartup)
777 lhnet_didWSAStartup = 0;
784 static const char *LHNETPRIVATE_StrError(void)
787 int i = WSAGetLastError();
790 case WSAEINTR: return "WSAEINTR";
791 case WSAEBADF: return "WSAEBADF";
792 case WSAEACCES: return "WSAEACCES";
793 case WSAEFAULT: return "WSAEFAULT";
794 case WSAEINVAL: return "WSAEINVAL";
795 case WSAEMFILE: return "WSAEMFILE";
796 case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
797 case WSAEINPROGRESS: return "WSAEINPROGRESS";
798 case WSAEALREADY: return "WSAEALREADY";
799 case WSAENOTSOCK: return "WSAENOTSOCK";
800 case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
801 case WSAEMSGSIZE: return "WSAEMSGSIZE";
802 case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
803 case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
804 case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
805 case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
806 case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
807 case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
808 case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
809 case WSAEADDRINUSE: return "WSAEADDRINUSE";
810 case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
811 case WSAENETDOWN: return "WSAENETDOWN";
812 case WSAENETUNREACH: return "WSAENETUNREACH";
813 case WSAENETRESET: return "WSAENETRESET";
814 case WSAECONNABORTED: return "WSAECONNABORTED";
815 case WSAECONNRESET: return "WSAECONNRESET";
816 case WSAENOBUFS: return "WSAENOBUFS";
817 case WSAEISCONN: return "WSAEISCONN";
818 case WSAENOTCONN: return "WSAENOTCONN";
819 case WSAESHUTDOWN: return "WSAESHUTDOWN";
820 case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
821 case WSAETIMEDOUT: return "WSAETIMEDOUT";
822 case WSAECONNREFUSED: return "WSAECONNREFUSED";
823 case WSAELOOP: return "WSAELOOP";
824 case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
825 case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
826 case WSAEHOSTUNREACH: return "WSAEHOSTUNREACH";
827 case WSAENOTEMPTY: return "WSAENOTEMPTY";
828 case WSAEPROCLIM: return "WSAEPROCLIM";
829 case WSAEUSERS: return "WSAEUSERS";
830 case WSAEDQUOT: return "WSAEDQUOT";
831 case WSAESTALE: return "WSAESTALE";
832 case WSAEREMOTE: return "WSAEREMOTE";
833 case WSAEDISCON: return "WSAEDISCON";
834 case 0: return "no error";
835 default: return "unknown WSAE error";
838 return strerror(errno);
842 void LHNET_SleepUntilPacket_Microseconds(int microseconds)
851 List_For_Each_Entry(s, &lhnet_socketlist.list, lhnetsocket_t, list)
853 if (s->address.addresstype == LHNETADDRESSTYPE_INET4 || s->address.addresstype == LHNETADDRESSTYPE_INET6)
855 if (lastfd < s->inetsocket)
856 lastfd = s->inetsocket;
857 #if defined(WIN32) && !defined(_MSC_VER)
858 FD_SET((int)s->inetsocket, &fdreadset);
860 FD_SET((unsigned int)s->inetsocket, &fdreadset);
864 tv.tv_sec = microseconds / 1000000;
865 tv.tv_usec = microseconds % 1000000;
866 select(lastfd + 1, &fdreadset, NULL, NULL, &tv);
868 Sys_Sleep(microseconds);
872 lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address)
874 lhnetsocket_t *lhnetsocket, *s;
877 lhnetsocket = (lhnetsocket_t *)Z_Malloc(sizeof(*lhnetsocket));
880 memset(lhnetsocket, 0, sizeof(*lhnetsocket));
881 lhnetsocket->address = *address;
882 switch(lhnetsocket->address.addresstype)
884 case LHNETADDRESSTYPE_LOOP:
885 if (lhnetsocket->address.port == 0)
887 // allocate a port dynamically
888 // this search will always terminate because there is never
889 // an allocated socket with port 0, so if the number wraps it
890 // will find the port is unused, and then refuse to use port
891 // 0, causing an intentional failure condition
892 lhnetsocket->address.port = 1024;
895 List_For_Each_Entry(s, &lhnet_socketlist.list, lhnetsocket_t, list)
896 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
898 if (s == &lhnet_socketlist)
900 lhnetsocket->address.port++;
903 // check if the port is available
904 List_For_Each_Entry(s, &lhnet_socketlist.list, lhnetsocket_t, list)
905 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
907 if (s == &lhnet_socketlist && lhnetsocket->address.port != 0)
909 List_Add_Tail(&lhnetsocket->list, &lhnet_socketlist.list);
913 case LHNETADDRESSTYPE_INET4:
914 #ifndef NOSUPPORTIPV6
915 case LHNETADDRESSTYPE_INET6:
918 if (lhnet_didWSAStartup)
921 #ifndef NOSUPPORTIPV6
922 if ((lhnetsocket->inetsocket = socket(address->addresstype == LHNETADDRESSTYPE_INET6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
924 if ((lhnetsocket->inetsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
938 if (ioctlsocket(lhnetsocket->inetsocket, FIONBIO, &_true) != -1)
942 // We need to set this flag to tell the OS that we only listen on IPv6. If we don't
943 // most OSes will create a dual-protocol socket that also listens on IPv4. In this case
944 // if an IPv4 socket is already bound to the port we want, our bind() call will fail.
946 if (address->addresstype != LHNETADDRESSTYPE_INET6
947 || setsockopt (lhnetsocket->inetsocket, IPPROTO_IPV6, IPV6_V6ONLY,
948 (const char *)&ipv6_only, sizeof(ipv6_only)) == 0
950 // The Win32 API only supports IPV6_V6ONLY since Windows Vista, but fortunately
951 // the default value is what we want on Win32 anyway (IPV6_V6ONLY = true)
952 || SOCKETERRNO == WSAENOPROTOOPT
957 lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
961 #if defined(SOL_RFC1149) && defined(RFC1149_1149ONLY)
962 // we got reports of massive lags when this protocol was chosen as transport
963 // so better turn it off
966 int rfc1149enabled = 0;
967 if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_1149ONLY, &rfc1149only))
968 Con_Printf(CON_ERROR "LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_1149ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
969 if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_ENABLED, &rfc1149enabled))
970 Con_Printf(CON_ERROR "LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_ENABLED) returned error: %s\n", LHNETPRIVATE_StrError());
974 #ifndef NOSUPPORTIPV6
975 if (address->addresstype == LHNETADDRESSTYPE_INET6)
977 namelen = sizeof(localaddress->addr.in6);
978 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
979 if (bindresult != -1)
981 if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen))
983 // If getsockname failed, we can assume the bound socket is useless.
991 namelen = sizeof(localaddress->addr.in);
992 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
993 if (bindresult != -1)
995 if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen))
997 // If getsockname failed, we can assume the bound socket is useless.
1002 if (bindresult != -1)
1005 // enable broadcast on this socket
1006 setsockopt(lhnetsocket->inetsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i));
1009 // enable DSCP for ToS support
1010 int tos = lhnet_default_dscp << 2;
1011 if (setsockopt(lhnetsocket->inetsocket, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos)))
1013 // Error in setsockopt - fine, we'll simply set no TOS then.
1017 List_Add_Tail(&lhnetsocket->list, &lhnet_socketlist.list);
1019 if (ioctlsocket(lhnetsocket->inetsocket, SIO_UDP_CONNRESET, &_false) == -1)
1020 Con_DPrintf("LHNET_OpenSocket_Connectionless: ioctlsocket SIO_UDP_CONNRESET returned error: %s\n", LHNETPRIVATE_StrError());
1025 Con_Printf("LHNET_OpenSocket_Connectionless: bind returned error: %s\n", LHNETPRIVATE_StrError());
1029 Con_Printf("LHNET_OpenSocket_Connectionless: setsockopt(IPV6_V6ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
1033 Con_Printf("LHNET_OpenSocket_Connectionless: ioctlsocket returned error: %s\n", LHNETPRIVATE_StrError());
1034 closesocket(lhnetsocket->inetsocket);
1037 Con_Printf("LHNET_OpenSocket_Connectionless: socket returned error: %s\n", LHNETPRIVATE_StrError());
1041 Con_Print("LHNET_OpenSocket_Connectionless: can't open a socket (WSAStartup failed during LHNET_Init)\n");
1047 Z_Free(lhnetsocket);
1052 void LHNET_CloseSocket(lhnetsocket_t *lhnetsocket)
1056 List_Delete(&lhnetsocket->list);
1057 // no special close code for loopback, just inet
1058 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4 || lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1060 closesocket(lhnetsocket->inetsocket);
1062 Z_Free(lhnetsocket);
1066 lhnetaddress_t *LHNET_AddressFromSocket(lhnetsocket_t *sock)
1069 return &sock->address;
1074 int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, lhnetaddress_t *vaddress)
1076 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
1078 if (!lhnetsocket || !address || !content || maxcontentlength < 1)
1080 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
1083 lhnetpacket_t *p, *pnext;
1084 // scan for any old packets to timeout while searching for a packet
1085 // that is waiting to be delivered to this socket
1086 currenttime = time(NULL);
1087 List_For_Each_Entry_Safe(p, pnext, &lhnet_packetlist.list, lhnetpacket_t, list)
1089 if (p->timeout < currenttime)
1092 List_Delete(&p->list);
1096 #ifndef STANDALONETEST
1097 if (net_fakelag.value && (host.realtime - net_fakelag.value * (1.0 / 2000.0)) < p->sentdoubletime)
1100 if (value == 0 && p->destinationport == lhnetsocket->address.port)
1102 if (p->length <= maxcontentlength)
1104 lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
1105 *address = *localaddress;
1106 address->port = p->sourceport;
1107 memcpy(content, p->data, p->length);
1113 List_Delete(&p->list);
1118 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
1120 SOCKLEN_T inetaddresslength;
1121 address->addresstype = LHNETADDRESSTYPE_NONE;
1122 inetaddresslength = sizeof(address->addr.in);
1123 value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength);
1126 address->addresstype = LHNETADDRESSTYPE_INET4;
1127 address->port = ntohs(address->addr.in.sin_port);
1132 int e = SOCKETERRNO;
1133 if (e == EWOULDBLOCK)
1138 Con_Print("Connection refused\n");
1141 Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
1144 #ifndef NOSUPPORTIPV6
1145 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1147 SOCKLEN_T inetaddresslength;
1148 address->addresstype = LHNETADDRESSTYPE_NONE;
1149 inetaddresslength = sizeof(address->addr.in6);
1150 value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength);
1153 address->addresstype = LHNETADDRESSTYPE_INET6;
1154 address->port = ntohs(address->addr.in6.sin6_port);
1157 else if (value == -1)
1159 int e = SOCKETERRNO;
1160 if (e == EWOULDBLOCK)
1165 Con_Print("Connection refused\n");
1168 Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
1175 int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *vaddress)
1177 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
1179 if (!lhnetsocket || !address || !content || contentlength < 1)
1181 if (lhnetsocket->address.addresstype != address->addresstype)
1183 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
1186 p = (lhnetpacket_t *)Z_Malloc(sizeof(*p) + contentlength);
1187 p->data = (void *)(p + 1);
1188 memcpy(p->data, content, contentlength);
1189 p->length = contentlength;
1190 p->sourceport = lhnetsocket->address.port;
1191 p->destinationport = address->port;
1192 p->timeout = time(NULL) + 10;
1193 List_Add_Tail(&p->list, &lhnet_packetlist.list);
1195 #ifndef STANDALONETEST
1196 p->sentdoubletime = host.realtime;
1198 value = contentlength;
1200 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
1202 value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, LHNET_SENDTO_FLAGS, (struct sockaddr *)&address->addr.in, sizeof(struct sockaddr_in));
1205 if (SOCKETERRNO == EWOULDBLOCK)
1207 Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
1210 #ifndef NOSUPPORTIPV6
1211 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1213 value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, 0, (struct sockaddr *)&address->addr.in6, sizeof(struct sockaddr_in6));
1216 if (SOCKETERRNO == EWOULDBLOCK)
1218 Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
1225 #ifdef STANDALONETEST
1226 int main(int argc, char **argv)
1229 char *buffer = "test", buffer2[1024];
1230 int blen = strlen(buffer);
1232 lhnetsocket_t *sock1;
1233 lhnetsocket_t *sock2;
1234 lhnetaddress_t myaddy1;
1235 lhnetaddress_t myaddy2;
1236 lhnetaddress_t myaddy3;
1237 lhnetaddress_t localhostaddy1;
1238 lhnetaddress_t localhostaddy2;
1242 printf("calling LHNET_Init\n");
1245 printf("calling LHNET_FromPort twice to create two local addresses\n");
1246 LHNETADDRESS_FromPort(&myaddy1, LHNETADDRESSTYPE_INET4, 4000);
1247 LHNETADDRESS_FromPort(&myaddy2, LHNETADDRESSTYPE_INET4, 4001);
1248 LHNETADDRESS_FromString(&localhostaddy1, "127.0.0.1", 4000);
1249 LHNETADDRESS_FromString(&localhostaddy2, "127.0.0.1", 4001);
1251 printf("calling LHNET_OpenSocket_Connectionless twice to create two local sockets\n");
1252 sock1 = LHNET_OpenSocket_Connectionless(&myaddy1);
1253 sock2 = LHNET_OpenSocket_Connectionless(&myaddy2);
1255 printf("calling LHNET_Write to send a packet from the first socket to the second socket\n");
1256 test1 = LHNET_Write(sock1, buffer, blen, &localhostaddy2);
1257 printf("sleeping briefly\n");
1263 printf("calling LHNET_Read on the second socket to read the packet sent from the first socket\n");
1264 test2 = LHNET_Read(sock2, buffer2, b2len - 1, &myaddy3);
1266 Con_Printf("socket to socket test succeeded\n");
1268 Con_Printf("socket to socket test failed\n");
1271 printf("press any key to exit\n");
1275 printf("calling LHNET_Shutdown\n");
1277 printf("exiting\n");
1280 lhnetsocket_t *sock[16], *sendsock;
1289 int sendmessagelength;
1290 lhnetaddress_t destaddress;
1291 lhnetaddress_t receiveaddress;
1292 lhnetaddress_t sockaddress[16];
1293 char buffer[1536], addressstring[128], addressstring2[128];
1294 if ((argc == 2 || argc == 5) && (port = atoi(argv[1])) >= 1 && port < 65535)
1296 printf("calling LHNET_Init()\n");
1300 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_LOOP, port);
1301 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET4, port);
1302 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET6, port+1);
1306 sendmessagelength = 0;
1308 for (i = 0;i < numsockets;i++)
1310 LHNETADDRESS_ToString(&sockaddress[i], addressstring, sizeof(addressstring), 1);
1311 printf("calling LHNET_OpenSocket_Connectionless(<%s>)\n", addressstring);
1312 if ((sock[i] = LHNET_OpenSocket_Connectionless(&sockaddress[i])))
1314 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1315 printf("opened socket successfully (address \"%s\")\n", addressstring2);
1319 printf("failed to open socket\n");
1330 count = atoi(argv[2]);
1331 if (LHNETADDRESS_FromString(&destaddress, argv[3], -1))
1333 sendmessage = argv[4];
1334 sendmessagelength = strlen(sendmessage);
1336 for (i = 0;i < numsockets;i++)
1337 if (sock[i] && LHNETADDRESS_GetAddressType(&destaddress) == LHNETADDRESS_GetAddressType(&sockaddress[i]))
1339 if (sendsock == NULL)
1341 printf("Could not find an open socket matching the addresstype (%i) of destination address, switching to listen only mode\n", LHNETADDRESS_GetAddressType(&destaddress));
1347 printf("LHNETADDRESS_FromString did not like the address \"%s\", switching to listen only mode\n", argv[3]);
1351 printf("started, now listening for \"exit\" on the opened sockets\n");
1352 oldtime = time(NULL);
1360 for (i = 0;i < numsockets;i++)
1364 length = LHNET_Read(sock[i], buffer, sizeof(buffer), &receiveaddress);
1366 printf("localsock read error: length < 0");
1367 else if (length > 0 && length < (int)sizeof(buffer))
1370 LHNETADDRESS_ToString(&receiveaddress, addressstring, sizeof(addressstring), 1);
1371 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1372 printf("received message \"%s\" from \"%s\" on socket \"%s\"\n", buffer, addressstring, addressstring2);
1373 if (!strcmp(buffer, "exit"))
1380 if (argc == 5 && count > 0)
1382 newtime = time(NULL);
1383 if (newtime != oldtime)
1385 LHNETADDRESS_ToString(&destaddress, addressstring, sizeof(addressstring), 1);
1386 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sendsock), addressstring2, sizeof(addressstring2), 1);
1387 printf("calling LHNET_Write(<%s>, \"%s\", %i, <%s>)\n", addressstring2, sendmessage, sendmessagelength, addressstring);
1388 length = LHNET_Write(sendsock, sendmessage, sendmessagelength, &destaddress);
1389 if (length == sendmessagelength)
1390 printf("sent successfully\n");
1392 printf("LH_Write failed, returned %i (length of message was %i)\n", length, strlen(argv[4]));
1396 printf("Done sending, still listening for \"exit\"\n");
1400 for (i = 0;i < numsockets;i++)
1404 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1405 printf("calling LHNET_CloseSocket(<%s>)\n", addressstring2);
1406 LHNET_CloseSocket(sock[i]);
1409 printf("calling LHNET_Shutdown()\n");
1413 printf("Testing code for lhnet.c\nusage: lhnettest <localportnumber> [<sendnumberoftimes> <sendaddress:port> <sendmessage>]\n");