#define MS_CLASS "RTC::TransportTuple"
#include "RTC/TransportTuple.hpp"
#include "Logger.hpp"
#include <cstring>
namespace RTC
{
TransportTuple::Protocol TransportTuple::ProtocolFromFbs(FBS::Transport::Protocol protocol)
{
MS_TRACE();
switch (protocol)
{
case FBS::Transport::Protocol::UDP:
{
return TransportTuple::Protocol::UDP;
}
case FBS::Transport::Protocol::TCP:
{
return TransportTuple::Protocol::TCP;
}
NO_DEFAULT_GCC();
}
}
FBS::Transport::Protocol TransportTuple::ProtocolToFbs(TransportTuple::Protocol protocol)
{
MS_TRACE();
switch (protocol)
{
case TransportTuple::Protocol::UDP:
{
return FBS::Transport::Protocol::UDP;
}
case TransportTuple::Protocol::TCP:
{
return FBS::Transport::Protocol::TCP;
}
NO_DEFAULT_GCC();
}
}
uint64_t TransportTuple::GenerateFnv1aHash(const uint8_t* data, size_t size)
{
MS_TRACE();
const uint64_t fnvOffsetBasis = 14695981039346656037ull;
const uint64_t fnvPrime = 1099511628211ull;
uint64_t hash = fnvOffsetBasis;
for (size_t i = 0; i < size; ++i)
{
hash = (hash ^ data[i]) * fnvPrime;
}
return hash;
}
void TransportTuple::CloseTcpConnection()
{
MS_TRACE();
if (this->protocol == Protocol::UDP)
{
MS_ABORT("cannot delete a UDP socket");
}
this->tcpConnection->TriggerClose();
}
flatbuffers::Offset<FBS::Transport::Tuple> TransportTuple::FillBuffer(
flatbuffers::FlatBufferBuilder& builder) const
{
MS_TRACE();
int family;
std::string localIp;
uint16_t localPort;
Utils::IP::GetAddressInfo(GetLocalAddress(), family, localIp, localPort);
std::string remoteIp;
uint16_t remotePort;
Utils::IP::GetAddressInfo(GetRemoteAddress(), family, remoteIp, remotePort);
auto protocol = TransportTuple::ProtocolToFbs(GetProtocol());
return FBS::Transport::CreateTupleDirect(
builder,
(this->localAnnouncedAddress.empty() ? localIp : this->localAnnouncedAddress).c_str(),
localPort,
remoteIp.c_str(),
remotePort,
protocol);
}
void TransportTuple::Dump(int indentation) const
{
MS_TRACE();
MS_DUMP_CLEAN(indentation, "<TransportTuple>");
int family;
std::string ip;
uint16_t port;
Utils::IP::GetAddressInfo(GetLocalAddress(), family, ip, port);
MS_DUMP_CLEAN(indentation, " localIp: %s", ip.c_str());
MS_DUMP_CLEAN(indentation, " localPort: %" PRIu16, port);
Utils::IP::GetAddressInfo(GetRemoteAddress(), family, ip, port);
MS_DUMP_CLEAN(indentation, " remoteIp: %s", ip.c_str());
MS_DUMP_CLEAN(indentation, " remotePort: %" PRIu16, port);
switch (GetProtocol())
{
case Protocol::UDP:
{
MS_DUMP_CLEAN(indentation, " protocol: udp");
break;
}
case Protocol::TCP:
{
MS_DUMP_CLEAN(indentation, " protocol: tcp");
break;
}
}
MS_DUMP_CLEAN(indentation, " hash: %" PRIu64, this->hash);
MS_DUMP_CLEAN(indentation, "</TransportTuple>");
}
void TransportTuple::GenerateHash()
{
MS_TRACE();
const auto* localSockAddr = GetLocalAddress();
const auto* remoteSockAddr = GetRemoteAddress();
static constexpr size_t BufferSize = ((16 + 2) * 2) + 1;
uint8_t buffer[BufferSize] = {};
size_t idx = 0;
auto appendSockAddr = [&](const struct sockaddr* addr)
{
if (addr->sa_family == AF_INET)
{
const auto* in = reinterpret_cast<const struct sockaddr_in*>(addr);
const auto* ip = reinterpret_cast<const uint8_t*>(&in->sin_addr.s_addr);
const uint16_t port = ntohs(in->sin_port);
std::memcpy(buffer + idx, ip, 4);
idx += 4;
buffer[idx++] = (port >> 8) & 0xFF;
buffer[idx++] = port & 0xFF;
}
else if (addr->sa_family == AF_INET6)
{
const auto* in6 = reinterpret_cast<const struct sockaddr_in6*>(addr);
const auto* ip = reinterpret_cast<const uint8_t*>(&in6->sin6_addr);
const uint16_t port = ntohs(in6->sin6_port);
std::memcpy(buffer + idx, ip, 16);
idx += 16;
buffer[idx++] = (port >> 8) & 0xFF;
buffer[idx++] = port & 0xFF;
}
};
appendSockAddr(localSockAddr);
appendSockAddr(remoteSockAddr);
buffer[idx] = static_cast<uint8_t>(this->protocol);
this->hash = TransportTuple::GenerateFnv1aHash(buffer, idx + 1);
}
}