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 const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress, char *ifname, size_t ifnamelength)
612 #ifndef NOSUPPORTIPV6
613 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
615 if (address && address->addresstype == LHNETADDRESSTYPE_INET6)
619 if (if_indextoname(address->addr.in6.sin6_scope_id, ifname) == ifname)
624 // The Win32 API doesn't have if_indextoname() until Windows Vista,
625 // but luckily it just uses the interface ID as the interface name
627 if (dpsnprintf(ifname, ifnamelength, "%lu", address->addr.in6.sin6_scope_id) > 0)
637 int LHNETADDRESS_GetPort(const lhnetaddress_t *address)
641 return address->port;
644 int LHNETADDRESS_SetPort(lhnetaddress_t *vaddress, int port)
646 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
649 address->port = port;
650 switch(address->addresstype)
652 case LHNETADDRESSTYPE_LOOP:
654 case LHNETADDRESSTYPE_INET4:
655 address->addr.in.sin_port = htons((unsigned short)port);
657 #ifndef NOSUPPORTIPV6
658 case LHNETADDRESSTYPE_INET6:
659 address->addr.in6.sin6_port = htons((unsigned short)port);
667 int LHNETADDRESS_Compare(const lhnetaddress_t *vaddress1, const lhnetaddress_t *vaddress2)
669 lhnetaddressnative_t *address1 = (lhnetaddressnative_t *)vaddress1;
670 lhnetaddressnative_t *address2 = (lhnetaddressnative_t *)vaddress2;
671 if (!address1 || !address2)
673 if (address1->addresstype != address2->addresstype)
675 switch(address1->addresstype)
677 case LHNETADDRESSTYPE_LOOP:
678 if (address1->port != address2->port)
681 case LHNETADDRESSTYPE_INET4:
682 if (address1->addr.in.sin_family != address2->addr.in.sin_family)
684 if (memcmp(&address1->addr.in.sin_addr, &address2->addr.in.sin_addr, sizeof(address1->addr.in.sin_addr)))
686 if (address1->port != address2->port)
689 #ifndef NOSUPPORTIPV6
690 case LHNETADDRESSTYPE_INET6:
691 if (address1->addr.in6.sin6_family != address2->addr.in6.sin6_family)
693 if (memcmp(&address1->addr.in6.sin6_addr, &address2->addr.in6.sin6_addr, sizeof(address1->addr.in6.sin6_addr)))
695 if (address1->port != address2->port)
704 typedef struct lhnetpacket_s
711 #ifndef STANDALONETEST
712 double sentdoubletime;
718 static int lhnet_active;
719 static lhnetsocket_t lhnet_socketlist;
720 static lhnetpacket_t lhnet_packetlist;
721 static int lhnet_default_dscp = 0;
723 static int lhnet_didWSAStartup = 0;
724 static WSADATA lhnet_winsockdata;
727 void LHNET_Init(void)
731 List_Create(&lhnet_socketlist.list);
732 List_Create(&lhnet_packetlist.list);
735 lhnet_didWSAStartup = !WSAStartup(MAKEWORD(1, 1), &lhnet_winsockdata);
736 if (!lhnet_didWSAStartup)
737 Con_Print("LHNET_Init: WSAStartup failed, networking disabled\n");
741 int LHNET_DefaultDSCP(int dscp)
744 int prev = lhnet_default_dscp;
746 lhnet_default_dscp = dscp;
753 void LHNET_Shutdown(void)
755 lhnetsocket_t *s, *snext;
756 lhnetpacket_t *p, *pnext;
759 List_For_Each_Entry_Safe(s, snext, &lhnet_socketlist.list, lhnetsocket_t, list)
760 LHNET_CloseSocket(s);
761 List_For_Each_Entry_Safe(p, pnext, &lhnet_packetlist.list, lhnetpacket_t, list)
763 List_Delete(&p->list);
767 if (lhnet_didWSAStartup)
769 lhnet_didWSAStartup = 0;
776 static const char *LHNETPRIVATE_StrError(void)
779 int i = WSAGetLastError();
782 case WSAEINTR: return "WSAEINTR";
783 case WSAEBADF: return "WSAEBADF";
784 case WSAEACCES: return "WSAEACCES";
785 case WSAEFAULT: return "WSAEFAULT";
786 case WSAEINVAL: return "WSAEINVAL";
787 case WSAEMFILE: return "WSAEMFILE";
788 case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
789 case WSAEINPROGRESS: return "WSAEINPROGRESS";
790 case WSAEALREADY: return "WSAEALREADY";
791 case WSAENOTSOCK: return "WSAENOTSOCK";
792 case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
793 case WSAEMSGSIZE: return "WSAEMSGSIZE";
794 case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
795 case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
796 case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
797 case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
798 case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
799 case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
800 case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
801 case WSAEADDRINUSE: return "WSAEADDRINUSE";
802 case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
803 case WSAENETDOWN: return "WSAENETDOWN";
804 case WSAENETUNREACH: return "WSAENETUNREACH";
805 case WSAENETRESET: return "WSAENETRESET";
806 case WSAECONNABORTED: return "WSAECONNABORTED";
807 case WSAECONNRESET: return "WSAECONNRESET";
808 case WSAENOBUFS: return "WSAENOBUFS";
809 case WSAEISCONN: return "WSAEISCONN";
810 case WSAENOTCONN: return "WSAENOTCONN";
811 case WSAESHUTDOWN: return "WSAESHUTDOWN";
812 case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
813 case WSAETIMEDOUT: return "WSAETIMEDOUT";
814 case WSAECONNREFUSED: return "WSAECONNREFUSED";
815 case WSAELOOP: return "WSAELOOP";
816 case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
817 case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
818 case WSAEHOSTUNREACH: return "WSAEHOSTUNREACH";
819 case WSAENOTEMPTY: return "WSAENOTEMPTY";
820 case WSAEPROCLIM: return "WSAEPROCLIM";
821 case WSAEUSERS: return "WSAEUSERS";
822 case WSAEDQUOT: return "WSAEDQUOT";
823 case WSAESTALE: return "WSAESTALE";
824 case WSAEREMOTE: return "WSAEREMOTE";
825 case WSAEDISCON: return "WSAEDISCON";
826 case 0: return "no error";
827 default: return "unknown WSAE error";
830 return strerror(errno);
834 void LHNET_SleepUntilPacket_Microseconds(int microseconds)
843 List_For_Each_Entry(s, &lhnet_socketlist.list, lhnetsocket_t, list)
845 if (s->address.addresstype == LHNETADDRESSTYPE_INET4 || s->address.addresstype == LHNETADDRESSTYPE_INET6)
847 if (lastfd < s->inetsocket)
848 lastfd = s->inetsocket;
849 #if defined(WIN32) && !defined(_MSC_VER)
850 FD_SET((int)s->inetsocket, &fdreadset);
852 FD_SET((unsigned int)s->inetsocket, &fdreadset);
856 tv.tv_sec = microseconds / 1000000;
857 tv.tv_usec = microseconds % 1000000;
858 select(lastfd + 1, &fdreadset, NULL, NULL, &tv);
860 Sys_Sleep(microseconds);
864 lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address)
866 lhnetsocket_t *lhnetsocket, *s;
869 lhnetsocket = (lhnetsocket_t *)Z_Malloc(sizeof(*lhnetsocket));
872 memset(lhnetsocket, 0, sizeof(*lhnetsocket));
873 lhnetsocket->address = *address;
874 switch(lhnetsocket->address.addresstype)
876 case LHNETADDRESSTYPE_LOOP:
877 if (lhnetsocket->address.port == 0)
879 // allocate a port dynamically
880 // this search will always terminate because there is never
881 // an allocated socket with port 0, so if the number wraps it
882 // will find the port is unused, and then refuse to use port
883 // 0, causing an intentional failure condition
884 lhnetsocket->address.port = 1024;
887 List_For_Each_Entry(s, &lhnet_socketlist.list, lhnetsocket_t, list)
888 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
890 if (s == &lhnet_socketlist)
892 lhnetsocket->address.port++;
895 // check if the port is available
896 List_For_Each_Entry(s, &lhnet_socketlist.list, lhnetsocket_t, list)
897 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
899 if (s == &lhnet_socketlist && lhnetsocket->address.port != 0)
901 List_Add_Tail(&lhnetsocket->list, &lhnet_socketlist.list);
905 case LHNETADDRESSTYPE_INET4:
906 #ifndef NOSUPPORTIPV6
907 case LHNETADDRESSTYPE_INET6:
910 if (lhnet_didWSAStartup)
913 #ifndef NOSUPPORTIPV6
914 if ((lhnetsocket->inetsocket = socket(address->addresstype == LHNETADDRESSTYPE_INET6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
916 if ((lhnetsocket->inetsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
930 if (ioctlsocket(lhnetsocket->inetsocket, FIONBIO, &_true) != -1)
934 // We need to set this flag to tell the OS that we only listen on IPv6. If we don't
935 // most OSes will create a dual-protocol socket that also listens on IPv4. In this case
936 // if an IPv4 socket is already bound to the port we want, our bind() call will fail.
938 if (address->addresstype != LHNETADDRESSTYPE_INET6
939 || setsockopt (lhnetsocket->inetsocket, IPPROTO_IPV6, IPV6_V6ONLY,
940 (const char *)&ipv6_only, sizeof(ipv6_only)) == 0
942 // The Win32 API only supports IPV6_V6ONLY since Windows Vista, but fortunately
943 // the default value is what we want on Win32 anyway (IPV6_V6ONLY = true)
944 || SOCKETERRNO == WSAENOPROTOOPT
949 lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
953 #if defined(SOL_RFC1149) && defined(RFC1149_1149ONLY)
954 // we got reports of massive lags when this protocol was chosen as transport
955 // so better turn it off
958 int rfc1149enabled = 0;
959 if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_1149ONLY, &rfc1149only))
960 Con_Printf(CON_ERROR "LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_1149ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
961 if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_ENABLED, &rfc1149enabled))
962 Con_Printf(CON_ERROR "LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_ENABLED) returned error: %s\n", LHNETPRIVATE_StrError());
966 #ifndef NOSUPPORTIPV6
967 if (address->addresstype == LHNETADDRESSTYPE_INET6)
969 namelen = sizeof(localaddress->addr.in6);
970 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
971 if (bindresult != -1)
973 if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen))
975 // If getsockname failed, we can assume the bound socket is useless.
983 namelen = sizeof(localaddress->addr.in);
984 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
985 if (bindresult != -1)
987 if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen))
989 // If getsockname failed, we can assume the bound socket is useless.
994 if (bindresult != -1)
997 // enable broadcast on this socket
998 setsockopt(lhnetsocket->inetsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i));
1001 // enable DSCP for ToS support
1002 int tos = lhnet_default_dscp << 2;
1003 if (setsockopt(lhnetsocket->inetsocket, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos)))
1005 // Error in setsockopt - fine, we'll simply set no TOS then.
1009 List_Add_Tail(&lhnetsocket->list, &lhnet_socketlist.list);
1011 if (ioctlsocket(lhnetsocket->inetsocket, SIO_UDP_CONNRESET, &_false) == -1)
1012 Con_DPrintf("LHNET_OpenSocket_Connectionless: ioctlsocket SIO_UDP_CONNRESET returned error: %s\n", LHNETPRIVATE_StrError());
1017 Con_Printf("LHNET_OpenSocket_Connectionless: bind returned error: %s\n", LHNETPRIVATE_StrError());
1021 Con_Printf("LHNET_OpenSocket_Connectionless: setsockopt(IPV6_V6ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
1025 Con_Printf("LHNET_OpenSocket_Connectionless: ioctlsocket returned error: %s\n", LHNETPRIVATE_StrError());
1026 closesocket(lhnetsocket->inetsocket);
1029 Con_Printf("LHNET_OpenSocket_Connectionless: socket returned error: %s\n", LHNETPRIVATE_StrError());
1033 Con_Print("LHNET_OpenSocket_Connectionless: can't open a socket (WSAStartup failed during LHNET_Init)\n");
1039 Z_Free(lhnetsocket);
1044 void LHNET_CloseSocket(lhnetsocket_t *lhnetsocket)
1048 List_Delete(&lhnetsocket->list);
1049 // no special close code for loopback, just inet
1050 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4 || lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1052 closesocket(lhnetsocket->inetsocket);
1054 Z_Free(lhnetsocket);
1058 lhnetaddress_t *LHNET_AddressFromSocket(lhnetsocket_t *sock)
1061 return &sock->address;
1066 int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, lhnetaddress_t *vaddress)
1068 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
1070 if (!lhnetsocket || !address || !content || maxcontentlength < 1)
1072 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
1075 lhnetpacket_t *p, *pnext;
1076 // scan for any old packets to timeout while searching for a packet
1077 // that is waiting to be delivered to this socket
1078 currenttime = time(NULL);
1079 List_For_Each_Entry_Safe(p, pnext, &lhnet_packetlist.list, lhnetpacket_t, list)
1081 if (p->timeout < currenttime)
1084 List_Delete(&p->list);
1088 #ifndef STANDALONETEST
1089 if (net_fakelag.value && (host.realtime - net_fakelag.value * (1.0 / 2000.0)) < p->sentdoubletime)
1092 if (value == 0 && p->destinationport == lhnetsocket->address.port)
1094 if (p->length <= maxcontentlength)
1096 lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
1097 *address = *localaddress;
1098 address->port = p->sourceport;
1099 memcpy(content, p->data, p->length);
1105 List_Delete(&p->list);
1110 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
1112 SOCKLEN_T inetaddresslength;
1113 address->addresstype = LHNETADDRESSTYPE_NONE;
1114 inetaddresslength = sizeof(address->addr.in);
1115 value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength);
1118 address->addresstype = LHNETADDRESSTYPE_INET4;
1119 address->port = ntohs(address->addr.in.sin_port);
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());
1136 #ifndef NOSUPPORTIPV6
1137 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1139 SOCKLEN_T inetaddresslength;
1140 address->addresstype = LHNETADDRESSTYPE_NONE;
1141 inetaddresslength = sizeof(address->addr.in6);
1142 value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength);
1145 address->addresstype = LHNETADDRESSTYPE_INET6;
1146 address->port = ntohs(address->addr.in6.sin6_port);
1149 else if (value == -1)
1151 int e = SOCKETERRNO;
1152 if (e == EWOULDBLOCK)
1157 Con_Print("Connection refused\n");
1160 Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
1167 int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *vaddress)
1169 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
1171 if (!lhnetsocket || !address || !content || contentlength < 1)
1173 if (lhnetsocket->address.addresstype != address->addresstype)
1175 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
1178 p = (lhnetpacket_t *)Z_Malloc(sizeof(*p) + contentlength);
1179 p->data = (void *)(p + 1);
1180 memcpy(p->data, content, contentlength);
1181 p->length = contentlength;
1182 p->sourceport = lhnetsocket->address.port;
1183 p->destinationport = address->port;
1184 p->timeout = time(NULL) + 10;
1185 List_Add_Tail(&p->list, &lhnet_packetlist.list);
1187 #ifndef STANDALONETEST
1188 p->sentdoubletime = host.realtime;
1190 value = contentlength;
1192 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
1194 value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, LHNET_SENDTO_FLAGS, (struct sockaddr *)&address->addr.in, sizeof(struct sockaddr_in));
1197 if (SOCKETERRNO == EWOULDBLOCK)
1199 Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
1202 #ifndef NOSUPPORTIPV6
1203 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1205 value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, 0, (struct sockaddr *)&address->addr.in6, sizeof(struct sockaddr_in6));
1208 if (SOCKETERRNO == EWOULDBLOCK)
1210 Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
1217 #ifdef STANDALONETEST
1218 int main(int argc, char **argv)
1221 char *buffer = "test", buffer2[1024];
1222 int blen = strlen(buffer);
1224 lhnetsocket_t *sock1;
1225 lhnetsocket_t *sock2;
1226 lhnetaddress_t myaddy1;
1227 lhnetaddress_t myaddy2;
1228 lhnetaddress_t myaddy3;
1229 lhnetaddress_t localhostaddy1;
1230 lhnetaddress_t localhostaddy2;
1234 printf("calling LHNET_Init\n");
1237 printf("calling LHNET_FromPort twice to create two local addresses\n");
1238 LHNETADDRESS_FromPort(&myaddy1, LHNETADDRESSTYPE_INET4, 4000);
1239 LHNETADDRESS_FromPort(&myaddy2, LHNETADDRESSTYPE_INET4, 4001);
1240 LHNETADDRESS_FromString(&localhostaddy1, "127.0.0.1", 4000);
1241 LHNETADDRESS_FromString(&localhostaddy2, "127.0.0.1", 4001);
1243 printf("calling LHNET_OpenSocket_Connectionless twice to create two local sockets\n");
1244 sock1 = LHNET_OpenSocket_Connectionless(&myaddy1);
1245 sock2 = LHNET_OpenSocket_Connectionless(&myaddy2);
1247 printf("calling LHNET_Write to send a packet from the first socket to the second socket\n");
1248 test1 = LHNET_Write(sock1, buffer, blen, &localhostaddy2);
1249 printf("sleeping briefly\n");
1255 printf("calling LHNET_Read on the second socket to read the packet sent from the first socket\n");
1256 test2 = LHNET_Read(sock2, buffer2, b2len - 1, &myaddy3);
1258 Con_Printf("socket to socket test succeeded\n");
1260 Con_Printf("socket to socket test failed\n");
1263 printf("press any key to exit\n");
1267 printf("calling LHNET_Shutdown\n");
1269 printf("exiting\n");
1272 lhnetsocket_t *sock[16], *sendsock;
1281 int sendmessagelength;
1282 lhnetaddress_t destaddress;
1283 lhnetaddress_t receiveaddress;
1284 lhnetaddress_t sockaddress[16];
1285 char buffer[1536], addressstring[128], addressstring2[128];
1286 if ((argc == 2 || argc == 5) && (port = atoi(argv[1])) >= 1 && port < 65535)
1288 printf("calling LHNET_Init()\n");
1292 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_LOOP, port);
1293 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET4, port);
1294 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET6, port+1);
1298 sendmessagelength = 0;
1300 for (i = 0;i < numsockets;i++)
1302 LHNETADDRESS_ToString(&sockaddress[i], addressstring, sizeof(addressstring), 1);
1303 printf("calling LHNET_OpenSocket_Connectionless(<%s>)\n", addressstring);
1304 if ((sock[i] = LHNET_OpenSocket_Connectionless(&sockaddress[i])))
1306 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1307 printf("opened socket successfully (address \"%s\")\n", addressstring2);
1311 printf("failed to open socket\n");
1322 count = atoi(argv[2]);
1323 if (LHNETADDRESS_FromString(&destaddress, argv[3], -1))
1325 sendmessage = argv[4];
1326 sendmessagelength = strlen(sendmessage);
1328 for (i = 0;i < numsockets;i++)
1329 if (sock[i] && LHNETADDRESS_GetAddressType(&destaddress) == LHNETADDRESS_GetAddressType(&sockaddress[i]))
1331 if (sendsock == NULL)
1333 printf("Could not find an open socket matching the addresstype (%i) of destination address, switching to listen only mode\n", LHNETADDRESS_GetAddressType(&destaddress));
1339 printf("LHNETADDRESS_FromString did not like the address \"%s\", switching to listen only mode\n", argv[3]);
1343 printf("started, now listening for \"exit\" on the opened sockets\n");
1344 oldtime = time(NULL);
1352 for (i = 0;i < numsockets;i++)
1356 length = LHNET_Read(sock[i], buffer, sizeof(buffer), &receiveaddress);
1358 printf("localsock read error: length < 0");
1359 else if (length > 0 && length < (int)sizeof(buffer))
1362 LHNETADDRESS_ToString(&receiveaddress, addressstring, sizeof(addressstring), 1);
1363 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1364 printf("received message \"%s\" from \"%s\" on socket \"%s\"\n", buffer, addressstring, addressstring2);
1365 if (!strcmp(buffer, "exit"))
1372 if (argc == 5 && count > 0)
1374 newtime = time(NULL);
1375 if (newtime != oldtime)
1377 LHNETADDRESS_ToString(&destaddress, addressstring, sizeof(addressstring), 1);
1378 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sendsock), addressstring2, sizeof(addressstring2), 1);
1379 printf("calling LHNET_Write(<%s>, \"%s\", %i, <%s>)\n", addressstring2, sendmessage, sendmessagelength, addressstring);
1380 length = LHNET_Write(sendsock, sendmessage, sendmessagelength, &destaddress);
1381 if (length == sendmessagelength)
1382 printf("sent successfully\n");
1384 printf("LH_Write failed, returned %i (length of message was %i)\n", length, strlen(argv[4]));
1388 printf("Done sending, still listening for \"exit\"\n");
1392 for (i = 0;i < numsockets;i++)
1396 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1397 printf("calling LHNET_CloseSocket(<%s>)\n", addressstring2);
1398 LHNET_CloseSocket(sock[i]);
1401 printf("calling LHNET_Shutdown()\n");
1405 printf("Testing code for lhnet.c\nusage: lhnettest <localportnumber> [<sendnumberoftimes> <sendaddress:port> <sendmessage>]\n");