6# pragma comment(lib, "ws2_32.lib")
10# define _WIN32_WINNT 0x0501
14# define FD_SETSIZE 1024
33#include <sys/socket.h>
37#include <netinet/in.h>
45#include <proto/socket.h>
54#define Con_Print printf
55#define Con_Printf printf
56#define Z_Malloc malloc
66#define EWOULDBLOCK WSAEWOULDBLOCK
67#define ECONNREFUSED WSAECONNREFUSED
69#define SOCKETERRNO WSAGetLastError()
71#define IOC_VENDOR 0x18000000
72#define _WSAIOW(x,y) (IOC_IN|(x)|(y))
73#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
76#elif defined(__MORPHOS__)
77#define ioctlsocket IoctlSocket
78#define closesocket CloseSocket
79#define SOCKETERRNO Errno()
83#define ioctlsocket ioctl
84#define closesocket close
85#define SOCKETERRNO errno
87#define SOCKLEN_T socklen_t
91#define LHNET_RECVFROM_FLAGS MSG_DONTWAIT
92#define LHNET_SENDTO_FLAGS 0
94#define LHNET_RECVFROM_FLAGS 0
95#define LHNET_SENDTO_FLAGS 0
98typedef struct lhnetaddressnative_s
104 struct sockaddr sock;
105 struct sockaddr_in in;
107 struct sockaddr_in6 in6;
115#define MAX_NAMECACHE 64
136 memset(address, 0,
sizeof(*address));
138 address->
port = port;
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);
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);
166 struct addrinfo hints;
167 struct addrinfo* addrinf;
170 dpsnprintf (port_buff,
sizeof (port_buff),
"%d", port);
171 port_buff[
sizeof (port_buff) - 1] =
'\0';
173 memset(&hints, 0,
sizeof (hints));
174 hints.ai_family = AF_UNSPEC;
175 hints.ai_socktype = SOCK_DGRAM;
178 err = getaddrinfo(
name, port_buff, &hints, &addrinf);
179 if (err != 0 || addrinf ==
NULL)
181 if (addrinf->ai_addr->sa_family != AF_INET6 && addrinf->ai_addr->sa_family != AF_INET)
183 freeaddrinfo (addrinf);
188 if (addrinf->ai_addr->sa_family == AF_INET6)
191 memcpy(&address->
addr.
in6, addrinf->ai_addr,
sizeof(address->
addr.
in6));
196 memcpy(&address->
addr.
in, addrinf->ai_addr,
sizeof(address->
addr.
in));
198 address->
port = port;
200 freeaddrinfo (addrinf);
207 int i, port, d1, d2, d3, d4, resolved;
214 const char* addr_start;
215 const char* addr_end =
NULL;
216 const char* port_name =
NULL;
217 int addr_family = AF_UNSPEC;
219 if (!address || !
string || !*
string)
221 memset(address, 0,
sizeof(*address));
226 if (
string[0] ==
'[')
228 const char* end_bracket = strchr(
string,
']');
230 if (end_bracket ==
NULL)
233 if (end_bracket[1] ==
':')
234 port_name = end_bracket + 2;
235 else if (end_bracket[1] !=
'\0')
238 addr_family = AF_INET6;
239 addr_start = &
string[1];
240 addr_end = end_bracket;
244 const char* first_colon;
250 first_colon = strchr(
string,
':');
251 if (first_colon !=
NULL)
253 const char* last_colon = strrchr(first_colon + 1,
':');
256 if (last_colon ==
NULL)
258 addr_end = first_colon;
259 port_name = first_colon + 1;
262 addr_family = AF_INET6;
266 if (addr_end !=
NULL)
267 namelen = addr_end - addr_start;
269 namelen =
strlen (addr_start);
271 if (namelen >=
sizeof(
name))
272 namelen =
sizeof(
name) - 1;
273 memcpy (
name, addr_start, namelen);
277 port = atoi(port_name);
283 if (!strcmp(
name,
"local"))
286 address->
port = port;
291 d1 = d2 = d3 = d4 = 0;
293#define sscanf sscanf_s
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)
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;
310 printf(
"manual parsing of ipv4 dotted decimal address \"%s\" successful: %s\n",
string, string2);
324 address->
port = port;
327 address->
addr.
in6.sin6_port = htons((
unsigned short)port);
332 address->
addr.
in.sin_port = htons((
unsigned short)port);
341#ifndef STANDALONETEST
350 const char *protoname;
361 protoname =
"UNKNOWN";
365 Con_Printf(
"LHNETADDRESS_Resolve(\"%s\") returned %s address %s\n",
string, protoname, string2);
372 printf(
"name resolution failed on address \"%s\"\n",
name);
384 int i, port, namelen, d1, d2, d3, d4;
385 struct hostent *hostentry;
392 if (!address || !
string || !*
string)
394 memset(address, 0,
sizeof(*address));
397 colon = strrchr(
string,
':');
398 if (colon && (colon == strchr(
string,
':') || (
string[0] ==
'[' && colon -
string > 0 && colon[-1] ==
']')))
402 port = atoi(colon + 1);
405 colon =
string +
strlen(
string);
411 if (
string[0] ==
'[' && namelen > 0 &&
string[namelen-1] ==
']')
416 memcpy(
name,
string, namelen);
419 if (!strcmp(
name,
"local"))
422 address->
port = port;
427 d1 = d2 = d3 = d4 = 0;
429#define sscanf sscanf_s
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)
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;
445 printf(
"manual parsing of ipv4 dotted decimal address \"%s\" successful: %s\n",
string, string2);
459 address->
port = port;
463 address->
addr.
in6.sin6_port = htons((
unsigned short)port);
469 address->
addr.
in.sin_port = htons((
unsigned short)port);
475 hostentry = gethostbyname(
name);
478 if (hostentry->h_addrtype == AF_INET6)
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));
490#ifndef STANDALONETEST
497 printf(
"gethostbyname(\"%s\") returned ipv6 address %s\n",
string, string2);
502 else if (hostentry->h_addrtype == AF_INET)
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));
513#ifndef STANDALONETEST
520 printf(
"gethostbyname(\"%s\") returned ipv4 address %s\n",
string, string2);
526 printf(
"gethostbyname failed on address \"%s\"\n",
name);
531#ifndef STANDALONETEST
543 const unsigned char *
a;
544 if (!address || !
string || stringbuffersize < 1)
554 if (stringbuffersize >= 12)
556 return dpsnprintf(
string, stringbuffersize,
"local:%d", address->
port);
561 if (stringbuffersize >= 6)
563 memcpy(
string,
"local", 6);
569 a = (
const unsigned char *)(&address->
addr.
in.sin_addr);
572 if (stringbuffersize >= 22)
574 return dpsnprintf(
string, stringbuffersize,
"%d.%d.%d.%d:%d",
a[0],
a[1],
a[2],
a[3], address->
port);
579 if (stringbuffersize >= 16)
581 return dpsnprintf(
string, stringbuffersize,
"%d.%d.%d.%d",
a[0],
a[1],
a[2],
a[3]);
587 a = (
const unsigned char *)(&address->
addr.
in6.sin6_addr);
590 if (stringbuffersize >= 88)
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);
597 if (stringbuffersize >= 80)
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]);
617 if (if_indextoname(address->
addr.
in6.sin6_scope_id, ifname) == ifname)
625 if (
dpsnprintf(ifname, ifnamelength,
"%lu", address->
addr.
in6.sin6_scope_id) > 0)
639 return address->
port;
647 address->
port = port;
653 address->
addr.
in.sin_port = htons((
unsigned short)port);
657 address->
addr.
in6.sin6_port = htons((
unsigned short)port);
669 if (!address1 || !address2)
676 if (address1->
port != address2->
port)
680 if (address1->
addr.
in.sin_family != address2->
addr.
in.sin_family)
682 if (memcmp(&address1->
addr.
in.sin_addr, &address2->
addr.
in.sin_addr,
sizeof(address1->
addr.
in.sin_addr)))
684 if (address1->
port != address2->
port)
689 if (address1->
addr.
in6.sin6_family != address2->
addr.
in6.sin6_family)
691 if (memcmp(&address1->
addr.
in6.sin6_addr, &address2->
addr.
in6.sin6_addr,
sizeof(address1->
addr.
in6.sin6_addr)))
693 if (address1->
port != address2->
port)
702typedef struct lhnetpacket_s
709#ifndef STANDALONETEST
721static int lhnet_didWSAStartup = 0;
722static WSADATA lhnet_winsockdata;
733 lhnet_didWSAStartup = !WSAStartup(MAKEWORD(1, 1), &lhnet_winsockdata);
734 if (!lhnet_didWSAStartup)
735 Con_Print(
"LHNET_Init: WSAStartup failed, networking disabled\n");
765 if (lhnet_didWSAStartup)
767 lhnet_didWSAStartup = 0;
777 int i = WSAGetLastError();
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";
828 return strerror(errno);
840 memset(lhnetsocket, 0,
sizeof(*lhnetsocket));
841 lhnetsocket->
address = *address;
878 if (lhnet_didWSAStartup)
884 if ((lhnetsocket->
inetsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
907 || setsockopt (lhnetsocket->
inetsocket, IPPROTO_IPV6, IPV6_V6ONLY,
908 (
const char *)&ipv6_only,
sizeof(ipv6_only)) == 0
921#if defined(SOL_RFC1149) && defined(RFC1149_1149ONLY)
926 int rfc1149enabled = 0;
927 if(setsockopt(lhnetsocket->
inetsocket, SOL_RFC1149, RFC1149_1149ONLY, &rfc1149only))
929 if(setsockopt(lhnetsocket->
inetsocket, SOL_RFC1149, RFC1149_ENABLED, &rfc1149enabled))
937 namelen =
sizeof(localaddress->
addr.
in6);
939 if (bindresult != -1)
951 namelen =
sizeof(localaddress->
addr.
in);
953 if (bindresult != -1)
962 if (bindresult != -1)
966 setsockopt(lhnetsocket->
inetsocket, SOL_SOCKET, SO_BROADCAST, (
char *)&
i,
sizeof(
i));
971 if (setsockopt(lhnetsocket->
inetsocket, IPPROTO_IP, IP_TOS, (
char *) &tos,
sizeof(tos)))
1001 Con_Print(
"LHNET_OpenSocket_Connectionless: can't open a socket (WSAStartup failed during LHNET_Init)\n");
1038 if (!lhnetsocket || !address || !content || maxcontentlength < 1)
1056#ifndef STANDALONETEST
1062 if (p->
length <= maxcontentlength)
1065 *address = *localaddress;
1082 inetaddresslength =
sizeof(address->
addr.
in);
1087 address->
port = ntohs(address->
addr.
in.sin_port);
1093 if (e == EWOULDBLOCK)
1104#ifndef NOSUPPORTIPV6
1109 inetaddresslength =
sizeof(address->
addr.
in6);
1114 address->
port = ntohs(address->
addr.
in6.sin6_port);
1117 else if (
value == -1)
1120 if (e == EWOULDBLOCK)
1139 if (!lhnetsocket || !address || !content || contentlength < 1)
1147 p->
data = (
void *)(p + 1);
1148 memcpy(p->
data, content, contentlength);
1149 p->
length = contentlength;
1155#ifndef STANDALONETEST
1158 value = contentlength;
1170#ifndef NOSUPPORTIPV6
1173 value = sendto(lhnetsocket->
inetsocket, (
char *)content, contentlength, 0, (
struct sockaddr *)&address->
addr.
in6,
sizeof(
struct sockaddr_in6));
1185#ifdef STANDALONETEST
1189 char *
buffer =
"test", buffer2[1024];
1202 printf(
"calling LHNET_Init\n");
1205 printf(
"calling LHNET_FromPort twice to create two local addresses\n");
1211 printf(
"calling LHNET_OpenSocket_Connectionless twice to create two local sockets\n");
1215 printf(
"calling LHNET_Write to send a packet from the first socket to the second socket\n");
1217 printf(
"sleeping briefly\n");
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);
1226 Con_Printf(
"socket to socket test succeeded\n");
1228 Con_Printf(
"socket to socket test failed\n");
1231 printf(
"press any key to exit\n");
1235 printf(
"calling LHNET_Shutdown\n");
1237 printf(
"exiting\n");
1249 int sendmessagelength;
1253 char buffer[1536], addressstring[128], addressstring2[128];
1254 if ((argc == 2 || argc == 5) && (port = atoi(
argv[1])) >= 1 && port < 65535)
1256 printf(
"calling LHNET_Init()\n");
1266 sendmessagelength = 0;
1268 for (
i = 0;
i < numsockets;
i++)
1271 printf(
"calling LHNET_OpenSocket_Connectionless(<%s>)\n", addressstring);
1275 printf(
"opened socket successfully (address \"%s\")\n", addressstring2);
1279 printf(
"failed to open socket\n");
1293 sendmessage =
argv[4];
1294 sendmessagelength =
strlen(sendmessage);
1296 for (
i = 0;
i < numsockets;
i++)
1299 if (sendsock ==
NULL)
1301 printf(
"Could not find an open socket matching the addresstype (%i) of destination address, switching to listen only mode\n",
LHNETADDRESS_GetAddressType(&destaddress));
1307 printf(
"LHNETADDRESS_FromString did not like the address \"%s\", switching to listen only mode\n",
argv[3]);
1311 printf(
"started, now listening for \"exit\" on the opened sockets\n");
1320 for (
i = 0;
i < numsockets;
i++)
1326 printf(
"localsock read error: length < 0");
1332 printf(
"received message \"%s\" from \"%s\" on socket \"%s\"\n",
buffer, addressstring, addressstring2);
1333 if (!strcmp(
buffer,
"exit"))
1340 if (argc == 5 &&
count > 0)
1343 if (newtime != oldtime)
1347 printf(
"calling LHNET_Write(<%s>, \"%s\", %i, <%s>)\n", addressstring2, sendmessage, sendmessagelength, addressstring);
1349 if (
length == sendmessagelength)
1350 printf(
"sent successfully\n");
1352 printf(
"LH_Write failed, returned %i (length of message was %i)\n",
length,
strlen(
argv[4]));
1356 printf(
"Done sending, still listening for \"exit\"\n");
1360 for (
i = 0;
i < numsockets;
i++)
1365 printf(
"calling LHNET_CloseSocket(<%s>)\n", addressstring2);
1369 printf(
"calling LHNET_Shutdown()\n");
1373 printf(
"Testing code for lhnet.c\nusage: lhnettest <localportnumber> [<sendnumberoftimes> <sendaddress:port> <sendmessage>]\n");
static void List_Create(llist_t *list)
static void List_Add_Tail(llist_t *node, llist_t *head)
static void List_Delete(llist_t *node)
#define List_For_Each_Entry_Safe(pos, n, head, type, member)
#define List_For_Each_Entry(pos, head, type, member)
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 ...
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
static int(ZEXPORT *qz_inflate)(z_stream *strm
GLsizei const GLfloat * value
GLsizei const GLchar ** string
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
int LHNETADDRESS_SetPort(lhnetaddress_t *vaddress, int port)
int LHNETADDRESS_FromPort(lhnetaddress_t *vaddress, lhnetaddresstype_t addresstype, int port)
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.
int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *vaddress)
const char * LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress, char *ifname, size_t ifnamelength)
void LHNET_CloseSocket(lhnetsocket_t *lhnetsocket)
static int namecacheposition
void LHNET_Shutdown(void)
int LHNET_DefaultDSCP(int dscp)
lhnetsocket_t * LHNET_OpenSocket_Connectionless(lhnetaddress_t *address)
#define LHNET_SENDTO_FLAGS
int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
static lhnetpacket_t lhnet_packetlist
int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, lhnetaddress_t *vaddress)
static int lhnet_default_dscp
lhnetaddress_t * LHNET_AddressFromSocket(lhnetsocket_t *sock)
lhnetsocket_t lhnet_socketlist
static int LHNETADDRESS_Resolve(lhnetaddressnative_t *address, const char *name, int port)
static struct namecache_s namecache[MAX_NAMECACHE]
int LHNETADDRESS_GetPort(const lhnetaddress_t *address)
#define LHNET_RECVFROM_FLAGS
int LHNETADDRESS_Compare(const lhnetaddress_t *vaddress1, const lhnetaddress_t *vaddress2)
static const char * LHNETPRIVATE_StrError(void)
static lhnetaddresstype_t LHNETADDRESS_GetAddressType(const lhnetaddress_t *address)
double realtime
the accumulated mainloop time since application started (with filtering), without any slowmo or clamp...
lhnetaddresstype_t addresstype
union lhnetaddressnative_t::@15 addr
lhnetaddresstype_t addresstype
lhnetaddressnative_t address