DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
lhnet.c
Go to the documentation of this file.
1
2// Written by Ashley Rose Hale (LadyHavoc) 2003-06-15 and placed into public domain.
3
4#ifdef WIN32
5# ifdef _MSC_VER
6# pragma comment(lib, "ws2_32.lib")
7# endif
8# ifndef NOSUPPORTIPV6
9// Windows XP or higher is required for getaddrinfo, but the inclusion of wspiapi provides fallbacks for older versions
10# define _WIN32_WINNT 0x0501
11# endif
12// To increase FD_SETSIZE (defaults to 64 on Windows)
13// it must be defined before the first inclusion of winsock2.h
14# define FD_SETSIZE 1024 // Matches Linux and BSD defaults
15# include <winsock2.h>
16# include <ws2tcpip.h>
17# ifdef USE_WSPIAPI_H
18# include <wspiapi.h>
19# endif
20#endif
21
22#ifndef STANDALONETEST
23#include "darkplaces.h"
24#endif
25
26#include <stdlib.h>
27#include <stdio.h>
28#include <time.h>
29#include <string.h>
30#ifndef WIN32
31#include <unistd.h>
32#include <sys/types.h>
33#include <sys/socket.h>
34#include <sys/ioctl.h>
35#include <errno.h>
36#include <netdb.h>
37#include <netinet/in.h>
38#include <arpa/inet.h>
39#ifndef NOSUPPORTIPV6
40#include <net/if.h>
41#endif
42#endif
43
44#ifdef __MORPHOS__
45#include <proto/socket.h>
46#endif
47
48// for Z_Malloc/Z_Free in quake
49#ifndef STANDALONETEST
50#include "zone.h"
51#include "sys.h"
52#include "netconn.h"
53#else
54#define Con_Print printf
55#define Con_Printf printf
56#define Z_Malloc malloc
57#define Z_Free free
58#endif
59
60#include "lhnet.h"
61
62#if defined(WIN32)
63// as of Visual Studio 2015, EWOULDBLOCK and ECONNREFUSED are real things, with different values than we want when talking to WinSock, so we have to undef them here or change the rest of the code.
64#undef EWOULDBLOCK
65#undef ECONNREFUSED
66#define EWOULDBLOCK WSAEWOULDBLOCK
67#define ECONNREFUSED WSAECONNREFUSED
68
69#define SOCKETERRNO WSAGetLastError()
70
71#define IOC_VENDOR 0x18000000
72#define _WSAIOW(x,y) (IOC_IN|(x)|(y))
73#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
74
75#define SOCKLEN_T int
76#elif defined(__MORPHOS__)
77#define ioctlsocket IoctlSocket
78#define closesocket CloseSocket
79#define SOCKETERRNO Errno()
80
81#define SOCKLEN_T int
82#else
83#define ioctlsocket ioctl
84#define closesocket close
85#define SOCKETERRNO errno
86
87#define SOCKLEN_T socklen_t
88#endif
89
90#ifdef MSG_DONTWAIT
91#define LHNET_RECVFROM_FLAGS MSG_DONTWAIT
92#define LHNET_SENDTO_FLAGS 0
93#else
94#define LHNET_RECVFROM_FLAGS 0
95#define LHNET_SENDTO_FLAGS 0
96#endif
97
98typedef struct lhnetaddressnative_s
99{
101 int port;
102 union
103 {
104 struct sockaddr sock;
105 struct sockaddr_in in;
106#ifndef NOSUPPORTIPV6
107 struct sockaddr_in6 in6;
108#endif
109 }
111}
113
114// to make LHNETADDRESS_FromString resolve repeated hostnames faster, cache them
115#define MAX_NAMECACHE 64
116static struct namecache_s
117{
120 char name[64];
121}
123static int namecacheposition = 0;
124
125int LHNETADDRESS_FromPort(lhnetaddress_t *vaddress, lhnetaddresstype_t addresstype, int port)
126{
127 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
128 if (!address)
129 return 0;
130 switch(addresstype)
131 {
132 default:
133 break;
135 // local:port (loopback)
136 memset(address, 0, sizeof(*address));
138 address->port = port;
139 return 1;
141 // 0.0.0.0:port (INADDR_ANY, binds to all interfaces)
142 memset(address, 0, sizeof(*address));
144 address->port = port;
145 address->addr.in.sin_family = AF_INET;
146 address->addr.in.sin_port = htons((unsigned short)port);
147 return 1;
148#ifndef NOSUPPORTIPV6
150 // [0:0:0:0:0:0:0:0]:port (IN6ADDR_ANY, binds to all interfaces)
151 memset(address, 0, sizeof(*address));
153 address->port = port;
154 address->addr.in6.sin6_family = AF_INET6;
155 address->addr.in6.sin6_port = htons((unsigned short)port);
156 return 1;
157#endif
158 }
159 return 0;
160}
161
162#ifndef NOSUPPORTIPV6
163static int LHNETADDRESS_Resolve(lhnetaddressnative_t *address, const char *name, int port)
164{
165 char port_buff [16];
166 struct addrinfo hints;
167 struct addrinfo* addrinf;
168 int err;
169
170 dpsnprintf (port_buff, sizeof (port_buff), "%d", port);
171 port_buff[sizeof (port_buff) - 1] = '\0';
172
173 memset(&hints, 0, sizeof (hints));
174 hints.ai_family = AF_UNSPEC;
175 hints.ai_socktype = SOCK_DGRAM;
176 //hints.ai_flags = AI_PASSIVE;
177
178 err = getaddrinfo(name, port_buff, &hints, &addrinf);
179 if (err != 0 || addrinf == NULL)
180 return 0;
181 if (addrinf->ai_addr->sa_family != AF_INET6 && addrinf->ai_addr->sa_family != AF_INET)
182 {
183 freeaddrinfo (addrinf);
184 return 0;
185 }
186
187 // great it worked
188 if (addrinf->ai_addr->sa_family == AF_INET6)
189 {
191 memcpy(&address->addr.in6, addrinf->ai_addr, sizeof(address->addr.in6));
192 }
193 else
194 {
196 memcpy(&address->addr.in, addrinf->ai_addr, sizeof(address->addr.in));
197 }
198 address->port = port;
199
200 freeaddrinfo (addrinf);
201 return 1;
202}
203
204int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
205{
206 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
207 int i, port, d1, d2, d3, d4, resolved;
208 size_t namelen;
209 unsigned char *a;
210 char name[128];
211#ifdef STANDALONETEST
212 char string2[128];
213#endif
214 const char* addr_start;
215 const char* addr_end = NULL;
216 const char* port_name = NULL;
217 int addr_family = AF_UNSPEC;
218
219 if (!address || !string || !*string)
220 return 0;
221 memset(address, 0, sizeof(*address));
223 port = 0;
224
225 // If it's a bracketed IPv6 address
226 if (string[0] == '[')
227 {
228 const char* end_bracket = strchr(string, ']');
229
230 if (end_bracket == NULL)
231 return 0;
232
233 if (end_bracket[1] == ':')
234 port_name = end_bracket + 2;
235 else if (end_bracket[1] != '\0')
236 return 0;
237
238 addr_family = AF_INET6;
239 addr_start = &string[1];
240 addr_end = end_bracket;
241 }
242 else
243 {
244 const char* first_colon;
245
246 addr_start = string;
247
248 // If it's a numeric non-bracket IPv6 address (-> no port),
249 // or it's a numeric IPv4 address, or a name, with a port
250 first_colon = strchr(string, ':');
251 if (first_colon != NULL)
252 {
253 const char* last_colon = strrchr(first_colon + 1, ':');
254
255 // If it's an numeric IPv4 address, or a name, with a port
256 if (last_colon == NULL)
257 {
258 addr_end = first_colon;
259 port_name = first_colon + 1;
260 }
261 else
262 addr_family = AF_INET6;
263 }
264 }
265
266 if (addr_end != NULL)
267 namelen = addr_end - addr_start;
268 else
269 namelen = strlen (addr_start);
270
271 if (namelen >= sizeof(name))
272 namelen = sizeof(name) - 1;
273 memcpy (name, addr_start, namelen);
274 name[namelen] = 0;
275
276 if (port_name)
277 port = atoi(port_name);
278
279 if (port == 0)
280 port = defaultport;
281
282 // handle loopback
283 if (!strcmp(name, "local"))
284 {
286 address->port = port;
287 return 1;
288 }
289 // try to parse as dotted decimal ipv4 address first
290 // note this supports partial ip addresses
291 d1 = d2 = d3 = d4 = 0;
292#if _MSC_VER >= 1400
293#define sscanf sscanf_s
294#endif
295 if (addr_family != AF_INET6 &&
296 sscanf(name, "%d.%d.%d.%d", &d1, &d2, &d3, &d4) >= 1 && (unsigned int)d1 < 256 && (unsigned int)d2 < 256 && (unsigned int)d3 < 256 && (unsigned int)d4 < 256)
297 {
298 // parsed a valid ipv4 address
300 address->port = port;
301 address->addr.in.sin_family = AF_INET;
302 address->addr.in.sin_port = htons((unsigned short)port);
303 a = (unsigned char *)&address->addr.in.sin_addr;
304 a[0] = d1;
305 a[1] = d2;
306 a[2] = d3;
307 a[3] = d4;
308#ifdef STANDALONETEST
309 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
310 printf("manual parsing of ipv4 dotted decimal address \"%s\" successful: %s\n", string, string2);
311#endif
312 return 1;
313 }
314 for (i = 0;i < MAX_NAMECACHE;i++)
315 if (!strcmp(namecache[i].name, name))
316 break;
317#ifdef STANDALONETEST
318 if (i < MAX_NAMECACHE)
319#else
321#endif
322 {
323 *address = namecache[i].address;
324 address->port = port;
325 if (address->addresstype == LHNETADDRESSTYPE_INET6)
326 {
327 address->addr.in6.sin6_port = htons((unsigned short)port);
328 return 1;
329 }
330 else if (address->addresstype == LHNETADDRESSTYPE_INET4)
331 {
332 address->addr.in.sin_port = htons((unsigned short)port);
333 return 1;
334 }
335 return 0;
336 }
337
338 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
341#ifndef STANDALONETEST
342 namecache[namecacheposition].expirationtime = host.realtime + 12 * 3600; // 12 hours
343#endif
344
345 // try resolving the address (handles dns and other ip formats)
346 resolved = LHNETADDRESS_Resolve(address, name, port);
347 if (resolved)
348 {
349#ifdef STANDALONETEST
350 const char *protoname;
351
352 switch (address->addresstype)
353 {
355 protoname = "ipv6";
356 break;
358 protoname = "ipv4";
359 break;
360 default:
361 protoname = "UNKNOWN";
362 break;
363 }
364 LHNETADDRESS_ToString(vaddress, string2, sizeof(string2), 1);
365 Con_Printf("LHNETADDRESS_Resolve(\"%s\") returned %s address %s\n", string, protoname, string2);
366#endif
368 }
369 else
370 {
371#ifdef STANDALONETEST
372 printf("name resolution failed on address \"%s\"\n", name);
373#endif
375 }
376
378 return resolved;
379}
380#else
381int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
382{
383 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
384 int i, port, namelen, d1, d2, d3, d4;
385 struct hostent *hostentry;
386 unsigned char *a;
387 const char *colon;
388 char name[128];
389#ifdef STANDALONETEST
390 char string2[128];
391#endif
392 if (!address || !string || !*string)
393 return 0;
394 memset(address, 0, sizeof(*address));
396 port = 0;
397 colon = strrchr(string, ':');
398 if (colon && (colon == strchr(string, ':') || (string[0] == '[' && colon - string > 0 && colon[-1] == ']')))
399 // EITHER: colon is the ONLY colon OR: colon comes after [...] delimited IPv6 address
400 // fixes misparsing of IPv6 addresses without port
401 {
402 port = atoi(colon + 1);
403 }
404 else
405 colon = string + strlen(string);
406 if (port == 0)
407 port = defaultport;
408 namelen = colon - string;
409 if (namelen > 127)
410 namelen = 127;
411 if (string[0] == '[' && namelen > 0 && string[namelen-1] == ']') // ipv6
412 {
413 string++;
414 namelen -= 2;
415 }
416 memcpy(name, string, namelen);
417 name[namelen] = 0;
418 // handle loopback
419 if (!strcmp(name, "local"))
420 {
422 address->port = port;
423 return 1;
424 }
425 // try to parse as dotted decimal ipv4 address first
426 // note this supports partial ip addresses
427 d1 = d2 = d3 = d4 = 0;
428#if _MSC_VER >= 1400
429#define sscanf sscanf_s
430#endif
431 if (sscanf(name, "%d.%d.%d.%d", &d1, &d2, &d3, &d4) >= 1 && (unsigned int)d1 < 256 && (unsigned int)d2 < 256 && (unsigned int)d3 < 256 && (unsigned int)d4 < 256)
432 {
433 // parsed a valid ipv4 address
435 address->port = port;
436 address->addr.in.sin_family = AF_INET;
437 address->addr.in.sin_port = htons((unsigned short)port);
438 a = (unsigned char *)&address->addr.in.sin_addr;
439 a[0] = d1;
440 a[1] = d2;
441 a[2] = d3;
442 a[3] = d4;
443#ifdef STANDALONETEST
444 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
445 printf("manual parsing of ipv4 dotted decimal address \"%s\" successful: %s\n", string, string2);
446#endif
447 return 1;
448 }
449 for (i = 0;i < MAX_NAMECACHE;i++)
450 if (!strcmp(namecache[i].name, name))
451 break;
452#ifdef STANDALONETEST
453 if (i < MAX_NAMECACHE)
454#else
456#endif
457 {
458 *address = namecache[i].address;
459 address->port = port;
460 if (address->addresstype == LHNETADDRESSTYPE_INET6)
461 {
462#ifndef NOSUPPORTIPV6
463 address->addr.in6.sin6_port = htons((unsigned short)port);
464 return 1;
465#endif
466 }
467 else if (address->addresstype == LHNETADDRESSTYPE_INET4)
468 {
469 address->addr.in.sin_port = htons((unsigned short)port);
470 return 1;
471 }
472 return 0;
473 }
474 // try gethostbyname (handles dns and other ip formats)
475 hostentry = gethostbyname(name);
476 if (hostentry)
477 {
478 if (hostentry->h_addrtype == AF_INET6)
479 {
480#ifndef NOSUPPORTIPV6
481 // great it worked
483 address->port = port;
484 address->addr.in6.sin6_family = hostentry->h_addrtype;
485 address->addr.in6.sin6_port = htons((unsigned short)port);
486 memcpy(&address->addr.in6.sin6_addr, hostentry->h_addr_list[0], sizeof(address->addr.in6.sin6_addr));
487 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
490#ifndef STANDALONETEST
491 namecache[namecacheposition].expirationtime = host.realtime + 12 * 3600; // 12 hours
492#endif
495#ifdef STANDALONETEST
496 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
497 printf("gethostbyname(\"%s\") returned ipv6 address %s\n", string, string2);
498#endif
499 return 1;
500#endif
501 }
502 else if (hostentry->h_addrtype == AF_INET)
503 {
504 // great it worked
506 address->port = port;
507 address->addr.in.sin_family = hostentry->h_addrtype;
508 address->addr.in.sin_port = htons((unsigned short)port);
509 memcpy(&address->addr.in.sin_addr, hostentry->h_addr_list[0], sizeof(address->addr.in.sin_addr));
510 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
513#ifndef STANDALONETEST
514 namecache[namecacheposition].expirationtime = host.realtime + 12 * 3600; // 12 hours
515#endif
518#ifdef STANDALONETEST
519 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
520 printf("gethostbyname(\"%s\") returned ipv4 address %s\n", string, string2);
521#endif
522 return 1;
523 }
524 }
525#ifdef STANDALONETEST
526 printf("gethostbyname failed on address \"%s\"\n", name);
527#endif
528 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
531#ifndef STANDALONETEST
532 namecache[namecacheposition].expirationtime = host.realtime + 12 * 3600; // 12 hours
533#endif
536 return 0;
537}
538#endif
539
540int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stringbuffersize, int includeport)
541{
542 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
543 const unsigned char *a;
544 if (!address || !string || stringbuffersize < 1)
545 return 0;
546 *string = 0;
547 switch(address->addresstype)
548 {
549 default:
550 break;
552 if (includeport)
553 {
554 if (stringbuffersize >= 12)
555 {
556 return dpsnprintf(string, stringbuffersize, "local:%d", address->port);
557 }
558 }
559 else
560 {
561 if (stringbuffersize >= 6)
562 {
563 memcpy(string, "local", 6);
564 return 5;
565 }
566 }
567 break;
569 a = (const unsigned char *)(&address->addr.in.sin_addr);
570 if (includeport)
571 {
572 if (stringbuffersize >= 22)
573 {
574 return dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d:%d", a[0], a[1], a[2], a[3], address->port);
575 }
576 }
577 else
578 {
579 if (stringbuffersize >= 16)
580 {
581 return dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
582 }
583 }
584 break;
585#ifndef NOSUPPORTIPV6
587 a = (const unsigned char *)(&address->addr.in6.sin6_addr);
588 if (includeport)
589 {
590 if (stringbuffersize >= 88)
591 {
592 return dpsnprintf(string, stringbuffersize, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d", a[0] * 256 + a[1], a[2] * 256 + a[3], a[4] * 256 + a[5], a[6] * 256 + a[7], a[8] * 256 + a[9], a[10] * 256 + a[11], a[12] * 256 + a[13], a[14] * 256 + a[15], address->port);
593 }
594 }
595 else
596 {
597 if (stringbuffersize >= 80)
598 {
599 return dpsnprintf(string, stringbuffersize, "%x:%x:%x:%x:%x:%x:%x:%x", a[0] * 256 + a[1], a[2] * 256 + a[3], a[4] * 256 + a[5], a[6] * 256 + a[7], a[8] * 256 + a[9], a[10] * 256 + a[11], a[12] * 256 + a[13], a[14] * 256 + a[15]);
600 }
601 }
602 break;
603#endif
604 }
605 return 0;
606}
607
608const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress, char *ifname, size_t ifnamelength)
609{
610#ifndef NOSUPPORTIPV6
611 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
612
613 if (address && address->addresstype == LHNETADDRESSTYPE_INET6)
614 {
615#ifndef _WIN32
616
617 if (if_indextoname(address->addr.in6.sin6_scope_id, ifname) == ifname)
618 return ifname;
619
620#else
621
622 // The Win32 API doesn't have if_indextoname() until Windows Vista,
623 // but luckily it just uses the interface ID as the interface name
624
625 if (dpsnprintf(ifname, ifnamelength, "%lu", address->addr.in6.sin6_scope_id) > 0)
626 return ifname;
627
628#endif
629 }
630#endif
631
632 return NULL;
633}
634
636{
637 if (!address)
638 return -1;
639 return address->port;
640}
641
642int LHNETADDRESS_SetPort(lhnetaddress_t *vaddress, int port)
643{
644 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
645 if (!address)
646 return 0;
647 address->port = port;
648 switch(address->addresstype)
649 {
651 return 1;
653 address->addr.in.sin_port = htons((unsigned short)port);
654 return 1;
655#ifndef NOSUPPORTIPV6
657 address->addr.in6.sin6_port = htons((unsigned short)port);
658 return 1;
659#endif
660 default:
661 return 0;
662 }
663}
664
665int LHNETADDRESS_Compare(const lhnetaddress_t *vaddress1, const lhnetaddress_t *vaddress2)
666{
667 lhnetaddressnative_t *address1 = (lhnetaddressnative_t *)vaddress1;
668 lhnetaddressnative_t *address2 = (lhnetaddressnative_t *)vaddress2;
669 if (!address1 || !address2)
670 return 1;
671 if (address1->addresstype != address2->addresstype)
672 return 1;
673 switch(address1->addresstype)
674 {
676 if (address1->port != address2->port)
677 return -1;
678 return 0;
680 if (address1->addr.in.sin_family != address2->addr.in.sin_family)
681 return 1;
682 if (memcmp(&address1->addr.in.sin_addr, &address2->addr.in.sin_addr, sizeof(address1->addr.in.sin_addr)))
683 return 1;
684 if (address1->port != address2->port)
685 return -1;
686 return 0;
687#ifndef NOSUPPORTIPV6
689 if (address1->addr.in6.sin6_family != address2->addr.in6.sin6_family)
690 return 1;
691 if (memcmp(&address1->addr.in6.sin6_addr, &address2->addr.in6.sin6_addr, sizeof(address1->addr.in6.sin6_addr)))
692 return 1;
693 if (address1->port != address2->port)
694 return -1;
695 return 0;
696#endif
697 default:
698 return 1;
699 }
700}
701
702typedef struct lhnetpacket_s
703{
704 void *data;
708 time_t timeout;
709#ifndef STANDALONETEST
711#endif
713}
715
716static int lhnet_active;
719static int lhnet_default_dscp = 0;
720#ifdef WIN32
721static int lhnet_didWSAStartup = 0;
722static WSADATA lhnet_winsockdata;
723#endif
724
725void LHNET_Init(void)
726{
727 if (lhnet_active)
728 return;
731 lhnet_active = 1;
732#ifdef WIN32
733 lhnet_didWSAStartup = !WSAStartup(MAKEWORD(1, 1), &lhnet_winsockdata);
734 if (!lhnet_didWSAStartup)
735 Con_Print("LHNET_Init: WSAStartup failed, networking disabled\n");
736#endif
737}
738
739int LHNET_DefaultDSCP(int dscp)
740{
741#ifdef IP_TOS
742 int prev = lhnet_default_dscp;
743 if(dscp >= 0)
744 lhnet_default_dscp = dscp;
745 return prev;
746#else
747 return -1;
748#endif
749}
750
752{
753 lhnetsocket_t *s, *snext;
754 lhnetpacket_t *p, *pnext;
755 if (!lhnet_active)
756 return;
760 {
761 List_Delete(&p->list);
762 Z_Free(p);
763 }
764#ifdef WIN32
765 if (lhnet_didWSAStartup)
766 {
767 lhnet_didWSAStartup = 0;
768 WSACleanup();
769 }
770#endif
771 lhnet_active = 0;
772}
773
774static const char *LHNETPRIVATE_StrError(void)
775{
776#ifdef WIN32
777 int i = WSAGetLastError();
778 switch (i)
779 {
780 case WSAEINTR: return "WSAEINTR";
781 case WSAEBADF: return "WSAEBADF";
782 case WSAEACCES: return "WSAEACCES";
783 case WSAEFAULT: return "WSAEFAULT";
784 case WSAEINVAL: return "WSAEINVAL";
785 case WSAEMFILE: return "WSAEMFILE";
786 case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
787 case WSAEINPROGRESS: return "WSAEINPROGRESS";
788 case WSAEALREADY: return "WSAEALREADY";
789 case WSAENOTSOCK: return "WSAENOTSOCK";
790 case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
791 case WSAEMSGSIZE: return "WSAEMSGSIZE";
792 case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
793 case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
794 case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
795 case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
796 case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
797 case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
798 case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
799 case WSAEADDRINUSE: return "WSAEADDRINUSE";
800 case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
801 case WSAENETDOWN: return "WSAENETDOWN";
802 case WSAENETUNREACH: return "WSAENETUNREACH";
803 case WSAENETRESET: return "WSAENETRESET";
804 case WSAECONNABORTED: return "WSAECONNABORTED";
805 case WSAECONNRESET: return "WSAECONNRESET";
806 case WSAENOBUFS: return "WSAENOBUFS";
807 case WSAEISCONN: return "WSAEISCONN";
808 case WSAENOTCONN: return "WSAENOTCONN";
809 case WSAESHUTDOWN: return "WSAESHUTDOWN";
810 case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
811 case WSAETIMEDOUT: return "WSAETIMEDOUT";
812 case WSAECONNREFUSED: return "WSAECONNREFUSED";
813 case WSAELOOP: return "WSAELOOP";
814 case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
815 case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
816 case WSAEHOSTUNREACH: return "WSAEHOSTUNREACH";
817 case WSAENOTEMPTY: return "WSAENOTEMPTY";
818 case WSAEPROCLIM: return "WSAEPROCLIM";
819 case WSAEUSERS: return "WSAEUSERS";
820 case WSAEDQUOT: return "WSAEDQUOT";
821 case WSAESTALE: return "WSAESTALE";
822 case WSAEREMOTE: return "WSAEREMOTE";
823 case WSAEDISCON: return "WSAEDISCON";
824 case 0: return "no error";
825 default: return "unknown WSAE error";
826 }
827#else
828 return strerror(errno);
829#endif
830}
831
833{
834 lhnetsocket_t *lhnetsocket, *s;
835 if (!address)
836 return NULL;
837 lhnetsocket = (lhnetsocket_t *)Z_Malloc(sizeof(*lhnetsocket));
838 if (lhnetsocket)
839 {
840 memset(lhnetsocket, 0, sizeof(*lhnetsocket));
841 lhnetsocket->address = *address;
842 switch(lhnetsocket->address.addresstype)
843 {
845 if (lhnetsocket->address.port == 0)
846 {
847 // allocate a port dynamically
848 // this search will always terminate because there is never
849 // an allocated socket with port 0, so if the number wraps it
850 // will find the port is unused, and then refuse to use port
851 // 0, causing an intentional failure condition
852 lhnetsocket->address.port = 1024;
853 for (;;)
854 {
856 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
857 break;
858 if (s == &lhnet_socketlist)
859 break;
860 lhnetsocket->address.port++;
861 }
862 }
863 // check if the port is available
865 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
866 break;
867 if (s == &lhnet_socketlist && lhnetsocket->address.port != 0)
868 {
869 List_Add_Tail(&lhnetsocket->list, &lhnet_socketlist.list);
870 return lhnetsocket;
871 }
872 break;
874#ifndef NOSUPPORTIPV6
876#endif
877#ifdef WIN32
878 if (lhnet_didWSAStartup)
879 {
880#endif
881#ifndef NOSUPPORTIPV6
882 if ((lhnetsocket->inetsocket = socket(address->addresstype == LHNETADDRESSTYPE_INET6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
883#else
884 if ((lhnetsocket->inetsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
885#endif
886 {
887#ifdef WIN32
888 u_long _false = 0;
889#endif
890#ifdef MSG_DONTWAIT
891 if (1)
892#else
893#ifdef WIN32
894 u_long _true = 1;
895#else
896 char _true = 1;
897#endif
898 if (ioctlsocket(lhnetsocket->inetsocket, FIONBIO, &_true) != -1)
899#endif
900 {
901#ifdef IPV6_V6ONLY
902 // We need to set this flag to tell the OS that we only listen on IPv6. If we don't
903 // most OSes will create a dual-protocol socket that also listens on IPv4. In this case
904 // if an IPv4 socket is already bound to the port we want, our bind() call will fail.
905 int ipv6_only = 1;
906 if (address->addresstype != LHNETADDRESSTYPE_INET6
907 || setsockopt (lhnetsocket->inetsocket, IPPROTO_IPV6, IPV6_V6ONLY,
908 (const char *)&ipv6_only, sizeof(ipv6_only)) == 0
909#ifdef WIN32
910 // The Win32 API only supports IPV6_V6ONLY since Windows Vista, but fortunately
911 // the default value is what we want on Win32 anyway (IPV6_V6ONLY = true)
912 || SOCKETERRNO == WSAENOPROTOOPT
913#endif
914 )
915#endif
916 {
917 lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
918 SOCKLEN_T namelen;
919 int bindresult;
920
921#if defined(SOL_RFC1149) && defined(RFC1149_1149ONLY)
922 // we got reports of massive lags when this protocol was chosen as transport
923 // so better turn it off
924 {
925 int rfc1149only = 0;
926 int rfc1149enabled = 0;
927 if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_1149ONLY, &rfc1149only))
928 Con_Printf(CON_ERROR "LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_1149ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
929 if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_ENABLED, &rfc1149enabled))
930 Con_Printf(CON_ERROR "LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_ENABLED) returned error: %s\n", LHNETPRIVATE_StrError());
931 }
932#endif
933
934#ifndef NOSUPPORTIPV6
935 if (address->addresstype == LHNETADDRESSTYPE_INET6)
936 {
937 namelen = sizeof(localaddress->addr.in6);
938 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
939 if (bindresult != -1)
940 {
941 if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen))
942 {
943 // If getsockname failed, we can assume the bound socket is useless.
944 bindresult = -1;
945 }
946 }
947 }
948 else
949#endif
950 {
951 namelen = sizeof(localaddress->addr.in);
952 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
953 if (bindresult != -1)
954 {
955 if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen))
956 {
957 // If getsockname failed, we can assume the bound socket is useless.
958 bindresult = -1;
959 }
960 }
961 }
962 if (bindresult != -1)
963 {
964 int i = 1;
965 // enable broadcast on this socket
966 setsockopt(lhnetsocket->inetsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i));
967#ifdef IP_TOS
968 {
969 // enable DSCP for ToS support
970 int tos = lhnet_default_dscp << 2;
971 if (setsockopt(lhnetsocket->inetsocket, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos)))
972 {
973 // Error in setsockopt - fine, we'll simply set no TOS then.
974 }
975 }
976#endif
977 List_Add_Tail(&lhnetsocket->list, &lhnet_socketlist.list);
978#ifdef WIN32
979 if (ioctlsocket(lhnetsocket->inetsocket, SIO_UDP_CONNRESET, &_false) == -1)
980 Con_DPrintf("LHNET_OpenSocket_Connectionless: ioctlsocket SIO_UDP_CONNRESET returned error: %s\n", LHNETPRIVATE_StrError());
981#endif
982 return lhnetsocket;
983 }
984 else
985 Con_Printf("LHNET_OpenSocket_Connectionless: bind returned error: %s\n", LHNETPRIVATE_StrError());
986 }
987#ifdef IPV6_V6ONLY
988 else
989 Con_Printf("LHNET_OpenSocket_Connectionless: setsockopt(IPV6_V6ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
990#endif
991 }
992 else
993 Con_Printf("LHNET_OpenSocket_Connectionless: ioctlsocket returned error: %s\n", LHNETPRIVATE_StrError());
994 closesocket(lhnetsocket->inetsocket);
995 }
996 else
997 Con_Printf("LHNET_OpenSocket_Connectionless: socket returned error: %s\n", LHNETPRIVATE_StrError());
998#ifdef WIN32
999 }
1000 else
1001 Con_Print("LHNET_OpenSocket_Connectionless: can't open a socket (WSAStartup failed during LHNET_Init)\n");
1002#endif
1003 break;
1004 default:
1005 break;
1006 }
1007 Z_Free(lhnetsocket);
1008 }
1009 return NULL;
1010}
1011
1013{
1014 if (lhnetsocket)
1015 {
1016 List_Delete(&lhnetsocket->list);
1017 // no special close code for loopback, just inet
1019 {
1020 closesocket(lhnetsocket->inetsocket);
1021 }
1022 Z_Free(lhnetsocket);
1023 }
1024}
1025
1027{
1028 if (sock)
1029 return &sock->address;
1030 else
1031 return NULL;
1032}
1033
1034int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, lhnetaddress_t *vaddress)
1035{
1036 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
1037 int value = 0;
1038 if (!lhnetsocket || !address || !content || maxcontentlength < 1)
1039 return -1;
1040 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
1041 {
1042 time_t currenttime;
1043 lhnetpacket_t *p, *pnext;
1044 // scan for any old packets to timeout while searching for a packet
1045 // that is waiting to be delivered to this socket
1046 currenttime = time(NULL);
1048 {
1049 if (p->timeout < currenttime)
1050 {
1051 // unlink and free
1052 List_Delete(&p->list);
1053 Z_Free(p);
1054 continue;
1055 }
1056#ifndef STANDALONETEST
1057 if (net_fakelag.value && (host.realtime - net_fakelag.value * (1.0 / 2000.0)) < p->sentdoubletime)
1058 continue;
1059#endif
1060 if (value == 0 && p->destinationport == lhnetsocket->address.port)
1061 {
1062 if (p->length <= maxcontentlength)
1063 {
1064 lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
1065 *address = *localaddress;
1066 address->port = p->sourceport;
1067 memcpy(content, p->data, p->length);
1068 value = p->length;
1069 }
1070 else
1071 value = -1;
1072 // unlink and free
1073 List_Delete(&p->list);
1074 Z_Free(p);
1075 }
1076 }
1077 }
1078 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
1079 {
1080 SOCKLEN_T inetaddresslength;
1082 inetaddresslength = sizeof(address->addr.in);
1083 value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength);
1084 if (value > 0)
1085 {
1087 address->port = ntohs(address->addr.in.sin_port);
1088 return value;
1089 }
1090 else if (value < 0)
1091 {
1092 int e = SOCKETERRNO;
1093 if (e == EWOULDBLOCK)
1094 return 0;
1095 switch (e)
1096 {
1097 case ECONNREFUSED:
1098 Con_Print("Connection refused\n");
1099 return 0;
1100 }
1101 Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
1102 }
1103 }
1104#ifndef NOSUPPORTIPV6
1105 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1106 {
1107 SOCKLEN_T inetaddresslength;
1109 inetaddresslength = sizeof(address->addr.in6);
1110 value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength);
1111 if (value > 0)
1112 {
1114 address->port = ntohs(address->addr.in6.sin6_port);
1115 return value;
1116 }
1117 else if (value == -1)
1118 {
1119 int e = SOCKETERRNO;
1120 if (e == EWOULDBLOCK)
1121 return 0;
1122 switch (e)
1123 {
1124 case ECONNREFUSED:
1125 Con_Print("Connection refused\n");
1126 return 0;
1127 }
1128 Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
1129 }
1130 }
1131#endif
1132 return value;
1133}
1134
1135int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *vaddress)
1136{
1137 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
1138 int value = -1;
1139 if (!lhnetsocket || !address || !content || contentlength < 1)
1140 return -1;
1141 if (lhnetsocket->address.addresstype != address->addresstype)
1142 return -1;
1143 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
1144 {
1145 lhnetpacket_t *p;
1146 p = (lhnetpacket_t *)Z_Malloc(sizeof(*p) + contentlength);
1147 p->data = (void *)(p + 1);
1148 memcpy(p->data, content, contentlength);
1149 p->length = contentlength;
1150 p->sourceport = lhnetsocket->address.port;
1151 p->destinationport = address->port;
1152 p->timeout = time(NULL) + 10;
1154
1155#ifndef STANDALONETEST
1157#endif
1158 value = contentlength;
1159 }
1160 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
1161 {
1162 value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, LHNET_SENDTO_FLAGS, (struct sockaddr *)&address->addr.in, sizeof(struct sockaddr_in));
1163 if (value == -1)
1164 {
1165 if (SOCKETERRNO == EWOULDBLOCK)
1166 return 0;
1167 Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
1168 }
1169 }
1170#ifndef NOSUPPORTIPV6
1171 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
1172 {
1173 value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, 0, (struct sockaddr *)&address->addr.in6, sizeof(struct sockaddr_in6));
1174 if (value == -1)
1175 {
1176 if (SOCKETERRNO == EWOULDBLOCK)
1177 return 0;
1178 Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
1179 }
1180 }
1181#endif
1182 return value;
1183}
1184
1185#ifdef STANDALONETEST
1186int main(int argc, char **argv)
1187{
1188#if 1
1189 char *buffer = "test", buffer2[1024];
1190 int blen = strlen(buffer);
1191 int b2len = 1024;
1192 lhnetsocket_t *sock1;
1193 lhnetsocket_t *sock2;
1194 lhnetaddress_t myaddy1;
1195 lhnetaddress_t myaddy2;
1196 lhnetaddress_t myaddy3;
1197 lhnetaddress_t localhostaddy1;
1198 lhnetaddress_t localhostaddy2;
1199 int test1;
1200 int test2;
1201
1202 printf("calling LHNET_Init\n");
1203 LHNET_Init();
1204
1205 printf("calling LHNET_FromPort twice to create two local addresses\n");
1208 LHNETADDRESS_FromString(&localhostaddy1, "127.0.0.1", 4000);
1209 LHNETADDRESS_FromString(&localhostaddy2, "127.0.0.1", 4001);
1210
1211 printf("calling LHNET_OpenSocket_Connectionless twice to create two local sockets\n");
1212 sock1 = LHNET_OpenSocket_Connectionless(&myaddy1);
1213 sock2 = LHNET_OpenSocket_Connectionless(&myaddy2);
1214
1215 printf("calling LHNET_Write to send a packet from the first socket to the second socket\n");
1216 test1 = LHNET_Write(sock1, buffer, blen, &localhostaddy2);
1217 printf("sleeping briefly\n");
1218#ifdef WIN32
1219 Sleep (100);
1220#else
1221 usleep (100000);
1222#endif
1223 printf("calling LHNET_Read on the second socket to read the packet sent from the first socket\n");
1224 test2 = LHNET_Read(sock2, buffer2, b2len - 1, &myaddy3);
1225 if (test2 > 0)
1226 Con_Printf("socket to socket test succeeded\n");
1227 else
1228 Con_Printf("socket to socket test failed\n");
1229
1230#ifdef WIN32
1231 printf("press any key to exit\n");
1232 getchar();
1233#endif
1234
1235 printf("calling LHNET_Shutdown\n");
1237 printf("exiting\n");
1238 return 0;
1239#else
1240 lhnetsocket_t *sock[16], *sendsock;
1241 int i;
1242 int numsockets;
1243 int count;
1244 int length;
1245 int port;
1246 time_t oldtime;
1247 time_t newtime;
1248 char *sendmessage;
1249 int sendmessagelength;
1250 lhnetaddress_t destaddress;
1251 lhnetaddress_t receiveaddress;
1252 lhnetaddress_t sockaddress[16];
1253 char buffer[1536], addressstring[128], addressstring2[128];
1254 if ((argc == 2 || argc == 5) && (port = atoi(argv[1])) >= 1 && port < 65535)
1255 {
1256 printf("calling LHNET_Init()\n");
1257 LHNET_Init();
1258
1259 numsockets = 0;
1260 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_LOOP, port);
1261 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET4, port);
1262 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET6, port+1);
1263
1264 sendsock = NULL;
1265 sendmessage = NULL;
1266 sendmessagelength = 0;
1267
1268 for (i = 0;i < numsockets;i++)
1269 {
1270 LHNETADDRESS_ToString(&sockaddress[i], addressstring, sizeof(addressstring), 1);
1271 printf("calling LHNET_OpenSocket_Connectionless(<%s>)\n", addressstring);
1272 if ((sock[i] = LHNET_OpenSocket_Connectionless(&sockaddress[i])))
1273 {
1274 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1275 printf("opened socket successfully (address \"%s\")\n", addressstring2);
1276 }
1277 else
1278 {
1279 printf("failed to open socket\n");
1280 if (i == 0)
1281 {
1283 return -1;
1284 }
1285 }
1286 }
1287 count = 0;
1288 if (argc == 5)
1289 {
1290 count = atoi(argv[2]);
1291 if (LHNETADDRESS_FromString(&destaddress, argv[3], -1))
1292 {
1293 sendmessage = argv[4];
1294 sendmessagelength = strlen(sendmessage);
1295 sendsock = NULL;
1296 for (i = 0;i < numsockets;i++)
1297 if (sock[i] && LHNETADDRESS_GetAddressType(&destaddress) == LHNETADDRESS_GetAddressType(&sockaddress[i]))
1298 sendsock = sock[i];
1299 if (sendsock == NULL)
1300 {
1301 printf("Could not find an open socket matching the addresstype (%i) of destination address, switching to listen only mode\n", LHNETADDRESS_GetAddressType(&destaddress));
1302 argc = 2;
1303 }
1304 }
1305 else
1306 {
1307 printf("LHNETADDRESS_FromString did not like the address \"%s\", switching to listen only mode\n", argv[3]);
1308 argc = 2;
1309 }
1310 }
1311 printf("started, now listening for \"exit\" on the opened sockets\n");
1312 oldtime = time(NULL);
1313 for(;;)
1314 {
1315#ifdef WIN32
1316 Sleep(1);
1317#else
1318 usleep(1);
1319#endif
1320 for (i = 0;i < numsockets;i++)
1321 {
1322 if (sock[i])
1323 {
1324 length = LHNET_Read(sock[i], buffer, sizeof(buffer), &receiveaddress);
1325 if (length < 0)
1326 printf("localsock read error: length < 0");
1327 else if (length > 0 && length < (int)sizeof(buffer))
1328 {
1329 buffer[length] = 0;
1330 LHNETADDRESS_ToString(&receiveaddress, addressstring, sizeof(addressstring), 1);
1331 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1332 printf("received message \"%s\" from \"%s\" on socket \"%s\"\n", buffer, addressstring, addressstring2);
1333 if (!strcmp(buffer, "exit"))
1334 break;
1335 }
1336 }
1337 }
1338 if (i < numsockets)
1339 break;
1340 if (argc == 5 && count > 0)
1341 {
1342 newtime = time(NULL);
1343 if (newtime != oldtime)
1344 {
1345 LHNETADDRESS_ToString(&destaddress, addressstring, sizeof(addressstring), 1);
1346 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sendsock), addressstring2, sizeof(addressstring2), 1);
1347 printf("calling LHNET_Write(<%s>, \"%s\", %i, <%s>)\n", addressstring2, sendmessage, sendmessagelength, addressstring);
1348 length = LHNET_Write(sendsock, sendmessage, sendmessagelength, &destaddress);
1349 if (length == sendmessagelength)
1350 printf("sent successfully\n");
1351 else
1352 printf("LH_Write failed, returned %i (length of message was %i)\n", length, strlen(argv[4]));
1353 oldtime = newtime;
1354 count--;
1355 if (count <= 0)
1356 printf("Done sending, still listening for \"exit\"\n");
1357 }
1358 }
1359 }
1360 for (i = 0;i < numsockets;i++)
1361 {
1362 if (sock[i])
1363 {
1364 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1365 printf("calling LHNET_CloseSocket(<%s>)\n", addressstring2);
1366 LHNET_CloseSocket(sock[i]);
1367 }
1368 }
1369 printf("calling LHNET_Shutdown()\n");
1371 return 0;
1372 }
1373 printf("Testing code for lhnet.c\nusage: lhnettest <localportnumber> [<sendnumberoftimes> <sendaddress:port> <sendmessage>]\n");
1374 return -1;
1375#endif
1376}
1377#endif
1378
static void List_Create(llist_t *list)
Definition com_list.h:220
static void List_Add_Tail(llist_t *node, llist_t *head)
Definition com_list.h:249
static void List_Delete(llist_t *node)
Definition com_list.h:274
#define List_For_Each_Entry_Safe(pos, n, head, type, member)
Definition com_list.h:173
#define List_For_Each_Entry(pos, head, type, member)
Definition com_list.h:121
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
Definition common.c:997
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
Definition console.c:1544
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
#define CON_ERROR
Definition console.h:102
float time
static int(ZEXPORT *qz_inflate)(z_stream *strm
GLsizei const GLfloat * value
Definition glquake.h:740
GLsizei const GLchar ** string
Definition glquake.h:728
GLuint buffer
Definition glquake.h:630
GLenum GLuint GLenum GLsizei length
Definition glquake.h:657
GLenum GLenum GLsizei count
Definition glquake.h:656
const GLchar * name
Definition glquake.h:601
host_static_t host
Definition host.c:41
int LHNETADDRESS_SetPort(lhnetaddress_t *vaddress, int port)
Definition lhnet.c:642
int LHNETADDRESS_FromPort(lhnetaddress_t *vaddress, lhnetaddresstype_t addresstype, int port)
Definition lhnet.c:125
int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stringbuffersize, int includeport)
Returns the number of bytes written to *string excluding the \0 terminator.
Definition lhnet.c:540
int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *vaddress)
Definition lhnet.c:1135
const char * LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress, char *ifname, size_t ifnamelength)
Definition lhnet.c:608
#define MAX_NAMECACHE
Definition lhnet.c:115
#define SOCKETERRNO
Definition lhnet.c:85
void LHNET_CloseSocket(lhnetsocket_t *lhnetsocket)
Definition lhnet.c:1012
static int namecacheposition
Definition lhnet.c:123
void LHNET_Shutdown(void)
Definition lhnet.c:751
void LHNET_Init(void)
Definition lhnet.c:725
int LHNET_DefaultDSCP(int dscp)
Definition lhnet.c:739
lhnetsocket_t * LHNET_OpenSocket_Connectionless(lhnetaddress_t *address)
Definition lhnet.c:832
#define LHNET_SENDTO_FLAGS
Definition lhnet.c:95
int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
Definition lhnet.c:204
#define SOCKLEN_T
Definition lhnet.c:87
static lhnetpacket_t lhnet_packetlist
Definition lhnet.c:718
int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, lhnetaddress_t *vaddress)
Definition lhnet.c:1034
static int lhnet_default_dscp
Definition lhnet.c:719
lhnetaddress_t * LHNET_AddressFromSocket(lhnetsocket_t *sock)
Definition lhnet.c:1026
lhnetsocket_t lhnet_socketlist
Definition lhnet.c:717
static int LHNETADDRESS_Resolve(lhnetaddressnative_t *address, const char *name, int port)
Definition lhnet.c:163
static int lhnet_active
Definition lhnet.c:716
static struct namecache_s namecache[MAX_NAMECACHE]
#define ioctlsocket
Definition lhnet.c:83
int LHNETADDRESS_GetPort(const lhnetaddress_t *address)
Definition lhnet.c:635
#define LHNET_RECVFROM_FLAGS
Definition lhnet.c:94
int LHNETADDRESS_Compare(const lhnetaddress_t *vaddress1, const lhnetaddress_t *vaddress2)
Definition lhnet.c:665
#define closesocket
Definition lhnet.c:84
static const char * LHNETPRIVATE_StrError(void)
Definition lhnet.c:774
lhnetaddresstype_t
Definition lhnet.h:11
@ LHNETADDRESSTYPE_INET6
Definition lhnet.h:15
@ LHNETADDRESSTYPE_NONE
Definition lhnet.h:12
@ LHNETADDRESSTYPE_INET4
Definition lhnet.h:14
@ LHNETADDRESSTYPE_LOOP
Definition lhnet.h:13
static lhnetaddresstype_t LHNETADDRESS_GetAddressType(const lhnetaddress_t *address)
Definition lhnet.h:31
float strlen(string s)
string argv(float n)
cvar_t net_fakelag
Definition netconn.c:91
int i
#define NULL
Definition qtypes.h:12
ret a
void main(void)\n"
float value
Definition cvar.h:74
double realtime
the accumulated mainloop time since application started (with filtering), without any slowmo or clamp...
Definition host.h:46
lhnetaddresstype_t addresstype
Definition lhnet.h:21
struct sockaddr sock
Definition lhnet.c:104
union lhnetaddressnative_t::@15 addr
struct sockaddr_in6 in6
Definition lhnet.c:107
struct sockaddr_in in
Definition lhnet.c:105
lhnetaddresstype_t addresstype
Definition lhnet.c:100
int destinationport
Definition lhnet.c:707
void * data
Definition lhnet.c:704
int sourceport
Definition lhnet.c:706
double sentdoubletime
Definition lhnet.c:710
time_t timeout
Definition lhnet.c:708
llist_t list
Definition lhnet.c:712
llist_t list
Definition lhnet.h:47
lhnetaddress_t address
Definition lhnet.h:45
int inetsocket
Definition lhnet.h:46
char name[64]
Definition lhnet.c:120
double expirationtime
Definition lhnet.c:119
lhnetaddressnative_t address
Definition lhnet.c:118
#define Z_Malloc(size)
Definition zone.h:161
#define Z_Free(data)
Definition zone.h:164