Some checks failed
ZaStoGram source guards / guards (push) Failing after 35s
Build three ZaStoGram APKs / build (armeabi-v7a, ZaStoGram-standalone-armeabi-v7a, Armv7, armv7) (push) Failing after 2m23s
Build three ZaStoGram APKs / build (arm64-v8a, ZaStoGram-standalone-arm64-v8a, Arm64, arm64) (push) Failing after 2m25s
Build three ZaStoGram APKs / build (x86, ZaStoGram-standalone-x86, X86, x86) (push) Failing after 2m31s
Слияние DrKLO/Telegram c84801762 (12.10.4) и обновления подмодулей.
- Пакет прокси остаётся в org/telegram/proxy; из апстрима взята поддержка
адреса WEB-прокси с путём (ProxySettings.webProxy, normalizeAddress) внутри
нашего движка WebProxyTransport.
- Переключатель «прокси для звонков» убран вслед за апстримом: звонки
больше не читают proxy_enabled_calls.
- Ротация прокси по-прежнему не показывается для WEB-прокси: наш
ProxyRotationController их не поддерживает.
- Страж check_web_proxy_isolation проверяет валидацию через
ProxySettings.webProxy.
- Подмодули absl, wamr, tlottie, media — на версиях апстрима.
1077 lines
40 KiB
C++
1077 lines
40 KiB
C++
#include "v2/NativeNetworkingImpl.h"
|
||
|
||
#include "p2p/base/basic_packet_socket_factory.h"
|
||
#include "p2p/client/basic_port_allocator.h"
|
||
#include "p2p/base/p2p_transport_channel.h"
|
||
#include "p2p/base/basic_async_resolver_factory.h"
|
||
#include "api/packet_socket_factory.h"
|
||
#include "rtc_base/rtc_certificate_generator.h"
|
||
#include "p2p/base/ice_credentials_iterator.h"
|
||
#include "api/jsep_ice_candidate.h"
|
||
#include "p2p/base/dtls_transport.h"
|
||
#include "p2p/base/dtls_transport_factory.h"
|
||
#include "pc/dtls_srtp_transport.h"
|
||
#include "pc/dtls_transport.h"
|
||
#include "pc/jsep_transport_controller.h"
|
||
#include "api/async_dns_resolver.h"
|
||
|
||
#include "TurnCustomizerImpl.h"
|
||
#include "ReflectorRelayPortFactory.h"
|
||
#include "SctpDataChannelProviderInterfaceImpl.h"
|
||
#include "StaticThreads.h"
|
||
#include "platform/PlatformInterface.h"
|
||
#include "p2p/base/turn_port.h"
|
||
|
||
#include "ReflectorPort.h"
|
||
#include "FieldTrialsConfig.h"
|
||
#include "EncryptedConnection.h"
|
||
#include "v2/CustomParameters.h"
|
||
|
||
namespace tgcalls {
|
||
|
||
namespace {
|
||
|
||
class CryptStringImpl : public rtc::CryptStringImpl {
|
||
public:
|
||
CryptStringImpl(std::string const &value) :
|
||
_value(value) {
|
||
}
|
||
|
||
virtual ~CryptStringImpl() override {
|
||
}
|
||
|
||
virtual size_t GetLength() const override {
|
||
return _value.size();
|
||
}
|
||
|
||
virtual void CopyTo(char* dest, bool nullterminate) const override {
|
||
memcpy(dest, _value.data(), _value.size());
|
||
if (nullterminate) {
|
||
dest[_value.size()] = 0;
|
||
}
|
||
}
|
||
virtual std::string UrlEncode() const override {
|
||
return _value;
|
||
}
|
||
virtual CryptStringImpl* Copy() const override {
|
||
return new CryptStringImpl(_value);
|
||
}
|
||
|
||
virtual void CopyRawTo(std::vector<unsigned char>* dest) const override {
|
||
dest->resize(_value.size());
|
||
memcpy(dest->data(), _value.data(), _value.size());
|
||
}
|
||
|
||
private:
|
||
std::string _value;
|
||
};
|
||
|
||
class WrappedAsyncPacketSocket : public rtc::AsyncPacketSocket {
|
||
public:
|
||
WrappedAsyncPacketSocket(std::unique_ptr<rtc::AsyncPacketSocket> &&wrappedSocket) :
|
||
_wrappedSocket(std::move(wrappedSocket)) {
|
||
_wrappedSocket->RegisterReceivedPacketCallback([this](AsyncPacketSocket *socket, rtc::ReceivedPacket const &packet) {
|
||
this->onReadPacket(packet);
|
||
});
|
||
_wrappedSocket->SignalSentPacket.connect(this, &WrappedAsyncPacketSocket::onSentPacket);
|
||
_wrappedSocket->SignalReadyToSend.connect(this, &WrappedAsyncPacketSocket::onReadyToSend);
|
||
_wrappedSocket->SignalAddressReady.connect(this, &WrappedAsyncPacketSocket::onAddressReady);
|
||
_wrappedSocket->SignalConnect.connect(this, &WrappedAsyncPacketSocket::onConnect);
|
||
_wrappedSocket->SubscribeCloseEvent(this, [this](AsyncPacketSocket* socket, int error) { onClose(socket, error); });
|
||
}
|
||
|
||
virtual ~WrappedAsyncPacketSocket() override {
|
||
_wrappedSocket->DeregisterReceivedPacketCallback();
|
||
_wrappedSocket->SignalSentPacket.disconnect(this);
|
||
_wrappedSocket->SignalReadyToSend.disconnect(this);
|
||
_wrappedSocket->SignalAddressReady.disconnect(this);
|
||
_wrappedSocket->SignalConnect.disconnect(this);
|
||
_wrappedSocket->UnsubscribeCloseEvent(this);
|
||
|
||
_wrappedSocket.reset();
|
||
}
|
||
|
||
virtual rtc::SocketAddress GetLocalAddress() const override {
|
||
return _wrappedSocket->GetLocalAddress();
|
||
}
|
||
|
||
virtual rtc::SocketAddress GetRemoteAddress() const override {
|
||
return _wrappedSocket->GetRemoteAddress();
|
||
}
|
||
|
||
virtual int Send(const void* pv, size_t cb, const rtc::PacketOptions& options) override {
|
||
return _wrappedSocket->Send(pv, cb, options);
|
||
}
|
||
|
||
virtual int SendTo(const void* pv,
|
||
size_t cb,
|
||
const rtc::SocketAddress& addr,
|
||
const rtc::PacketOptions& options) override {
|
||
return _wrappedSocket->SendTo(pv, cb, addr, options);
|
||
}
|
||
|
||
virtual int Close() override {
|
||
return _wrappedSocket->Close();
|
||
}
|
||
|
||
virtual State GetState() const override {
|
||
return _wrappedSocket->GetState();
|
||
}
|
||
|
||
virtual int GetOption(rtc::Socket::Option opt, int* value) override {
|
||
return _wrappedSocket->GetOption(opt, value);
|
||
}
|
||
|
||
virtual int SetOption(rtc::Socket::Option opt, int value) override {
|
||
return _wrappedSocket->SetOption(opt, value);
|
||
}
|
||
|
||
virtual int GetError() const override {
|
||
return _wrappedSocket->GetError();
|
||
}
|
||
|
||
virtual void SetError(int error) override {
|
||
_wrappedSocket->SetError(error);
|
||
}
|
||
|
||
private:
|
||
void onReadPacket(rtc::ReceivedPacket const &packet) {
|
||
NotifyPacketReceived(packet);
|
||
}
|
||
|
||
void onSentPacket(AsyncPacketSocket *socket, const rtc::SentPacket &packet) {
|
||
SignalSentPacket.emit(this, packet);
|
||
}
|
||
|
||
void onReadyToSend(AsyncPacketSocket *socket) {
|
||
SignalReadyToSend.emit(this);
|
||
}
|
||
|
||
void onAddressReady(AsyncPacketSocket *socket, const rtc::SocketAddress &address) {
|
||
SignalAddressReady.emit(this, address);
|
||
}
|
||
|
||
void onConnect(AsyncPacketSocket *socket) {
|
||
SignalConnect.emit(this);
|
||
}
|
||
|
||
void onClose(AsyncPacketSocket *socket, int value) {
|
||
SignalClose(this, value);
|
||
}
|
||
|
||
private:
|
||
std::unique_ptr<rtc::AsyncPacketSocket> _wrappedSocket;
|
||
};
|
||
|
||
class WrappedBasicPacketSocketFactory : public rtc::PacketSocketFactory {
|
||
public:
|
||
WrappedBasicPacketSocketFactory(std::unique_ptr<rtc::BasicPacketSocketFactory> &&impl, bool standaloneReflectorMode) :
|
||
_impl(std::move(impl)),
|
||
_standaloneReflectorMode(standaloneReflectorMode) {
|
||
}
|
||
|
||
virtual ~WrappedBasicPacketSocketFactory() {
|
||
}
|
||
|
||
virtual rtc::AsyncPacketSocket *CreateUdpSocket(const rtc::SocketAddress& address, uint16_t min_port, uint16_t max_port) override {
|
||
in_addr v4addr;
|
||
inet_pton(AF_INET, "0.1.2.3", &v4addr);
|
||
rtc::IPAddress ipAddress(v4addr);
|
||
if (_standaloneReflectorMode && address.ipaddr() == ipAddress && address.port() != 12345) {
|
||
return nullptr;
|
||
} else {
|
||
rtc::SocketAddress updatedAddress = address;
|
||
if (updatedAddress.port() == 12345) {
|
||
updatedAddress.SetPort(0);
|
||
}
|
||
return _impl->CreateUdpSocket(updatedAddress, min_port, max_port);
|
||
}
|
||
}
|
||
|
||
virtual rtc::AsyncListenSocket *CreateServerTcpSocket(const rtc::SocketAddress &local_address, uint16_t min_port, uint16_t max_port, int opts) override {
|
||
in_addr v4addr;
|
||
inet_pton(AF_INET, "0.1.2.3", &v4addr);
|
||
rtc::IPAddress ipAddress(v4addr);
|
||
if (_standaloneReflectorMode && local_address.ipaddr() == ipAddress) {
|
||
return nullptr;
|
||
} else {
|
||
return _impl->CreateServerTcpSocket(local_address, min_port, max_port, opts);
|
||
}
|
||
}
|
||
|
||
virtual rtc::AsyncPacketSocket *CreateClientTcpSocket(const rtc::SocketAddress &local_address, const rtc::SocketAddress& remote_address, const rtc::ProxyInfo& proxy_info, const std::string &user_agent, const rtc::PacketSocketTcpOptions& tcp_options) override {
|
||
in_addr v4addr;
|
||
inet_pton(AF_INET, "0.1.2.3", &v4addr);
|
||
rtc::IPAddress ipAddress(v4addr);
|
||
if (_standaloneReflectorMode && local_address.ipaddr() == ipAddress) {
|
||
return nullptr;
|
||
} else {
|
||
return _impl->CreateClientTcpSocket(local_address, remote_address, proxy_info, user_agent, tcp_options);
|
||
}
|
||
}
|
||
|
||
virtual std::unique_ptr<webrtc::AsyncDnsResolverInterface> CreateAsyncDnsResolver() override {
|
||
return _impl->CreateAsyncDnsResolver();
|
||
}
|
||
private:
|
||
std::unique_ptr<rtc::BasicPacketSocketFactory> _impl;
|
||
bool _standaloneReflectorMode = false;
|
||
};
|
||
|
||
class WrappedNetworkManager: public rtc::NetworkManager, public sigslot::has_slots<> {
|
||
public:
|
||
WrappedNetworkManager(rtc::NetworkMonitorFactory *networkMonitorFactory, rtc::SocketFactory *socketFactory) {
|
||
in_addr v4addr;
|
||
inet_pton(AF_INET, "0.1.2.3", &v4addr);
|
||
rtc::IPAddress ipAddress(v4addr);
|
||
_sharedReflectorNetwork = std::make_unique<rtc::Network>(
|
||
"shared-reflector-network",
|
||
"shared-reflector-network",
|
||
ipAddress,
|
||
0,
|
||
rtc::AdapterType::ADAPTER_TYPE_UNKNOWN
|
||
);
|
||
_sharedReflectorNetwork->AddIP(ipAddress);
|
||
|
||
_impl = std::make_unique<rtc::BasicNetworkManager>(networkMonitorFactory, socketFactory);
|
||
|
||
_impl->SignalNetworksChanged.connect(this, &WrappedNetworkManager::PassthroughSignalNetworksChanged);
|
||
_impl->SignalError.connect(this, &WrappedNetworkManager::PassthroughSignalError);
|
||
}
|
||
|
||
public:
|
||
void PassthroughSignalNetworksChanged() {
|
||
SignalNetworksChanged();
|
||
}
|
||
|
||
void PassthroughSignalError() {
|
||
SignalError();
|
||
}
|
||
|
||
virtual void Initialize() override {
|
||
_impl->Initialize();
|
||
}
|
||
|
||
virtual void StartUpdating() override {
|
||
_impl->StartUpdating();
|
||
}
|
||
|
||
virtual void StopUpdating() override {
|
||
_impl->StopUpdating();
|
||
}
|
||
|
||
virtual std::vector<const rtc::Network *> GetNetworks() const override {
|
||
//return _impl->GetNetworks();
|
||
|
||
std::vector<const rtc::Network *> result;
|
||
result.push_back(_sharedReflectorNetwork.get());
|
||
return result;
|
||
}
|
||
|
||
virtual EnumerationPermission enumeration_permission() const override {
|
||
return _impl->enumeration_permission();
|
||
}
|
||
|
||
virtual std::vector<const rtc::Network *> GetAnyAddressNetworks() override {
|
||
return _impl->GetAnyAddressNetworks();
|
||
}
|
||
|
||
virtual void DumpNetworks() override {
|
||
_impl->DumpNetworks();
|
||
}
|
||
|
||
bool GetDefaultLocalAddress(int family, rtc::IPAddress *ipaddr) const override {
|
||
return _impl->GetDefaultLocalAddress(family, ipaddr);
|
||
}
|
||
|
||
webrtc::MdnsResponderInterface* GetMdnsResponder() const override {
|
||
return _impl->GetMdnsResponder();
|
||
}
|
||
|
||
virtual void set_vpn_list(const std::vector<rtc::NetworkMask> &vpn) override {
|
||
_impl->set_vpn_list(vpn);
|
||
}
|
||
|
||
private:
|
||
std::unique_ptr<rtc::BasicNetworkManager> _impl;
|
||
std::unique_ptr<rtc::Network> _sharedReflectorNetwork;
|
||
};
|
||
|
||
class MtProtoPacketTransport : public rtc::PacketTransportInternal {
|
||
public:
|
||
MtProtoPacketTransport(
|
||
rtc::PacketTransportInternal *rawTransport,
|
||
EncryptionKey encryptionKey
|
||
) :
|
||
_rawTransport(rawTransport) {
|
||
_rawTransport->SignalWritableState.connect(this, &MtProtoPacketTransport::InternalOnWritableState);
|
||
_rawTransport->SignalReadyToSend.connect(this, &MtProtoPacketTransport::InternalOnReadyToSend);
|
||
_rawTransport->SignalReceivingState.connect(this, &MtProtoPacketTransport::InternalOnReceivingState);
|
||
_rawTransport->SignalReadPacket.connect(this, &MtProtoPacketTransport::InternalOnReadPacket);
|
||
_rawTransport->SignalSentPacket.connect(this, &MtProtoPacketTransport::InternalOnSentPacket);
|
||
_rawTransport->SignalNetworkRouteChanged.connect(this, &MtProtoPacketTransport::InternalOnNetworkRouteChanged);
|
||
_rawTransport->SignalClosed.connect(this, &MtProtoPacketTransport::InternalOnClosed);
|
||
|
||
_transportEncryption = std::make_unique<EncryptedConnection>(
|
||
EncryptedConnection::Type::Transport,
|
||
encryptionKey,
|
||
[=](int delayMs, int cause) {
|
||
}
|
||
);
|
||
}
|
||
|
||
virtual ~MtProtoPacketTransport() {
|
||
_rawTransport->SignalWritableState.disconnect(this);
|
||
_rawTransport->SignalReadyToSend.disconnect(this);
|
||
_rawTransport->SignalReceivingState.disconnect(this);
|
||
_rawTransport->SignalReadPacket.disconnect(this);
|
||
_rawTransport->SignalSentPacket.disconnect(this);
|
||
_rawTransport->SignalNetworkRouteChanged.disconnect(this);
|
||
_rawTransport->SignalClosed.disconnect(this);
|
||
}
|
||
|
||
virtual const std::string& transport_name() const override {
|
||
return _rawTransport->transport_name();
|
||
}
|
||
|
||
virtual bool writable() const override {
|
||
return _rawTransport->writable();
|
||
}
|
||
|
||
virtual bool receiving() const override {
|
||
return _rawTransport->receiving();
|
||
}
|
||
|
||
virtual int SendPacket(
|
||
const char *data,
|
||
size_t len,
|
||
const rtc::PacketOptions &options,
|
||
int flags
|
||
) override {
|
||
if (flags != 0) {
|
||
rtc::CopyOnWriteBuffer buffer;
|
||
buffer.AppendData((const unsigned char *)data, len);
|
||
SendPacketInternal(buffer, options);
|
||
return 0;
|
||
} else {
|
||
rtc::CopyOnWriteBuffer buffer;
|
||
uint32_t magic = 0xdcdcdcdc; // SCTP
|
||
buffer.AppendData((const unsigned char *)&magic, 4);
|
||
buffer.AppendData((const unsigned char *)data, len);
|
||
SendPacketInternal(buffer, options);
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
virtual int SetOption(rtc::Socket::Option opt, int value) override {
|
||
return _rawTransport->SetOption(opt, value);
|
||
}
|
||
|
||
virtual bool GetOption(rtc::Socket::Option opt, int* value) override {
|
||
return _rawTransport->GetOption(opt, value);
|
||
}
|
||
|
||
virtual int GetError() override {
|
||
return _rawTransport->GetError();
|
||
}
|
||
|
||
virtual absl::optional<rtc::NetworkRoute> network_route() const override {
|
||
return _rawTransport->network_route();
|
||
}
|
||
|
||
private:
|
||
void InternalOnWritableState(PacketTransportInternal *transport) {
|
||
SignalWritableState(this);
|
||
}
|
||
|
||
void InternalOnReadyToSend(PacketTransportInternal *transport) {
|
||
SignalReadyToSend(this);
|
||
}
|
||
|
||
void InternalOnReceivingState(PacketTransportInternal *transport) {
|
||
SignalReceivingState(this);
|
||
}
|
||
|
||
void InternalOnReadPacket(PacketTransportInternal *transport, const char *data, size_t size, const int64_t ×tamp, int flags) {
|
||
if (const auto packet = _transportEncryption->handleIncomingRawPacket(data, size)) {
|
||
ProcessReadPacketInternal(packet.value().main.message, timestamp);
|
||
|
||
for (const auto &additional : packet.value().additional) {
|
||
ProcessReadPacketInternal(additional.message, timestamp);
|
||
}
|
||
}
|
||
}
|
||
|
||
void InternalOnSentPacket(PacketTransportInternal *transport, const rtc::SentPacket &packet) {
|
||
SignalSentPacket(this, packet);
|
||
}
|
||
|
||
void InternalOnNetworkRouteChanged(absl::optional<rtc::NetworkRoute> route) {
|
||
SignalNetworkRouteChanged(route);
|
||
}
|
||
|
||
void InternalOnClosed(PacketTransportInternal *transport) {
|
||
SignalClosed(this);
|
||
}
|
||
|
||
private:
|
||
void SendPacketInternal(rtc::CopyOnWriteBuffer &packet, const rtc::PacketOptions &options) {
|
||
if (const auto encryptedPacket = _transportEncryption->prepareForSendingRawMessage(packet, false)) {
|
||
_rawTransport->SendPacket((const char *)encryptedPacket->bytes.data(), encryptedPacket->bytes.size(), options);
|
||
}
|
||
}
|
||
|
||
void ProcessReadPacketInternal(rtc::CopyOnWriteBuffer const &data, int64_t timestamp) {
|
||
if (data.size() >= 4) {
|
||
uint32_t header = 0;
|
||
memcpy(&header, data.data(), 4);
|
||
uint32_t magic = 0xdcdcdcdc; // SCTP
|
||
if (header == magic) {
|
||
SignalReadPacket(this, (const char *)(data.data() + 4), data.size() - 4, timestamp, 0);
|
||
} else {
|
||
SignalReadPacket(this, (const char *)data.data(), data.size(), timestamp, 1);
|
||
}
|
||
} else {
|
||
SignalReadPacket(this, (const char *)data.data(), data.size(), timestamp, 1);
|
||
}
|
||
}
|
||
|
||
private:
|
||
rtc::PacketTransportInternal *_rawTransport = nullptr;
|
||
std::unique_ptr<EncryptedConnection> _transportEncryption;
|
||
};
|
||
|
||
class MtProtoRtpTransport : public webrtc::RtpTransport {
|
||
public:
|
||
explicit MtProtoRtpTransport(cricket::IceTransportInternal *iceTransport, EncryptionKey encryptionKey) :
|
||
webrtc::RtpTransport(true) {
|
||
_packetTransport = std::make_unique<MtProtoPacketTransport>(iceTransport, encryptionKey);
|
||
SetRtpPacketTransport(_packetTransport.get());
|
||
}
|
||
|
||
virtual bool IsSrtpActive() const override {
|
||
return true;
|
||
}
|
||
|
||
virtual void OnWritableState(rtc::PacketTransportInternal *packet_transport) override {
|
||
webrtc::RtpTransport::OnWritableState(packet_transport);
|
||
|
||
SignalWritableState(packet_transport);
|
||
}
|
||
|
||
public:
|
||
sigslot::signal1<rtc::PacketTransportInternal *> SignalWritableState;
|
||
sigslot::signal1<rtc::PacketTransportInternal *> SignalReceivingState;
|
||
|
||
private:
|
||
std::unique_ptr<MtProtoPacketTransport> _packetTransport;
|
||
};
|
||
|
||
}
|
||
|
||
InstanceNetworking::ConnectionDescription::CandidateDescription InstanceNetworking::connectionDescriptionFromCandidate(cricket::Candidate const &candidate) {
|
||
InstanceNetworking::ConnectionDescription::CandidateDescription result;
|
||
|
||
result.type = candidate.type();
|
||
result.protocol = candidate.protocol();
|
||
result.address = candidate.address().ToString();
|
||
|
||
return result;
|
||
}
|
||
|
||
webrtc::CryptoOptions NativeNetworkingImpl::getDefaulCryptoOptions() {
|
||
auto options = webrtc::CryptoOptions();
|
||
options.srtp.enable_aes128_sha1_80_crypto_cipher = true;
|
||
options.srtp.enable_gcm_crypto_suites = true;
|
||
return options;
|
||
}
|
||
|
||
NativeNetworkingImpl::NativeNetworkingImpl(Configuration &&configuration) :
|
||
_threads(std::move(configuration.threads)),
|
||
_isOutgoing(configuration.isOutgoing),
|
||
_encryptionKey(configuration.encryptionKey),
|
||
_enableStunMarking(configuration.enableStunMarking),
|
||
_enableTCP(configuration.enableTCP),
|
||
_enableP2P(configuration.enableP2P),
|
||
_rtcServers(configuration.rtcServers),
|
||
_proxy(configuration.proxy),
|
||
_customParameters(configuration.customParameters),
|
||
_stateUpdated(std::move(configuration.stateUpdated)),
|
||
_candidateGathered(std::move(configuration.candidateGathered)),
|
||
_transportMessageReceived(std::move(configuration.transportMessageReceived)),
|
||
_rtcpPacketReceived(std::move(configuration.rtcpPacketReceived)),
|
||
_dataChannelStateUpdated(configuration.dataChannelStateUpdated),
|
||
_dataChannelMessageReceived(configuration.dataChannelMessageReceived) {
|
||
assert(_threads->getNetworkThread()->IsCurrent());
|
||
|
||
_localIceParameters = PeerIceParameters(rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), rtc::CreateRandomString(cricket::ICE_PWD_LENGTH), true);
|
||
|
||
_localCertificate = rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams(rtc::KT_ECDSA), absl::nullopt);
|
||
|
||
_underlyingSocketFactory = _threads->getNetworkThread()->socketserver();
|
||
|
||
_networkMonitorFactory = PlatformInterface::SharedInstance()->createNetworkMonitorFactory();
|
||
if (getCustomParameterBool(_customParameters, "network_standalone_reflectors")) {
|
||
_socketFactory = std::make_unique<WrappedBasicPacketSocketFactory>(std::make_unique<rtc::BasicPacketSocketFactory>(_threads->getNetworkThread()->socketserver()), true);
|
||
_networkManager = std::make_unique<WrappedNetworkManager>(_networkMonitorFactory.get(), _threads->getNetworkThread()->socketserver());
|
||
} else {
|
||
_socketFactory = std::make_unique<rtc::BasicPacketSocketFactory>(_threads->getNetworkThread()->socketserver());
|
||
_networkManager = std::make_unique<rtc::BasicNetworkManager>(_networkMonitorFactory.get(), _threads->getNetworkThread()->socketserver());
|
||
}
|
||
|
||
_asyncResolverFactory = std::make_unique<webrtc::BasicAsyncDnsResolverFactory>();
|
||
|
||
if (getCustomParameterBool(_customParameters, "network_use_mtproto")) {
|
||
|
||
} else {
|
||
_dtlsSrtpTransport = std::make_unique<webrtc::DtlsSrtpTransport>(true, fieldTrialsBasedConfig);
|
||
_dtlsSrtpTransport->SetDtlsTransports(nullptr, nullptr);
|
||
_dtlsSrtpTransport->SetActiveResetSrtpParams(false);
|
||
_dtlsSrtpTransport->SubscribeReadyToSend(this, [this](bool value) {
|
||
this->DtlsReadyToSend(value);
|
||
});
|
||
_dtlsSrtpTransport->SubscribeRtcpPacketReceived(this, [this](rtc::CopyOnWriteBuffer *packet, int64_t timestamp) {
|
||
this->OnRtcpPacketReceived_n(packet, timestamp);
|
||
});
|
||
}
|
||
resetDtlsSrtpTransport();
|
||
}
|
||
|
||
NativeNetworkingImpl::~NativeNetworkingImpl() {
|
||
assert(_threads->getNetworkThread()->IsCurrent());
|
||
|
||
RTC_LOG(LS_INFO) << "NativeNetworkingImpl::~NativeNetworkingImpl()";
|
||
|
||
_mtProtoRtpTransport.reset();
|
||
_dtlsSrtpTransport.reset();
|
||
_dtlsTransport.reset();
|
||
_dataChannelInterface.reset();
|
||
_transportChannel.reset();
|
||
_asyncResolverFactory.reset();
|
||
_portAllocator.reset();
|
||
_networkManager.reset();
|
||
_underlyingSocketFactory = nullptr;
|
||
_socketFactory.reset();
|
||
_networkMonitorFactory.reset();
|
||
}
|
||
|
||
void NativeNetworkingImpl::resetDtlsSrtpTransport() {
|
||
if (_enableStunMarking) {
|
||
_turnCustomizer.reset(new TurnCustomizerImpl());
|
||
}
|
||
|
||
bool standaloneReflectorMode = getCustomParameterBool(_customParameters, "network_standalone_reflectors");
|
||
|
||
uint32_t standaloneReflectorRoleId = 0;
|
||
if (standaloneReflectorMode) {
|
||
if (_isOutgoing) {
|
||
standaloneReflectorRoleId = 1;
|
||
} else {
|
||
standaloneReflectorRoleId = 2;
|
||
}
|
||
}
|
||
|
||
_relayPortFactory.reset(new ReflectorRelayPortFactory(_rtcServers, standaloneReflectorMode, standaloneReflectorRoleId, _underlyingSocketFactory, getCustomParameterBool(_customParameters, "network_reflector_resolve_remote_candidate_ip")));
|
||
|
||
_portAllocator.reset(new cricket::BasicPortAllocator(_networkManager.get(), _socketFactory.get(), _turnCustomizer.get(), _relayPortFactory.get()));
|
||
|
||
uint32_t flags = _portAllocator->flags();
|
||
|
||
if (getCustomParameterBool(_customParameters, "network_use_default_route")) {
|
||
flags |= cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION;
|
||
}
|
||
|
||
if (getCustomParameterBool(_customParameters, "network_enable_shared_socket")) {
|
||
flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET;
|
||
}
|
||
|
||
flags |=
|
||
cricket::PORTALLOCATOR_ENABLE_IPV6 |
|
||
cricket::PORTALLOCATOR_ENABLE_IPV6_ON_WIFI;
|
||
|
||
if (!_enableTCP) {
|
||
flags |= cricket::PORTALLOCATOR_DISABLE_TCP;
|
||
}
|
||
|
||
if (_proxy || !_enableP2P) {
|
||
flags |= cricket::PORTALLOCATOR_DISABLE_UDP;
|
||
flags |= cricket::PORTALLOCATOR_DISABLE_STUN;
|
||
uint32_t candidateFilter = _portAllocator->candidate_filter();
|
||
candidateFilter &= ~(cricket::CF_REFLEXIVE);
|
||
_portAllocator->SetCandidateFilter(candidateFilter);
|
||
}
|
||
|
||
_portAllocator->set_step_delay(cricket::kMinimumStepDelay);
|
||
|
||
_portAllocator->set_flags(flags);
|
||
_portAllocator->Initialize();
|
||
|
||
cricket::ServerAddresses stunServers;
|
||
std::vector<cricket::RelayServerConfig> turnServers;
|
||
|
||
for (auto &server : _rtcServers) {
|
||
if (server.isTurn) {
|
||
cricket::ProtocolType proto = cricket::PROTO_UDP;
|
||
if (server.isTls) {
|
||
proto = cricket::PROTO_TLS;
|
||
} else if (server.isTcp) {
|
||
proto = cricket::PROTO_TCP;
|
||
}
|
||
cricket::RelayServerConfig relayConfig(
|
||
rtc::SocketAddress(server.host, server.port),
|
||
server.login,
|
||
server.password,
|
||
proto
|
||
);
|
||
if (server.isTls) {
|
||
// Сервер адресуется по IP, а не по имени, поэтому проверять цепочку
|
||
// сертификата не по чему. TLS здесь не защищает медиа — оно и так
|
||
// зашифровано выше по стеку — а только придаёт трафику вид HTTPS.
|
||
relayConfig.tls_cert_policy = cricket::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK;
|
||
}
|
||
RTC_LOG(LS_INFO) << "Adding TURN server: " << server.host << ":" << server.port
|
||
<< " proto=" << (server.isTls ? "tls" : (server.isTcp ? "tcp" : "udp"));
|
||
turnServers.push_back(std::move(relayConfig));
|
||
} else {
|
||
rtc::SocketAddress stunAddress = rtc::SocketAddress(server.host, server.port);
|
||
stunServers.insert(stunAddress);
|
||
}
|
||
}
|
||
|
||
_portAllocator->SetConfiguration(stunServers, turnServers, 0, webrtc::NO_PRUNE, _turnCustomizer.get());
|
||
|
||
webrtc::IceTransportInit iceTransportInit;
|
||
iceTransportInit.set_port_allocator(_portAllocator.get());
|
||
iceTransportInit.set_async_dns_resolver_factory(_asyncResolverFactory.get());
|
||
|
||
_transportChannel = cricket::P2PTransportChannel::Create("transport", 0, std::move(iceTransportInit));
|
||
|
||
cricket::IceConfig iceConfig;
|
||
iceConfig.continual_gathering_policy = cricket::GATHER_CONTINUALLY;
|
||
iceConfig.prioritize_most_likely_candidate_pairs = true;
|
||
iceConfig.regather_on_failed_networks_interval = cricket::REGATHER_ON_FAILED_NETWORKS_INTERVAL;
|
||
|
||
if (getCustomParameterBool(_customParameters, "network_skip_initial_ping")) {
|
||
iceConfig.presume_writable_when_fully_relayed = true;
|
||
}
|
||
_transportChannel->SetIceConfig(iceConfig);
|
||
|
||
cricket::IceParameters localIceParameters(
|
||
_localIceParameters.ufrag,
|
||
_localIceParameters.pwd,
|
||
_localIceParameters.supportsRenomination
|
||
);
|
||
|
||
_transportChannel->SetIceParameters(localIceParameters);
|
||
_transportChannel->SetIceRole(_isOutgoing ? cricket::ICEROLE_CONTROLLING : cricket::ICEROLE_CONTROLLED);
|
||
_transportChannel->SetRemoteIceMode(cricket::ICEMODE_FULL);
|
||
|
||
_transportChannel->SignalCandidateGathered.connect(this, &NativeNetworkingImpl::candidateGathered);
|
||
_transportChannel->SignalIceTransportStateChanged.connect(this, &NativeNetworkingImpl::transportStateChanged);
|
||
_transportChannel->SetCandidatePairChangeCallback([this](cricket::CandidatePairChangeEvent const &event) {
|
||
this->candidatePairChanged(event);
|
||
});
|
||
_transportChannel->SignalNetworkRouteChanged.connect(this, &NativeNetworkingImpl::transportRouteChanged);
|
||
|
||
if (getCustomParameterBool(_customParameters, "network_use_mtproto")) {
|
||
_mtProtoRtpTransport = std::make_unique<MtProtoRtpTransport>(_transportChannel.get(), _encryptionKey);
|
||
|
||
((MtProtoRtpTransport *)_mtProtoRtpTransport.get())->SignalWritableState.connect(this, &NativeNetworkingImpl::OnTransportWritableState_n);
|
||
((MtProtoRtpTransport *)_mtProtoRtpTransport.get())->SignalReceivingState.connect(this, &NativeNetworkingImpl::OnTransportReceivingState_n);
|
||
|
||
_mtProtoRtpTransport->SubscribeReadyToSend(this, [this](bool value) {
|
||
this->DtlsReadyToSend(value);
|
||
});
|
||
_mtProtoRtpTransport->SubscribeRtcpPacketReceived(this, [this](rtc::CopyOnWriteBuffer *packet, int64_t timestamp) {
|
||
this->OnRtcpPacketReceived_n(packet, timestamp);
|
||
});
|
||
} else {
|
||
webrtc::CryptoOptions cryptoOptions = NativeNetworkingImpl::getDefaulCryptoOptions();
|
||
_dtlsTransport.reset(new cricket::DtlsTransport(_transportChannel.get(), cryptoOptions, nullptr));
|
||
|
||
_dtlsTransport->SignalWritableState.connect(this, &NativeNetworkingImpl::OnTransportWritableState_n);
|
||
_dtlsTransport->SignalReceivingState.connect(this, &NativeNetworkingImpl::OnTransportReceivingState_n);
|
||
|
||
_dtlsTransport->SetLocalCertificate(_localCertificate);
|
||
|
||
_dtlsSrtpTransport->SetDtlsTransports(_dtlsTransport.get(), nullptr);
|
||
}
|
||
}
|
||
|
||
void NativeNetworkingImpl::start() {
|
||
_transportChannel->MaybeStartGathering();
|
||
|
||
rtc::PacketTransportInternal *sctpPacketTransport = nullptr;
|
||
if (_mtProtoRtpTransport) {
|
||
sctpPacketTransport = _mtProtoRtpTransport->rtp_packet_transport();
|
||
} else {
|
||
sctpPacketTransport = _dtlsTransport.get();
|
||
}
|
||
|
||
const auto weak = std::weak_ptr<NativeNetworkingImpl>(shared_from_this());
|
||
_dataChannelInterface.reset(new SctpDataChannelProviderInterfaceImpl(
|
||
sctpPacketTransport,
|
||
_isOutgoing,
|
||
[weak, threads = _threads](bool state) {
|
||
assert(threads->getNetworkThread()->IsCurrent());
|
||
const auto strong = weak.lock();
|
||
if (!strong) {
|
||
return;
|
||
}
|
||
strong->_dataChannelStateUpdated(state);
|
||
},
|
||
[weak, threads = _threads]() {
|
||
assert(threads->getNetworkThread()->IsCurrent());
|
||
const auto strong = weak.lock();
|
||
if (!strong) {
|
||
return;
|
||
}
|
||
//strong->restartDataChannel();
|
||
},
|
||
[weak, threads = _threads](std::string const &message) {
|
||
assert(threads->getNetworkThread()->IsCurrent());
|
||
const auto strong = weak.lock();
|
||
if (!strong) {
|
||
return;
|
||
}
|
||
strong->_dataChannelMessageReceived(message);
|
||
},
|
||
_threads
|
||
));
|
||
|
||
_lastDisconnectedTimestamp = rtc::TimeMillis();
|
||
checkConnectionTimeout();
|
||
}
|
||
|
||
void NativeNetworkingImpl::stop() {
|
||
_transportChannel->SignalCandidateGathered.disconnect(this);
|
||
_transportChannel->SignalIceTransportStateChanged.disconnect(this);
|
||
_transportChannel->SignalReadPacket.disconnect(this);
|
||
_transportChannel->SignalNetworkRouteChanged.disconnect(this);
|
||
|
||
_dataChannelInterface.reset();
|
||
|
||
if (_dtlsTransport) {
|
||
_dtlsTransport->SignalWritableState.disconnect(this);
|
||
_dtlsTransport->SignalReceivingState.disconnect(this);
|
||
}
|
||
if (_dtlsSrtpTransport) {
|
||
_dtlsSrtpTransport->SetDtlsTransports(nullptr, nullptr);
|
||
}
|
||
|
||
if (_mtProtoRtpTransport) {
|
||
((MtProtoRtpTransport *)_mtProtoRtpTransport.get())->SignalWritableState.disconnect(this);
|
||
((MtProtoRtpTransport *)_mtProtoRtpTransport.get())->SignalReceivingState.disconnect(this);
|
||
_mtProtoRtpTransport.reset();
|
||
}
|
||
|
||
_dtlsTransport.reset();
|
||
_transportChannel.reset();
|
||
_portAllocator.reset();
|
||
|
||
_localIceParameters = PeerIceParameters(rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), rtc::CreateRandomString(cricket::ICE_PWD_LENGTH), true);
|
||
|
||
_localCertificate = rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams(rtc::KT_ECDSA), absl::nullopt);
|
||
}
|
||
|
||
PeerIceParameters NativeNetworkingImpl::getLocalIceParameters() {
|
||
return _localIceParameters;
|
||
}
|
||
|
||
std::unique_ptr<rtc::SSLFingerprint> NativeNetworkingImpl::getLocalFingerprint() {
|
||
auto certificate = _localCertificate;
|
||
if (!certificate) {
|
||
return nullptr;
|
||
}
|
||
return rtc::SSLFingerprint::CreateFromCertificate(*certificate);
|
||
}
|
||
|
||
void NativeNetworkingImpl::setRemoteParams(PeerIceParameters const &remoteIceParameters, rtc::SSLFingerprint *fingerprint, std::string const &sslSetup) {
|
||
_remoteIceParameters = remoteIceParameters;
|
||
|
||
cricket::IceParameters parameters(
|
||
remoteIceParameters.ufrag,
|
||
remoteIceParameters.pwd,
|
||
remoteIceParameters.supportsRenomination
|
||
);
|
||
|
||
_transportChannel->SetRemoteIceParameters(parameters);
|
||
|
||
rtc::SSLRole sslRole;
|
||
if (sslSetup == "active") {
|
||
sslRole = rtc::SSLRole::SSL_SERVER;
|
||
} else if (sslSetup == "passive") {
|
||
sslRole = rtc::SSLRole::SSL_CLIENT;
|
||
} else {
|
||
sslRole = _isOutgoing ? rtc::SSLRole::SSL_CLIENT : rtc::SSLRole::SSL_SERVER;
|
||
}
|
||
|
||
if (fingerprint) {
|
||
if (_dtlsTransport) {
|
||
_dtlsTransport->SetRemoteParameters(fingerprint->algorithm, fingerprint->digest.data(), fingerprint->digest.size(), sslRole);
|
||
}
|
||
}
|
||
|
||
processPendingLocalStandaloneReflectorCandidates();
|
||
}
|
||
|
||
void NativeNetworkingImpl::addCandidates(std::vector<cricket::Candidate> const &candidates) {
|
||
bool standaloneReflectorMode = getCustomParameterBool(_customParameters, "network_standalone_reflectors");
|
||
|
||
for (const auto &candidate : candidates) {
|
||
if (standaloneReflectorMode) {
|
||
if (absl::EndsWith(candidate.address().hostname(), ".reflector")) {
|
||
continue;
|
||
}
|
||
}
|
||
|
||
_transportChannel->AddRemoteCandidate(candidate);
|
||
}
|
||
}
|
||
|
||
void NativeNetworkingImpl::sendDataChannelMessage(std::string const &message) {
|
||
if (_dataChannelInterface) {
|
||
_dataChannelInterface->sendDataChannelMessage(message);
|
||
}
|
||
}
|
||
|
||
webrtc::RtpTransport *NativeNetworkingImpl::getRtpTransport() {
|
||
if (_mtProtoRtpTransport) {
|
||
return _mtProtoRtpTransport.get();
|
||
} else {
|
||
return _dtlsSrtpTransport.get();
|
||
}
|
||
}
|
||
|
||
void NativeNetworkingImpl::checkConnectionTimeout() {
|
||
const auto weak = std::weak_ptr<NativeNetworkingImpl>(shared_from_this());
|
||
_threads->getNetworkThread()->PostDelayedTask([weak]() {
|
||
auto strong = weak.lock();
|
||
if (!strong) {
|
||
return;
|
||
}
|
||
|
||
int64_t currentTimestamp = rtc::TimeMillis();
|
||
const int64_t maxTimeout = 20000;
|
||
|
||
if (!strong->_isConnected && strong->_lastDisconnectedTimestamp + maxTimeout < currentTimestamp) {
|
||
RTC_LOG(LS_INFO) << "NativeNetworkingImpl timeout " << (currentTimestamp - strong->_lastDisconnectedTimestamp) << " ms";
|
||
|
||
strong->_isFailed = true;
|
||
strong->notifyStateUpdated();
|
||
}
|
||
|
||
strong->checkConnectionTimeout();
|
||
}, webrtc::TimeDelta::Millis(1000));
|
||
}
|
||
|
||
void NativeNetworkingImpl::candidateGathered(cricket::IceTransportInternal *transport, const cricket::Candidate &candidate) {
|
||
assert(_threads->getNetworkThread()->IsCurrent());
|
||
|
||
bool standaloneReflectorMode = getCustomParameterBool(_customParameters, "network_standalone_reflectors");
|
||
if (standaloneReflectorMode && absl::EndsWith(candidate.address().hostname(), ".reflector")) {
|
||
_pendingLocalStandaloneReflectorCandidates.push_back(candidate);
|
||
|
||
if (_remoteIceParameters) {
|
||
processPendingLocalStandaloneReflectorCandidates();
|
||
}
|
||
} else {
|
||
_candidateGathered(candidate);
|
||
}
|
||
}
|
||
|
||
void NativeNetworkingImpl::processPendingLocalStandaloneReflectorCandidates() {
|
||
if (!_remoteIceParameters) {
|
||
return;
|
||
}
|
||
|
||
auto candidates = _pendingLocalStandaloneReflectorCandidates;
|
||
_pendingLocalStandaloneReflectorCandidates.clear();
|
||
|
||
for (const auto &candidate : candidates) {
|
||
auto remoteHostname = candidate.address().hostname();
|
||
if (!remoteHostname.empty()) {
|
||
uint32_t standaloneReflectorRoleId = 0;
|
||
if (_isOutgoing) {
|
||
standaloneReflectorRoleId = 1;
|
||
} else {
|
||
standaloneReflectorRoleId = 2;
|
||
}
|
||
|
||
std::string prefixFormat = "reflector-";
|
||
std::string suffixFormat = "-" + std::to_string(standaloneReflectorRoleId) + ".reflector";
|
||
if (!absl::StartsWith(remoteHostname, prefixFormat) || !absl::EndsWith(remoteHostname, suffixFormat)) {
|
||
return;
|
||
}
|
||
|
||
auto startPosition = prefixFormat.size();
|
||
auto tagString = remoteHostname.substr(startPosition, remoteHostname.size() - suffixFormat.size() - startPosition);
|
||
|
||
std::stringstream tagStringStream(tagString);
|
||
|
||
uint32_t resolvedServerId = 0;
|
||
tagStringStream >> resolvedServerId;
|
||
|
||
uint32_t remoteReflectorRoleId = 0;
|
||
if (!_isOutgoing) {
|
||
remoteReflectorRoleId = 1;
|
||
} else {
|
||
remoteReflectorRoleId = 2;
|
||
}
|
||
|
||
if (resolvedServerId != 0) {
|
||
cricket::Candidate remoteCandidate = candidate;
|
||
rtc::SocketAddress address = remoteCandidate.address();
|
||
const auto remoteHost = "reflector-" + std::to_string(resolvedServerId) + "-" + std::to_string(remoteReflectorRoleId) + ".reflector";
|
||
address.SetIP(remoteHost);
|
||
address.SetResolvedIP(remoteCandidate.address().ipaddr());
|
||
remoteCandidate.set_address(address);
|
||
remoteCandidate.set_username(_remoteIceParameters->ufrag);
|
||
remoteCandidate.set_password(_remoteIceParameters->pwd);
|
||
_transportChannel->AddRemoteCandidate(remoteCandidate);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void NativeNetworkingImpl::candidateGatheringState(cricket::IceTransportInternal *transport) {
|
||
assert(_threads->getNetworkThread()->IsCurrent());
|
||
}
|
||
|
||
void NativeNetworkingImpl::OnTransportWritableState_n(rtc::PacketTransportInternal *transport) {
|
||
assert(_threads->getNetworkThread()->IsCurrent());
|
||
|
||
UpdateAggregateStates_n();
|
||
}
|
||
void NativeNetworkingImpl::OnTransportReceivingState_n(rtc::PacketTransportInternal *transport) {
|
||
assert(_threads->getNetworkThread()->IsCurrent());
|
||
|
||
UpdateAggregateStates_n();
|
||
}
|
||
|
||
void NativeNetworkingImpl::DtlsReadyToSend(bool isReadyToSend) {
|
||
UpdateAggregateStates_n();
|
||
|
||
if (isReadyToSend) {
|
||
const auto weak = std::weak_ptr<NativeNetworkingImpl>(shared_from_this());
|
||
_threads->getNetworkThread()->PostTask([weak]() {
|
||
const auto strong = weak.lock();
|
||
if (!strong) {
|
||
return;
|
||
}
|
||
strong->UpdateAggregateStates_n();
|
||
});
|
||
}
|
||
}
|
||
|
||
void NativeNetworkingImpl::transportStateChanged(cricket::IceTransportInternal *transport) {
|
||
UpdateAggregateStates_n();
|
||
}
|
||
|
||
void NativeNetworkingImpl::transportReadyToSend(cricket::IceTransportInternal *transport) {
|
||
assert(_threads->getNetworkThread()->IsCurrent());
|
||
}
|
||
|
||
void NativeNetworkingImpl::transportRouteChanged(absl::optional<rtc::NetworkRoute> route) {
|
||
assert(_threads->getNetworkThread()->IsCurrent());
|
||
|
||
if (route.has_value()) {
|
||
/*cricket::IceTransportStats iceTransportStats;
|
||
if (_transportChannel->GetStats(&iceTransportStats)) {
|
||
}*/
|
||
|
||
RTC_LOG(LS_INFO) << "NativeNetworkingImpl route changed: " << route->DebugString();
|
||
|
||
bool localIsWifi = route->local.adapter_type() == rtc::AdapterType::ADAPTER_TYPE_WIFI;
|
||
bool remoteIsWifi = route->remote.adapter_type() == rtc::AdapterType::ADAPTER_TYPE_WIFI;
|
||
|
||
RTC_LOG(LS_INFO) << "NativeNetworkingImpl is wifi: local=" << localIsWifi << ", remote=" << remoteIsWifi;
|
||
|
||
std::string localDescription = route->local.uses_turn() ? "turn" : "p2p";
|
||
std::string remoteDescription = route->remote.uses_turn() ? "turn" : "p2p";
|
||
|
||
RouteDescription routeDescription(localDescription, remoteDescription);
|
||
|
||
if (!_currentRouteDescription || routeDescription != _currentRouteDescription.value()) {
|
||
_currentRouteDescription = std::move(routeDescription);
|
||
notifyStateUpdated();
|
||
}
|
||
}
|
||
}
|
||
|
||
void NativeNetworkingImpl::candidatePairChanged(cricket::CandidatePairChangeEvent const &event) {
|
||
ConnectionDescription connectionDescription;
|
||
|
||
connectionDescription.local = InstanceNetworking::connectionDescriptionFromCandidate(event.selected_candidate_pair.local);
|
||
connectionDescription.remote = InstanceNetworking::connectionDescriptionFromCandidate(event.selected_candidate_pair.remote);
|
||
|
||
if (!_currentConnectionDescription || _currentConnectionDescription.value() != connectionDescription) {
|
||
_currentConnectionDescription = std::move(connectionDescription);
|
||
notifyStateUpdated();
|
||
}
|
||
}
|
||
|
||
void NativeNetworkingImpl::RtpPacketReceived_n(rtc::CopyOnWriteBuffer *packet, int64_t packet_time_us, bool isUnresolved) {
|
||
if (_transportMessageReceived) {
|
||
_transportMessageReceived(*packet, isUnresolved);
|
||
}
|
||
}
|
||
|
||
void NativeNetworkingImpl::OnRtcpPacketReceived_n(rtc::CopyOnWriteBuffer *packet, int64_t packet_time_us) {
|
||
if (_rtcpPacketReceived) {
|
||
_rtcpPacketReceived(*packet, packet_time_us);
|
||
}
|
||
}
|
||
|
||
void NativeNetworkingImpl::UpdateAggregateStates_n() {
|
||
assert(_threads->getNetworkThread()->IsCurrent());
|
||
|
||
auto state = _transportChannel->GetIceTransportState();
|
||
bool isConnected = false;
|
||
switch (state) {
|
||
case webrtc::IceTransportState::kConnected:
|
||
case webrtc::IceTransportState::kCompleted:
|
||
isConnected = true;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (_mtProtoRtpTransport) {
|
||
if (!_mtProtoRtpTransport->IsWritable(false)) {
|
||
isConnected = false;
|
||
}
|
||
} else {
|
||
if (!_dtlsSrtpTransport->IsWritable(false)) {
|
||
isConnected = false;
|
||
}
|
||
}
|
||
|
||
if (_isConnected != isConnected) {
|
||
_isConnected = isConnected;
|
||
|
||
if (!isConnected) {
|
||
_lastDisconnectedTimestamp = rtc::TimeMillis();
|
||
}
|
||
|
||
notifyStateUpdated();
|
||
|
||
if (_dataChannelInterface) {
|
||
_dataChannelInterface->updateIsConnected(isConnected);
|
||
}
|
||
}
|
||
}
|
||
|
||
void NativeNetworkingImpl::notifyStateUpdated() {
|
||
NativeNetworkingImpl::State emitState;
|
||
emitState.isReadyToSendData = _isConnected;
|
||
emitState.route = _currentRouteDescription;
|
||
emitState.connection = _currentConnectionDescription;
|
||
emitState.isFailed = _isFailed;
|
||
_stateUpdated(emitState);
|
||
}
|
||
|
||
void NativeNetworkingImpl::sctpReadyToSendData() {
|
||
}
|
||
|
||
} // namespace tgcalls
|