diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index eacee1a2da..535d221a68 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -131,26 +131,78 @@ namespace RTC } private: + /* + * Hash for IPv4 + * + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | PORT | IP | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | IP | |F|P| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Hash for IPv6 + * + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | PORT | IP[0] ^ IP[1] ^ IP[2] ^ IP[3]| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |IP[0] ^ IP[1] ^ IP[2] ^ IP[3] | IP[0] >> 16 |F|P| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ void SetHash() { - const std::string protocol = this->protocol == Protocol::UDP ? "udp" : "tcp"; - int family; - std::string localIp; - uint16_t localPort; - std::string remoteIp; - uint16_t remotePort; + const struct sockaddr* remoteSockAddr = GetRemoteAddress(); - Utils::IP::GetAddressInfo(GetLocalAddress(), family, localIp, localPort); - Utils::IP::GetAddressInfo(GetRemoteAddress(), family, remoteIp, remotePort); + switch (remoteSockAddr->sa_family) + { + case AF_INET: + { + auto* remoteSockAddrIn = reinterpret_cast(remoteSockAddr); - std::string id = remoteIp + std::to_string(remotePort) + localIp + std::to_string(localPort) + - std::to_string(family) + protocol; + const uint64_t address = ntohl(remoteSockAddrIn->sin_addr.s_addr); + const uint64_t port = (ntohs(remoteSockAddrIn->sin_port)); - this->hash = std::hash{}(id); + this->hash = port << 48; + this->hash |= address << 16; + this->hash |= 0x0000; // AF_INET. + + break; + } + + case AF_INET6: + { + auto* remoteSockAddrIn6 = reinterpret_cast(remoteSockAddr); + auto* a = reinterpret_cast(std::addressof(remoteSockAddrIn6->sin6_addr)); + + const auto address1 = a[0] ^ a[1] ^ a[2] ^ a[3]; + const auto address2 = a[0]; + const uint64_t port = ntohs(remoteSockAddrIn6->sin6_port); + + this->hash = port << 48; + this->hash |= static_cast(address1) << 16; + this->hash |= address2 >> 16 & 0xFFFC; + this->hash |= 0x0002; // AF_INET6. + + break; + } + } + + // Override least significant bit with protocol information: + // - If UDP, start with 0. + // - If TCP, start with 1. + if (this->protocol == Protocol::UDP) + { + this->hash |= 0x0000; + } + else + { + this->hash |= 0x0001; + } } public: - size_t hash; + uint64_t hash{ 0u }; private: // Passed by argument. diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index 504ff18f81..cb53233c4f 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -100,7 +100,7 @@ namespace RTC // Map of WebRtcTransports indexed by local ICE usernameFragment. absl::flat_hash_map mapLocalIceUsernameFragmentWebRtcTransport; // Map of WebRtcTransports indexed by TransportTuple.hash. - absl::flat_hash_map mapTupleWebRtcTransport; + absl::flat_hash_map mapTupleWebRtcTransport; }; } // namespace RTC