2 // Written by Forest Hale 2003-06-15 and placed into public domain.
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <sys/ioctl.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
27 #include <proto/socket.h>
30 // for Z_Malloc/Z_Free in quake
31 #ifndef STANDALONETEST
36 #define Con_Print printf
37 #define Con_Printf printf
38 #define Z_Malloc malloc
45 #define EWOULDBLOCK WSAEWOULDBLOCK
46 #define ECONNREFUSED WSAECONNREFUSED
48 #define SOCKETERRNO WSAGetLastError()
50 #define IOC_VENDOR 0x18000000
51 #define _WSAIOW(x,y) (IOC_IN|(x)|(y))
52 #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
55 #elif defined(__MORPHOS__)
56 #define ioctlsocket IoctlSocket
57 #define closesocket CloseSocket
58 #define SOCKETERRNO Errno()
62 #define ioctlsocket ioctl
63 #define closesocket close
64 #define SOCKETERRNO errno
66 #define SOCKLEN_T socklen_t
69 typedef struct lhnetaddressnative_s
71 lhnetaddresstype_t addresstype;
76 struct sockaddr_in in;
77 struct sockaddr_in6 in6;
83 // to make LHNETADDRESS_FromString resolve repeated hostnames faster, cache them
84 #define MAX_NAMECACHE 64
85 static struct namecache_s
87 lhnetaddressnative_t address;
88 double expirationtime;
91 namecache[MAX_NAMECACHE];
92 static int namecacheposition = 0;
94 int LHNETADDRESS_FromPort(lhnetaddress_t *vaddress, lhnetaddresstype_t addresstype, int port)
96 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
103 case LHNETADDRESSTYPE_LOOP:
104 // local:port (loopback)
105 memset(address, 0, sizeof(*address));
106 address->addresstype = LHNETADDRESSTYPE_LOOP;
107 address->port = port;
109 case LHNETADDRESSTYPE_INET4:
110 // 0.0.0.0:port (INADDR_ANY, binds to all interfaces)
111 memset(address, 0, sizeof(*address));
112 address->addresstype = LHNETADDRESSTYPE_INET4;
113 address->port = port;
114 address->addr.in.sin_family = AF_INET;
115 address->addr.in.sin_port = htons((unsigned short)port);
117 case LHNETADDRESSTYPE_INET6:
118 // [0:0:0:0:0:0:0:0]:port (IN6ADDR_ANY, binds to all interfaces)
119 memset(address, 0, sizeof(*address));
120 address->addresstype = LHNETADDRESSTYPE_INET6;
121 address->port = port;
122 address->addr.in6.sin6_family = AF_INET6;
123 address->addr.in6.sin6_port = htons((unsigned short)port);
129 int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
131 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
132 int i, port, namelen, d1, d2, d3, d4;
133 struct hostent *hostentry;
137 #ifdef STANDALONETEST
140 if (!address || !string || !*string)
142 memset(address, 0, sizeof(*address));
143 address->addresstype = LHNETADDRESSTYPE_NONE;
145 colon = strrchr(string, ':');
147 port = atoi(colon + 1);
149 colon = string + strlen(string);
152 namelen = colon - string;
155 if (string[0] == '[' && namelen > 0 && string[namelen-1] == ']') // ipv6
160 memcpy(name, string, namelen);
163 if (!strcmp(name, "local"))
165 address->addresstype = LHNETADDRESSTYPE_LOOP;
166 address->port = port;
169 // try to parse as dotted decimal ipv4 address first
170 // note this supports partial ip addresses
171 d1 = d2 = d3 = d4 = 0;
173 #define sscanf sscanf_s
175 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)
177 // parsed a valid ipv4 address
178 address->addresstype = LHNETADDRESSTYPE_INET4;
179 address->port = port;
180 address->addr.in.sin_family = AF_INET;
181 address->addr.in.sin_port = htons((unsigned short)port);
182 a = (unsigned char *)&address->addr.in.sin_addr;
187 #ifdef STANDALONETEST
188 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
189 printf("manual parsing of ipv4 dotted decimal address \"%s\" successful: %s\n", string, string2);
193 for (i = 0;i < MAX_NAMECACHE;i++)
194 if (!strcmp(namecache[i].name, name))
196 #ifdef STANDALONETEST
197 if (i < MAX_NAMECACHE)
199 if (i < MAX_NAMECACHE && realtime < namecache[i].expirationtime)
202 *address = namecache[i].address;
203 address->port = port;
204 if (address->addresstype == LHNETADDRESSTYPE_INET6)
206 address->addr.in6.sin6_port = htons((unsigned short)port);
209 else if (address->addresstype == LHNETADDRESSTYPE_INET4)
211 address->addr.in.sin_port = htons((unsigned short)port);
216 // try gethostbyname (handles dns and other ip formats)
217 hostentry = gethostbyname(name);
220 if (hostentry->h_addrtype == AF_INET6)
223 address->addresstype = LHNETADDRESSTYPE_INET6;
224 address->port = port;
225 address->addr.in6.sin6_family = hostentry->h_addrtype;
226 address->addr.in6.sin6_port = htons((unsigned short)port);
227 memcpy(&address->addr.in6.sin6_addr, hostentry->h_addr_list[0], sizeof(address->addr.in6.sin6_addr));
228 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
229 namecache[namecacheposition].name[i] = name[i];
230 namecache[namecacheposition].name[i] = 0;
231 #ifndef STANDALONETEST
232 namecache[namecacheposition].expirationtime = realtime + 12 * 3600; // 12 hours
234 namecache[namecacheposition].address = *address;
235 namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
236 #ifdef STANDALONETEST
237 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
238 printf("gethostbyname(\"%s\") returned ipv6 address %s\n", string, string2);
242 else if (hostentry->h_addrtype == AF_INET)
245 address->addresstype = LHNETADDRESSTYPE_INET4;
246 address->port = port;
247 address->addr.in.sin_family = hostentry->h_addrtype;
248 address->addr.in.sin_port = htons((unsigned short)port);
249 memcpy(&address->addr.in.sin_addr, hostentry->h_addr_list[0], sizeof(address->addr.in.sin_addr));
250 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
251 namecache[namecacheposition].name[i] = name[i];
252 namecache[namecacheposition].name[i] = 0;
253 #ifndef STANDALONETEST
254 namecache[namecacheposition].expirationtime = realtime + 12 * 3600; // 12 hours
256 namecache[namecacheposition].address = *address;
257 namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
258 #ifdef STANDALONETEST
259 LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
260 printf("gethostbyname(\"%s\") returned ipv4 address %s\n", string, string2);
265 #ifdef STANDALONETEST
266 printf("gethostbyname failed on address \"%s\"\n", name);
268 for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
269 namecache[namecacheposition].name[i] = name[i];
270 namecache[namecacheposition].name[i] = 0;
271 #ifndef STANDALONETEST
272 namecache[namecacheposition].expirationtime = realtime + 12 * 3600; // 12 hours
274 namecache[namecacheposition].address.addresstype = LHNETADDRESSTYPE_NONE;
275 namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
279 int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stringbuffersize, int includeport)
281 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
282 const unsigned char *a;
284 if (!address || !string || stringbuffersize < 1)
286 switch(address->addresstype)
290 case LHNETADDRESSTYPE_LOOP:
293 if (stringbuffersize >= 12)
295 dpsnprintf(string, stringbuffersize, "local:%d", address->port);
301 if (stringbuffersize >= 6)
303 memcpy(string, "local", 6);
308 case LHNETADDRESSTYPE_INET4:
309 a = (const unsigned char *)(&address->addr.in.sin_addr);
312 if (stringbuffersize >= 22)
314 dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d:%d", a[0], a[1], a[2], a[3], address->port);
320 if (stringbuffersize >= 16)
322 dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
327 case LHNETADDRESSTYPE_INET6:
328 a = (const unsigned char *)(&address->addr.in6.sin6_addr);
331 if (stringbuffersize >= 88)
333 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);
339 if (stringbuffersize >= 80)
341 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]);
350 int LHNETADDRESS_GetAddressType(const lhnetaddress_t *address)
353 return address->addresstype;
355 return LHNETADDRESSTYPE_NONE;
358 int LHNETADDRESS_GetPort(const lhnetaddress_t *address)
362 return address->port;
365 int LHNETADDRESS_SetPort(lhnetaddress_t *vaddress, int port)
367 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
370 address->port = port;
371 switch(address->addresstype)
373 case LHNETADDRESSTYPE_LOOP:
375 case LHNETADDRESSTYPE_INET4:
376 address->addr.in.sin_port = htons((unsigned short)port);
378 case LHNETADDRESSTYPE_INET6:
379 address->addr.in6.sin6_port = htons((unsigned short)port);
386 int LHNETADDRESS_Compare(const lhnetaddress_t *vaddress1, const lhnetaddress_t *vaddress2)
388 lhnetaddressnative_t *address1 = (lhnetaddressnative_t *)vaddress1;
389 lhnetaddressnative_t *address2 = (lhnetaddressnative_t *)vaddress2;
390 if (!address1 || !address2)
392 if (address1->addresstype != address2->addresstype)
394 switch(address1->addresstype)
396 case LHNETADDRESSTYPE_LOOP:
397 if (address1->port != address2->port)
400 case LHNETADDRESSTYPE_INET4:
401 if (address1->addr.in.sin_family != address2->addr.in.sin_family)
403 if (memcmp(&address1->addr.in.sin_addr, &address2->addr.in.sin_addr, sizeof(address1->addr.in.sin_addr)))
405 if (address1->port != address2->port)
408 case LHNETADDRESSTYPE_INET6:
409 if (address1->addr.in6.sin6_family != address2->addr.in6.sin6_family)
411 if (memcmp(&address1->addr.in6.sin6_addr, &address2->addr.in6.sin6_addr, sizeof(address1->addr.in6.sin6_addr)))
413 if (address1->port != address2->port)
421 typedef struct lhnetpacket_s
428 #ifndef STANDALONETEST
429 double sentdoubletime;
431 struct lhnetpacket_s *next, *prev;
435 static int lhnet_active;
436 static lhnetsocket_t lhnet_socketlist;
437 static lhnetpacket_t lhnet_packetlist;
439 static int lhnet_didWSAStartup = 0;
440 static WSADATA lhnet_winsockdata;
443 void LHNET_Init(void)
447 lhnet_socketlist.next = lhnet_socketlist.prev = &lhnet_socketlist;
448 lhnet_packetlist.next = lhnet_packetlist.prev = &lhnet_packetlist;
451 lhnet_didWSAStartup = !WSAStartup(MAKEWORD(1, 1), &lhnet_winsockdata);
452 if (!lhnet_didWSAStartup)
453 Con_Print("LHNET_Init: WSAStartup failed, networking disabled\n");
457 void LHNET_Shutdown(void)
462 while (lhnet_socketlist.next != &lhnet_socketlist)
463 LHNET_CloseSocket(lhnet_socketlist.next);
464 while (lhnet_packetlist.next != &lhnet_packetlist)
466 p = lhnet_packetlist.next;
467 p->prev->next = p->next;
468 p->next->prev = p->prev;
472 if (lhnet_didWSAStartup)
474 lhnet_didWSAStartup = 0;
481 static const char *LHNETPRIVATE_StrError(void)
484 int i = WSAGetLastError();
487 case WSAEINTR: return "WSAEINTR";
488 case WSAEBADF: return "WSAEBADF";
489 case WSAEACCES: return "WSAEACCES";
490 case WSAEFAULT: return "WSAEFAULT";
491 case WSAEINVAL: return "WSAEINVAL";
492 case WSAEMFILE: return "WSAEMFILE";
493 case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
494 case WSAEINPROGRESS: return "WSAEINPROGRESS";
495 case WSAEALREADY: return "WSAEALREADY";
496 case WSAENOTSOCK: return "WSAENOTSOCK";
497 case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
498 case WSAEMSGSIZE: return "WSAEMSGSIZE";
499 case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
500 case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
501 case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
502 case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
503 case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
504 case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
505 case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
506 case WSAEADDRINUSE: return "WSAEADDRINUSE";
507 case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
508 case WSAENETDOWN: return "WSAENETDOWN";
509 case WSAENETUNREACH: return "WSAENETUNREACH";
510 case WSAENETRESET: return "WSAENETRESET";
511 case WSAECONNABORTED: return "WSAECONNABORTED";
512 case WSAECONNRESET: return "WSAECONNRESET";
513 case WSAENOBUFS: return "WSAENOBUFS";
514 case WSAEISCONN: return "WSAEISCONN";
515 case WSAENOTCONN: return "WSAENOTCONN";
516 case WSAESHUTDOWN: return "WSAESHUTDOWN";
517 case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
518 case WSAETIMEDOUT: return "WSAETIMEDOUT";
519 case WSAECONNREFUSED: return "WSAECONNREFUSED";
520 case WSAELOOP: return "WSAELOOP";
521 case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
522 case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
523 case WSAEHOSTUNREACH: return "WSAEHOSTUNREACH";
524 case WSAENOTEMPTY: return "WSAENOTEMPTY";
525 case WSAEPROCLIM: return "WSAEPROCLIM";
526 case WSAEUSERS: return "WSAEUSERS";
527 case WSAEDQUOT: return "WSAEDQUOT";
528 case WSAESTALE: return "WSAESTALE";
529 case WSAEREMOTE: return "WSAEREMOTE";
530 case WSAEDISCON: return "WSAEDISCON";
531 case 0: return "no error";
532 default: return "unknown WSAE error";
535 return strerror(errno);
539 void LHNET_SleepUntilPacket_Microseconds(int microseconds)
547 for (s = lhnet_socketlist.next;s != &lhnet_socketlist;s = s->next)
549 if (s->address.addresstype == LHNETADDRESSTYPE_INET4 || s->address.addresstype == LHNETADDRESSTYPE_INET6)
551 if (lastfd < s->inetsocket)
552 lastfd = s->inetsocket;
553 FD_SET((unsigned int)s->inetsocket, &fdreadset);
556 tv.tv_sec = microseconds / 1000000;
557 tv.tv_usec = microseconds % 1000000;
558 select(lastfd + 1, &fdreadset, NULL, NULL, &tv);
561 lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address)
563 lhnetsocket_t *lhnetsocket, *s;
566 lhnetsocket = (lhnetsocket_t *)Z_Malloc(sizeof(*lhnetsocket));
569 memset(lhnetsocket, 0, sizeof(*lhnetsocket));
570 lhnetsocket->address = *address;
571 switch(lhnetsocket->address.addresstype)
573 case LHNETADDRESSTYPE_LOOP:
574 if (lhnetsocket->address.port == 0)
576 // allocate a port dynamically
577 // this search will always terminate because there is never
578 // an allocated socket with port 0, so if the number wraps it
579 // will find the port is unused, and then refuse to use port
580 // 0, causing an intentional failure condition
581 lhnetsocket->address.port = 1024;
584 for (s = lhnet_socketlist.next;s != &lhnet_socketlist;s = s->next)
585 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
587 if (s == &lhnet_socketlist)
589 lhnetsocket->address.port++;
592 // check if the port is available
593 for (s = lhnet_socketlist.next;s != &lhnet_socketlist;s = s->next)
594 if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
596 if (s == &lhnet_socketlist && lhnetsocket->address.port != 0)
598 lhnetsocket->next = &lhnet_socketlist;
599 lhnetsocket->prev = lhnetsocket->next->prev;
600 lhnetsocket->next->prev = lhnetsocket;
601 lhnetsocket->prev->next = lhnetsocket;
605 case LHNETADDRESSTYPE_INET4:
606 case LHNETADDRESSTYPE_INET6:
608 if (lhnet_didWSAStartup)
611 if ((lhnetsocket->inetsocket = socket(address->addresstype == LHNETADDRESSTYPE_INET6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
619 if (ioctlsocket(lhnetsocket->inetsocket, FIONBIO, &_true) != -1)
621 lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
624 if (address->addresstype == LHNETADDRESSTYPE_INET6)
626 namelen = sizeof(localaddress->addr.in6);
627 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
628 if (bindresult != -1)
629 getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen);
633 namelen = sizeof(localaddress->addr.in);
634 bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
635 if (bindresult != -1)
636 getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen);
638 if (bindresult != -1)
641 // enable broadcast on this socket
642 setsockopt(lhnetsocket->inetsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i));
643 lhnetsocket->next = &lhnet_socketlist;
644 lhnetsocket->prev = lhnetsocket->next->prev;
645 lhnetsocket->next->prev = lhnetsocket;
646 lhnetsocket->prev->next = lhnetsocket;
648 if (ioctlsocket(lhnetsocket->inetsocket, SIO_UDP_CONNRESET, &_false) == -1)
649 Con_DPrintf("LHNET_OpenSocket_Connectionless: ioctlsocket SIO_UDP_CONNRESET returned error: %s\n", LHNETPRIVATE_StrError());
654 Con_Printf("LHNET_OpenSocket_Connectionless: bind returned error: %s\n", LHNETPRIVATE_StrError());
657 Con_Printf("LHNET_OpenSocket_Connectionless: ioctlsocket returned error: %s\n", LHNETPRIVATE_StrError());
658 closesocket(lhnetsocket->inetsocket);
661 Con_Printf("LHNET_OpenSocket_Connectionless: socket returned error: %s\n", LHNETPRIVATE_StrError());
665 Con_Print("LHNET_OpenSocket_Connectionless: can't open a socket (WSAStartup failed during LHNET_Init)\n");
676 void LHNET_CloseSocket(lhnetsocket_t *lhnetsocket)
680 // unlink from socket list
681 if (lhnetsocket->next == NULL)
683 lhnetsocket->next->prev = lhnetsocket->prev;
684 lhnetsocket->prev->next = lhnetsocket->next;
685 lhnetsocket->next = NULL;
686 lhnetsocket->prev = NULL;
688 // no special close code for loopback, just inet
689 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4 || lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
691 closesocket(lhnetsocket->inetsocket);
697 lhnetaddress_t *LHNET_AddressFromSocket(lhnetsocket_t *sock)
700 return &sock->address;
705 int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, lhnetaddress_t *vaddress)
707 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
709 if (!lhnetsocket || !address || !content || maxcontentlength < 1)
711 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
714 lhnetpacket_t *p, *pnext;
715 // scan for any old packets to timeout while searching for a packet
716 // that is waiting to be delivered to this socket
717 currenttime = time(NULL);
718 for (p = lhnet_packetlist.next;p != &lhnet_packetlist;p = pnext)
721 if (p->timeout < currenttime)
724 p->next->prev = p->prev;
725 p->prev->next = p->next;
729 #ifndef STANDALONETEST
730 if (cl_netlocalping.value && (realtime - cl_netlocalping.value * (1.0 / 2000.0)) < p->sentdoubletime)
733 if (value == 0 && p->destinationport == lhnetsocket->address.port)
735 if (p->length <= maxcontentlength)
737 lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
738 *address = *localaddress;
739 address->port = p->sourceport;
740 memcpy(content, p->data, p->length);
746 p->next->prev = p->prev;
747 p->prev->next = p->next;
752 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
754 unsigned int inetaddresslength;
755 address->addresstype = LHNETADDRESSTYPE_NONE;
756 inetaddresslength = sizeof(address->addr.in);
757 value = recvfrom(lhnetsocket->inetsocket, content, maxcontentlength, 0, &address->addr.sock, &inetaddresslength);
760 address->addresstype = LHNETADDRESSTYPE_INET4;
761 address->port = ntohs(address->addr.in.sin_port);
764 else if (value == -1)
767 if (e == EWOULDBLOCK)
772 Con_Print("Connection refused\n");
775 Con_Printf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
778 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
780 unsigned int inetaddresslength;
781 address->addresstype = LHNETADDRESSTYPE_NONE;
782 inetaddresslength = sizeof(address->addr.in6);
783 value = recvfrom(lhnetsocket->inetsocket, content, maxcontentlength, 0, &address->addr.sock, &inetaddresslength);
786 address->addresstype = LHNETADDRESSTYPE_INET6;
787 address->port = ntohs(address->addr.in6.sin6_port);
790 else if (value == -1)
793 if (e == EWOULDBLOCK)
798 Con_Print("Connection refused\n");
801 Con_Printf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
807 int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *vaddress)
809 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
811 if (!lhnetsocket || !address || !content || contentlength < 1)
813 if (lhnetsocket->address.addresstype != address->addresstype)
815 if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
818 p = (lhnetpacket_t *)Z_Malloc(sizeof(*p) + contentlength);
819 p->data = (void *)(p + 1);
820 memcpy(p->data, content, contentlength);
821 p->length = contentlength;
822 p->sourceport = lhnetsocket->address.port;
823 p->destinationport = address->port;
824 p->timeout = time(NULL) + 10;
825 p->next = &lhnet_packetlist;
826 p->prev = p->next->prev;
829 #ifndef STANDALONETEST
830 p->sentdoubletime = realtime;
832 value = contentlength;
834 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
836 value = sendto(lhnetsocket->inetsocket, content, contentlength, 0, (struct sockaddr *)&address->addr.in, sizeof(struct sockaddr_in));
839 if (SOCKETERRNO == EWOULDBLOCK)
841 Con_Printf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
844 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
846 value = sendto(lhnetsocket->inetsocket, content, contentlength, 0, (struct sockaddr *)&address->addr.in6, sizeof(struct sockaddr_in6));
849 if (SOCKETERRNO == EWOULDBLOCK)
851 Con_Printf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
857 #ifdef STANDALONETEST
858 int main(int argc, char **argv)
861 char *buffer = "test", buffer2[1024];
862 int blen = strlen(buffer);
864 lhnetsocket_t *sock1;
865 lhnetsocket_t *sock2;
866 lhnetaddress_t myaddy1;
867 lhnetaddress_t myaddy2;
868 lhnetaddress_t myaddy3;
869 lhnetaddress_t localhostaddy1;
870 lhnetaddress_t localhostaddy2;
874 printf("calling LHNET_Init\n");
877 printf("calling LHNET_FromPort twice to create two local addresses\n");
878 LHNETADDRESS_FromPort(&myaddy1, LHNETADDRESSTYPE_INET4, 4000);
879 LHNETADDRESS_FromPort(&myaddy2, LHNETADDRESSTYPE_INET4, 4001);
880 LHNETADDRESS_FromString(&localhostaddy1, "127.0.0.1", 4000);
881 LHNETADDRESS_FromString(&localhostaddy2, "127.0.0.1", 4001);
883 printf("calling LHNET_OpenSocket_Connectionless twice to create two local sockets\n");
884 sock1 = LHNET_OpenSocket_Connectionless(&myaddy1);
885 sock2 = LHNET_OpenSocket_Connectionless(&myaddy2);
887 printf("calling LHNET_Write to send a packet from the first socket to the second socket\n");
888 test1 = LHNET_Write(sock1, buffer, blen, &localhostaddy2);
889 printf("sleeping briefly\n");
895 printf("calling LHNET_Read on the second socket to read the packet sent from the first socket\n");
896 test2 = LHNET_Read(sock2, buffer2, b2len - 1, &myaddy3);
898 Con_Printf("socket to socket test succeeded\n");
900 Con_Printf("socket to socket test failed\n");
903 printf("press any key to exit\n");
907 printf("calling LHNET_Shutdown\n");
912 lhnetsocket_t *sock[16], *sendsock;
921 int sendmessagelength;
922 lhnetaddress_t destaddress;
923 lhnetaddress_t receiveaddress;
924 lhnetaddress_t sockaddress[16];
925 char buffer[1536], addressstring[128], addressstring2[128];
926 if ((argc == 2 || argc == 5) && (port = atoi(argv[1])) >= 1 && port < 65535)
928 printf("calling LHNET_Init()\n");
932 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_LOOP, port);
933 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET4, port);
934 LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET6, port+1);
938 sendmessagelength = 0;
940 for (i = 0;i < numsockets;i++)
942 LHNETADDRESS_ToString(&sockaddress[i], addressstring, sizeof(addressstring), 1);
943 printf("calling LHNET_OpenSocket_Connectionless(<%s>)\n", addressstring);
944 if ((sock[i] = LHNET_OpenSocket_Connectionless(&sockaddress[i])))
946 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
947 printf("opened socket successfully (address \"%s\")\n", addressstring2);
951 printf("failed to open socket\n");
962 count = atoi(argv[2]);
963 if (LHNETADDRESS_FromString(&destaddress, argv[3], -1))
965 sendmessage = argv[4];
966 sendmessagelength = strlen(sendmessage);
968 for (i = 0;i < numsockets;i++)
969 if (sock[i] && LHNETADDRESS_GetAddressType(&destaddress) == LHNETADDRESS_GetAddressType(&sockaddress[i]))
971 if (sendsock == NULL)
973 printf("Could not find an open socket matching the addresstype (%i) of destination address, switching to listen only mode\n", LHNETADDRESS_GetAddressType(&destaddress));
979 printf("LHNETADDRESS_FromString did not like the address \"%s\", switching to listen only mode\n", argv[3]);
983 printf("started, now listening for \"exit\" on the opened sockets\n");
984 oldtime = time(NULL);
992 for (i = 0;i < numsockets;i++)
996 length = LHNET_Read(sock[i], buffer, sizeof(buffer), &receiveaddress);
998 printf("localsock read error: length < 0");
999 else if (length > 0 && length < (int)sizeof(buffer))
1002 LHNETADDRESS_ToString(&receiveaddress, addressstring, sizeof(addressstring), 1);
1003 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1004 printf("received message \"%s\" from \"%s\" on socket \"%s\"\n", buffer, addressstring, addressstring2);
1005 if (!strcmp(buffer, "exit"))
1012 if (argc == 5 && count > 0)
1014 newtime = time(NULL);
1015 if (newtime != oldtime)
1017 LHNETADDRESS_ToString(&destaddress, addressstring, sizeof(addressstring), 1);
1018 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sendsock), addressstring2, sizeof(addressstring2), 1);
1019 printf("calling LHNET_Write(<%s>, \"%s\", %i, <%s>)\n", addressstring2, sendmessage, sendmessagelength, addressstring);
1020 length = LHNET_Write(sendsock, sendmessage, sendmessagelength, &destaddress);
1021 if (length == sendmessagelength)
1022 printf("sent successfully\n");
1024 printf("LH_Write failed, returned %i (length of message was %i)\n", length, strlen(argv[4]));
1028 printf("Done sending, still listening for \"exit\"\n");
1032 for (i = 0;i < numsockets;i++)
1036 LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
1037 printf("calling LHNET_CloseSocket(<%s>)\n", addressstring2);
1038 LHNET_CloseSocket(sock[i]);
1041 printf("calling LHNET_Shutdown()\n");
1045 printf("Testing code for lhnet.c\nusage: lhnettest <localportnumber> [<sendnumberoftimes> <sendaddress:port> <sendmessage>]\n");