#include <winsock.h>
#else
#include <netdb.h>
-//#include <netinet/in.h>
+#include <netinet/in.h>
//#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>
// for Z_Malloc/Z_Free in quake
#ifndef STANDALONETEST
+#include "quakedef.h"
#include "zone.h"
+#include "sys.h"
+#include "netconn.h"
#else
+#define Con_Print printf
+#define Con_Printf printf
#define Z_Malloc malloc
#define Z_Free free
#endif
address->addressdata.loop.port = port;
return 1;
}
- // try to parse with gethostbyname first, because it can handle ipv4 and
- // ipv6 (in various address formats), as well as dns names
+ // try to parse as dotted decimal ipv4 address first
+ if (sscanf(name, "%d.%d.%d.%d", &d1, &d2, &d3, &d4) == 4 && (unsigned int)d1 < 256 && (unsigned int)d2 < 256 && (unsigned int)d3 < 256 && (unsigned int)d4 < 256)
+ {
+ // parsed a valid ipv4 address
+ address->addresstype = LHNETADDRESSTYPE_INET4;
+ address->addressdata.inet4.family = LHNETADDRESSTYPE_INET4_FAMILY;
+ address->addressdata.inet4.port = htons((unsigned short)port);
+ address->addressdata.inet4.address[0] = (unsigned char)d1;
+ address->addressdata.inet4.address[1] = (unsigned char)d2;
+ address->addressdata.inet4.address[2] = (unsigned char)d3;
+ address->addressdata.inet4.address[3] = (unsigned char)d4;
+#ifdef STANDALONETEST
+ printf("manual parsing of ipv4 dotted decimal address \"%s\" successful: %d.%d.%d.%d:%d\n", string, (int)address->addressdata.inet4.address[0], (int)address->addressdata.inet4.address[1], (int)address->addressdata.inet4.address[2], (int)address->addressdata.inet4.address[3], (int)ntohs(address->addressdata.inet4.port));
+#endif
+ return 1;
+ }
+ // try gethostbyname (handles dns and other ip formats)
hostentry = gethostbyname(name);
if (hostentry)
{
return 1;
}
}
- // failed, try to parse as an ipv4 address as a fallback (is this needed?)
-#ifdef STANDALONETEST
- printf("gethostbyname and gethostbyaddr failed on address \"%s\"\n", name);
-#endif
- if (sscanf(name, "%d.%d.%d.%d", &d1, &d2, &d3, &d4) == 4 && (unsigned int)d1 < 256 && (unsigned int)d2 < 256 && (unsigned int)d3 < 256 && (unsigned int)d4 < 256)
- {
- // parsed a valid ipv4 address
- address->addresstype = LHNETADDRESSTYPE_INET4;
- address->addressdata.inet4.family = LHNETADDRESSTYPE_INET4_FAMILY;
- address->addressdata.inet4.port = htons((unsigned short)port);
- address->addressdata.inet4.address[0] = (unsigned char)d1;
- address->addressdata.inet4.address[1] = (unsigned char)d2;
- address->addressdata.inet4.address[2] = (unsigned char)d3;
- address->addressdata.inet4.address[3] = (unsigned char)d4;
#ifdef STANDALONETEST
- printf("manual parsing of ipv4 dotted decimal address \"%s\" successful: %d.%d.%d.%d:%d\n", string, (int)address->addressdata.inet4.address[0], (int)address->addressdata.inet4.address[1], (int)address->addressdata.inet4.address[2], (int)address->addressdata.inet4.address[3], (int)ntohs(address->addressdata.inet4.port));
+ printf("gethostbyname failed on address \"%s\"\n", name);
#endif
- return 1;
- }
return 0;
}
int sourceport;
int destinationport;
time_t timeout;
+#ifndef STANDALONETEST
+ double sentdoubletime;
+#endif
struct lhnetpacket_s *next, *prev;
}
lhnetpacket_t;
lhnet_active = 0;
}
+static const char *LHNETPRIVATE_StrError(void)
+{
+#ifdef WIN32
+ int i = WSAGetLastError();
+ switch (i)
+ {
+ case WSAEINTR: return "WSAEINTR";
+ case WSAEBADF: return "WSAEBADF";
+ case WSAEACCES: return "WSAEACCES";
+ case WSAEFAULT: return "WSAEFAULT";
+ case WSAEINVAL: return "WSAEINVAL";
+ case WSAEMFILE: return "WSAEMFILE";
+ case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
+ case WSAEINPROGRESS: return "WSAEINPROGRESS";
+ case WSAEALREADY: return "WSAEALREADY";
+ case WSAENOTSOCK: return "WSAENOTSOCK";
+ case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
+ case WSAEMSGSIZE: return "WSAEMSGSIZE";
+ case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
+ case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
+ case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
+ case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
+ case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
+ case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
+ case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
+ case WSAEADDRINUSE: return "WSAEADDRINUSE";
+ case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
+ case WSAENETDOWN: return "WSAENETDOWN";
+ case WSAENETUNREACH: return "WSAENETUNREACH";
+ case WSAENETRESET: return "WSAENETRESET";
+ case WSAECONNABORTED: return "WSAECONNABORTED";
+ case WSAECONNRESET: return "WSAECONNRESET";
+ case WSAENOBUFS: return "WSAENOBUFS";
+ case WSAEISCONN: return "WSAEISCONN";
+ case WSAENOTCONN: return "WSAENOTCONN";
+ case WSAESHUTDOWN: return "WSAESHUTDOWN";
+ case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
+ case WSAETIMEDOUT: return "WSAETIMEDOUT";
+ case WSAECONNREFUSED: return "WSAECONNREFUSED";
+ case WSAELOOP: return "WSAELOOP";
+ case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
+ case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
+ case WSAEHOSTUNREACH: return "WSAEHOSTUNREACH";
+ case WSAENOTEMPTY: return "WSAENOTEMPTY";
+ case WSAEPROCLIM: return "WSAEPROCLIM";
+ case WSAEUSERS: return "WSAEUSERS";
+ case WSAEDQUOT: return "WSAEDQUOT";
+ case WSAESTALE: return "WSAESTALE";
+ case WSAEREMOTE: return "WSAEREMOTE";
+ case WSAEDISCON: return "WSAEDISCON";
+ case 0: return "no error";
+ default: return "unknown WSAE error";
+ }
+#else
+ return strerror(errno);
+#endif
+}
+
lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address)
{
lhnetsocket_t *lhnetsocket, *s;
case LHNETADDRESSTYPE_INET4:
case LHNETADDRESSTYPE_INET6:
#ifdef WIN32
- if (!lhnet_didWSAStartup && !WSAStartup(MAKEWORD(1, 1), &lhnet_winsockdata))
- {
- lhnet_didWSAStartup = 1;
-#else
+ if (lhnet_didWSAStartup || (lhnet_didWSAStartup = !WSAStartup(MAKEWORD(1, 1), &lhnet_winsockdata)))
{
#endif
- if (address->addresstype == LHNETADDRESSTYPE_INET6)
- lhnetsocket->inetsocket = socket(LHNETADDRESSTYPE_INET6_FAMILY, SOCK_DGRAM, IPPROTO_UDP);
- else
- lhnetsocket->inetsocket = socket(LHNETADDRESSTYPE_INET4_FAMILY, SOCK_DGRAM, IPPROTO_UDP);
- if (lhnetsocket->inetsocket != -1)
+ if ((lhnetsocket->inetsocket = socket(address->addresstype == LHNETADDRESSTYPE_INET6 ? LHNETADDRESSTYPE_INET6_FAMILY : LHNETADDRESSTYPE_INET4_FAMILY, SOCK_DGRAM, IPPROTO_UDP)) != -1)
{
#ifdef WIN32
u_long _true = 1;
if (ioctl(lhnetsocket->inetsocket, FIONBIO, &_true) != -1)
#endif
{
- if (bind(lhnetsocket->inetsocket, (void *)&lhnetsocket->address.addressdata, address->addresstype == LHNETADDRESSTYPE_INET6 ? sizeof(lhnetsocket->address.addressdata.inet6) : sizeof(lhnetsocket->address.addressdata.inet4)) != -1)
+#ifdef WIN32
+ int namelen;
+#else
+ socklen_t namelen;
+#endif
+ namelen = address->addresstype == LHNETADDRESSTYPE_INET6 ? sizeof(lhnetsocket->address.addressdata.inet6) : sizeof(lhnetsocket->address.addressdata.inet4);
+ if (bind(lhnetsocket->inetsocket, (void *)&lhnetsocket->address.addressdata, namelen) != -1)
{
+ getsockname(lhnetsocket->inetsocket, (void *)&lhnetsocket->address.addressdata, &namelen);
lhnetsocket->next = &lhnet_socketlist;
lhnetsocket->prev = lhnetsocket->next->prev;
lhnetsocket->next->prev = lhnetsocket;
lhnetsocket->prev->next = lhnetsocket;
return lhnetsocket;
}
+ else
+ Con_Printf("LHNET_OpenSocket_Connectionless: bind returned error: %s\n", LHNETPRIVATE_StrError());
}
+ else
+ Con_Printf("LHNET_OpenSocket_Connectionless: ioctlsocket returned error: %s\n", LHNETPRIVATE_StrError());
#ifdef WIN32
closesocket(lhnetsocket->inetsocket);
#else
close(lhnetsocket->inetsocket);
#endif
}
+ else
+ Con_Printf("LHNET_OpenSocket_Connectionless: socket returned error: %s\n", LHNETPRIVATE_StrError());
+#ifdef WIN32
}
+ else
+ Con_Print("LHNET_OpenSocket_Connectionless: WSAStartup failed\n");
+#endif
break;
default:
break;
for (p = lhnet_packetlist.next;p != &lhnet_packetlist;p = pnext)
{
pnext = p->next;
+ if (p->timeout < currenttime)
+ {
+ // unlink and free
+ p->next->prev = p->prev;
+ p->prev->next = p->next;
+ Z_Free(p);
+ continue;
+ }
+#ifndef STANDALONETEST
+ if (cl_netlocalping.value && (Sys_DoubleTime() - cl_netlocalping.value * 1000.0) < p->sentdoubletime)
+ continue;
+#endif
if (value == 0 && p->destinationport == lhnetsocket->address.addressdata.loop.port)
{
if (p->length <= maxcontentlength)
p->prev->next = p->next;
Z_Free(p);
}
- else if (p->timeout < currenttime)
- {
- // unlink and free
- p->next->prev = p->prev;
- p->prev->next = p->next;
- Z_Free(p);
- }
}
}
else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
{
#ifdef WIN32
int e = WSAGetLastError();
- if (e == WSAEWOULDBLOCK || e == WSAECONNREFUSED)
+ if (e == WSAEWOULDBLOCK)
return 0;
+ switch (e)
+ {
+ case WSAECONNREFUSED:
+ Con_Print("Connection refused\n");
+ return 0;
+ }
#else
- if (errno == EWOULDBLOCK || errno == ECONNREFUSED)
+ if (errno == EWOULDBLOCK)
return 0;
+ switch (errno)
+ {
+ case ECONNREFUSED:
+ Con_Print("Connection refused\n");
+ return 0;
+ }
#endif
}
}
{
#ifdef WIN32
int e = WSAGetLastError();
- if (e == WSAEWOULDBLOCK || e == WSAECONNREFUSED)
+ if (e == WSAEWOULDBLOCK)
return 0;
+ switch (e)
+ {
+ case WSAECONNREFUSED:
+ Con_Print("Connection refused\n");
+ return 0;
+ }
#else
- if (errno == EWOULDBLOCK || errno == ECONNREFUSED)
+ if (errno == EWOULDBLOCK)
return 0;
+ switch (errno)
+ {
+ case ECONNREFUSED:
+ Con_Print("Connection refused\n");
+ return 0;
+ }
#endif
}
}
int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *address)
{
int value = -1;
- if (!lhnetsocket || !address || !content || maxcontentlength < 1)
+ if (!lhnetsocket || !address || !content || contentlength < 1)
return -1;
if (lhnetsocket->address.addresstype != address->addresstype)
return -1;
p->prev = p->next->prev;
p->next->prev = p;
p->prev->next = p;
+#ifndef STANDALONETEST
+ p->sentdoubletime = Sys_DoubleTime();
+#endif
value = contentlength;
}
else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)