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
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;
722 struct lhnetpacket_s *next, *prev;
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 lhnet_socketlist.next = lhnet_socketlist.prev = &lhnet_socketlist;
740 lhnet_packetlist.next = lhnet_packetlist.prev = &lhnet_packetlist;
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)
766 while (lhnet_socketlist.next != &lhnet_socketlist)
767 LHNET_CloseSocket(lhnet_socketlist.next);
768 while (lhnet_packetlist.next != &lhnet_packetlist)
770 p = lhnet_packetlist.next;
771 p->prev->next = p->next;
772 p->next->prev = p->prev;
776 if (lhnet_didWSAStartup)
778 lhnet_didWSAStartup = 0;
785 static const char *LHNETPRIVATE_StrError(void)
788 int i = WSAGetLastError();
791 case WSAEINTR: return "WSAEINTR";
792 case WSAEBADF: return "WSAEBADF";
793 case WSAEACCES: return "WSAEACCES";
794 case WSAEFAULT: return "WSAEFAULT";
795 case WSAEINVAL: return "WSAEINVAL";
796 case WSAEMFILE: return "WSAEMFILE";
797 case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
798 case WSAEINPROGRESS: return "WSAEINPROGRESS";
799 case WSAEALREADY: return "WSAEALREADY";
800 case WSAENOTSOCK: return "WSAENOTSOCK";
801 case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
802 case WSAEMSGSIZE: return "WSAEMSGSIZE";
803 case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
804 case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
805 case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
806 case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
807 case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
808 case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
809 case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
810 case WSAEADDRINUSE: return "WSAEADDRINUSE";
811 case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
812 case WSAENETDOWN: return "WSAENETDOWN";
813 case WSAENETUNREACH: return "WSAENETUNREACH";
814 case WSAENETRESET: return "WSAENETRESET";
815 case WSAECONNABORTED: return "WSAECONNABORTED";
816 case WSAECONNRESET: return "WSAECONNRESET";
817 case WSAENOBUFS: return "WSAENOBUFS";
818 case WSAEISCONN: return "WSAEISCONN";
819 case WSAENOTCONN: return "WSAENOTCONN";
820 case WSAESHUTDOWN: return "WSAESHUTDOWN";
821 case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
822 case WSAETIMEDOUT: return "WSAETIMEDOUT";
823 case WSAECONNREFUSED: return "WSAECONNREFUSED";
824 case WSAELOOP: return "WSAELOOP";
825 case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
826 case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
827 case WSAEHOSTUNREACH: return "WSAEHOSTUNREACH";
828 case WSAENOTEMPTY: return "WSAENOTEMPTY";
829 case WSAEPROCLIM: return "WSAEPROCLIM";
830 case WSAEUSERS: return "WSAEUSERS";
831 case WSAEDQUOT: return "WSAEDQUOT";
832 case WSAESTALE: return "WSAESTALE";
833 case WSAEREMOTE: return "WSAEREMOTE";
834 case WSAEDISCON: return "WSAEDISCON";
835 case 0: return "no error";
836 default: return "unknown WSAE error";
839 return strerror(errno);
843 void LHNET_SleepUntilPacket_Microseconds(int microseconds)
852 for (s = lhnet_socketlist.next;s != &lhnet_socketlist;s = s->next)
854 if (s->address.addresstype == LHNETADDRESSTYPE_INET4 || s->address.addresstype == LHNETADDRESSTYPE_INET6)
856 if (lastfd < s->inetsocket)
857 lastfd = s->inetsocket;
858 #if defined(WIN32) && !defined(_MSC_VER)
859 FD_SET((int)s->inetsocket, &fdreadset);
861 FD_SET((unsigned int)s->inetsocket, &fdreadset);
865 tv.tv_sec = microseconds / 1000000;
866 tv.tv_usec = microseconds % 1000000;
867 select(lastfd + 1, &fdreadset, NULL, NULL, &tv);
869 Sys_Sleep(microseconds);
873 lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address)
875 lhnetsocket_t *lhnetsocket, *s;
878 lhnetsocket = (lhnetsocket_t *)Z_Malloc(sizeof(*lhnetsocket));
881 memset(lhnetsocket, 0, sizeof(*lhnetsocket));
882 lhnetsocket->address = *address;
883 switch(lhnetsocket->address.addresstype)
885 case LHNETADDRESSTYPE_LOOP:
886 if (lhnetsocket->address.port == 0)
888 // allocate a port dynamically
889 // this search will always terminate because there is never
890 // an allocated socket with port 0, so if the number wraps it
891 // will find the port is unused, and then refuse to use port
892 // 0, causing an intentional failure condition
893 lhnetsocket->address.port = 1024;
896 for (s = lhnet_socketlist.next;s != &lhnet_socketlist;s = s->next)
897 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
899 if (s == &lhnet_socketlist)
901 lhnetsocket->address.port++;
904 // check if the port is available
905 for (s = lhnet_socketlist.next;s != &lhnet_socketlist;s = s->next)
906 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
908 if (s == &lhnet_socketlist && lhnetsocket->address.port != 0)
910 lhnetsocket->next = &lhnet_socketlist;
911 lhnetsocket->prev = lhnetsocket->next->prev;
912 lhnetsocket->next->prev = lhnetsocket;
913 lhnetsocket->prev->next = lhnetsocket;
917 case LHNETADDRESSTYPE_INET4:
918 #ifndef NOSUPPORTIPV6
919 case LHNETADDRESSTYPE_INET6:
922 if (lhnet_didWSAStartup)
925 #ifndef NOSUPPORTIPV6
926 if ((lhnetsocket->inetsocket = socket(address->addresstype == LHNETADDRESSTYPE_INET6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
928 if ((lhnetsocket->inetsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
942 if (ioctlsocket(lhnetsocket->inetsocket, FIONBIO, &_true) != -1)
946 // We need to set this flag to tell the OS that we only listen on IPv6. If we don't
947 // most OSes will create a dual-protocol socket that also listens on IPv4. In this case
948 // if an IPv4 socket is already bound to the port we want, our bind() call will fail.
950 if (address->addresstype != LHNETADDRESSTYPE_INET6
951 || setsockopt (lhnetsocket->inetsocket, IPPROTO_IPV6, IPV6_V6ONLY,
952 (const char *)&ipv6_only, sizeof(ipv6_only)) == 0
954 // The Win32 API only supports IPV6_V6ONLY since Windows Vista, but fortunately
955 // the default value is what we want on Win32 anyway (IPV6_V6ONLY = true)
956 || SOCKETERRNO == WSAENOPROTOOPT
961 lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
965 #if defined(SOL_RFC1149) && defined(RFC1149_1149ONLY)
966 // we got reports of massive lags when this protocol was chosen as transport
967 // so better turn it off
970 int rfc1149enabled = 0;
971 if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_1149ONLY, &rfc1149only))
972 Con_Printf(CON_ERROR "LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_1149ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
973 if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_ENABLED, &rfc1149enabled))
974 Con_Printf(CON_ERROR "LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_ENABLED) returned error: %s\n", LHNETPRIVATE_StrError());
978 #ifndef NOSUPPORTIPV6
979 if (address->addresstype == LHNETADDRESSTYPE_INET6)
981 namelen = sizeof(localaddress->addr.in6);
982 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
983 if (bindresult != -1)
985 if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen))
987 // If getsockname failed, we can assume the bound socket is useless.
995 namelen = sizeof(localaddress->addr.in);
996 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
997 if (bindresult != -1)
999 if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen))
1001 // If getsockname failed, we can assume the bound socket is useless.
1006 if (bindresult != -1)
1009 // enable broadcast on this socket
1010 setsockopt(lhnetsocket->inetsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i));
1013 // enable DSCP for ToS support
1014 int tos = lhnet_default_dscp << 2;
1015 if (setsockopt(lhnetsocket->inetsocket, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos)))
1017 // Error in setsockopt - fine, we'll simply set no TOS then.
1021 lhnetsocket->next = &lhnet_socketlist;
1022 lhnetsocket->prev = lhnetsocket->next->prev;
1023 lhnetsocket->next->prev = lhnetsocket;
1024 lhnetsocket->prev->next = lhnetsocket;
1026 if (ioctlsocket(lhnetsocket->inetsocket, SIO_UDP_CONNRESET, &_false) == -1)
1027 Con_DPrintf("LHNET_OpenSocket_Connectionless: ioctlsocket SIO_UDP_CONNRESET returned error: %s\n", LHNETPRIVATE_StrError());
1032 Con_Printf("LHNET_OpenSocket_Connectionless: bind returned error: %s\n", LHNETPRIVATE_StrError());
1036 Con_Printf("LHNET_OpenSocket_Connectionless: setsockopt(IPV6_V6ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
1040 Con_Printf("LHNET_OpenSocket_Connectionless: ioctlsocket returned error: %s\n", LHNETPRIVATE_StrError());
1041 closesocket(lhnetsocket->inetsocket);
1044 Con_Printf("LHNET_OpenSocket_Connectionless: socket returned error: %s\n", LHNETPRIVATE_StrError());
1048 Con_Print("LHNET_OpenSocket_Connectionless: can't open a socket (WSAStartup failed during LHNET_Init)\n");
1054 Z_Free(lhnetsocket);
1059 void LHNET_CloseSocket(lhnetsocket_t *lhnetsocket)
1063 // unlink from socket list
1064 if (lhnetsocket->next == NULL)
1066 lhnetsocket->next->prev = lhnetsocket->prev;
1067 lhnetsocket->prev->next = lhnetsocket->next;
1068 lhnetsocket->next = NULL;
1069 lhnetsocket->prev = NULL;
1071 // no special close code for loopback, just inet
1072 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4 || lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1074 closesocket(lhnetsocket->inetsocket);
1076 Z_Free(lhnetsocket);
1080 lhnetaddress_t *LHNET_AddressFromSocket(lhnetsocket_t *sock)
1083 return &sock->address;
1088 int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, lhnetaddress_t *vaddress)
1090 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
1092 if (!lhnetsocket || !address || !content || maxcontentlength < 1)
1094 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
1097 lhnetpacket_t *p, *pnext;
1098 // scan for any old packets to timeout while searching for a packet
1099 // that is waiting to be delivered to this socket
1100 currenttime = time(NULL);
1101 for (p = lhnet_packetlist.next;p != &lhnet_packetlist;p = pnext)
1104 if (p->timeout < currenttime)
1107 p->next->prev = p->prev;
1108 p->prev->next = p->next;
1112 #ifndef STANDALONETEST
1113 if (net_fakelag.value && (host.realtime - net_fakelag.value * (1.0 / 2000.0)) < p->sentdoubletime)
1116 if (value == 0 && p->destinationport == lhnetsocket->address.port)
1118 if (p->length <= maxcontentlength)
1120 lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
1121 *address = *localaddress;
1122 address->port = p->sourceport;
1123 memcpy(content, p->data, p->length);
1129 p->next->prev = p->prev;
1130 p->prev->next = p->next;
1135 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
1137 SOCKLEN_T inetaddresslength;
1138 address->addresstype = LHNETADDRESSTYPE_NONE;
1139 inetaddresslength = sizeof(address->addr.in);
1140 value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength);
1143 address->addresstype = LHNETADDRESSTYPE_INET4;
1144 address->port = ntohs(address->addr.in.sin_port);
1149 int e = SOCKETERRNO;
1150 if (e == EWOULDBLOCK)
1155 Con_Print("Connection refused\n");
1158 Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
1161 #ifndef NOSUPPORTIPV6
1162 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1164 SOCKLEN_T inetaddresslength;
1165 address->addresstype = LHNETADDRESSTYPE_NONE;
1166 inetaddresslength = sizeof(address->addr.in6);
1167 value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength);
1170 address->addresstype = LHNETADDRESSTYPE_INET6;
1171 address->port = ntohs(address->addr.in6.sin6_port);
1174 else if (value == -1)
1176 int e = SOCKETERRNO;
1177 if (e == EWOULDBLOCK)
1182 Con_Print("Connection refused\n");
1185 Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
1192 int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *vaddress)
1194 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
1196 if (!lhnetsocket || !address || !content || contentlength < 1)
1198 if (lhnetsocket->address.addresstype != address->addresstype)
1200 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
1203 p = (lhnetpacket_t *)Z_Malloc(sizeof(*p) + contentlength);
1204 p->data = (void *)(p + 1);
1205 memcpy(p->data, content, contentlength);
1206 p->length = contentlength;
1207 p->sourceport = lhnetsocket->address.port;
1208 p->destinationport = address->port;
1209 p->timeout = time(NULL) + 10;
1210 p->next = &lhnet_packetlist;
1211 p->prev = p->next->prev;
1214 #ifndef STANDALONETEST
1215 p->sentdoubletime = host.realtime;
1217 value = contentlength;
1219 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
1221 value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, LHNET_SENDTO_FLAGS, (struct sockaddr *)&address->addr.in, sizeof(struct sockaddr_in));
1224 if (SOCKETERRNO == EWOULDBLOCK)
1226 Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
1229 #ifndef NOSUPPORTIPV6
1230 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1232 value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, 0, (struct sockaddr *)&address->addr.in6, sizeof(struct sockaddr_in6));
1235 if (SOCKETERRNO == EWOULDBLOCK)
1237 Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
1244 #ifdef STANDALONETEST
1245 int main(int argc, char **argv)
1248 char *buffer = "test", buffer2[1024];
1249 int blen = strlen(buffer);
1251 lhnetsocket_t *sock1;
1252 lhnetsocket_t *sock2;
1253 lhnetaddress_t myaddy1;
1254 lhnetaddress_t myaddy2;
1255 lhnetaddress_t myaddy3;
1256 lhnetaddress_t localhostaddy1;
1257 lhnetaddress_t localhostaddy2;
1261 printf("calling LHNET_Init\n");
1264 printf("calling LHNET_FromPort twice to create two local addresses\n");
1265 LHNETADDRESS_FromPort(&myaddy1, LHNETADDRESSTYPE_INET4, 4000);
1266 LHNETADDRESS_FromPort(&myaddy2, LHNETADDRESSTYPE_INET4, 4001);
1267 LHNETADDRESS_FromString(&localhostaddy1, "127.0.0.1", 4000);
1268 LHNETADDRESS_FromString(&localhostaddy2, "127.0.0.1", 4001);
1270 printf("calling LHNET_OpenSocket_Connectionless twice to create two local sockets\n");
1271 sock1 = LHNET_OpenSocket_Connectionless(&myaddy1);
1272 sock2 = LHNET_OpenSocket_Connectionless(&myaddy2);
1274 printf("calling LHNET_Write to send a packet from the first socket to the second socket\n");
1275 test1 = LHNET_Write(sock1, buffer, blen, &localhostaddy2);
1276 printf("sleeping briefly\n");
1282 printf("calling LHNET_Read on the second socket to read the packet sent from the first socket\n");
1283 test2 = LHNET_Read(sock2, buffer2, b2len - 1, &myaddy3);
1285 Con_Printf("socket to socket test succeeded\n");
1287 Con_Printf("socket to socket test failed\n");
1290 printf("press any key to exit\n");
1294 printf("calling LHNET_Shutdown\n");
1296 printf("exiting\n");
1299 lhnetsocket_t *sock[16], *sendsock;
1308 int sendmessagelength;
1309 lhnetaddress_t destaddress;
1310 lhnetaddress_t receiveaddress;
1311 lhnetaddress_t sockaddress[16];
1312 char buffer[1536], addressstring[128], addressstring2[128];
1313 if ((argc == 2 || argc == 5) && (port = atoi(argv[1])) >= 1 && port < 65535)
1315 printf("calling LHNET_Init()\n");
1319 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_LOOP, port);
1320 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET4, port);
1321 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET6, port+1);
1325 sendmessagelength = 0;
1327 for (i = 0;i < numsockets;i++)
1329 LHNETADDRESS_ToString(&sockaddress[i], addressstring, sizeof(addressstring), 1);
1330 printf("calling LHNET_OpenSocket_Connectionless(<%s>)\n", addressstring);
1331 if ((sock[i] = LHNET_OpenSocket_Connectionless(&sockaddress[i])))
1333 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1334 printf("opened socket successfully (address \"%s\")\n", addressstring2);
1338 printf("failed to open socket\n");
1349 count = atoi(argv[2]);
1350 if (LHNETADDRESS_FromString(&destaddress, argv[3], -1))
1352 sendmessage = argv[4];
1353 sendmessagelength = strlen(sendmessage);
1355 for (i = 0;i < numsockets;i++)
1356 if (sock[i] && LHNETADDRESS_GetAddressType(&destaddress) == LHNETADDRESS_GetAddressType(&sockaddress[i]))
1358 if (sendsock == NULL)
1360 printf("Could not find an open socket matching the addresstype (%i) of destination address, switching to listen only mode\n", LHNETADDRESS_GetAddressType(&destaddress));
1366 printf("LHNETADDRESS_FromString did not like the address \"%s\", switching to listen only mode\n", argv[3]);
1370 printf("started, now listening for \"exit\" on the opened sockets\n");
1371 oldtime = time(NULL);
1379 for (i = 0;i < numsockets;i++)
1383 length = LHNET_Read(sock[i], buffer, sizeof(buffer), &receiveaddress);
1385 printf("localsock read error: length < 0");
1386 else if (length > 0 && length < (int)sizeof(buffer))
1389 LHNETADDRESS_ToString(&receiveaddress, addressstring, sizeof(addressstring), 1);
1390 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1391 printf("received message \"%s\" from \"%s\" on socket \"%s\"\n", buffer, addressstring, addressstring2);
1392 if (!strcmp(buffer, "exit"))
1399 if (argc == 5 && count > 0)
1401 newtime = time(NULL);
1402 if (newtime != oldtime)
1404 LHNETADDRESS_ToString(&destaddress, addressstring, sizeof(addressstring), 1);
1405 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sendsock), addressstring2, sizeof(addressstring2), 1);
1406 printf("calling LHNET_Write(<%s>, \"%s\", %i, <%s>)\n", addressstring2, sendmessage, sendmessagelength, addressstring);
1407 length = LHNET_Write(sendsock, sendmessage, sendmessagelength, &destaddress);
1408 if (length == sendmessagelength)
1409 printf("sent successfully\n");
1411 printf("LH_Write failed, returned %i (length of message was %i)\n", length, strlen(argv[4]));
1415 printf("Done sending, still listening for \"exit\"\n");
1419 for (i = 0;i < numsockets;i++)
1423 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1424 printf("calling LHNET_CloseSocket(<%s>)\n", addressstring2);
1425 LHNET_CloseSocket(sock[i]);
1428 printf("calling LHNET_Shutdown()\n");
1432 printf("Testing code for lhnet.c\nusage: lhnettest <localportnumber> [<sendnumberoftimes> <sendaddress:port> <sendmessage>]\n");