X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=lhnet.c;h=58033bac8fe18646028a5621af32c318a558a675;hb=ff46d6ff516fda192c5adc55a5c9b82007545bd2;hp=b728fa2c48bbe80ed150c9b96fc5cc747dc91351;hpb=0a2edb85ad96a5fe17d5c3d694e70ab8aaf65def;p=xonotic%2Fdarkplaces.git diff --git a/lhnet.c b/lhnet.c index b728fa2c..58033bac 100644 --- a/lhnet.c +++ b/lhnet.c @@ -9,7 +9,7 @@ #include #else #include -//#include +#include //#include #include #include @@ -18,8 +18,11 @@ #endif // for Z_Malloc/Z_Free in quake -#if 1 +#ifndef STANDALONETEST +#include "quakedef.h" #include "zone.h" +#include "sys.h" +#include "netconn.h" #else #define Z_Malloc malloc #define Z_Free free @@ -29,6 +32,8 @@ int LHNETADDRESS_FromPort(lhnetaddress_t *address, int addresstype, int port) { + if (!address) + return 0; switch(addresstype) { case LHNETADDRESSTYPE_LOOP: @@ -42,14 +47,14 @@ int LHNETADDRESS_FromPort(lhnetaddress_t *address, int addresstype, int port) memset(address, 0, sizeof(*address)); address->addresstype = LHNETADDRESSTYPE_INET4; address->addressdata.inet4.family = LHNETADDRESSTYPE_INET4_FAMILY; - address->addressdata.inet4.port = htons(port); + address->addressdata.inet4.port = htons((unsigned short)port); return 1; case LHNETADDRESSTYPE_INET6: // [0:0:0:0:0:0:0:0]:port (IN6ADDR_ANY, binds to all interfaces) memset(address, 0, sizeof(*address)); address->addresstype = LHNETADDRESSTYPE_INET6; address->addressdata.inet6.family = LHNETADDRESSTYPE_INET6_FAMILY; - address->addressdata.inet6.port = htons(port); + address->addressdata.inet6.port = htons((unsigned short)port); return 1; } return 0; @@ -57,10 +62,12 @@ int LHNETADDRESS_FromPort(lhnetaddress_t *address, int addresstype, int port) int LHNETADDRESS_FromString(lhnetaddress_t *address, const char *string, int defaultport) { - int i, port, namelen, number; + int port, namelen, d1, d2, d3, d4; struct hostent *hostentry; const char *colon; char name[128]; + if (!address || !string) + return 0; memset(address, 0, sizeof(*address)); address->addresstype = LHNETADDRESSTYPE_NONE; port = 0; @@ -88,79 +95,62 @@ int LHNETADDRESS_FromString(lhnetaddress_t *address, const char *string, int def 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 - for (i = 0;i < 3;i++) + // 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) { - if (i == 0) - hostentry = gethostbyaddr(name, namelen, LHNETADDRESSTYPE_INET6_FAMILY); - else if (i == 1) - hostentry = gethostbyaddr(name, namelen, LHNETADDRESSTYPE_INET4_FAMILY); - else - hostentry = gethostbyname(name); - if (hostentry) - { - if (hostentry->h_addrtype == LHNETADDRESSTYPE_INET6_FAMILY) - { - // great it worked - address->addresstype = LHNETADDRESSTYPE_INET6; - address->addressdata.inet6.family = hostentry->h_addrtype; - address->addressdata.inet6.port = htons(port); - memcpy(address->addressdata.inet6.address, hostentry->h_addr_list[0], sizeof(address->addressdata.inet6.address)); + // 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("gethostbyname(\"%s\") returned ipv6 address [%x:%x:%x:%x:%x:%x:%x:%x]:%d\n", name, (int)address->addressdata.inet6.address[0], (int)address->addressdata.inet6.address[1], (int)address->addressdata.inet6.address[2], (int)address->addressdata.inet6.address[3], (int)address->addressdata.inet6.address[4], (int)address->addressdata.inet6.address[5], (int)address->addressdata.inet6.address[6], (int)address->addressdata.inet6.address[7], (int)ntohs(address->addressdata.inet6.port)); + 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; - } - else if (hostentry->h_addrtype == LHNETADDRESSTYPE_INET4_FAMILY) - { - // great it worked - address->addresstype = LHNETADDRESSTYPE_INET4; - address->addressdata.inet4.family = hostentry->h_addrtype; - address->addressdata.inet4.port = htons(port); - memcpy(address->addressdata.inet4.address, hostentry->h_addr_list[0], sizeof(address->addressdata.inet4.address)); + return 1; + } + // try gethostbyname (handles dns and other ip formats) + hostentry = gethostbyname(name); + if (hostentry) + { + if (hostentry->h_addrtype == LHNETADDRESSTYPE_INET6_FAMILY) + { + // great it worked + address->addresstype = LHNETADDRESSTYPE_INET6; + address->addressdata.inet6.family = hostentry->h_addrtype; + address->addressdata.inet6.port = htons((unsigned short)port); + memcpy(address->addressdata.inet6.address, hostentry->h_addr_list[0], sizeof(address->addressdata.inet6.address)); #ifdef STANDALONETEST - printf("gethostbyname(\"%s\") returned ipv4 address %d.%d.%d.%d:%d\n", name, (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(\"%s\") returned ipv6 address [%x:%x:%x:%x:%x:%x:%x:%x]:%d\n", name, (int)address->addressdata.inet6.address[0], (int)address->addressdata.inet6.address[1], (int)address->addressdata.inet6.address[2], (int)address->addressdata.inet6.address[3], (int)address->addressdata.inet6.address[4], (int)address->addressdata.inet6.address[5], (int)address->addressdata.inet6.address[6], (int)address->addressdata.inet6.address[7], (int)ntohs(address->addressdata.inet6.port)); #endif - return 1; - } + return 1; } - } - // failed, try to parse as an ipv4 address as a fallback (is this needed?) + else if (hostentry->h_addrtype == LHNETADDRESSTYPE_INET4_FAMILY) + { + // great it worked + address->addresstype = LHNETADDRESSTYPE_INET4; + address->addressdata.inet4.family = hostentry->h_addrtype; + address->addressdata.inet4.port = htons((unsigned short)port); + memcpy(address->addressdata.inet4.address, hostentry->h_addr_list[0], sizeof(address->addressdata.inet4.address)); #ifdef STANDALONETEST - printf("gethostbyname and gethostbyaddr failed on address \"%s\"\n", name); + printf("gethostbyname(\"%s\") returned ipv4 address %d.%d.%d.%d:%d\n", name, (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 - for (i = 0, number = 0;i < 4;string++) - { - if (*string >= '0' && *string <= '9') - number = number * 10 + (*string - '0'); - else if (number < 256 && (*string == '.' || *string == ':')) - { - address->addressdata.inet4.address[i++] = number; - number = 0; + return 1; } - else - break; - if (*string == 0 || *string == ':') - break; } - if (i == 4) - { - // parsed a valid ipv4 address - address->addresstype = LHNETADDRESSTYPE_INET4; - address->addressdata.inet4.family = LHNETADDRESSTYPE_INET4_FAMILY; - address->addressdata.inet4.port = htons(port); #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 LHNETADDRESS_ToString(const lhnetaddress_t *address, char *string, int stringbuffersize, int includeport) { *string = 0; + if (!address || !string || stringbuffersize < 1) + return 0; switch(address->addresstype) { default: @@ -225,11 +215,16 @@ int LHNETADDRESS_ToString(const lhnetaddress_t *address, char *string, int strin int LHNETADDRESS_GetAddressType(const lhnetaddress_t *address) { - return address->addresstype; + if (address) + return address->addresstype; + else + return LHNETADDRESSTYPE_NONE; } int LHNETADDRESS_GetPort(const lhnetaddress_t *address) { + if (!address) + return -1; switch(address->addresstype) { case LHNETADDRESSTYPE_LOOP: @@ -245,16 +240,18 @@ int LHNETADDRESS_GetPort(const lhnetaddress_t *address) int LHNETADDRESS_SetPort(lhnetaddress_t *address, int port) { + if (!address) + return 0; switch(address->addresstype) { case LHNETADDRESSTYPE_LOOP: address->addressdata.loop.port = port; return 1; case LHNETADDRESSTYPE_INET4: - address->addressdata.inet4.port = htons(port); + address->addressdata.inet4.port = htons((unsigned short)port); return 1; case LHNETADDRESSTYPE_INET6: - address->addressdata.inet6.port = htons(port); + address->addressdata.inet6.port = htons((unsigned short)port); return 1; default: return 0; @@ -263,6 +260,8 @@ int LHNETADDRESS_SetPort(lhnetaddress_t *address, int port) int LHNETADDRESS_Compare(const lhnetaddress_t *address1, const lhnetaddress_t *address2) { + if (!address1 || !address2) + return 1; if (address1->addresstype != address2->addresstype) return 1; switch(address1->addresstype) @@ -299,6 +298,9 @@ typedef struct lhnetpacket_s int sourceport; int destinationport; time_t timeout; +#ifndef STANDALONETEST + double sentdoubletime; +#endif struct lhnetpacket_s *next, *prev; } lhnetpacket_t; @@ -337,9 +339,69 @@ void LHNET_Shutdown(void) 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; + if (!address) + return NULL; lhnetsocket = Z_Malloc(sizeof(*lhnetsocket)); if (lhnetsocket) { @@ -382,17 +444,10 @@ lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address) 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; @@ -410,14 +465,24 @@ lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address) 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; @@ -461,12 +526,17 @@ void LHNET_CloseSocket(lhnetsocket_t *lhnetsocket) lhnetaddress_t *LHNET_AddressFromSocket(lhnetsocket_t *sock) { - return &sock->address; + if (sock) + return &sock->address; + else + return NULL; } int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, lhnetaddress_t *address) { int value = 0; + if (!lhnetsocket || !address || !content || maxcontentlength < 1) + return -1; if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP) { time_t currenttime; @@ -477,6 +547,18 @@ int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, 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 (p->sentdoubletime && Sys_DoubleTime() < p->sentdoubletime) + continue; +#endif if (value == 0 && p->destinationport == lhnetsocket->address.addressdata.loop.port) { if (p->length <= maxcontentlength) @@ -493,13 +575,6 @@ int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int 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) @@ -517,11 +592,23 @@ int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, { #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 } } @@ -540,11 +627,23 @@ int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, { #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 } } @@ -554,6 +653,8 @@ int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *address) { int value = -1; + if (!lhnetsocket || !address || !content || contentlength < 1) + return -1; if (lhnetsocket->address.addresstype != address->addresstype) return -1; if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP) @@ -570,6 +671,10 @@ int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentleng p->prev = p->next->prev; p->next->prev = p; p->prev->next = p; +#ifndef STANDALONETEST + if (cl_fakelocalping_min.value || cl_fakelocalping_max.value) + p->sentdoubletime = Sys_DoubleTime() + lhrandom(cl_fakelocalping_min.value, cl_fakelocalping_max.value) * (0.5 / 1000.0); +#endif value = contentlength; } else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)