X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=lhnet.c;h=20781f820af82ef0c2b83eaf0da8cf32e8c8ac76;hb=81804fa83299b491dc24dd5f058527165faa38da;hp=aa6cbc94153b5f6c9f65f8960ed835515a61ce63;hpb=bbdd576471843ae0f2f400e3c60fd643e669d90d;p=xonotic%2Fdarkplaces.git diff --git a/lhnet.c b/lhnet.c index aa6cbc94..20781f82 100644 --- a/lhnet.c +++ b/lhnet.c @@ -5,7 +5,7 @@ #ifdef _MSC_VER #pragma comment(lib, "ws2_32.lib") #endif -# ifdef SUPPORTIPV6 +# ifndef NOSUPPORTIPV6 // Windows XP or higher is required for getaddrinfo, but the inclusion of wspiapi provides fallbacks for older versions # define _WIN32_WINNT 0x0501 # endif @@ -33,7 +33,7 @@ #include #include #include -#ifdef SUPPORTIPV6 +#ifndef NOSUPPORTIPV6 #include #endif #endif @@ -97,7 +97,7 @@ typedef struct lhnetaddressnative_s { struct sockaddr sock; struct sockaddr_in in; -#ifdef SUPPORTIPV6 +#ifndef NOSUPPORTIPV6 struct sockaddr_in6 in6; #endif } @@ -139,7 +139,7 @@ int LHNETADDRESS_FromPort(lhnetaddress_t *vaddress, lhnetaddresstype_t addressty address->addr.in.sin_family = AF_INET; address->addr.in.sin_port = htons((unsigned short)port); return 1; -#ifdef SUPPORTIPV6 +#ifndef NOSUPPORTIPV6 case LHNETADDRESSTYPE_INET6: // [0:0:0:0:0:0:0:0]:port (IN6ADDR_ANY, binds to all interfaces) memset(address, 0, sizeof(*address)); @@ -153,8 +153,8 @@ int LHNETADDRESS_FromPort(lhnetaddress_t *vaddress, lhnetaddresstype_t addressty return 0; } -#ifdef SUPPORTIPV6 -int LHNETADDRESS_Resolve(lhnetaddressnative_t *address, const char *name, int port) +#ifndef NOSUPPORTIPV6 +static int LHNETADDRESS_Resolve(lhnetaddressnative_t *address, const char *name, int port) { char port_buff [16]; struct addrinfo hints; @@ -389,8 +389,12 @@ int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int de address->addresstype = LHNETADDRESSTYPE_NONE; port = 0; colon = strrchr(string, ':'); - if (colon) + if (colon && (colon == strchr(string, ':') || (string[0] == '[' && colon - string > 0 && colon[-1] == ']'))) + // EITHER: colon is the ONLY colon OR: colon comes after [...] delimited IPv6 address + // fixes misparsing of IPv6 addresses without port + { port = atoi(colon + 1); + } else colon = string + strlen(string); if (port == 0) @@ -449,7 +453,7 @@ int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int de address->port = port; if (address->addresstype == LHNETADDRESSTYPE_INET6) { -#ifdef SUPPORTIPV6 +#ifndef NOSUPPORTIPV6 address->addr.in6.sin6_port = htons((unsigned short)port); return 1; #endif @@ -467,7 +471,7 @@ int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int de { if (hostentry->h_addrtype == AF_INET6) { -#ifdef SUPPORTIPV6 +#ifndef NOSUPPORTIPV6 // great it worked address->addresstype = LHNETADDRESSTYPE_INET6; address->port = port; @@ -531,9 +535,9 @@ int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stri { lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress; const unsigned char *a; - *string = 0; if (!address || !string || stringbuffersize < 1) return 0; + *string = 0; switch(address->addresstype) { default: @@ -575,7 +579,7 @@ int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stri } } break; -#ifdef SUPPORTIPV6 +#ifndef NOSUPPORTIPV6 case LHNETADDRESSTYPE_INET6: a = (const unsigned char *)(&address->addr.in6.sin6_addr); if (includeport) @@ -608,17 +612,15 @@ int LHNETADDRESS_GetAddressType(const lhnetaddress_t *address) return LHNETADDRESSTYPE_NONE; } -const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress) +const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress, char *ifname, size_t ifnamelength) { -#ifdef SUPPORTIPV6 +#ifndef NOSUPPORTIPV6 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress; if (address && address->addresstype == LHNETADDRESSTYPE_INET6) { #ifndef _WIN32 - static char ifname [IF_NAMESIZE]; - if (if_indextoname(address->addr.in6.sin6_scope_id, ifname) == ifname) return ifname; @@ -627,9 +629,7 @@ const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress) // The Win32 API doesn't have if_indextoname() until Windows Vista, // but luckily it just uses the interface ID as the interface name - static char ifname [16]; - - if (dpsnprintf(ifname, sizeof(ifname), "%lu", address->addr.in6.sin6_scope_id) > 0) + if (dpsnprintf(ifname, ifnamelength, "%lu", address->addr.in6.sin6_scope_id) > 0) return ifname; #endif @@ -659,7 +659,7 @@ int LHNETADDRESS_SetPort(lhnetaddress_t *vaddress, int port) case LHNETADDRESSTYPE_INET4: address->addr.in.sin_port = htons((unsigned short)port); return 1; -#ifdef SUPPORTIPV6 +#ifndef NOSUPPORTIPV6 case LHNETADDRESSTYPE_INET6: address->addr.in6.sin6_port = htons((unsigned short)port); return 1; @@ -691,7 +691,7 @@ int LHNETADDRESS_Compare(const lhnetaddress_t *vaddress1, const lhnetaddress_t * if (address1->port != address2->port) return -1; return 0; -#ifdef SUPPORTIPV6 +#ifndef NOSUPPORTIPV6 case LHNETADDRESSTYPE_INET6: if (address1->addr.in6.sin6_family != address2->addr.in6.sin6_family) return 1; @@ -723,6 +723,7 @@ lhnetpacket_t; static int lhnet_active; static lhnetsocket_t lhnet_socketlist; static lhnetpacket_t lhnet_packetlist; +static int lhnet_default_dscp = 0; #ifdef WIN32 static int lhnet_didWSAStartup = 0; static WSADATA lhnet_winsockdata; @@ -742,6 +743,18 @@ void LHNET_Init(void) #endif } +int LHNET_DefaultDSCP(int dscp) +{ +#ifdef IP_TOS + int prev = lhnet_default_dscp; + if(dscp >= 0) + lhnet_default_dscp = dscp; + return prev; +#else + return -1; +#endif +} + void LHNET_Shutdown(void) { lhnetpacket_t *p; @@ -839,7 +852,7 @@ void LHNET_SleepUntilPacket_Microseconds(int microseconds) { if (lastfd < s->inetsocket) lastfd = s->inetsocket; -#ifdef WIN32 +#if defined(WIN32) && !defined(_MSC_VER) FD_SET((int)s->inetsocket, &fdreadset); #else FD_SET((unsigned int)s->inetsocket, &fdreadset); @@ -899,14 +912,14 @@ lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address) } break; case LHNETADDRESSTYPE_INET4: -#ifdef SUPPORTIPV6 +#ifndef NOSUPPORTIPV6 case LHNETADDRESSTYPE_INET6: #endif #ifdef WIN32 if (lhnet_didWSAStartup) { #endif -#ifdef SUPPORTIPV6 +#ifndef NOSUPPORTIPV6 if ((lhnetsocket->inetsocket = socket(address->addresstype == LHNETADDRESSTYPE_INET6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1) #else if ((lhnetsocket->inetsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1) @@ -945,13 +958,33 @@ lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address) lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address; SOCKLEN_T namelen; int bindresult; -#ifdef SUPPORTIPV6 + +#if defined(SOL_RFC1149) && defined(RFC1149_1149ONLY) + // we got reports of massive lags when this protocol was chosen as transport + // so better turn it off + { + int rfc1149only = 0; + int rfc1149enabled = 0; + if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_1149ONLY, &rfc1149only)) + Con_Printf("LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_1149ONLY) returned error: %s\n", LHNETPRIVATE_StrError()); + if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_ENABLED, &rfc1149enabled)) + Con_Printf("LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_ENABLED) returned error: %s\n", LHNETPRIVATE_StrError()); + } +#endif + +#ifndef NOSUPPORTIPV6 if (address->addresstype == LHNETADDRESSTYPE_INET6) { namelen = sizeof(localaddress->addr.in6); bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen); if (bindresult != -1) - getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen); + { + if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen)) + { + // If getsockname failed, we can assume the bound socket is useless. + bindresult = -1; + } + } } else #endif @@ -959,13 +992,29 @@ lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address) namelen = sizeof(localaddress->addr.in); bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen); if (bindresult != -1) - getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen); + { + if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen)) + { + // If getsockname failed, we can assume the bound socket is useless. + bindresult = -1; + } + } } if (bindresult != -1) { int i = 1; // enable broadcast on this socket setsockopt(lhnetsocket->inetsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)); +#ifdef IP_TOS + { + // enable DSCP for ToS support + int tos = lhnet_default_dscp << 2; + if (setsockopt(lhnetsocket->inetsocket, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos))) + { + // Error in setsockopt - fine, we'll simply set no TOS then. + } + } +#endif lhnetsocket->next = &lhnet_socketlist; lhnetsocket->prev = lhnetsocket->next->prev; lhnetsocket->next->prev = lhnetsocket; @@ -1103,16 +1152,16 @@ int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, Con_Print("Connection refused\n"); return 0; } - Con_Printf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError()); + Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError()); } } -#ifdef SUPPORTIPV6 +#ifndef NOSUPPORTIPV6 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6) { SOCKLEN_T inetaddresslength; address->addresstype = LHNETADDRESSTYPE_NONE; inetaddresslength = sizeof(address->addr.in6); - value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, 0, &address->addr.sock, &inetaddresslength); + value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength); if (value > 0) { address->addresstype = LHNETADDRESSTYPE_INET6; @@ -1130,7 +1179,7 @@ int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, Con_Print("Connection refused\n"); return 0; } - Con_Printf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError()); + Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError()); } } #endif @@ -1171,10 +1220,10 @@ int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentleng { if (SOCKETERRNO == EWOULDBLOCK) return 0; - Con_Printf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError()); + Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError()); } } -#ifdef SUPPORTIPV6 +#ifndef NOSUPPORTIPV6 else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6) { value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, 0, (struct sockaddr *)&address->addr.in6, sizeof(struct sockaddr_in6)); @@ -1182,7 +1231,7 @@ int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentleng { if (SOCKETERRNO == EWOULDBLOCK) return 0; - Con_Printf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError()); + Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError()); } } #endif