1
0
mirror of https://github.com/danog/libtgvoip.git synced 2024-12-02 17:51:06 +01:00
libtgvoip/controller/protocol/Endpoints.cpp

154 lines
4.6 KiB
C++

#include "../../VoIPController.h"
using namespace tgvoip;
Endpoint &VoIPController::GetRemoteEndpoint()
{
return endpoints.at(currentEndpoint);
}
Endpoint *VoIPController::GetEndpointForPacket(const OutgoingPacket &pkt)
{
return GetEndpointById(pkt.endpoint);
}
Endpoint *VoIPController::GetEndpointForPacket(const PendingOutgoingPacket &pkt)
{
return GetEndpointById(pkt.endpoint);
}
Endpoint *VoIPController::GetEndpointById(const int64_t id)
{
if (id)
{
try
{
return &endpoints.at(id);
}
catch (out_of_range &x)
{
LOGW("Unable to send packet via nonexistent endpoint %" PRIu64, id);
return NULL;
}
}
return &endpoints.at(currentEndpoint);
}
int64_t VoIPController::GetPreferredRelayID()
{
return preferredRelay;
}
void VoIPController::SetRemoteEndpoints(vector<Endpoint> endpoints, bool allowP2p, int32_t connectionMaxLayer)
{
LOGW("Set remote endpoints, allowP2P=%d, connectionMaxLayer=%u", allowP2p ? 1 : 0, connectionMaxLayer);
assert(!runReceiver);
preferredRelay = 0;
this->endpoints.clear();
didAddTcpRelays = false;
useTCP = true;
for (auto it = endpoints.begin(); it != endpoints.end(); ++it)
{
if (this->endpoints.find(it->id) != this->endpoints.end())
LOGE("Endpoint IDs are not unique!");
this->endpoints[it->id] = *it;
if (currentEndpoint == 0)
currentEndpoint = it->id;
if (it->type == Endpoint::Type::UDP_RELAY)
useTCP = false;
else if (it->type == Endpoint::Type::TCP_RELAY)
didAddTcpRelays = true;
LOGV("Adding endpoint: %s:%d, %s", it->address.ToString().c_str(), it->port, it->type == Endpoint::Type::UDP_RELAY ? "UDP" : "TCP");
}
preferredRelay = currentEndpoint;
this->allowP2p = allowP2p;
ver.connectionMaxLayer = connectionMaxLayer;
if (connectionMaxLayer >= 74)
{
useMTProto2 = true;
}
AddIPv6Relays();
}
void VoIPController::AddIPv6Relays()
{
if (!myIPv6.IsEmpty() && !didAddIPv6Relays)
{
unordered_map<string, vector<Endpoint>> endpointsByAddress;
for (pair<const int64_t, Endpoint> &_e : endpoints)
{
Endpoint &e = _e.second;
if (e.IsReflector() && !e.v6address.IsEmpty() && !e.address.IsEmpty())
{
endpointsByAddress[e.v6address.ToString()].push_back(e);
}
}
MutexGuard m(endpointsMutex);
for (pair<const string, vector<Endpoint>> &addr : endpointsByAddress)
{
for (Endpoint &e : addr.second)
{
didAddIPv6Relays = true;
e.address = NetworkAddress::Empty();
e.id = e.id ^ (static_cast<int64_t>(FOURCC('I', 'P', 'v', '6')) << 32);
e.averageRTT = 0;
e.lastPingSeq = 0;
e.lastPingTime = 0;
e.rtts.Reset();
e.udpPongCount = 0;
endpoints[e.id] = e;
LOGD("Adding IPv6-only endpoint [%s]:%u", e.v6address.ToString().c_str(), e.port);
}
}
}
}
void VoIPController::AddTCPRelays()
{
if (!didAddTcpRelays)
{
bool wasSetCurrentToTCP = setCurrentEndpointToTCP;
LOGV("Adding TCP relays");
vector<Endpoint> relays;
for (pair<const int64_t, Endpoint> &_e : endpoints)
{
Endpoint &e = _e.second;
if (e.type != Endpoint::Type::UDP_RELAY)
continue;
if (wasSetCurrentToTCP && !useUDP)
{
e.rtts.Reset();
e.averageRTT = 0;
e.lastPingSeq = 0;
}
Endpoint tcpRelay(e);
tcpRelay.type = Endpoint::Type::TCP_RELAY;
tcpRelay.averageRTT = 0;
tcpRelay.lastPingSeq = 0;
tcpRelay.lastPingTime = 0;
tcpRelay.rtts.Reset();
tcpRelay.udpPongCount = 0;
tcpRelay.id = tcpRelay.id ^ (static_cast<int64_t>(FOURCC('T', 'C', 'P', 0)) << 32);
if (setCurrentEndpointToTCP && endpoints.at(currentEndpoint).type != Endpoint::Type::TCP_RELAY)
{
LOGV("Setting current endpoint to TCP");
setCurrentEndpointToTCP = false;
currentEndpoint = tcpRelay.id;
preferredRelay = tcpRelay.id;
}
relays.push_back(tcpRelay);
}
MutexGuard m(endpointsMutex);
for (Endpoint &e : relays)
{
endpoints[e.id] = e;
}
didAddTcpRelays = true;
}
}