From 9df96bf93600f7eea4df98a8688212c8158ad704 Mon Sep 17 00:00:00 2001 From: Thad House Date: Fri, 5 Jun 2020 17:25:38 -0700 Subject: [PATCH] Moves linux platform functions in public header to be inlined (#470) * Moves linux platform functions in public header to be inlined Because they were included from the public header, any attempt to use them before would get undefined symbols. This fixes that by inlining the functions like Windows Closes #468 --- src/inc/msquic_linux.h | 246 ++++++++++++++++++++++++++++--- src/platform/inline.c | 89 +++++++++++ src/platform/platform_linux.c | 270 ---------------------------------- 3 files changed, 315 insertions(+), 290 deletions(-) diff --git a/src/inc/msquic_linux.h b/src/inc/msquic_linux.h index ec71660d2..8e67cb1fe 100644 --- a/src/inc/msquic_linux.h +++ b/src/inc/msquic_linux.h @@ -30,6 +30,7 @@ Environment: #include #include #include +#include #include #include @@ -192,76 +193,257 @@ extern char *QuicOpenSslClientTrustedCert; // IP Address Abstraction Helpers // +inline BOOLEAN QuicAddrFamilyIsValid( - QUIC_ADDRESS_FAMILY Family - ); - + _In_ QUIC_ADDRESS_FAMILY Family + ) +{ + return Family == AF_INET || Family == AF_INET6 || Family == AF_UNSPEC; +} + +inline BOOLEAN QuicAddrIsValid( _In_ const QUIC_ADDR* const Addr - ); + ) +{ + return QuicAddrFamilyIsValid(Addr->si_family); +} +inline BOOLEAN QuicAddrCompareIp( _In_ const QUIC_ADDR* const Addr1, _In_ const QUIC_ADDR* const Addr2 - ); + ) +{ + if (AF_INET == Addr1->si_family) { + return memcmp(&Addr1->Ipv4.sin_addr, &Addr2->Ipv4.sin_addr, sizeof(IN_ADDR)) == 0; + } else { + return memcmp(&Addr1->Ipv6.sin6_addr, &Addr2->Ipv6.sin6_addr, sizeof(IN6_ADDR)) == 0; + } +} +inline BOOLEAN QuicAddrCompare( _In_ const QUIC_ADDR* const Addr1, _In_ const QUIC_ADDR* const Addr2 - ); + ) +{ + if (Addr1->si_family != Addr2->si_family || + Addr1->Ipv4.sin_port != Addr2->Ipv4.sin_port) { + return FALSE; + } + if (AF_INET == Addr1->si_family) { + return memcmp(&Addr1->Ipv4.sin_addr, &Addr2->Ipv4.sin_addr, sizeof(IN_ADDR)) == 0; + } else { + return memcmp(&Addr1->Ipv6.sin6_addr, &Addr2->Ipv6.sin6_addr, sizeof(IN6_ADDR)) == 0; + } +} + +inline uint16_t QuicAddrGetFamily( _In_ const QUIC_ADDR* const Addr - ); + ) +{ + return Addr->si_family; +} +inline void QuicAddrSetFamily( _In_ QUIC_ADDR* Addr, _In_ uint16_t Family - ); + ) +{ + Addr->si_family = Family; +} -uint16_t // Returns in host byte order. +inline +uint16_t QuicAddrGetPort( _In_ const QUIC_ADDR* const Addr - ); + ) +{ + if (AF_INET == Addr->si_family) { + return ntohs(Addr->Ipv4.sin_port); + } else { + return ntohs(Addr->Ipv6.sin6_port); + } +} +inline void QuicAddrSetPort( - _In_ QUIC_ADDR* Addr, - _In_ uint16_t Port // Host byte order - ); + _Out_ QUIC_ADDR* Addr, + _In_ uint16_t Port + ) +{ + if (AF_INET == Addr->si_family) { + Addr->Ipv4.sin_port = htons(Port); + } else { + Addr->Ipv6.sin6_port = htons(Port); + } +} +inline BOOLEAN QuicAddrIsBoundExplicitly( _In_ const QUIC_ADDR* const Addr - ); + ) +{ + // LINUX_TODO: How to handle IPv4? Windows just does the below. + // + // Scope ID of zero indicates we are sending from a connected binding. + // + + return Addr->Ipv6.sin6_scope_id == 0; +} + +inline void QuicAddrSetToLoopback( - _In_ QUIC_ADDR* Addr - ); + _Inout_ QUIC_ADDR* Addr + ) +{ + if (Addr->si_family == AF_INET) { + Addr->Ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + } else { + Addr->Ipv6.sin6_addr = in6addr_loopback; + } +} +inline uint32_t QuicAddrHash( _In_ const QUIC_ADDR* Addr - ); + ) +{ + uint32_t Hash = 5387; // A random prime number. +#define UPDATE_HASH(byte) Hash = ((Hash << 5) - Hash) + (byte) + if (Addr->si_family == AF_INET) { + UPDATE_HASH(Addr->Ipv4.sin_port & 0xFF); + UPDATE_HASH(Addr->Ipv4.sin_port >> 8); + for (uint8_t i = 0; i < sizeof(Addr->Ipv4.sin_addr); ++i) { + UPDATE_HASH(((uint8_t*)&Addr->Ipv4.sin_addr)[i]); + } + } else { + UPDATE_HASH(Addr->Ipv6.sin6_port & 0xFF); + UPDATE_HASH(Addr->Ipv6.sin6_port >> 8); + for (uint8_t i = 0; i < sizeof(Addr->Ipv6.sin6_addr); ++i) { + UPDATE_HASH(((uint8_t*)&Addr->Ipv6.sin6_addr)[i]); + } + } + return Hash; +} +inline BOOLEAN QuicAddrIsWildCard( _In_ const QUIC_ADDR* const Addr - ); + ) +{ + if (Addr->si_family == AF_UNSPEC) { + return TRUE; + } else if (Addr->si_family == AF_INET) { + const IN_ADDR ZeroAddr = {0}; + return memcmp(&Addr->Ipv4.sin_addr.s_addr, &ZeroAddr, sizeof(IN_ADDR)) == 0; + } else { + const IN6_ADDR ZeroAddr = {0}; + return memcmp(&Addr->Ipv6.sin6_addr, &ZeroAddr, sizeof(IN6_ADDR)) == 0; + } +} +inline +BOOLEAN +QuicAddr4FromString( + _In_z_ const char* AddrStr, + _Out_ QUIC_ADDR* Addr + ) +{ + if (AddrStr[0] == '[') { + return FALSE; + } + + const char* PortStart = strchr(AddrStr, ':'); + if (PortStart != NULL) { + if (strchr(PortStart+1, ':') != NULL) { + return FALSE; + } + + char TmpAddrStr[16]; + size_t AddrLength = PortStart - AddrStr; + if (AddrLength >= sizeof(TmpAddrStr)) { + return FALSE; + } + memcpy(TmpAddrStr, AddrStr, AddrLength); + TmpAddrStr[AddrLength] = '\0'; + + if (inet_pton(AF_INET, TmpAddrStr, &Addr->Ipv4.sin_addr) != 1) { + return FALSE; + } + Addr->Ipv4.sin_port = htons(atoi(PortStart+1)); + } else { + if (inet_pton(AF_INET, AddrStr, &Addr->Ipv4.sin_addr) != 1) { + return FALSE; + } + } + Addr->si_family = AF_INET; + return TRUE; +} + +inline +BOOLEAN +QuicAddr6FromString( + _In_z_ const char* AddrStr, + _Out_ QUIC_ADDR* Addr + ) +{ + if (AddrStr[0] == '[') { + const char* BracketEnd = strchr(AddrStr, ']'); + if (BracketEnd == NULL || *(BracketEnd+1) != ':') { + return FALSE; + } + + char TmpAddrStr[64]; + size_t AddrLength = BracketEnd - AddrStr; + if (AddrLength >= sizeof(TmpAddrStr)) { + return FALSE; + } + memcpy(TmpAddrStr, AddrStr, AddrLength); + TmpAddrStr[AddrLength] = '\0'; + + if (inet_pton(AF_INET6, TmpAddrStr, &Addr->Ipv6.sin6_addr) != 1) { + return FALSE; + } + Addr->Ipv6.sin6_port = htons(atoi(BracketEnd+2)); + } else { + if (inet_pton(AF_INET6, AddrStr, &Addr->Ipv6.sin6_addr) != 1) { + return FALSE; + } + } + Addr->si_family = AF_INET6; + return TRUE; +} + +inline BOOLEAN QuicAddrFromString( _In_z_ const char* AddrStr, _In_ uint16_t Port, // Host byte order _Out_ QUIC_ADDR* Addr - ); + ) +{ + Addr->Ipv4.sin_port = htons(Port); + return + QuicAddr4FromString(AddrStr, Addr) || + QuicAddr6FromString(AddrStr, Addr); +} // // Represents an IP address and (optionally) port number as a string. @@ -270,11 +452,35 @@ typedef struct QUIC_ADDR_STR { char Address[64]; } QUIC_ADDR_STR; +inline BOOLEAN QuicAddrToString( _In_ const QUIC_ADDR* Addr, _Out_ QUIC_ADDR_STR* AddrStr - ); + ) +{ + char* Address = AddrStr->Address; + if (Addr->si_family == AF_INET6 && Addr->Ipv6.sin6_port != 0) { + Address[0] = '['; + Address++; + } + if (inet_ntop( + Addr->si_family, + &Addr->Ipv4.sin_addr, + Address, + sizeof(QUIC_ADDR_STR)) != 0) { + return FALSE; + } + if (Addr->Ipv4.sin_port != 0) { + Address += strlen(Address); + if (Addr->si_family == AF_INET6) { + Address[0] = ']'; + Address++; + } + sprintf(Address, ":%hu", ntohs(Addr->Ipv4.sin_port)); + } + return TRUE; +} #if defined(__cplusplus) } diff --git a/src/platform/inline.c b/src/platform/inline.c index 976312a31..d5c028886 100644 --- a/src/platform/inline.c +++ b/src/platform/inline.c @@ -179,3 +179,92 @@ QuicTlsAlpnFindInList( _In_reads_(FindAlpnLength) const uint8_t* FindAlpn ); + +BOOLEAN +QuicAddrFamilyIsValid( + _In_ QUIC_ADDRESS_FAMILY Family + ); + +BOOLEAN +QuicAddrIsValid( + _In_ const QUIC_ADDR* const Addr + ); + +BOOLEAN +QuicAddrCompareIp( + _In_ const QUIC_ADDR* const Addr1, + _In_ const QUIC_ADDR* const Addr2 + ); + +BOOLEAN +QuicAddrCompare( + _In_ const QUIC_ADDR* const Addr1, + _In_ const QUIC_ADDR* const Addr2 + ); + +uint16_t +QuicAddrGetFamily( + _In_ const QUIC_ADDR* const Addr + ); + +void +QuicAddrSetFamily( + _In_ QUIC_ADDR* Addr, + _In_ uint16_t Family + ); + +uint16_t +QuicAddrGetPort( + _In_ const QUIC_ADDR* const Addr + ); + +void +QuicAddrSetPort( + _Out_ QUIC_ADDR* Addr, + _In_ uint16_t Port + ); + +BOOLEAN +QuicAddrIsBoundExplicitly( + _In_ const QUIC_ADDR* const Addr + ); + +void +QuicAddrSetToLoopback( + _Inout_ QUIC_ADDR* Addr + ); + +uint32_t +QuicAddrHash( + _In_ const QUIC_ADDR* Addr + ); + +BOOLEAN +QuicAddrIsWildCard( + _In_ const QUIC_ADDR* const Addr + ); + +BOOLEAN +QuicAddr4FromString( + _In_z_ const char* AddrStr, + _Out_ QUIC_ADDR* Addr + ); + +BOOLEAN +QuicAddr6FromString( + _In_z_ const char* AddrStr, + _Out_ QUIC_ADDR* Addr + ); + +BOOLEAN +QuicAddrFromString( + _In_z_ const char* AddrStr, + _In_ uint16_t Port, // Host byte order + _Out_ QUIC_ADDR* Addr + ); + +BOOLEAN +QuicAddrToString( + _In_ const QUIC_ADDR* Addr, + _Out_ QUIC_ADDR_STR* AddrStr + ); diff --git a/src/platform/platform_linux.c b/src/platform/platform_linux.c index 5405e87c6..12dd73a2e 100644 --- a/src/platform/platform_linux.c +++ b/src/platform/platform_linux.c @@ -21,7 +21,6 @@ Environment: #include #include #include -#include #include "quic_trace.h" #include "quic_platform_dispatch.h" @@ -610,275 +609,6 @@ QuicConvertFromMappedV6( } } -BOOLEAN -QuicAddrFamilyIsValid( - _In_ QUIC_ADDRESS_FAMILY Family - ) -{ - return Family == AF_INET || Family == AF_INET6 || Family == AF_UNSPEC; -} - -BOOLEAN -QuicAddrIsValid( - _In_ const QUIC_ADDR* const Addr - ) -{ - QUIC_DBG_ASSERT(Addr); - return QuicAddrFamilyIsValid(Addr->si_family); -} - -BOOLEAN -QuicAddrCompareIp( - _In_ const QUIC_ADDR* const Addr1, - _In_ const QUIC_ADDR* const Addr2 - ) -{ - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr1)); - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr2)); - - if (AF_INET == Addr1->si_family) { - return memcmp(&Addr1->Ipv4.sin_addr, &Addr2->Ipv4.sin_addr, sizeof(IN_ADDR)) == 0; - } else { - return memcmp(&Addr1->Ipv6.sin6_addr, &Addr2->Ipv6.sin6_addr, sizeof(IN6_ADDR)) == 0; - } -} - -BOOLEAN -QuicAddrCompare( - _In_ const QUIC_ADDR* const Addr1, - _In_ const QUIC_ADDR* const Addr2 - ) -{ - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr1)); - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr2)); - - if (Addr1->si_family != Addr2->si_family || - Addr1->Ipv4.sin_port != Addr2->Ipv4.sin_port) { - return FALSE; - } - - if (AF_INET == Addr1->si_family) { - return memcmp(&Addr1->Ipv4.sin_addr, &Addr2->Ipv4.sin_addr, sizeof(IN_ADDR)) == 0; - } else { - return memcmp(&Addr1->Ipv6.sin6_addr, &Addr2->Ipv6.sin6_addr, sizeof(IN6_ADDR)) == 0; - } -} - -uint16_t -QuicAddrGetFamily( - _In_ const QUIC_ADDR* const Addr - ) -{ - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr)); - return Addr->si_family; -} - -void -QuicAddrSetFamily( - _In_ QUIC_ADDR* Addr, - _In_ uint16_t Family - ) -{ - QUIC_DBG_ASSERT(Addr); - QUIC_DBG_ASSERT(QuicAddrFamilyIsValid(Family)); - Addr->si_family = Family; -} - -uint16_t -QuicAddrGetPort( - _In_ const QUIC_ADDR* const Addr - ) -{ - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr)); - - if (AF_INET == Addr->si_family) { - return ntohs(Addr->Ipv4.sin_port); - } else { - return ntohs(Addr->Ipv6.sin6_port); - } -} - -void -QuicAddrSetPort( - _Out_ QUIC_ADDR* Addr, - _In_ uint16_t Port - ) -{ - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr)); - - if (AF_INET == Addr->si_family) { - Addr->Ipv4.sin_port = htons(Port); - } else { - Addr->Ipv6.sin6_port = htons(Port); - } -} - -BOOLEAN -QuicAddrIsBoundExplicitly( - _In_ const QUIC_ADDR* const Addr - ) -{ - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr)); - - // LINUX_TODO: How to handle IPv4? Windows just does the below. - - // - // Scope ID of zero indicates we are sending from a connected binding. - // - - return Addr->Ipv6.sin6_scope_id == 0; -} - -void -QuicAddrSetToLoopback( - _Inout_ QUIC_ADDR* Addr - ) -{ - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr)); - - if (Addr->si_family == AF_INET) { - Addr->Ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - } else { - Addr->Ipv6.sin6_addr = in6addr_loopback; - } -} - -uint32_t -QuicAddrHash( - _In_ const QUIC_ADDR* Addr - ) -{ - uint32_t Hash = 5387; // A random prime number. -#define UPDATE_HASH(byte) Hash = ((Hash << 5) - Hash) + (byte) - if (Addr->si_family == AF_INET) { - UPDATE_HASH(Addr->Ipv4.sin_port & 0xFF); - UPDATE_HASH(Addr->Ipv4.sin_port >> 8); - for (uint8_t i = 0; i < sizeof(Addr->Ipv4.sin_addr); ++i) { - UPDATE_HASH(((uint8_t*)&Addr->Ipv4.sin_addr)[i]); - } - } else { - UPDATE_HASH(Addr->Ipv6.sin6_port & 0xFF); - UPDATE_HASH(Addr->Ipv6.sin6_port >> 8); - for (uint8_t i = 0; i < sizeof(Addr->Ipv6.sin6_addr); ++i) { - UPDATE_HASH(((uint8_t*)&Addr->Ipv6.sin6_addr)[i]); - } - } - return Hash; -} - -BOOLEAN -QuicAddrIsWildCard( - _In_ const QUIC_ADDR* const Addr - ) -{ - if (Addr->si_family == AF_UNSPEC) { - return TRUE; - } else if (Addr->si_family == AF_INET) { - const IN_ADDR ZeroAddr = {0}; - return memcmp(&Addr->Ipv4.sin_addr.s_addr, &ZeroAddr, sizeof(IN_ADDR)) == 0; - } else { - const IN6_ADDR ZeroAddr = {0}; - return memcmp(&Addr->Ipv6.sin6_addr, &ZeroAddr, sizeof(IN6_ADDR)) == 0; - } -} - -BOOLEAN -QuicAddr4FromString( - _In_z_ const char* AddrStr, - _Out_ QUIC_ADDR* Addr - ) -{ - if (AddrStr[0] == '[') { - return FALSE; - } - char* PortStart = strchr(AddrStr, ':'); - if (PortStart != NULL) { - if (strchr(PortStart+1, ':') != NULL) { - return FALSE; - } - *PortStart = '\0'; - if (inet_pton(AF_INET, AddrStr, &Addr->Ipv4.sin_addr) != 1) { - return FALSE; - } - *PortStart = ':'; - Addr->Ipv4.sin_port = htons(atoi(PortStart+1)); - } else { - if (inet_pton(AF_INET, AddrStr, &Addr->Ipv4.sin_addr) != 1) { - return FALSE; - } - } - Addr->si_family = AF_INET; - return TRUE; -} - -BOOLEAN -QuicAddr6FromString( - _In_z_ const char* AddrStr, - _Out_ QUIC_ADDR* Addr - ) -{ - if (AddrStr[0] == '[') { - char* BracketEnd = strchr(AddrStr, ']'); - if (BracketEnd == NULL || *(BracketEnd+1) != ':') { - return FALSE; - } - *BracketEnd = '\0'; - if (inet_pton(AF_INET6, AddrStr+1, &Addr->Ipv6.sin6_addr) != 1) { - return FALSE; - } - *BracketEnd = ']'; - Addr->Ipv6.sin6_port = htons(atoi(BracketEnd+2)); - } else { - if (inet_pton(AF_INET6, AddrStr, &Addr->Ipv6.sin6_addr) != 1) { - return FALSE; - } - } - Addr->si_family = AF_INET6; - return TRUE; -} - -BOOLEAN -QuicAddrFromString( - _In_z_ const char* AddrStr, - _In_ uint16_t Port, // Host byte order - _Out_ QUIC_ADDR* Addr - ) -{ - Addr->Ipv4.sin_port = htons(Port); - return - QuicAddr4FromString(AddrStr, Addr) || - QuicAddr6FromString(AddrStr, Addr); -} - -BOOLEAN -QuicAddrToString( - _In_ const QUIC_ADDR* Addr, - _Out_ QUIC_ADDR_STR* AddrStr - ) -{ - char* Address = AddrStr->Address; - if (Addr->si_family == AF_INET6 && Addr->Ipv6.sin6_port != 0) { - Address[0] = '['; - Address++; - } - if (inet_ntop( - Addr->si_family, - &Addr->Ipv4.sin_addr, - Address, - sizeof(QUIC_ADDR_STR)) != NULL) { - return FALSE; - } - if (Addr->Ipv4.sin_port != 0) { - Address += strlen(Address); - if (Addr->si_family == AF_INET6) { - Address[0] = ']'; - Address++; - } - sprintf(Address, ":%hu", ntohs(Addr->Ipv4.sin_port)); - } - return TRUE; -} - int _strnicmp( _In_ const char * _Str1,