From a9a992b4343f6e8c45f50c06d785eebeeda3e340 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 12 Jun 2020 19:33:38 +0400 Subject: [PATCH] Temp --- .../ChatTextInputActionButtonsNode.swift | 2 +- .../ChatTextInputMediaRecordingButton.swift | 6 +- submodules/TelegramUI/Sources/LockView.swift | 4 +- .../Sources/OngoingCallContext.swift | 10 +- submodules/TgVoipWebrtc/Impl/Connector.h | 85 ++--- submodules/TgVoipWebrtc/Impl/Connector.mm | 338 +++++++----------- submodules/TgVoipWebrtc/Impl/Controller.h | 27 +- submodules/TgVoipWebrtc/Impl/Controller.mm | 161 +++------ submodules/TgVoipWebrtc/Impl/Endpoint.h | 126 ------- submodules/TgVoipWebrtc/Impl/Endpoint.mm | 205 ----------- submodules/TgVoipWebrtc/Impl/Layer92.cpp | 238 ------------ submodules/TgVoipWebrtc/Impl/Layer92.h | 49 --- submodules/TgVoipWebrtc/Impl/LayerBase.cpp | 17 - submodules/TgVoipWebrtc/Impl/LayerBase.h | 38 -- .../TgVoipWebrtc/Impl/MediaEngineBase.h | 2 +- .../TgVoipWebrtc/Impl/MediaEngineWebrtc.h | 43 +-- .../TgVoipWebrtc/Impl/MediaEngineWebrtc.mm | 238 +++++++----- submodules/TgVoipWebrtc/Impl/Message.h | 134 ------- submodules/TgVoipWebrtc/Impl/PlatformCodecs.h | 6 - .../TgVoipWebrtc/Impl/PlatformCodecs.mm | 2 - submodules/TgVoipWebrtc/Impl/Protocol10.cpp | 159 -------- submodules/TgVoipWebrtc/Impl/Protocol10.h | 44 --- submodules/TgVoipWebrtc/Impl/ProtocolBase.cpp | 23 -- submodules/TgVoipWebrtc/Impl/ProtocolBase.h | 33 -- submodules/TgVoipWebrtc/Impl/TgVoip.h | 24 +- submodules/TgVoipWebrtc/Impl/TgVoip.mm | 106 +++--- .../TgVoip/OngoingCallThreadLocalContext.h | 3 +- .../Sources/OngoingCallThreadLocalContext.mm | 53 ++- third-party/webrtc/build-webrtc-bazel.sh | 2 +- 29 files changed, 485 insertions(+), 1693 deletions(-) delete mode 100644 submodules/TgVoipWebrtc/Impl/Endpoint.h delete mode 100644 submodules/TgVoipWebrtc/Impl/Endpoint.mm delete mode 100644 submodules/TgVoipWebrtc/Impl/Layer92.cpp delete mode 100644 submodules/TgVoipWebrtc/Impl/Layer92.h delete mode 100644 submodules/TgVoipWebrtc/Impl/LayerBase.cpp delete mode 100644 submodules/TgVoipWebrtc/Impl/LayerBase.h delete mode 100644 submodules/TgVoipWebrtc/Impl/Message.h delete mode 100644 submodules/TgVoipWebrtc/Impl/PlatformCodecs.h delete mode 100644 submodules/TgVoipWebrtc/Impl/PlatformCodecs.mm delete mode 100644 submodules/TgVoipWebrtc/Impl/Protocol10.cpp delete mode 100644 submodules/TgVoipWebrtc/Impl/Protocol10.h delete mode 100644 submodules/TgVoipWebrtc/Impl/ProtocolBase.cpp delete mode 100644 submodules/TgVoipWebrtc/Impl/ProtocolBase.h diff --git a/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift b/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift index b2881a33ab..843549408b 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift @@ -29,7 +29,7 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode { init(theme: PresentationTheme, strings: PresentationStrings, presentController: @escaping (ViewController) -> Void) { self.strings = strings - self.micButton = ChatTextInputMediaRecordingButton(theme: theme, presentController: presentController) + self.micButton = ChatTextInputMediaRecordingButton(theme: theme, strings: strings, presentController: presentController) self.sendButton = HighlightTrackingButtonNode(pointerStyle: .lift) //self.sendButton.adjustsImageWhenHighlighted = false //self.sendButton.adjustsImageWhenDisabled = false diff --git a/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift b/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift index 354a2ad6d3..5853a96c38 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift @@ -155,6 +155,7 @@ private final class ChatTextInputMediaRecordingButtonPresenter : NSObject, TGMod final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButton, TGModernConversationInputMicButtonDelegate { private var theme: PresentationTheme + private let strings: PresentationStrings var mode: ChatTextInputMediaRecordingButtonMode = .audio var account: Account? @@ -236,8 +237,9 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto } } - init(theme: PresentationTheme, presentController: @escaping (ViewController) -> Void) { + init(theme: PresentationTheme, strings: PresentationStrings, presentController: @escaping (ViewController) -> Void) { self.theme = theme + self.strings = strings self.innerIconView = UIImageView() self.presentController = presentController @@ -399,7 +401,7 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto } func micButtonLock() -> (UIView & TGModernConversationInputMicButtonLock)! { - let lockView = LockView(frame: CGRect(origin: CGPoint(), size: CGSize(width: 40.0, height: 60.0)), theme: self.theme) + let lockView = LockView(frame: CGRect(origin: CGPoint(), size: CGSize(width: 40.0, height: 60.0)), theme: self.theme, strings: self.strings) lockView.addTarget(self, action: #selector(handleStopTap), for: .touchUpInside) return lockView } diff --git a/submodules/TelegramUI/Sources/LockView.swift b/submodules/TelegramUI/Sources/LockView.swift index 3f8a3132ee..44ae5da37f 100644 --- a/submodules/TelegramUI/Sources/LockView.swift +++ b/submodules/TelegramUI/Sources/LockView.swift @@ -32,9 +32,11 @@ final class LockView: UIButton, TGModernConversationInputMicButtonLock { return view }() - init(frame: CGRect, theme: PresentationTheme) { + init(frame: CGRect, theme: PresentationTheme, strings: PresentationStrings) { super.init(frame: frame) + accessibilityLabel = strings.VoiceOver_Recording_StopAndPreview + addSubview(idleView) idleView.frame = bounds diff --git a/submodules/TelegramVoip/Sources/OngoingCallContext.swift b/submodules/TelegramVoip/Sources/OngoingCallContext.swift index 6d1e151fea..a1080aa44d 100644 --- a/submodules/TelegramVoip/Sources/OngoingCallContext.swift +++ b/submodules/TelegramVoip/Sources/OngoingCallContext.swift @@ -464,7 +464,9 @@ public final class OngoingCallContext { break } } - let context = OngoingCallThreadLocalContextWebrtc(queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForTypeWebrtc(initialNetworkType), dataSaving: ongoingDataSavingForTypeWebrtc(dataSaving), derivedState: derivedState.data, key: key, isOutgoing: isOutgoing, primaryConnection: callConnectionDescriptionWebrtc(connections.primary), alternativeConnections: connections.alternatives.map(callConnectionDescriptionWebrtc), maxLayer: maxLayer, allowP2P: allowP2P, logPath: logPath) + let context = OngoingCallThreadLocalContextWebrtc(queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForTypeWebrtc(initialNetworkType), dataSaving: ongoingDataSavingForTypeWebrtc(dataSaving), derivedState: derivedState.data, key: key, isOutgoing: isOutgoing, primaryConnection: callConnectionDescriptionWebrtc(connections.primary), alternativeConnections: connections.alternatives.map(callConnectionDescriptionWebrtc), maxLayer: maxLayer, allowP2P: allowP2P, logPath: logPath, sendSignalingData: { [weak callSessionManager] data in + callSessionManager?.sendSignalingData(internalId: internalId, data: data) + }) strongSelf.contextRef = Unmanaged.passRetained(OngoingCallThreadLocalContextHolder(context)) context.stateChanged = { state in @@ -513,9 +515,9 @@ public final class OngoingCallContext { self.signalingDataDisposable = (callSessionManager.callSignalingData(internalId: internalId) |> deliverOn(self.queue)).start(next: { [weak self] data in self?.withContext { context in - /*if let context = context as? OngoingCallThreadLocalContextWebrtcCustom { - context.receiveSignaling(data) - }*/ + if let context = context as? OngoingCallThreadLocalContextWebrtc { + context.addSignaling(data) + } } }) } diff --git a/submodules/TgVoipWebrtc/Impl/Connector.h b/submodules/TgVoipWebrtc/Impl/Connector.h index 4331460a27..35187efafa 100644 --- a/submodules/TgVoipWebrtc/Impl/Connector.h +++ b/submodules/TgVoipWebrtc/Impl/Connector.h @@ -1,79 +1,50 @@ #ifndef DEMO_CONNECTOR_H #define DEMO_CONNECTOR_H - -#include "Endpoint.h" -#include "LayerBase.h" -#include "Message.h" - #include "p2p/base/basic_packet_socket_factory.h" #include "rtc_base/proxy_info.h" #include "rtc_base/task_utils/repeating_task.h" #include "rtc_base/third_party/sigslot/sigslot.h" #include "rtc_base/thread.h" +#include "p2p/base/p2p_transport_channel.h" +#include "p2p/client/basic_port_allocator.h" +#include "p2p/base/basic_async_resolver_factory.h" + #include #include class Connector : public sigslot::has_slots<> { public: - explicit Connector(std::unique_ptr layer); + explicit Connector(bool isOutgoing); ~Connector() override; void Start(); - void AddEndpointRelayTcpObfuscated(const rtc::SocketAddress& addr, const Relay::PeerTag& peer_tag); - void AddEndpointRelayUdp(const rtc::SocketAddress& addr, const Relay::PeerTag& peer_tag); - void SetEndpointP2p(const rtc::SocketAddress& addr); - sigslot::signal1 SignalMessage; - void SendMessage(const message::Base&); - void ResetActiveEndpoint(); - void SetProxy(rtc::ProxyType type, const rtc::SocketAddress& addr, const std::string& username, - const std::string& password); + + sigslot::signal1&> SignalCandidatesGathered; + sigslot::signal1 SignalReadyToSendStateChanged; + sigslot::signal1 SignalPacketReceived; + + void AddRemoteCandidates(const std::vector &candidates); + void SendPacket(const rtc::CopyOnWriteBuffer& data); private: - class PingHistory { - public: - PingHistory(); - void Ping(uint32_t id); - void Pong(uint32_t id); - double Average(); + void CandidateGathered(cricket::IceTransportInternal *transport, const cricket::Candidate &candidate); + void CandidateGatheringState(cricket::IceTransportInternal *transport); + void TransportStateChanged(cricket::IceTransportInternal *transport); + void TransportRoleConflict(cricket::IceTransportInternal *transport); + void TransportReadyToSend(cricket::IceTransportInternal *transport); + void TransportPacketReceived(rtc::PacketTransportInternal *transport, const char *bytes, size_t size, const int64_t ×tamp, int unused); - private: - void AppendPing(int64_t ms); - void UpdatePing(int64_t ms); - - static const size_t history_length; - static const int64_t unavailable_ms; - - std::queue history; - int64_t ping_sum; - uint32_t sent_id; - int64_t sent_time; - }; - - static const int64_t tcp_reconnect_delay; - static const int64_t ping_interval_ms; - static const int64_t endpoint_ping_diff_ms; - static const std::set multicast_types; - - EndpointP2p *GetP2pEndpoint() const; - void AddEndpoint(std::unique_ptr); - void DeleteEndpoint(EndpointBase *ep); - void RecvPacket(rtc::AsyncPacketSocket *socket, const char *data, size_t len, - const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us); - void Ready(rtc::AsyncPacketSocket *); - void RecvMessage(const message::Base&, EndpointBase *); - void UpdateActiveEndpoint(); - - rtc::ProxyInfo proxy_info; - EndpointBase *active_endpoint; - std::unique_ptr thread; - rtc::BasicPacketSocketFactory socket_factory; - std::unique_ptr socket; - std::unique_ptr layer; - std::map> endpoints; - std::map ping_history; - webrtc::RepeatingTaskHandle pinger; - uint32_t ping_seq; + std::unique_ptr networkThread; + + bool isOutgoing; + std::unique_ptr socketFactory; + std::unique_ptr networkManager; + std::unique_ptr portAllocator; + std::unique_ptr asyncResolverFactory; + std::unique_ptr transportChannel; + + std::vector collectedLocalCandidates; }; #endif //DEMO_CONNECTOR_H diff --git a/submodules/TgVoipWebrtc/Impl/Connector.mm b/submodules/TgVoipWebrtc/Impl/Connector.mm index 15576f5c2f..2480940642 100644 --- a/submodules/TgVoipWebrtc/Impl/Connector.mm +++ b/submodules/TgVoipWebrtc/Impl/Connector.mm @@ -1,232 +1,158 @@ #include "Connector.h" -#include "Endpoint.h" -#include "Layer92.h" #include "MediaEngineWebrtc.h" -#include "Protocol10.h" #include "api/packet_socket_factory.h" #include "rtc_base/task_utils/to_queued_task.h" +#include "p2p/base/ice_credentials_iterator.h" +#include "api/jsep_ice_candidate.h" #include -const int64_t Connector::tcp_reconnect_delay = 5000; -const int64_t Connector::ping_interval_ms = 10000; -const int64_t Connector::endpoint_ping_diff_ms = 20; -const std::set Connector::multicast_types = { - message::Type::tInit, message::Type::tInitAck, message::Type::tPing -}; -const size_t Connector::PingHistory::history_length = 5; -const int64_t Connector::PingHistory::unavailable_ms = 100000; - -Connector::PingHistory::PingHistory() -: ping_sum(0) -, sent_id(0) -, sent_time(0) { - for (size_t i = 0; i < history_length; ++i) - AppendPing(unavailable_ms); +Connector::Connector(bool isOutgoing) { + networkThread = rtc::Thread::CreateWithSocketServer(); + + this->isOutgoing = isOutgoing; } -void Connector::PingHistory::AppendPing(int64_t ms) { - if (history.size() >= history_length) { - ping_sum -= history.front(); - history.pop(); - } - if (history.size() < history_length) { - ping_sum += ms; - history.emplace(ms); - } -} - -void Connector::PingHistory::UpdatePing(int64_t ms) { - if (!history.empty()) { - ping_sum = ping_sum - history.back() + ms; - history.back() = ms; - } else - AppendPing(ms); -} - -void Connector::PingHistory::Ping(uint32_t id) { - sent_id = id; - sent_time = rtc::TimeMillis(); -} - -void Connector::PingHistory::Pong(uint32_t id) { - if (id != sent_id) - return; - sent_id = 0; - UpdatePing(std::min(rtc::TimeMillis() - sent_time, unavailable_ms)); - sent_time = 0; -} - -double Connector::PingHistory::Average() { - return static_cast(ping_sum) / history.size(); -} - -Connector::Connector(std::unique_ptr layer) -: active_endpoint(nullptr) -, thread(rtc::Thread::CreateWithSocketServer()) -, socket_factory(thread.get()) -, layer(std::move(layer)) -, ping_seq(0) { - pinger = webrtc::RepeatingTaskHandle::Start(thread.get(), [this]() { - Connector::UpdateActiveEndpoint(); - return webrtc::TimeDelta::ms(ping_interval_ms); +Connector::~Connector() { + networkThread->Invoke(RTC_FROM_HERE, [this]() { + transportChannel = nullptr; + asyncResolverFactory = nullptr; + portAllocator = nullptr; + networkManager = nullptr; + socketFactory = nullptr; }); } void Connector::Start() { - thread->Start(); - thread->Invoke(RTC_FROM_HERE, [this]() { - socket.reset(socket_factory.CreateUdpSocket( - rtc::SocketAddress(rtc::GetAnyIP(AF_INET), 0), 0, 0)); - socket->SignalReadPacket.connect(this, &Connector::RecvPacket); - socket->SignalReadyToSend.connect(this, &Connector::Ready); + NSLog(@"Started %d", (int)[[NSDate date] timeIntervalSince1970]); + networkThread->Start(); + + networkThread->Invoke(RTC_FROM_HERE, [this] { + socketFactory.reset(new rtc::BasicPacketSocketFactory(networkThread.get())); + + networkManager = std::make_unique(); + portAllocator.reset(new cricket::BasicPortAllocator(networkManager.get(), socketFactory.get(), /*turn_customizer=*/ nullptr, /*relay_port_factory=*/ nullptr)); + uint32_t flags = cricket::PORTALLOCATOR_DISABLE_TCP; + //flags |= cricket::PORTALLOCATOR_DISABLE_UDP; + portAllocator->set_flags(portAllocator->flags() | flags); + portAllocator->Initialize(); + + rtc::SocketAddress defaultStunAddress = rtc::SocketAddress("hlgkfjdrtjfykgulhijkljhulyo.uksouth.cloudapp.azure.com", 3478); + cricket::ServerAddresses stunServers; + stunServers.insert(defaultStunAddress); + std::vector turnServers; + turnServers.push_back(cricket::RelayServerConfig( + rtc::SocketAddress("hlgkfjdrtjfykgulhijkljhulyo.uksouth.cloudapp.azure.com", 3478), + "user", + "root", + cricket::PROTO_UDP + )); + portAllocator->SetConfiguration(stunServers, turnServers, 2, webrtc::NO_PRUNE); + + asyncResolverFactory = std::make_unique(); + transportChannel.reset(new cricket::P2PTransportChannel("transport", 0, portAllocator.get(), asyncResolverFactory.get(), /*event_log=*/ nullptr)); + + cricket::IceConfig iceConfig; + iceConfig.continual_gathering_policy = cricket::GATHER_CONTINUALLY; + transportChannel->SetIceConfig(iceConfig); + + cricket::IceParameters localIceParameters( + "gcp3", + "zWDKozH8/3JWt8he3M/CMj5R", + false + ); + cricket::IceParameters remoteIceParameters( + "acp3", + "aWDKozH8/3JWt8he3M/CMj5R", + false + ); + + transportChannel->SetIceParameters(isOutgoing ? localIceParameters : remoteIceParameters); + transportChannel->SetIceRole(isOutgoing ? cricket::ICEROLE_CONTROLLING : cricket::ICEROLE_CONTROLLED); + + transportChannel->SignalCandidateGathered.connect(this, &Connector::CandidateGathered); + transportChannel->SignalGatheringState.connect(this, &Connector::CandidateGatheringState); + transportChannel->SignalIceTransportStateChanged.connect(this, &Connector::TransportStateChanged); + transportChannel->SignalRoleConflict.connect(this, &Connector::TransportRoleConflict); + transportChannel->SignalReadPacket.connect(this, &Connector::TransportPacketReceived); + + transportChannel->MaybeStartGathering(); + + transportChannel->SetRemoteIceMode(cricket::ICEMODE_FULL); + transportChannel->SetRemoteIceParameters((!isOutgoing) ? localIceParameters : remoteIceParameters); }); } -void Connector::RecvPacket(rtc::AsyncPacketSocket *sock, const char *data, size_t len, - const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) { - for (const auto& ep : endpoints) { - auto ep_udp = dynamic_cast(ep.first); - if (ep_udp && ep_udp->address == remote_addr) { - ep_udp->RecvPacket(sock, data, len, remote_addr, packet_time_us); +void Connector::AddRemoteCandidates(const std::vector &candidates) { + networkThread->Invoke(RTC_FROM_HERE, [this, candidates] { + for (auto &serializedCandidate : candidates) { + webrtc::JsepIceCandidate parseCandidate("", 0); + if (parseCandidate.Initialize(serializedCandidate, nullptr)) { + auto candidate = parseCandidate.candidate(); + printf("Add remote candidate %s\n", serializedCandidate.c_str()); + transportChannel->AddRemoteCandidate(candidate); + } + } + }); +} + +void Connector::CandidateGathered(cricket::IceTransportInternal *transport, const cricket::Candidate &candidate) { + assert(networkThread->IsCurrent()); + + webrtc::JsepIceCandidate iceCandidate("", 0); + iceCandidate.SetCandidate(candidate); + std::string serializedCandidate; + if (iceCandidate.ToString(&serializedCandidate)) { + std::vector arrayOfOne; + arrayOfOne.push_back(serializedCandidate); + SignalCandidatesGathered(arrayOfOne); + + webrtc::JsepIceCandidate parseCandidate("", 0); + if (parseCandidate.Initialize(serializedCandidate, nullptr)) { + auto candidate = parseCandidate.candidate(); + + } + } +} + +void Connector::CandidateGatheringState(cricket::IceTransportInternal *transport) { + if (transport->gathering_state() == cricket::IceGatheringState::kIceGatheringComplete) { + /*if (collectedLocalCandidates.size() != 0) { + SignalCandidatesGathered(collectedLocalCandidates); + }*/ + } +} + +void Connector::TransportStateChanged(cricket::IceTransportInternal *transport) { + auto state = transport->GetIceTransportState(); + switch (state) { + case webrtc::IceTransportState::kConnected: + case webrtc::IceTransportState::kCompleted: + SignalReadyToSendStateChanged(true); + printf("===== State: Connected\n"); + break; + default: + SignalReadyToSendStateChanged(false); + printf("===== State: Disconnected\n"); break; - } } } -void Connector::Ready(rtc::AsyncPacketSocket *) { - SignalMessage(message::Ready()); +void Connector::TransportRoleConflict(cricket::IceTransportInternal *transport) { + printf("===== Role conflict\n"); } -void Connector::AddEndpointRelayTcpObfuscated(const rtc::SocketAddress& addr, const Relay::PeerTag& peer_tag) { - thread->Invoke(RTC_FROM_HERE, [this, addr, peer_tag]() { - std::unique_ptr sock(socket_factory.CreateClientTcpSocket( - rtc::SocketAddress(rtc::GetAnyIP(AF_INET), 0), - addr, proxy_info, "", rtc::PacketSocketTcpOptions())); - AddEndpoint(std::make_unique(std::move(sock), peer_tag, layer.get())); +void Connector::TransportPacketReceived(rtc::PacketTransportInternal *transport, const char *bytes, size_t size, const int64_t ×tamp, __unused int unused) { + rtc::CopyOnWriteBuffer data; + data.AppendData(bytes, size); + SignalPacketReceived(data); +} + +void Connector::SendPacket(const rtc::CopyOnWriteBuffer& data) { + networkThread->Invoke(RTC_FROM_HERE, [this, data] { + rtc::PacketOptions options; + transportChannel->SendPacket((const char *)data.data(), data.size(), options, 0); }); } - -void Connector::AddEndpointRelayUdp(const rtc::SocketAddress& addr, const Relay::PeerTag& peer_tag) { - thread->Invoke(RTC_FROM_HERE, [this, addr, peer_tag]() { - assert(socket); - AddEndpoint(std::make_unique(addr, peer_tag, socket.get(), layer.get())); - }); -} - -void Connector::SetEndpointP2p(const rtc::SocketAddress& addr) { - thread->Invoke(RTC_FROM_HERE, [this, addr]() { - assert(socket); - if (auto ep = GetP2pEndpoint()) - DeleteEndpoint(ep); - AddEndpoint(std::make_unique(addr, socket.get(), layer.get())); - }); -} - -Connector::~Connector() { - thread->Invoke(RTC_FROM_HERE, [this]() { - pinger.Stop(); - active_endpoint = nullptr; - endpoints.clear(); - ping_history.clear(); - }); -} - -void Connector::RecvMessage(const message::Base& msg, EndpointBase *endpoint) { - if (msg.ID == message::tDisconnected && endpoint->type == EndpointBase::Type::RelayObfuscatedTcp) { - thread->PostDelayedTask(webrtc::ToQueuedTask([this, endpoint]() { - if (endpoints.find(endpoint) == endpoints.end()) - return; - auto final_ep = dynamic_cast(endpoint); - if (!final_ep) - return; - std::unique_ptr sock(socket_factory.CreateClientTcpSocket( - rtc::SocketAddress(rtc::GetAnyIP(AF_INET), 0), - final_ep->address, proxy_info, "", rtc::PacketSocketTcpOptions())); - final_ep->Reconnect(std::move(sock)); - }), tcp_reconnect_delay); - if (active_endpoint == endpoint) - ResetActiveEndpoint(); - return; - } - if (auto msg_ping = dynamic_cast(&msg)) { - message::Pong msg_pong; - msg_pong.id = msg_ping->id; - endpoint->SendMessage(msg_pong); - return; - } - if (auto msg_pong = dynamic_cast(&msg)) { - ping_history[endpoint].Pong(msg_pong->id); - return; - } - // fallback if no active endpoint set - if (!active_endpoint) - active_endpoint = endpoint; - SignalMessage(msg); -} - -void Connector::SendMessage(const message::Base& msg) { - if (!active_endpoint || multicast_types.find(msg.ID) != multicast_types.end()) { - for (const auto& ep : endpoints) { - ep.first->SendMessage(msg); - if (auto msg_ping = dynamic_cast(&msg)) - ping_history[ep.first].Ping(msg_ping->id); - } - return; - } - active_endpoint->SendMessage(msg); -} - -EndpointP2p *Connector::GetP2pEndpoint() const { - for (const auto& ep : endpoints) - if (auto ep_p2p = dynamic_cast(ep.first)) - return ep_p2p; - return nullptr; -} - -void Connector::AddEndpoint(std::unique_ptr endpoint) { - EndpointBase *ep = endpoint.get(); - ep->SignalMessage.connect(this, &Connector::RecvMessage); - endpoints[ep] = std::move(endpoint); - ping_history[ep] = PingHistory(); -} - -void Connector::DeleteEndpoint(EndpointBase *ep) { - // TODO: must be invoked to thread when become public - endpoints.erase(ep); - ping_history.erase(ep); -} - -void Connector::ResetActiveEndpoint() { - active_endpoint = nullptr; -} - -void Connector::UpdateActiveEndpoint() { - if (ping_history.empty()) - return; - if (ping_history.size() == 1) { - active_endpoint = ping_history.begin()->first; - return; - } - std::vector> times; - for (auto ping : ping_history) - times.emplace_back(ping.second.Average(), ping.first); - std::sort(times.begin(), times.end()); - EndpointBase *candidate = times.front().second; - if (!active_endpoint || (active_endpoint != candidate && - ping_history[active_endpoint].Average() - times.front().first > endpoint_ping_diff_ms)) - active_endpoint = candidate; - message::Ping msg; - msg.id = ++ping_seq; - SendMessage(msg); -} - -void Connector::SetProxy(rtc::ProxyType type, const rtc::SocketAddress& addr, const std::string& username, - const std::string& password) { - proxy_info.type = type; - proxy_info.address = addr; - proxy_info.username = username; - proxy_info.password = rtc::CryptString(); -} diff --git a/submodules/TgVoipWebrtc/Impl/Controller.h b/submodules/TgVoipWebrtc/Impl/Controller.h index 3870f5311b..ac22631d8e 100644 --- a/submodules/TgVoipWebrtc/Impl/Controller.h +++ b/submodules/TgVoipWebrtc/Impl/Controller.h @@ -4,7 +4,6 @@ #include "Connector.h" #include "MediaEngineWebrtc.h" -#include "Layer92.h" #include "rtc_base/copy_on_write_buffer.h" #include "rtc_base/socket_address.h" @@ -30,21 +29,21 @@ public: Reconnecting, }; - explicit Controller(bool is_outgoing, const EncryptionKey& encryption_key, size_t init_timeout, size_t reconnect_timeout); + explicit Controller(bool is_outgoing, size_t init_timeout, size_t reconnect_timeout); ~Controller() override; - void AddEndpoint(const rtc::SocketAddress& address, const Relay::PeerTag& peer_tag, EndpointType type); void Start(); - void SetNetworkType(message::NetworkType network_type); + //void SetNetworkType(message::NetworkType network_type); void SetDataSaving(bool data_saving); void SetMute(bool mute); - void AttachVideoView(VideoMetalView *videoView); - void SetProxy(rtc::ProxyType type, const rtc::SocketAddress& addr, const std::string& username, - const std::string& password); + void AttachVideoView(rtc::VideoSinkInterface *sink); + void SetProxy(rtc::ProxyType type, const rtc::SocketAddress& addr, const std::string& username, const std::string& password); + void AddRemoteCandidates(const std::vector &candidates); - static std::map network_params; + //static std::map network_params; static MediaEngineWebrtc::NetworkParams default_network_params; static MediaEngineWebrtc::NetworkParams datasaving_network_params; sigslot::signal1 SignalNewState; + sigslot::signal1&> SignalCandidatesGathered; private: std::unique_ptr thread; @@ -59,17 +58,17 @@ private: const size_t reconnect_timeout; bool local_datasaving; bool final_datasaving; - message::NetworkType local_network_type; - message::NetworkType final_network_type; + //message::NetworkType local_network_type; + //message::NetworkType final_network_type; - template void StartRepeating(Closure&& closure); - void StopRepeating(); - void NewMessage(const message::Base& msg); + void PacketReceived(const rtc::CopyOnWriteBuffer &); + void WriteableStateChanged(bool); + void CandidatesGathered(const std::vector &); void SetFail(); void Play(const int16_t *data, size_t size); void Record(int16_t *data, size_t size); void SendRtp(rtc::CopyOnWriteBuffer packet); - void UpdateNetworkParams(const message::RtpStream& rtp); + //void UpdateNetworkParams(const message::RtpStream& rtp); }; diff --git a/submodules/TgVoipWebrtc/Impl/Controller.mm b/submodules/TgVoipWebrtc/Impl/Controller.mm index e042e528ad..8a1a0a1c3f 100644 --- a/submodules/TgVoipWebrtc/Impl/Controller.mm +++ b/submodules/TgVoipWebrtc/Impl/Controller.mm @@ -1,24 +1,22 @@ #include "Controller.h" -#include "Layer92.h" - #include "modules/rtp_rtcp/source/rtp_utility.h" #include "rtc_base/time_utils.h" #include "rtc_base/message_handler.h" #include -std::map Controller::network_params = { +/*std::map Controller::network_params = { {message::NetworkType::nGprs, {6, 8, 6, 120, false, false, false}}, {message::NetworkType::nEdge, {6, 16, 6, 120, false, false, false}}, {message::NetworkType::n3gOrAbove, {6, 32, 16, 60, false, false, false}}, }; MediaEngineWebrtc::NetworkParams Controller::default_network_params = {6, 32, 16, 30, false, false, false}; -MediaEngineWebrtc::NetworkParams Controller::datasaving_network_params = {6, 8, 6, 120, false, false, true}; +MediaEngineWebrtc::NetworkParams Controller::datasaving_network_params = {6, 8, 6, 120, false, false, true};*/ -Controller::Controller(bool is_outgoing, const EncryptionKey& encryption_key, size_t init_timeout, size_t reconnect_timeout) +Controller::Controller(bool is_outgoing, size_t init_timeout, size_t reconnect_timeout) : thread(rtc::Thread::Create()) -, connector(std::make_unique(std::make_unique(encryption_key, is_outgoing))) +, connector(std::make_unique(is_outgoing)) , state(State::Starting) , last_recv_time(rtc::TimeMillis()) , last_send_time(rtc::TimeMillis()) @@ -27,11 +25,16 @@ Controller::Controller(bool is_outgoing, const EncryptionKey& encryption_key, si , reconnect_timeout(reconnect_timeout * 1000) , local_datasaving(false) , final_datasaving(false) -, local_network_type(message::NetworkType::nUnknown) -, final_network_type(message::NetworkType::nUnknown) { - connector->SignalMessage.connect(this, &Controller::NewMessage); + connector->SignalReadyToSendStateChanged.connect(this, &Controller::WriteableStateChanged); + connector->SignalPacketReceived.connect(this, &Controller::PacketReceived); + connector->SignalCandidatesGathered.connect(this, &Controller::CandidatesGathered); thread->Start(); + + thread->Invoke(RTC_FROM_HERE, [this, is_outgoing]() { + media.reset(new MediaEngineWebrtc(is_outgoing)); + media->Send.connect(this, &Controller::SendRtp); + }); } Controller::~Controller() { @@ -41,121 +44,37 @@ Controller::~Controller() { }); } -void Controller::AddEndpoint(const rtc::SocketAddress& address, const Relay::PeerTag &peer_tag, - Controller::EndpointType type) { - if (type == EndpointType::UDP) - connector->AddEndpointRelayUdp(address, peer_tag); - else if (type == EndpointType::TCP) - connector->AddEndpointRelayTcpObfuscated(address, peer_tag); - else if (type == EndpointType::P2P) - connector->SetEndpointP2p(address); -} - void Controller::Start() { last_recv_time = rtc::TimeMillis(); connector->Start(); } -void Controller::NewMessage(const message::Base& msg) { - if (msg.ID == message::tReady && state == State::Starting) { - state = State::WaitInit; - SignalNewState(state); - StartRepeating([this]() { - message::Init msg; - msg.minVer = ProtocolBase::minimal_version; - msg.ver = ProtocolBase::actual_version; - connector->SendMessage(msg); - //if (rtc::TimeMillis() - last_recv_time > init_timeout) - // SetFail(); - return webrtc::TimeDelta::seconds(1); - }); - } else if ((msg.ID == message::tInit || msg.ID == message::tInitAck) && state == State::WaitInit) { - state = State::WaitInitAck; - SignalNewState(state); - StartRepeating([this]() { - message::InitAck msg; - // TODO: version matching - msg.minVer = ProtocolBase::minimal_version; - msg.ver = ProtocolBase::actual_version; - connector->SendMessage(msg); - //if (rtc::TimeMillis() - last_recv_time > init_timeout) - // SetFail(); - return webrtc::TimeDelta::seconds(1); - }); - } else if ((msg.ID == message::tInitAck || msg.ID == message::tRtpStream) && state == State::WaitInitAck) { - state = State::Established; - SignalNewState(state); - thread->PostTask(RTC_FROM_HERE, [this]() { - media = std::make_unique(is_outgoing); - media->Send.connect(this, &Controller::SendRtp); - }); - StartRepeating([this]() { - if (state == State::Established && rtc::TimeMillis() - last_recv_time > 1000) { - connector->ResetActiveEndpoint(); - state = State::Reconnecting; - SignalNewState(state); - } else if (state == State::Reconnecting && rtc::TimeMillis() - last_recv_time > reconnect_timeout) { - //SetFail(); - } - return webrtc::TimeDelta::seconds(1); - }); - } if ((msg.ID == message::tRtpStream) && (state == State::Established || state == State::Reconnecting)) { - const auto msg_rtp = *dynamic_cast(&msg); - thread->PostTask(RTC_FROM_HERE, [this, msg_rtp]() { - if (media) { - media->Receive(msg_rtp.data); - UpdateNetworkParams(msg_rtp); - } - }); - if (!webrtc::RtpUtility::RtpHeaderParser(msg_rtp.data.data(), msg_rtp.data.size()).RTCP()) { - //printf("rtp received size %d\n", (int)(msg_rtp.data.size())); - last_recv_time = rtc::TimeMillis(); - if (state == State::Reconnecting) { - state = State::Established; - SignalNewState(state); - } - } else { - //printf("rtcp received size %d\n", (int)(msg_rtp.data.size())); +void Controller::PacketReceived(const rtc::CopyOnWriteBuffer &data) { + thread->PostTask(RTC_FROM_HERE, [this, data]() { + if (media) { + media->Receive(data); } - } else if (msg.ID == message::tBufferOverflow || - msg.ID == message::tPacketIncorrect || - msg.ID == message::tWrongProtocol) { - SetFail(); - } -} - -template -void Controller::StartRepeating(Closure&& closure) { - //StopRepeating(); - repeatable = webrtc::RepeatingTaskHandle::Start(thread.get(), std::forward(closure)); -} - -void Controller::StopRepeating() { - thread->Invoke(RTC_FROM_HERE, [this]() { - repeatable.Stop(); }); } -void Controller::SetFail() { - thread->PostTask(RTC_FROM_HERE, [this]() { - media = nullptr; - }); - if (state != State::Failed) { - state = State::Failed; - SignalNewState(state); +void Controller::WriteableStateChanged(bool isWriteable) { + if (isWriteable) { + SignalNewState(State::Established); + } else { + SignalNewState(State::Reconnecting); } - StopRepeating(); + thread->PostTask(RTC_FROM_HERE, [this, isWriteable]() { + if (media) { + media->SetCanSendPackets(isWriteable); + } + }); } void Controller::SendRtp(rtc::CopyOnWriteBuffer packet) { - message::RtpStream msg; - msg.data = packet; - msg.network_type = local_network_type; - msg.data_saving = local_datasaving; - connector->SendMessage(msg); + connector->SendPacket(packet); } -void Controller::UpdateNetworkParams(const message::RtpStream& rtp) { +/*void Controller::UpdateNetworkParams(const message::RtpStream& rtp) { bool new_datasaving = local_datasaving || rtp.data_saving; if (!new_datasaving) { final_datasaving = false; @@ -172,17 +91,17 @@ void Controller::UpdateNetworkParams(const message::RtpStream& rtp) { final_datasaving = true; media->SetNetworkParams(datasaving_network_params); } -} +}*/ -void Controller::AttachVideoView(VideoMetalView *videoView) { - thread->PostTask(RTC_FROM_HERE, [this, videoView]() { - media->AttachVideoView(videoView); +void Controller::AttachVideoView(rtc::VideoSinkInterface *sink) { + thread->PostTask(RTC_FROM_HERE, [this, sink]() { + media->AttachVideoView(sink); }); } -void Controller::SetNetworkType(message::NetworkType network_type) { +/*void Controller::SetNetworkType(message::NetworkType network_type) { local_network_type = network_type; -} +}*/ void Controller::SetDataSaving(bool data_saving) { local_datasaving = data_saving; @@ -195,7 +114,13 @@ void Controller::SetMute(bool mute) { }); } -void Controller::SetProxy(rtc::ProxyType type, const rtc::SocketAddress& addr, const std::string& username, - const std::string& password) { - connector->SetProxy(type, addr, username, password); +void Controller::SetProxy(rtc::ProxyType type, const rtc::SocketAddress& addr, const std::string& username, const std::string& password) { +} + +void Controller::CandidatesGathered(const std::vector &candidates) { + SignalCandidatesGathered(candidates); +} + +void Controller::AddRemoteCandidates(const std::vector &candidates) { + connector->AddRemoteCandidates(candidates); } diff --git a/submodules/TgVoipWebrtc/Impl/Endpoint.h b/submodules/TgVoipWebrtc/Impl/Endpoint.h deleted file mode 100644 index 3d6593aeec..0000000000 --- a/submodules/TgVoipWebrtc/Impl/Endpoint.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef DEMO_ENDPOINT_H -#define DEMO_ENDPOINT_H - - -#include "LayerBase.h" -#include "Message.h" - -#include "rtc_base/async_packet_socket.h" -#include "rtc_base/buffer_queue.h" -#include "rtc_base/socket_address.h" - -class Connector; - -class EndpointBase : public sigslot::has_slots<> { -public: - enum Type { - Unknown, - RelayUdp, - RelayObfuscatedTcp, - P2p, - }; - - EndpointBase(const EndpointBase&) = delete; - virtual void SendMessage(const message::Base&) = 0; - sigslot::signal2 SignalMessage; - const Type type; - -protected: - explicit EndpointBase(LayerBase *layer, Type type); - virtual void RecvPacket(rtc::AsyncPacketSocket *socket, const char *data, size_t len, - const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us); - virtual void SendPacket(const uint8_t *data, size_t size) = 0; - - LayerBase *layer; - rtc::PacketOptions packet_options; - std::unique_ptr in_buffer; - size_t in_remains; -}; - -class Relay { -public: - typedef unsigned char PeerTag[16]; - - virtual ~Relay() = default; - -protected: - explicit Relay(const PeerTag& peer_tag); - bool CheckPacket(rtc::ByteBufferReader *packet); - const rtc::Buffer& PreparePacket(const rtc::Buffer& packet); - - PeerTag peer_tag; // how to initialize it in initializer list? - -private: - rtc::Buffer buffer; -}; - -class EndpointUdp : public EndpointBase { -public: - const rtc::SocketAddress address; - -protected: - friend class Connector; -// friend void Connector::RecvPacket(rtc::AsyncPacketSocket *, const char *, size_t, -// const rtc::SocketAddress&, const int64_t&); - - EndpointUdp(const rtc::SocketAddress& addr, rtc::AsyncPacketSocket *socket, LayerBase *layer, Type type); - void SendPacket(const uint8_t *data, size_t size) override; - - rtc::AsyncPacketSocket *socket; -}; - -class EndpointTcp : public EndpointBase { -public: - const rtc::SocketAddress address; - - void Reconnect(std::unique_ptr socket_); - -protected: - explicit EndpointTcp(std::unique_ptr socket, LayerBase *layer, Type type); - void SendPacket(const uint8_t *data, size_t size) override; - - virtual void Ready(rtc::AsyncPacketSocket *) = 0; - virtual void Close(rtc::AsyncPacketSocket *, int) = 0; - - std::unique_ptr socket; -}; - -class EndpointRelayObfuscatedTcp final : public Relay, public EndpointTcp { -public: - EndpointRelayObfuscatedTcp(std::unique_ptr socket, const PeerTag& peer_tag, - LayerBase *layer); - void SendMessage(const message::Base&) override; - -private: - void RecvPacket(rtc::AsyncPacketSocket *socket, const char *data, size_t len, - const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) override; - void Ready(rtc::AsyncPacketSocket *) override; - void Close(rtc::AsyncPacketSocket *, int) override; - void SendPacket(const uint8_t *data, size_t size) override; - - TCPO2State recvState; - TCPO2State sendState; -}; - -class EndpointRelayUdp final : public Relay, public EndpointUdp { -public: - EndpointRelayUdp(const rtc::SocketAddress& addr, const PeerTag& peer_tag, - rtc::AsyncPacketSocket *socket, LayerBase *layer); - void SendMessage(const message::Base&) override; - -private: - void RecvPacket(rtc::AsyncPacketSocket *socket, const char *data, size_t len, - const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) override; -}; - -class EndpointP2p final : public EndpointUdp { -public: - EndpointP2p(const rtc::SocketAddress& addr, rtc::AsyncPacketSocket *socket, LayerBase *layer); - void SendMessage(const message::Base&) override; - -private: - void RecvPacket(rtc::AsyncPacketSocket *socket, const char *data, size_t len, - const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) override; -}; - -#endif //DEMO_ENDPOINT_H diff --git a/submodules/TgVoipWebrtc/Impl/Endpoint.mm b/submodules/TgVoipWebrtc/Impl/Endpoint.mm deleted file mode 100644 index 7ef75142c0..0000000000 --- a/submodules/TgVoipWebrtc/Impl/Endpoint.mm +++ /dev/null @@ -1,205 +0,0 @@ -#include "Endpoint.h" - -#include "rtc_base/buffer.h" -#include "rtc_base/byte_buffer.h" - -#include -#include - -EndpointBase::EndpointBase(LayerBase *layer, Type type) -: type(type) -, layer(layer) -, in_buffer(std::make_unique(nullptr, 0)) -, in_remains(0) {} - -void EndpointBase::RecvPacket(rtc::AsyncPacketSocket *, const char *data, size_t len, - const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) { - if (in_buffer && in_buffer->Length() > 0) { - rtc::Buffer tmp(in_buffer->Data(), in_buffer->Length() + len); - memcpy(tmp.data() + in_buffer->Length(), data, len); - in_buffer = std::make_unique(reinterpret_cast(tmp.data()), tmp.size()); - } else - in_buffer = std::make_unique(data, len); -} - -EndpointUdp::EndpointUdp(const rtc::SocketAddress& addr, rtc::AsyncPacketSocket *socket, LayerBase *layer, Type type) -: EndpointBase(layer, type) -, address(addr) -, socket(socket) {} - -void EndpointUdp::SendPacket(const uint8_t *data, size_t size) { - socket->SendTo(data, size, address, packet_options); -} - -EndpointTcp::EndpointTcp(std::unique_ptr socket, LayerBase *layer, Type type) -: EndpointBase(layer, type) -, address(socket->GetRemoteAddress()) -, socket(nullptr) { - Reconnect(std::move(socket)); -} - -void EndpointTcp::Reconnect(std::unique_ptr socket_) { - socket = std::move(socket_); - socket->SignalReadPacket.connect(dynamic_cast(this), &EndpointTcp::RecvPacket); - socket->SignalReadyToSend.connect(this, &EndpointTcp::Ready); - socket->SignalClose.connect(this, &EndpointTcp::Close); -} - -void EndpointTcp::SendPacket(const uint8_t *data, size_t size) { - socket->Send(data, size, packet_options); -} - -Relay::Relay(const PeerTag& peer_tag_) : peer_tag() { - memcpy(peer_tag, peer_tag_, sizeof(PeerTag)); -} - -bool Relay::CheckPacket(rtc::ByteBufferReader *packet) { - if (packet->Length() >= 16 && memcmp(peer_tag, packet->Data(), 16) == 0) { - packet->Consume(16); - return true; - } - return false; -} - -const rtc::Buffer& Relay::PreparePacket(const rtc::Buffer& packet) { - buffer.Clear(); - if (!packet.empty()) { - buffer.AppendData(peer_tag, 16); - buffer.AppendData(packet); - } - return buffer; -} - -EndpointRelayObfuscatedTcp::EndpointRelayObfuscatedTcp(std::unique_ptr socket, - const PeerTag& peer_tag, LayerBase *layer) -: Relay(peer_tag) -, EndpointTcp(std::move(socket), layer, Type::RelayObfuscatedTcp) -, recvState() -, sendState() {} - -void EndpointRelayObfuscatedTcp::Ready(rtc::AsyncPacketSocket *) { - unsigned char buf[64]; - layer->GenerateTCPO2States(buf, &recvState, &sendState); - EndpointTcp::SendPacket(buf, 64); - SignalMessage(message::Connected(), this); -} - -void EndpointRelayObfuscatedTcp::Close(rtc::AsyncPacketSocket *, int) { - SignalMessage(message::Disconnected(), this); -} - -void EndpointRelayObfuscatedTcp::RecvPacket(rtc::AsyncPacketSocket *socket, const char *data, size_t packet_len, - const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) { - EndpointBase::RecvPacket(socket, data, packet_len, remote_addr, packet_time_us); - - do { - if (in_remains > in_buffer->Length()) - break; - if (in_remains > 0 && CheckPacket(in_buffer.get())) { - auto msg = layer->DecodePacket(*in_buffer); - if (msg) - SignalMessage(*msg, this); - } - - unsigned char len1; - size_t packetLen = 0; - if (!in_buffer->ReadUInt8(&len1)) - break; - layer->EncryptForTCPO2(&len1, 1, &recvState); - if (len1 < 0x7F) { - packetLen = (size_t) len1 * 4; - } else { - unsigned char len2[3]; - if (!in_buffer->ReadBytes(reinterpret_cast(&len2), 3)) { - SignalMessage(message::PacketIncorrect(), this); - return; - } - layer->EncryptForTCPO2(len2, 3, &recvState); - packetLen = ((size_t) len2[0] | ((size_t) len2[1] << 8) | ((size_t) len2[2] << 16)) * 4; - } - - in_remains = packetLen; - if (packetLen > in_buffer->Length()) { - in_remains = packetLen; - break; - } - } while (true); -} - -void EndpointRelayObfuscatedTcp::SendMessage(const message::Base& msg_base) { - if (socket->GetState() == rtc::AsyncPacketSocket::State::STATE_CLOSED) - return; - const rtc::Buffer& out = PreparePacket(layer->EncodePacket(&msg_base)); - if (!out.empty()) - SendPacket(out.data(), out.size()); -} - -void EndpointRelayObfuscatedTcp::SendPacket(const uint8_t *data, size_t size) { - rtc::ByteBufferWriter out; - size_t len = size / 4; - if (len < 0x7F) { - out.WriteUInt8(len); - } else { - out.WriteUInt8(0x7F); - out.WriteUInt8(len & 0xFF); - out.WriteUInt8((len >> 8) & 0xFF); - out.WriteUInt8((len >> 16) & 0xFF); - } - out.WriteBytes(reinterpret_cast(data), size); - layer->EncryptForTCPO2(reinterpret_cast(out.ReserveWriteBuffer(0)), - out.Length(), &sendState); - EndpointTcp::SendPacket(reinterpret_cast(out.Data()), out.Length()); -} - -EndpointRelayUdp::EndpointRelayUdp(const rtc::SocketAddress& addr, const PeerTag& peer_tag, - rtc::AsyncPacketSocket *socket, LayerBase *layer) - : Relay(peer_tag) - , EndpointUdp(addr, socket, layer, Type::RelayUdp) {} - -void EndpointRelayUdp::SendMessage(const message::Base& msg_base) { - const rtc::Buffer& out = PreparePacket(layer->EncodePacket(&msg_base)); - if (!out.empty()) - SendPacket(out.data(), out.size()); -} - -void EndpointRelayUdp::RecvPacket(rtc::AsyncPacketSocket *sock, const char *data, size_t len, - const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) { - bool glued; - bool processed = false; - do { - EndpointBase::RecvPacket(sock, data, len, remote_addr, packet_time_us); - glued = in_buffer->Length() > len; - std::unique_ptr msg; - while (CheckPacket(in_buffer.get()) && (msg = layer->DecodePacket(*in_buffer))) { - processed = true; - SignalMessage(*msg, this); - } - if (!processed) - in_buffer = std::make_unique(nullptr, 0); - } while (!processed && glued); -} - -EndpointP2p::EndpointP2p(const rtc::SocketAddress& addr, rtc::AsyncPacketSocket *socket, LayerBase *layer) -: EndpointUdp(addr, socket, layer, Type::P2p) {} - -void EndpointP2p::SendMessage(const message::Base& msg_base) { - rtc::Buffer out = layer->EncodePacket(&msg_base); - if (!out.empty()) - SendPacket(out.data(), out.size()); -} - -void EndpointP2p::RecvPacket(rtc::AsyncPacketSocket *sock, const char *data, size_t len, - const rtc::SocketAddress& remote_addr, const int64_t& packet_time_us) { - bool glued; - bool processed = false; - do { - EndpointBase::RecvPacket(sock, data, len, remote_addr, packet_time_us); - glued = in_buffer->Length() > len; - while (auto msg = layer->DecodePacket(*in_buffer)) { - processed = true; - SignalMessage(*msg, this); - } - if (!processed) - in_buffer = std::make_unique(nullptr, 0); - } while (!processed && glued); -} diff --git a/submodules/TgVoipWebrtc/Impl/Layer92.cpp b/submodules/TgVoipWebrtc/Impl/Layer92.cpp deleted file mode 100644 index 8bea191d6b..0000000000 --- a/submodules/TgVoipWebrtc/Impl/Layer92.cpp +++ /dev/null @@ -1,238 +0,0 @@ -#include "Layer92.h" - -#include "Message.h" - -#include "rtc_base/byte_buffer.h" -#include "rtc_base/byte_order.h" - -#include -#include - -namespace { - -#define TLID_UDP_REFLECTOR_SELF_INFO 0xc01572c7 -#define TLID_UDP_REFLECTOR_PEER_INFO 0x27D9371C - -#ifdef _MSC_VER -#define MSC_STACK_FALLBACK(a, b) (b) -#else -#define MSC_STACK_FALLBACK(a, b) (a) -#endif - -} - -Layer92::Layer92(const EncryptionKey& encryptionKey_, bool isOutgoing) -: LayerBase(92) -, encryptionKey() -, isOutgoing(isOutgoing) { - memcpy(encryptionKey, encryptionKey_, sizeof(encryptionKey)); -} - -void Layer92::EncryptForTCPO2(unsigned char *buffer, size_t len, TCPO2State *state) { - crypto.aes_ctr_encrypt(buffer, len, state->key, state->iv, state->ecount, &state->num); -} - -void Layer92::GenerateTCPO2States(unsigned char* buffer, TCPO2State* recvState, TCPO2State* sendState) { - memset(recvState, 0, sizeof(TCPO2State)); - memset(sendState, 0, sizeof(TCPO2State)); - unsigned char nonce[64]; - uint32_t *first = reinterpret_cast(nonce), *second = first + 1; - uint32_t first1 = 0x44414548U, first2 = 0x54534f50U, first3 = 0x20544547U, first4 = 0x20544547U, first5 = 0xeeeeeeeeU; - uint32_t second1 = 0; - do { - crypto.rand_bytes(nonce, sizeof(nonce)); - } while (*first == first1 || *first == first2 || *first == first3 || *first == first4 || *first == first5 || - *second == second1 || *reinterpret_cast(nonce) == 0xef); - - // prepare encryption key/iv - memcpy(sendState->key, nonce + 8, 32); - memcpy(sendState->iv, nonce + 8 + 32, 16); - - // prepare decryption key/iv - char reversed[48]; - memcpy(reversed, nonce + 8, sizeof(reversed)); - std::reverse(reversed, reversed + sizeof(reversed)); - memcpy(recvState->key, reversed, 32); - memcpy(recvState->iv, reversed + 32, 16); - - // write protocol identifier - *reinterpret_cast(nonce + 56) = 0xefefefefU; - memcpy(buffer, nonce, 56); - EncryptForTCPO2(nonce, sizeof(nonce), sendState); - memcpy(buffer + 56, nonce + 56, 8); -} - -std::unique_ptr Layer92::DecodeRelayPacket(rtc::ByteBufferReader& in) { - if (in.Length() < 12 + 4 + 16) - return nullptr; - if (*reinterpret_cast(in.Data()) != 0xFFFFFFFFFFFFFFFFLL) - return nullptr; - if (*reinterpret_cast(in.Data() + 8) != 0xFFFFFFFF) - return nullptr; - - // relay special request response - in.Consume(12); - uint32_t tlid; - if (!in.ReadUInt32(&tlid)) - return nullptr; - - if (tlid == TLID_UDP_REFLECTOR_SELF_INFO) { - if (in.Length() < 32) - return nullptr; - - auto msg = std::make_unique(); - in.ReadUInt32(&msg->date); - in.ReadUInt64(&msg->query_id); - in6_addr myIP{}; - in.ReadBytes(reinterpret_cast(&myIP), 16); - uint32_t myPort; // int32_t in src; why not uint16_t? - in.ReadUInt32(&myPort); - msg->my_addr = rtc::SocketAddress(rtc::IPAddress(myIP), myPort); - return msg; - } - if (tlid == TLID_UDP_REFLECTOR_PEER_INFO) { - if (in.Length() < 16) - return nullptr; - auto msg = std::make_unique(); - uint32_t myAddr; - uint32_t myPort; - uint32_t peerAddr; - uint32_t peerPort; - in.ReadUInt32(&myAddr); - in.ReadUInt32(&myPort); - in.ReadUInt32(&peerAddr); - in.ReadUInt32(&peerPort); - msg->my_addr = rtc::SocketAddress(myAddr, myPort); - msg->peer_addr = rtc::SocketAddress(peerAddr, peerPort); - return msg; - } - return nullptr; -} - -void Layer92::KDF2(unsigned char *msgKey, size_t x, unsigned char *aesKey, unsigned char *aesIv) { - uint8_t sA[32], sB[32]; - uint8_t buf[16 + 36]; - memcpy(buf, msgKey, 16); - memcpy(buf + 16, encryptionKey + x, 36); - crypto.sha256(buf, 16 + 36, sA); - memcpy(buf, encryptionKey + 40 + x, 36); - memcpy(buf + 36, msgKey, 16); - crypto.sha256(buf, 36 + 16, sB); - memcpy(aesKey, sA, 8); - memcpy(aesKey + 8, sB + 8, 16); - memcpy(aesKey + 8 + 16, sA + 24, 8); - memcpy(aesIv, sB, 8); - memcpy(aesIv + 8, sA + 8, 16); - memcpy(aesIv + 8 + 16, sB + 24, 8); -} - -std::unique_ptr Layer92::DecodeProtocolPacket(rtc::ByteBufferReader& in) { - unsigned char msgKey[16]; - memcpy(msgKey, in.Data(), 16); - - unsigned char decrypted[1500]; - unsigned char aesKey[32], aesIv[32]; - KDF2(msgKey, isOutgoing ? 8 : 0, aesKey, aesIv); - size_t decryptedLen = in.Length() - 16; - if (decryptedLen > sizeof(decrypted)) - return nullptr; - if (decryptedLen % 16 != 0) - return nullptr; // wrong decrypted length - - in.Consume(16); - crypto.aes_ige_decrypt((uint8_t *)in.Data(), decrypted, decryptedLen, aesKey, aesIv); - in.Consume(decryptedLen); - - rtc::ByteBufferWriter buf; - size_t x = isOutgoing ? 8 : 0; - buf.WriteBytes((char *)encryptionKey + 88 + x, 32); - buf.WriteBytes((char *)decrypted, decryptedLen); - unsigned char msgKeyLarge[32]; - crypto.sha256((uint8_t *)buf.Data(), buf.Length(), msgKeyLarge); - if (memcmp(msgKey, msgKeyLarge + 8, 16) != 0) - return nullptr; // packet has wrong hash - - uint16_t innerLen; - memcpy(&innerLen, decrypted, 2); - if (innerLen > decryptedLen) - return nullptr; // packet has wrong inner length -// if (decryptedLen - innerLen < 16) -// return nullptr; // packet has too little padding - return protocol->ReadProtocolPacket(decrypted + 2, innerLen); -} - -std::unique_ptr Layer92::DecodePacket(rtc::ByteBufferReader& in) { - auto msg = DecodeRelayPacket(in); - if (msg) - return msg; - return DecodeProtocolPacket(in); -} - -rtc::Buffer Layer92::EncodePacket(const message::Base *msg_base) { - auto buf = EncodeRelayPacket(msg_base); - if (!buf.empty()) - return buf; - return EncodeProtocolPacket(msg_base); -} - -rtc::Buffer Layer92::EncodeRelayPacket(const message::Base *msg_base) { - if (msg_base->ID == message::tRelayPing) { - const auto *msg = dynamic_cast(msg_base); - if (!msg) - return rtc::Buffer(); - unsigned char buf[16]; - memset(buf, 0xFF, 16); - return rtc::Buffer(buf, 16); - } - if (msg_base->ID == message::tGetPeerInfo) { - const auto *msg = dynamic_cast(msg_base); - if (!msg) - return rtc::Buffer(); - rtc::ByteBufferWriter out; - out.WriteUInt32(-1); - out.WriteUInt32(-1); - out.WriteUInt32(-1); - out.WriteUInt32(-1); - int64_t id; - crypto.rand_bytes(reinterpret_cast(&id), 8); - out.WriteUInt64(id); - return rtc::Buffer(out.Data(), out.Length()); - } - return rtc::Buffer(); -} - -rtc::Buffer Layer92::EncodeProtocolPacket(const message::Base *msg_base) { - rtc::Buffer internal = protocol->WriteProtocolPacket(msg_base); - if (internal.empty()) - return rtc::Buffer(); - - rtc::ByteBufferWriter out; - rtc::ByteBufferWriter inner; - uint16_t len = internal.size(); - inner.WriteBytes((char *)&len, 2); // for backward compatibility - inner.WriteBytes((char *)internal.data(), internal.size()); - - size_t padLen = 16 - inner.Length() % 16; -// if (padLen < 16) -// padLen += 16; - uint8_t padding[32]; - crypto.rand_bytes(padding, padLen); - inner.WriteBytes((char *)padding, padLen); - assert(inner.Length() % 16 == 0); - - unsigned char key[32], iv[32], msgKey[16]; - rtc::ByteBufferWriter buf; - size_t x = isOutgoing ? 0 : 8; - buf.WriteBytes((char *)encryptionKey + 88 + x, 32); - buf.WriteBytes(inner.Data(), inner.Length()); - unsigned char msgKeyLarge[32]; - crypto.sha256((uint8_t *)buf.Data(), buf.Length(), msgKeyLarge); - memcpy(msgKey, msgKeyLarge + 8, 16); - KDF2(msgKey, isOutgoing ? 0 : 8, key, iv); - out.WriteBytes((char *)msgKey, 16); - - unsigned char aesOut[MSC_STACK_FALLBACK(inner.Length(), 1500)]; - crypto.aes_ige_encrypt((uint8_t *)inner.Data(), aesOut, inner.Length(), key, iv); - out.WriteBytes((char *)aesOut, inner.Length()); - return rtc::Buffer(out.Data(), out.Length()); -} diff --git a/submodules/TgVoipWebrtc/Impl/Layer92.h b/submodules/TgVoipWebrtc/Impl/Layer92.h deleted file mode 100644 index f751a95b12..0000000000 --- a/submodules/TgVoipWebrtc/Impl/Layer92.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef DEMO_LAYER92_H -#define DEMO_LAYER92_H - - -#include "LayerBase.h" -#include "Message.h" -#include "Protocol10.h" - -#include "rtc_base/byte_buffer.h" - -#include -#include - -struct CryptoFunctions { - void (*rand_bytes)(uint8_t* buffer, size_t length); - void (*sha1)(uint8_t* msg, size_t length, uint8_t* output); - void (*sha256)(uint8_t* msg, size_t length, uint8_t* output); - void (*aes_ige_encrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv); - void (*aes_ige_decrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv); - void (*aes_ctr_encrypt)(uint8_t* inout, size_t length, uint8_t* key, uint8_t* iv, uint8_t* ecount, uint32_t* num); - void (*aes_cbc_encrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv); - void (*aes_cbc_decrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv); -}; - -typedef unsigned char EncryptionKey[256]; - -class Layer92 : public LayerBase { -public: - static CryptoFunctions crypto; - - explicit Layer92(const EncryptionKey& encryptionKey, bool isOutgoing); - void EncryptForTCPO2(unsigned char *buffer, size_t len, TCPO2State *state) override; - void GenerateTCPO2States(unsigned char *buffer, TCPO2State *recvState, TCPO2State *sendState) override; - std::unique_ptr DecodePacket(rtc::ByteBufferReader& in) override; - rtc::Buffer EncodePacket(const message::Base *msg_base) override; - -private: - void KDF2(unsigned char* msgKey, size_t x, unsigned char *aesKey, unsigned char *aesIv); - std::unique_ptr DecodeRelayPacket(rtc::ByteBufferReader& in); - std::unique_ptr DecodeProtocolPacket(rtc::ByteBufferReader& in); - rtc::Buffer EncodeRelayPacket(const message::Base *msg_base); - rtc::Buffer EncodeProtocolPacket(const message::Base *msg_base); - - EncryptionKey encryptionKey; - bool isOutgoing; -}; - - -#endif //DEMO_LAYER92_H diff --git a/submodules/TgVoipWebrtc/Impl/LayerBase.cpp b/submodules/TgVoipWebrtc/Impl/LayerBase.cpp deleted file mode 100644 index 9e6dbab457..0000000000 --- a/submodules/TgVoipWebrtc/Impl/LayerBase.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "LayerBase.h" - -#include "Layer92.h" - -bool LayerBase::ChangeProtocol(uint32_t protocol_version) { - if (protocol && protocol->version == protocol_version) - return true; - auto new_protocol = ProtocolBase::CreateProtocol(protocol_version); - if (!new_protocol) - return false; - protocol = std::move(new_protocol); - return true; -} - -LayerBase::LayerBase(uint32_t version) -: version(version) -, protocol(ProtocolBase::CreateProtocol(ProtocolBase::actual_version)) {} diff --git a/submodules/TgVoipWebrtc/Impl/LayerBase.h b/submodules/TgVoipWebrtc/Impl/LayerBase.h deleted file mode 100644 index 5d2db961d4..0000000000 --- a/submodules/TgVoipWebrtc/Impl/LayerBase.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef DEMO_LAYERBASE_H -#define DEMO_LAYERBASE_H - - -#include "ProtocolBase.h" - -#include "rtc_base/buffer.h" -#include "rtc_base/byte_buffer.h" - -#include -#include - -struct TCPO2State { - unsigned char key[32]; - unsigned char iv[16]; - unsigned char ecount[16]; - uint32_t num; -}; - -class LayerBase { -public: - bool ChangeProtocol(uint32_t protocol_version); - - virtual ~LayerBase() = default; - virtual void EncryptForTCPO2(unsigned char *buffer, size_t len, TCPO2State *state) = 0; - virtual void GenerateTCPO2States(unsigned char* buffer, TCPO2State* recvState, TCPO2State* sendState) = 0; - virtual std::unique_ptr DecodePacket(rtc::ByteBufferReader& in) = 0; - virtual rtc::Buffer EncodePacket(const message::Base *msg_base) = 0; - - const uint32_t version; - -protected: - explicit LayerBase(uint32_t version); - - std::unique_ptr protocol; -}; - -#endif //DEMO_LAYERBASE_H diff --git a/submodules/TgVoipWebrtc/Impl/MediaEngineBase.h b/submodules/TgVoipWebrtc/Impl/MediaEngineBase.h index fc2d1cde56..1c2eda6c1c 100644 --- a/submodules/TgVoipWebrtc/Impl/MediaEngineBase.h +++ b/submodules/TgVoipWebrtc/Impl/MediaEngineBase.h @@ -12,7 +12,7 @@ public: MediaEngineBase() = default; virtual ~MediaEngineBase() = default; - sigslot::signal1 Send; + virtual void Receive(rtc::CopyOnWriteBuffer) = 0; }; diff --git a/submodules/TgVoipWebrtc/Impl/MediaEngineWebrtc.h b/submodules/TgVoipWebrtc/Impl/MediaEngineWebrtc.h index 90b1a27694..206717dd9a 100644 --- a/submodules/TgVoipWebrtc/Impl/MediaEngineWebrtc.h +++ b/submodules/TgVoipWebrtc/Impl/MediaEngineWebrtc.h @@ -1,8 +1,8 @@ #ifndef DEMO_MEDIAENGINEWEBRTC_H #define DEMO_MEDIAENGINEWEBRTC_H - -#include "MediaEngineBase.h" +#include "rtc_base/copy_on_write_buffer.h" +#include "rtc_base/third_party/sigslot/sigslot.h" #include "api/transport/field_trial_based_config.h" #include "call/call.h" @@ -15,7 +15,7 @@ #import "VideoCameraCapturer.h" #import "VideoMetalView.h" -class MediaEngineWebrtc : public MediaEngineBase { +class MediaEngineWebrtc : public sigslot::has_slots<> { public: struct NetworkParams { uint8_t min_bitrate_kbps; @@ -27,40 +27,28 @@ public: bool noise_suppression; }; - explicit MediaEngineWebrtc(bool outgoing, bool send = true, bool recv = true); - ~MediaEngineWebrtc() override; - void Receive(rtc::CopyOnWriteBuffer) override; + explicit MediaEngineWebrtc(bool outgoing); + ~MediaEngineWebrtc(); + void Receive(rtc::CopyOnWriteBuffer); void OnSentPacket(const rtc::SentPacket& sent_packet); void SetNetworkParams(const NetworkParams& params); void SetMute(bool mute); - void AttachVideoView(VideoMetalView *videoView); + void SetCanSendPackets(bool); + void AttachVideoView(rtc::VideoSinkInterface *sink); + + sigslot::signal1 Send; private: class Sender final : public cricket::MediaChannel::NetworkInterface { public: - explicit Sender(MediaEngineWebrtc&); + explicit Sender(MediaEngineWebrtc &engine, bool isVideo); bool SendPacket(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) override; bool SendRtcp(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) override; int SetOption(SocketType type, rtc::Socket::Option opt, int option) override; + private: - MediaEngineWebrtc& engine; - }; - - class AudioProcessor { - public: - AudioProcessor(webrtc::AudioTransport *transport, webrtc::TaskQueueFactory *task_queue_factory, - MediaEngineBase& engine, bool send, bool recv); - ~AudioProcessor(); - private: - bool send; - bool recv; - webrtc::AudioTransport *transport; - size_t delay_us; - int16_t *buf_send; - int16_t *buf_recv; - MediaEngineBase& engine; - std::unique_ptr task_queue_send; - std::unique_ptr task_queue_recv; + MediaEngineWebrtc &engine; + bool isVideo; }; const uint32_t ssrc_send; @@ -73,7 +61,8 @@ private: std::unique_ptr task_queue_factory; webrtc::FieldTrialBasedConfig field_trials; webrtc::LocalAudioSinkAdapter audio_source; - Sender data_sender; + Sender audio_sender; + Sender video_sender; std::unique_ptr voice_channel; std::unique_ptr video_channel; std::unique_ptr video_bitrate_allocator_factory; diff --git a/submodules/TgVoipWebrtc/Impl/MediaEngineWebrtc.mm b/submodules/TgVoipWebrtc/Impl/MediaEngineWebrtc.mm index 5f82c6cf31..90775e8011 100644 --- a/submodules/TgVoipWebrtc/Impl/MediaEngineWebrtc.mm +++ b/submodules/TgVoipWebrtc/Impl/MediaEngineWebrtc.mm @@ -23,16 +23,11 @@ #include "sdk/objc/native/api/video_encoder_factory.h" #include "sdk/objc/native/api/video_decoder_factory.h" -#if WEBRTC_ENABLE_PROTOBUF -#include "modules/audio_coding/audio_network_adaptor/config.pb.h" -#endif - -#include "PlatformCodecs.h" - #include "sdk/objc/native/src/objc_video_track_source.h" #include "api/video_track_source_proxy.h" #include "sdk/objc/api/RTCVideoRendererAdapter.h" #include "sdk/objc/native/api/video_frame.h" +#include "api/media_types.h" namespace { const size_t frame_samples = 480; @@ -45,9 +40,10 @@ const uint8_t sdp_channels = 2; const uint32_t sdp_bitrate = 0; const uint32_t caller_ssrc = 1; const uint32_t called_ssrc = 2; -const uint32_t caller_ssrc_video = 1; -const uint32_t called_ssrc_video = 2; +const uint32_t caller_ssrc_video = 3; +const uint32_t called_ssrc_video = 4; const int extension_sequence = 1; +const int extension_sequence_video = 1; } static void AddDefaultFeedbackParams(cricket::VideoCodec* codec) { @@ -76,7 +72,6 @@ static std::vector AssignPayloadTypesAndDefaultCodecs(std:: static const int kLastDynamicPayloadType = 127; int payload_type = kFirstDynamicPayloadType; - //input_formats.push_back(webrtc::SdpVideoFormat(cricket::kH264CodecName)); input_formats.push_back(webrtc::SdpVideoFormat(cricket::kRedCodecName)); input_formats.push_back(webrtc::SdpVideoFormat(cricket::kUlpfecCodecName)); @@ -89,6 +84,9 @@ static std::vector AssignPayloadTypesAndDefaultCodecs(std:: flexfec_format.parameters = {{kFlexfecFmtpRepairWindow, "10000000"}}; input_formats.push_back(flexfec_format); }*/ + + bool found = false; + bool useVP9 = true; std::vector output_codecs; for (const webrtc::SdpVideoFormat& format : input_formats) { @@ -97,11 +95,17 @@ static std::vector AssignPayloadTypesAndDefaultCodecs(std:: AddDefaultFeedbackParams(&codec); output_codecs.push_back(codec); - if (codec.name == cricket::kVp9CodecName) { - //outCodecId = codec.id; + if (useVP9 && codec.name == cricket::kVp9CodecName) { + if (!found) { + outCodecId = codec.id; + found = true; + } } - if (codec.name == cricket::kH264CodecName) { - outCodecId = codec.id; + if (!useVP9 && codec.name == cricket::kH264CodecName) { + if (!found) { + outCodecId = codec.id; + found = true; + } } // Increment payload type. @@ -128,14 +132,15 @@ static std::vector AssignPayloadTypesAndDefaultCodecs(std:: return output_codecs; } -MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv) +MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing) : ssrc_send(outgoing ? caller_ssrc : called_ssrc) , ssrc_recv(outgoing ? called_ssrc : caller_ssrc) , ssrc_send_video(outgoing ? caller_ssrc_video : called_ssrc_video) , ssrc_recv_video(outgoing ? called_ssrc_video : caller_ssrc_video) , event_log(std::make_unique()) , task_queue_factory(webrtc::CreateDefaultTaskQueueFactory()) -, data_sender(*this) +, audio_sender(*this, false) +, video_sender(*this, true) , signaling_thread(rtc::Thread::Create()) , worker_thread(rtc::Thread::Create()) { signaling_thread->Start(); @@ -172,16 +177,14 @@ MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv) call.get(), cricket::MediaConfig(), cricket::AudioOptions(), webrtc::CryptoOptions::NoGcm())); video_channel.reset(media_engine->video().CreateMediaChannel(call.get(), cricket::MediaConfig(), cricket::VideoOptions(), webrtc::CryptoOptions::NoGcm(), video_bitrate_allocator_factory.get())); - if (false && send) { + if (true) { voice_channel->AddSendStream(cricket::StreamParams::CreateLegacy(ssrc_send)); SetNetworkParams({6, 32, 6, 120, false, false, false}); SetMute(false); - voice_channel->SetInterface(&data_sender, webrtc::MediaTransportConfig()); - voice_channel->OnReadyToSend(true); - voice_channel->SetSend(true); + voice_channel->SetInterface(&audio_sender, webrtc::MediaTransportConfig()); } - if (send) { + if (true) { video_channel->AddSendStream(cricket::StreamParams::CreateLegacy(ssrc_send_video)); for (auto codec : videoCodecs) { @@ -189,66 +192,68 @@ MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv) rtc::scoped_refptr objCVideoTrackSource(new rtc::RefCountedObject()); _nativeVideoSource = webrtc::VideoTrackSourceProxy::Create(signaling_thread.get(), worker_thread.get(), objCVideoTrackSource); - codec.SetParam(cricket::kCodecParamMinBitrate, 32); - codec.SetParam(cricket::kCodecParamStartBitrate, 100); - codec.SetParam(cricket::kCodecParamMaxBitrate, 1500); - + codec.SetParam(cricket::kCodecParamMinBitrate, 64); + codec.SetParam(cricket::kCodecParamStartBitrate, 256); + codec.SetParam(cricket::kCodecParamMaxBitrate, 2500); + + dispatch_async(dispatch_get_main_queue(), ^{ #if TARGET_IPHONE_SIMULATOR #else - _videoCapturer = [[VideoCameraCapturer alloc] initWithSource:_nativeVideoSource]; - - AVCaptureDevice *frontCamera = nil; - for (AVCaptureDevice *device in [VideoCameraCapturer captureDevices]) { - if (device.position == AVCaptureDevicePositionFront) { - frontCamera = device; - break; + _videoCapturer = [[VideoCameraCapturer alloc] initWithSource:_nativeVideoSource]; + + AVCaptureDevice *frontCamera = nil; + for (AVCaptureDevice *device in [VideoCameraCapturer captureDevices]) { + if (device.position == AVCaptureDevicePositionFront) { + frontCamera = device; + break; + } } - } - - if (frontCamera == nil) { - assert(false); - return; - } - - NSArray *sortedFormats = [[VideoCameraCapturer supportedFormatsForDevice:frontCamera] sortedArrayUsingComparator:^NSComparisonResult(AVCaptureDeviceFormat* lhs, AVCaptureDeviceFormat *rhs) { - int32_t width1 = CMVideoFormatDescriptionGetDimensions(lhs.formatDescription).width; - int32_t width2 = CMVideoFormatDescriptionGetDimensions(rhs.formatDescription).width; - return width1 < width2 ? NSOrderedAscending : NSOrderedDescending; - }]; - - AVCaptureDeviceFormat *bestFormat = nil; - for (AVCaptureDeviceFormat *format in sortedFormats) { - CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(format.formatDescription); - if (dimensions.width >= 1000 || dimensions.height >= 1000) { - bestFormat = format; - break; + + if (frontCamera == nil) { + assert(false); + return; } - } - - if (bestFormat == nil) { - assert(false); - return; - } - - AVFrameRateRange *frameRateRange = [[bestFormat.videoSupportedFrameRateRanges sortedArrayUsingComparator:^NSComparisonResult(AVFrameRateRange *lhs, AVFrameRateRange *rhs) { - if (lhs.maxFrameRate < rhs.maxFrameRate) { - return NSOrderedAscending; - } else { - return NSOrderedDescending; + + NSArray *sortedFormats = [[VideoCameraCapturer supportedFormatsForDevice:frontCamera] sortedArrayUsingComparator:^NSComparisonResult(AVCaptureDeviceFormat* lhs, AVCaptureDeviceFormat *rhs) { + int32_t width1 = CMVideoFormatDescriptionGetDimensions(lhs.formatDescription).width; + int32_t width2 = CMVideoFormatDescriptionGetDimensions(rhs.formatDescription).width; + return width1 < width2 ? NSOrderedAscending : NSOrderedDescending; + }]; + + AVCaptureDeviceFormat *bestFormat = nil; + for (AVCaptureDeviceFormat *format in sortedFormats) { + CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(format.formatDescription); + if (dimensions.width >= 1000 || dimensions.height >= 1000) { + bestFormat = format; + break; + } } - }] lastObject]; - - if (frameRateRange == nil) { - assert(false); - return; - } - - [_videoCapturer startCaptureWithDevice:frontCamera format:bestFormat fps:27]; + + if (bestFormat == nil) { + assert(false); + return; + } + + AVFrameRateRange *frameRateRange = [[bestFormat.videoSupportedFrameRateRanges sortedArrayUsingComparator:^NSComparisonResult(AVFrameRateRange *lhs, AVFrameRateRange *rhs) { + if (lhs.maxFrameRate < rhs.maxFrameRate) { + return NSOrderedAscending; + } else { + return NSOrderedDescending; + } + }] lastObject]; + + if (frameRateRange == nil) { + assert(false); + return; + } + + [_videoCapturer startCaptureWithDevice:frontCamera format:bestFormat fps:27]; #endif + }); cricket::VideoSendParameters send_parameters; send_parameters.codecs.push_back(codec); - send_parameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, extension_sequence); + send_parameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, extension_sequence_video); //send_parameters.options.echo_cancellation = params.echo_cancellation; //send_parameters.options.noise_suppression = params.noise_suppression; //send_parameters.options.auto_gain_control = params.auto_gain_control; @@ -261,15 +266,13 @@ MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv) video_channel->SetVideoSend(ssrc_send_video, NULL, _nativeVideoSource.get()); - video_channel->SetInterface(&data_sender, webrtc::MediaTransportConfig()); - video_channel->OnReadyToSend(true); - video_channel->SetSend(true); + video_channel->SetInterface(&video_sender, webrtc::MediaTransportConfig()); break; } } } - if (false && recv) { + if (true) { cricket::AudioRecvParameters recv_parameters; recv_parameters.codecs.emplace_back(sdp_payload, sdp_name, clockrate, sdp_bitrate, sdp_channels); recv_parameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, extension_sequence); @@ -279,7 +282,7 @@ MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv) voice_channel->SetRecvParameters(recv_parameters); voice_channel->SetPlayout(true); } - if (recv) { + if (true) { for (auto codec : videoCodecs) { if (codec.id == outCodecId) { codec.SetParam(cricket::kCodecParamMinBitrate, 32); @@ -288,7 +291,7 @@ MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv) cricket::VideoRecvParameters recv_parameters; recv_parameters.codecs.emplace_back(codec); - recv_parameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, extension_sequence); + recv_parameters.extensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, extension_sequence_video); //recv_parameters.rtcp.reduced_size = true; recv_parameters.rtcp.remote_estimate = true; video_channel->AddRecvStream(cricket::StreamParams::CreateLegacy(ssrc_recv_video)); @@ -300,14 +303,35 @@ MediaEngineWebrtc::MediaEngineWebrtc(bool outgoing, bool send, bool recv) } } -MediaEngineWebrtc::~MediaEngineWebrtc() = default; +MediaEngineWebrtc::~MediaEngineWebrtc() { + [_videoCapturer stopCapture]; + video_channel->SetSink(ssrc_recv_video, nullptr); + video_channel->RemoveSendStream(ssrc_send_video); + video_channel->RemoveRecvStream(ssrc_recv_video); + + voice_channel->SetPlayout(false); + voice_channel->RemoveSendStream(ssrc_send); + voice_channel->RemoveRecvStream(ssrc_recv); +}; void MediaEngineWebrtc::Receive(rtc::CopyOnWriteBuffer packet) { - if (voice_channel) { - //voice_channel->OnPacketReceived(packet, -1); + if (packet.size() < 1) { + return; } - if (video_channel) { - video_channel->OnPacketReceived(packet, -1); + + uint8_t header = ((uint8_t *)packet.data())[0]; + rtc::CopyOnWriteBuffer unwrappedPacket = packet.Slice(1, packet.size() - 1); + + if (header == 0xba) { + if (voice_channel) { + voice_channel->OnPacketReceived(unwrappedPacket, -1); + } + } else if (header == 0xbf) { + if (video_channel) { + video_channel->OnPacketReceived(unwrappedPacket, -1); + } + } else { + printf("----- Unknown packet header"); } } @@ -336,29 +360,55 @@ void MediaEngineWebrtc::SetNetworkParams(const MediaEngineWebrtc::NetworkParams& // send_parameters.max_bandwidth_bps = 16000; send_parameters.rtcp.reduced_size = true; send_parameters.rtcp.remote_estimate = true; - //voice_channel->SetSendParameters(send_parameters); + voice_channel->SetSendParameters(send_parameters); } void MediaEngineWebrtc::SetMute(bool mute) { - //voice_channel->SetAudioSend(ssrc_send, !mute, nullptr, &audio_source); + } -void MediaEngineWebrtc::AttachVideoView(VideoMetalView *videoView) { - //VideoMetalView *remoteRenderer = [[VideoMetalView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 240.0f)]; - //remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill; - - video_channel->SetSink(ssrc_recv_video, [videoView getSink]); +void MediaEngineWebrtc::SetCanSendPackets(bool canSendPackets) { + if (canSendPackets) { + call->SignalChannelNetworkState(webrtc::MediaType::AUDIO, webrtc::kNetworkUp); + call->SignalChannelNetworkState(webrtc::MediaType::VIDEO, webrtc::kNetworkUp); + } else { + call->SignalChannelNetworkState(webrtc::MediaType::AUDIO, webrtc::kNetworkDown); + call->SignalChannelNetworkState(webrtc::MediaType::VIDEO, webrtc::kNetworkDown); + } + if (voice_channel) { + voice_channel->OnReadyToSend(canSendPackets); + voice_channel->SetSend(canSendPackets); + voice_channel->SetAudioSend(ssrc_send, true, nullptr, &audio_source); + } + if (video_channel) { + video_channel->OnReadyToSend(canSendPackets); + video_channel->SetSend(canSendPackets); + } +} + +void MediaEngineWebrtc::AttachVideoView(rtc::VideoSinkInterface *sink) { + video_channel->SetSink(ssrc_recv_video, sink); } bool MediaEngineWebrtc::Sender::SendPacket(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) { - engine.Send(*packet); + rtc::CopyOnWriteBuffer wrappedPacket; + uint8_t header = isVideo ? 0xbf : 0xba; + wrappedPacket.AppendData(&header, 1); + wrappedPacket.AppendData(*packet); + + engine.Send(wrappedPacket); rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(), options.info_signaled_after_sent); engine.OnSentPacket(sent_packet); return true; } bool MediaEngineWebrtc::Sender::SendRtcp(rtc::CopyOnWriteBuffer *packet, const rtc::PacketOptions& options) { - engine.Send(*packet); + rtc::CopyOnWriteBuffer wrappedPacket; + uint8_t header = isVideo ? 0xbf : 0xba; + wrappedPacket.AppendData(&header, 1); + wrappedPacket.AppendData(*packet); + + engine.Send(wrappedPacket); rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(), options.info_signaled_after_sent); engine.OnSentPacket(sent_packet); return true; @@ -368,4 +418,8 @@ int MediaEngineWebrtc::Sender::SetOption(cricket::MediaChannel::NetworkInterface return -1; // in general, the result is not important yet } -MediaEngineWebrtc::Sender::Sender(MediaEngineWebrtc& engine) : engine(engine) {} +MediaEngineWebrtc::Sender::Sender(MediaEngineWebrtc &engine, bool isVideo) : +engine(engine), +isVideo(isVideo) { + +} diff --git a/submodules/TgVoipWebrtc/Impl/Message.h b/submodules/TgVoipWebrtc/Impl/Message.h deleted file mode 100644 index 9d9f62e4ca..0000000000 --- a/submodules/TgVoipWebrtc/Impl/Message.h +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef DEMO_MESSAGE_H -#define DEMO_MESSAGE_H - -#include "rtc_base/copy_on_write_buffer.h" -#include "rtc_base/socket_address.h" - -namespace message { - -enum Type { - tUnknown, - tReady, - tConnected, - tDisconnected, - tRelayPing, - tRelayPong, - tGetPeerInfo, - tPeerInfo, - tSelfIPv6, - tSelfLocalIP, - tInit, - tInitAck, - tPing, - tPong, - tBufferOverflow, - tPacketIncorrect, - tWrongProtocol, - tRtpStream, -}; - -enum NetworkType { - nGprs, - nEdge, - n3gOrAbove, - nHighSpeed, - nUnknown, -}; - -struct Base { - virtual ~Base() = default; - explicit Base(Type ID) : ID(ID) {} - const Type ID; -}; - -struct Unknown : Base { - Unknown() : Base(Type::tUnknown) {} -}; - -struct Ready : Base { - Ready() : Base(Type::tReady) {} -}; - -struct Connected : Base { - Connected() : Base(Type::tConnected) {} -}; - -struct Disconnected : Base { - Disconnected() : Base(Type::tDisconnected) {} -}; - -struct RelayPing : Base { - RelayPing() : Base(Type::tRelayPing) {} -}; - -struct RelayPong : Base { - RelayPong() : Base(Type::tRelayPong) {} - uint32_t date{}; // int32_t in src - uint64_t query_id{}; //int64_t in src - rtc::SocketAddress my_addr; -}; - -struct GetPeerInfo : Base { - GetPeerInfo() : Base(Type::tGetPeerInfo) {} -}; - -struct PeerInfo : Base { - PeerInfo() : Base(Type::tPeerInfo) {} - rtc::SocketAddress my_addr; - rtc::SocketAddress peer_addr; -}; - -struct SelfIPv6 : Base { - SelfIPv6() : Base(Type::tSelfIPv6) {} - rtc::SocketAddress my_addr; -}; - -struct SelfLocalIP : Base { - SelfLocalIP() : Base(Type::tSelfLocalIP) {} -}; - -struct Init : Base { - Init() : Base(Type::tInit) {} - uint32_t ver{}; - uint32_t minVer{}; - uint32_t flags{}; -}; - -struct InitAck : Base { - InitAck() : Base(Type::tInitAck) {} - uint32_t ver{}; - uint32_t minVer{}; -}; - -struct Ping : Base { - Ping() : Base(Type::tPing) {} - uint32_t id{}; -}; - -struct Pong : Base { - Pong() : Base(Type::tPong) {} - uint32_t id{}; -}; - -struct BufferOverflow : Base { - BufferOverflow() : Base(Type::tBufferOverflow) {} -}; - -struct PacketIncorrect : Base { - PacketIncorrect() : Base(Type::tPacketIncorrect) {} -}; - -struct WrongProtocol : Base { - WrongProtocol() : Base(Type::tWrongProtocol) {} -}; - -struct RtpStream : Base { - RtpStream() : Base(Type::tRtpStream) {} - bool data_saving{false}; - NetworkType network_type{NetworkType::nUnknown}; - rtc::CopyOnWriteBuffer data; -}; - -} - -#endif //DEMO_MESSAGE_H diff --git a/submodules/TgVoipWebrtc/Impl/PlatformCodecs.h b/submodules/TgVoipWebrtc/Impl/PlatformCodecs.h deleted file mode 100644 index 9c61de32f6..0000000000 --- a/submodules/TgVoipWebrtc/Impl/PlatformCodecs.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef PLATFORM_CODECS_H -#define PLATFORM_CODECS_H - - - -#endif //PLATFORM_CODECS_H diff --git a/submodules/TgVoipWebrtc/Impl/PlatformCodecs.mm b/submodules/TgVoipWebrtc/Impl/PlatformCodecs.mm deleted file mode 100644 index d572231b37..0000000000 --- a/submodules/TgVoipWebrtc/Impl/PlatformCodecs.mm +++ /dev/null @@ -1,2 +0,0 @@ -#include "PlatformCodecs.h" - diff --git a/submodules/TgVoipWebrtc/Impl/Protocol10.cpp b/submodules/TgVoipWebrtc/Impl/Protocol10.cpp deleted file mode 100644 index 05d47da952..0000000000 --- a/submodules/TgVoipWebrtc/Impl/Protocol10.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include "Protocol10.h" - -#include "rtc_base/byte_buffer.h" - -#include -#include - -const std::map Protocol10::decoders = { - {Protocol10::PacketType::tInit, Protocol10::InitDecode}, // back compatibility - {Protocol10::PacketType::tInitAck, Protocol10::InitAckDecode}, // back compatibility - {Protocol10::PacketType::tRtpStream, Protocol10::RtpStreamDecode}, - {Protocol10::PacketType::tPing, Protocol10::PingDecode}, - {Protocol10::PacketType::tPong, Protocol10::PongDecode}, -}; - -const std::map Protocol10::encoders = { - {message::tInit, Protocol10::InitEncode}, - {message::tInitAck, Protocol10::InitAckEncode}, - {message::tRtpStream, Protocol10::RtpStreamEncode}, - {message::tPing, Protocol10::PingEncode}, - {message::tPong, Protocol10::PongEncode}, -}; - -Protocol10::Protocol10() : ProtocolBase(10) {} - -std::unique_ptr Protocol10::ReadProtocolPacket(const uint8_t *buffer, size_t size) { - uint8_t type = buffer[0]; - auto deserializer = decoders.find(type); - if (deserializer == decoders.end()) - return nullptr; - return deserializer->second(buffer + 1, size - 1); -} - -rtc::Buffer Protocol10::WriteProtocolPacket(const message::Base *msg) { - auto serializer = encoders.find(msg->ID); - if (serializer == encoders.end()) - return rtc::Buffer(); - return serializer->second(msg); -} - -rtc::Buffer Protocol10::InitEncode(const message::Base *msg_base) { - const auto *msg = dynamic_cast(msg_base); - if (!msg) - return rtc::Buffer(); - rtc::ByteBufferWriter out; - out.WriteUInt8(PacketType::tInit); - out.Resize(14); - out.WriteUInt32(rtc::NetworkToHost32(msg->ver)); - out.WriteUInt32(rtc::NetworkToHost32(msg->minVer)); - out.WriteUInt32(rtc::NetworkToHost32(msg->flags)); - return rtc::Buffer(out.Data(), out.Length()); -} - -std::unique_ptr Protocol10::InitDecode(const uint8_t *buffer, size_t size) { - rtc::ByteBufferReader in(reinterpret_cast(buffer), size); - uint32_t ackId = 0, pseq = 0, acks = 0; - unsigned char pflags = 0; - in.ReadUInt32(&ackId); - in.ReadUInt32(&pseq); - in.ReadUInt32(&acks); - in.ReadUInt8(&pflags); - auto msg = std::make_unique(); - in.ReadUInt32(&msg->ver); - in.ReadUInt32(&msg->minVer); - in.ReadUInt32(&msg->flags); - msg->ver = rtc::HostToNetwork32(msg->ver); - msg->minVer = rtc::HostToNetwork32(msg->minVer); - msg->flags = rtc::HostToNetwork32(msg->flags); - if (ProtocolBase::IsSupported(msg->ver)) - return msg; - // TODO: support matching of lower supported versions - return std::make_unique(); -} - -rtc::Buffer Protocol10::InitAckEncode(const message::Base *msg_base) { - const auto *msg = dynamic_cast(msg_base); - if (!msg) - return rtc::Buffer(); - rtc::ByteBufferWriter out; - out.WriteUInt8(PacketType::tInitAck); - out.Resize(14); - out.WriteUInt32(rtc::NetworkToHost32(msg->ver)); - out.WriteUInt32(rtc::NetworkToHost32(msg->minVer)); - return rtc::Buffer(out.Data(), out.Length()); -} - -std::unique_ptr Protocol10::InitAckDecode(const uint8_t *buffer, size_t size) { - rtc::ByteBufferReader in(reinterpret_cast(buffer), size); - uint32_t ackId = 0, pseq = 0, acks = 0; - unsigned char pflags = 0; - in.ReadUInt32(&ackId); - in.ReadUInt32(&pseq); - in.ReadUInt32(&acks); - in.ReadUInt8(&pflags); - auto msg = std::make_unique(); - in.ReadUInt32(&msg->ver); - in.ReadUInt32(&msg->minVer); - msg->ver = rtc::HostToNetwork32(msg->ver); - msg->minVer = rtc::HostToNetwork32(msg->minVer); - if (ProtocolBase::IsSupported(msg->ver)) - return msg; - // TODO: support matching of lower supported versions - return std::make_unique(); -} - -rtc::Buffer Protocol10::RtpStreamEncode(const message::Base *msg_base) { - const auto *msg = dynamic_cast(msg_base); - if (!msg) - return rtc::Buffer(); - rtc::ByteBufferWriter out; - out.WriteUInt8(PacketType::tRtpStream); - uint8_t meta = (msg->network_type & 0b111) | (msg->data_saving << 3); - out.WriteUInt8(meta); - out.WriteBytes(reinterpret_cast(msg->data.data()), msg->data.size()); - return rtc::Buffer(out.Data(), out.Length()); -} - -std::unique_ptr Protocol10::RtpStreamDecode(const uint8_t *buffer, size_t size) { - auto msg = std::make_unique(); - uint8_t meta = buffer[0]; - msg->network_type = (message::NetworkType) (meta & 0b111); - msg->data_saving = (meta >> 3) & 0b1; - msg->data = rtc::CopyOnWriteBuffer(buffer + 1, size - 1); - return msg; -} - -rtc::Buffer Protocol10::PingEncode(const message::Base *msg_base) { - const auto *msg = dynamic_cast(msg_base); - if (!msg) - return rtc::Buffer(); - rtc::ByteBufferWriter out; - out.WriteUInt8(PacketType::tPing); - out.WriteUInt32(msg->id); - return rtc::Buffer(out.Data(), out.Length()); -} - -std::unique_ptr Protocol10::PingDecode(const uint8_t *buffer, size_t size) { - rtc::ByteBufferReader in(reinterpret_cast(buffer), size); - auto msg = std::make_unique(); - in.ReadUInt32(&msg->id); - return msg; -} - -rtc::Buffer Protocol10::PongEncode(const message::Base *msg_base) { - const auto *msg = dynamic_cast(msg_base); - if (!msg) - return rtc::Buffer(); - rtc::ByteBufferWriter out; - out.WriteUInt8(PacketType::tPong); - out.WriteUInt32(msg->id); - return rtc::Buffer(out.Data(), out.Length()); -} - -std::unique_ptr Protocol10::PongDecode(const uint8_t *buffer, size_t size) { - rtc::ByteBufferReader in(reinterpret_cast(buffer), size); - auto msg = std::make_unique(); - in.ReadUInt32(&msg->id); - return msg; -} diff --git a/submodules/TgVoipWebrtc/Impl/Protocol10.h b/submodules/TgVoipWebrtc/Impl/Protocol10.h deleted file mode 100644 index 6ba7a6e4de..0000000000 --- a/submodules/TgVoipWebrtc/Impl/Protocol10.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef DEMO_PROTOCOL10_H -#define DEMO_PROTOCOL10_H - - -#include "Message.h" -#include "ProtocolBase.h" - -#include - -class Protocol10 : public ProtocolBase { -public: - enum PacketType { - tInit = 1, - tInitAck, - tRtpStream, - tPing, - tPong, - }; - - Protocol10(); - std::unique_ptr ReadProtocolPacket(const uint8_t *buffer, size_t size) override; - rtc::Buffer WriteProtocolPacket(const message::Base *msg) override; - -private: - typedef std::function(const uint8_t *, size_t)> Deserializer; - typedef std::function Serializer; - - static const std::map decoders; - static const std::map encoders; - - static rtc::Buffer InitEncode(const message::Base *msg_base); - static std::unique_ptr InitDecode(const uint8_t *buffer, size_t size); - static rtc::Buffer InitAckEncode(const message::Base *msg_base); - static std::unique_ptr InitAckDecode(const uint8_t *buffer, size_t size); - static rtc::Buffer RtpStreamEncode(const message::Base *msg_base); - static std::unique_ptr RtpStreamDecode(const uint8_t *buffer, size_t size); - static rtc::Buffer PingEncode(const message::Base *msg_base); - static std::unique_ptr PingDecode(const uint8_t *buffer, size_t size); - static rtc::Buffer PongEncode(const message::Base *msg_base); - static std::unique_ptr PongDecode(const uint8_t *buffer, size_t size); -}; - - -#endif //DEMO_PROTOCOL10_H diff --git a/submodules/TgVoipWebrtc/Impl/ProtocolBase.cpp b/submodules/TgVoipWebrtc/Impl/ProtocolBase.cpp deleted file mode 100644 index 38476d4d4b..0000000000 --- a/submodules/TgVoipWebrtc/Impl/ProtocolBase.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "ProtocolBase.h" - -#include "Protocol10.h" - -const std::map ProtocolBase::constructors = { - {10, std::make_unique}, -}; - -const uint32_t ProtocolBase::actual_version = 10; -const uint32_t ProtocolBase::minimal_version = 10; - -std::unique_ptr ProtocolBase::CreateProtocol(uint32_t version) { - auto protocol = constructors.find(version); - if (protocol == constructors.end()) - return nullptr; - return protocol->second(); -} - -bool ProtocolBase::IsSupported(uint32_t version) { - return constructors.find(version) != constructors.end(); -} - -ProtocolBase::ProtocolBase(uint32_t version) : version(version) {} diff --git a/submodules/TgVoipWebrtc/Impl/ProtocolBase.h b/submodules/TgVoipWebrtc/Impl/ProtocolBase.h deleted file mode 100644 index e15610b0f6..0000000000 --- a/submodules/TgVoipWebrtc/Impl/ProtocolBase.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef DEMO_PROTOCOLBASE_H -#define DEMO_PROTOCOLBASE_H - - -#include "Message.h" - -#include -#include -#include - -class ProtocolBase { -public: - static const uint32_t actual_version; - static const uint32_t minimal_version; - static std::unique_ptr CreateProtocol(uint32_t version); - static bool IsSupported(uint32_t version); - - virtual ~ProtocolBase() = default; - virtual std::unique_ptr ReadProtocolPacket(const uint8_t *buffer, size_t size) = 0; - virtual rtc::Buffer WriteProtocolPacket(const message::Base *msg) = 0; - - const uint32_t version; - -protected: - explicit ProtocolBase(uint32_t version); - -private: - typedef std::function()> Constructor; - static const std::map constructors; -}; - - -#endif //DEMO_PROTOCOLBASE_H diff --git a/submodules/TgVoipWebrtc/Impl/TgVoip.h b/submodules/TgVoipWebrtc/Impl/TgVoip.h index 2f1b1e1759..220975e71b 100644 --- a/submodules/TgVoipWebrtc/Impl/TgVoip.h +++ b/submodules/TgVoipWebrtc/Impl/TgVoip.h @@ -66,19 +66,6 @@ struct TgVoipPersistentState { std::vector value; }; -#ifdef TGVOIP_USE_CUSTOM_CRYPTO -struct TgVoipCrypto { - void (*rand_bytes)(uint8_t* buffer, size_t length); - void (*sha1)(uint8_t* msg, size_t length, uint8_t* output); - void (*sha256)(uint8_t* msg, size_t length, uint8_t* output); - void (*aes_ige_encrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv); - void (*aes_ige_decrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv); - void (*aes_ctr_encrypt)(uint8_t* inout, size_t length, uint8_t* key, uint8_t* iv, uint8_t* ecount, uint32_t* num); - void (*aes_cbc_encrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv); - void (*aes_cbc_decrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv); -}; -#endif - struct TgVoipConfig { double initializationTimeout; double receiveTimeout; @@ -145,14 +132,6 @@ public: std::unique_ptr const &proxy, TgVoipNetworkType initialNetworkType, TgVoipEncryptionKey const &encryptionKey -#ifdef TGVOIP_USE_CUSTOM_CRYPTO - , - TgVoipCrypto const &crypto -#endif -#ifdef TGVOIP_USE_CALLBACK_AUDIO_IO - , - TgVoipAudioDataCallbacks const &audioDataCallbacks -#endif ); virtual ~TgVoip(); @@ -172,6 +151,9 @@ public: virtual void setOnStateUpdated(std::function onStateUpdated) = 0; virtual void setOnSignalBarsUpdated(std::function onSignalBarsUpdated) = 0; + virtual void setOnCandidatesGathered(std::function &)> onCandidatesGathered) = 0; + + virtual void addRemoteCandidates(const std::vector &candidates) = 0; virtual TgVoipFinalState stop() = 0; }; diff --git a/submodules/TgVoipWebrtc/Impl/TgVoip.mm b/submodules/TgVoipWebrtc/Impl/TgVoip.mm index f1046f705c..8ebefc7aa4 100644 --- a/submodules/TgVoipWebrtc/Impl/TgVoip.mm +++ b/submodules/TgVoipWebrtc/Impl/TgVoip.mm @@ -3,14 +3,12 @@ #include "TgVoip.h" #include "Controller.h" -#include "Layer92.h" -#include "Message.h" #include #include #ifndef TGVOIP_USE_CUSTOM_CRYPTO -extern "C" { +/*extern "C" { #include #include #include @@ -18,52 +16,48 @@ extern "C" { #include } -void tgvoip_openssl_aes_ige_encrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){ +static void tgvoip_openssl_aes_ige_encrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){ AES_KEY akey; AES_set_encrypt_key(key, 32*8, &akey); AES_ige_encrypt(in, out, length, &akey, iv, AES_ENCRYPT); } -void tgvoip_openssl_aes_ige_decrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){ +static void tgvoip_openssl_aes_ige_decrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){ AES_KEY akey; AES_set_decrypt_key(key, 32*8, &akey); AES_ige_encrypt(in, out, length, &akey, iv, AES_DECRYPT); } -void tgvoip_openssl_rand_bytes(uint8_t* buffer, size_t len){ +static void tgvoip_openssl_rand_bytes(uint8_t* buffer, size_t len){ RAND_bytes(buffer, (int)len); } -void tgvoip_openssl_sha1(uint8_t* msg, size_t len, uint8_t* output){ +static void tgvoip_openssl_sha1(uint8_t* msg, size_t len, uint8_t* output){ SHA1(msg, len, output); } -void tgvoip_openssl_sha256(uint8_t* msg, size_t len, uint8_t* output){ +static void tgvoip_openssl_sha256(uint8_t* msg, size_t len, uint8_t* output){ SHA256(msg, len, output); } -void tgvoip_openssl_aes_ctr_encrypt(uint8_t* inout, size_t length, uint8_t* key, uint8_t* iv, uint8_t* ecount, uint32_t* num){ +static void tgvoip_openssl_aes_ctr_encrypt(uint8_t* inout, size_t length, uint8_t* key, uint8_t* iv, uint8_t* ecount, uint32_t* num){ AES_KEY akey; AES_set_encrypt_key(key, 32*8, &akey); CRYPTO_ctr128_encrypt(inout, inout, length, &akey, iv, ecount, num, (block128_f) AES_encrypt); } -void tgvoip_openssl_aes_cbc_encrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){ +static void tgvoip_openssl_aes_cbc_encrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){ AES_KEY akey; AES_set_encrypt_key(key, 256, &akey); AES_cbc_encrypt(in, out, length, &akey, iv, AES_ENCRYPT); } -void tgvoip_openssl_aes_cbc_decrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){ +static void tgvoip_openssl_aes_cbc_decrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){ AES_KEY akey; AES_set_decrypt_key(key, 256, &akey); AES_cbc_encrypt(in, out, length, &akey, iv, AES_DECRYPT); } -const char * openssl_version() { - return SSLeay_version(SSLEAY_VERSION); -} - CryptoFunctions Layer92::crypto={ tgvoip_openssl_rand_bytes, tgvoip_openssl_sha1, @@ -73,7 +67,7 @@ CryptoFunctions Layer92::crypto={ tgvoip_openssl_aes_ctr_encrypt, tgvoip_openssl_aes_cbc_encrypt, tgvoip_openssl_aes_cbc_decrypt -}; +};*/ #endif @@ -82,6 +76,9 @@ namespace TGVOIP_NAMESPACE { #endif class TgVoipImpl : public TgVoip, public sigslot::has_slots<> { +private: + + public: TgVoipImpl( std::vector const &endpoints, @@ -90,38 +87,17 @@ public: TgVoipConfig const &config, TgVoipEncryptionKey const &encryptionKey, TgVoipNetworkType initialNetworkType -#ifdef TGVOIP_USE_CUSTOM_CRYPTO - , - TgVoipCrypto const &crypto -#endif -#ifdef TGVOIP_USE_CALLBACK_AUDIO_IO - , - TgVoipAudioDataCallbacks const &audioDataCallbacks -#endif ) { -#ifdef TGVOIP_USE_CUSTOM_CRYPTO - tgvoip::VoIPController::crypto.sha1 = crypto.sha1; - tgvoip::VoIPController::crypto.sha256 = crypto.sha256; - tgvoip::VoIPController::crypto.rand_bytes = crypto.rand_bytes; - tgvoip::VoIPController::crypto.aes_ige_encrypt = crypto.aes_ige_encrypt; - tgvoip::VoIPController::crypto.aes_ige_decrypt = crypto.aes_ige_decrypt; - tgvoip::VoIPController::crypto.aes_ctr_encrypt = crypto.aes_ctr_encrypt; -#endif + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + rtc::LogMessage::LogToDebug(rtc::LS_INFO); + rtc::LogMessage::SetLogToStderr(true); + }); -// std::cerr << "OpenSSL version: " << openssl_version() << std::endl; // to verify because of WebRTC BoringSSL - - EncryptionKey encryptionKeyValue; - memcpy(encryptionKeyValue, encryptionKey.value.data(), 256); - controller_ = new Controller(encryptionKey.isOutgoing, encryptionKeyValue, 5, 3); - -#ifdef TGVOIP_USE_CALLBACK_AUDIO_IO - audioCallbacks = audioDataCallbacks; - controller_->SignalRecord.connect(this, &TgVoipImpl::record); - controller_->SignalPlay.connect(this, &TgVoipImpl::play); -#ifdef TGVOIP_PREPROCESSED_OUTPUT - controller_->SignalPreprocessed.connect(this, &TgVoipImpl::preprocessed); -#endif -#endif + /*EncryptionKey encryptionKeyValue; + memcpy(encryptionKeyValue, encryptionKey.value.data(), 256);*/ + controller_ = new Controller(encryptionKey.isOutgoing, 5, 3); if (proxy != nullptr) { controller_->SetProxy(rtc::ProxyType::PROXY_SOCKS5, rtc::SocketAddress(proxy->host, proxy->port), @@ -129,6 +105,7 @@ public: } controller_->SignalNewState.connect(this, &TgVoipImpl::controllerStateCallback); + controller_->SignalCandidatesGathered.connect(this, &TgVoipImpl::candidatesGathered); controller_->Start(); for (const auto &endpoint : endpoints) { @@ -149,7 +126,7 @@ public: type = Controller::EndpointType::UDP; break; } - controller_->AddEndpoint(addr, endpoint.peerTag, type); + //controller_->AddEndpoint(addr, endpoint.peerTag, type); } /*rtc::SocketAddress addr("192.168.8.118", 7325); unsigned char peerTag[16]; @@ -183,9 +160,17 @@ public: std::lock_guard lock(m_onSignalBarsUpdated); onSignalBarsUpdated_ = onSignalBarsUpdated; } + + void setOnCandidatesGathered(std::function &)> onCandidatesGathered) override { + onCandidatesGathered_ = onCandidatesGathered; + } + + void addRemoteCandidates(const std::vector &candidates) override { + controller_->AddRemoteCandidates(candidates); + } void setNetworkType(TgVoipNetworkType networkType) override { - message::NetworkType mappedType; + /*message::NetworkType mappedType; switch (networkType) { case TgVoipNetworkType::Unknown: @@ -229,7 +214,7 @@ public: break; } - controller_->SetNetworkType(mappedType); + controller_->SetNetworkType(mappedType);*/ } void setMuteMicrophone(bool muteMicrophone) override { @@ -237,7 +222,7 @@ public: } void AttachVideoView(VideoMetalView *videoView) override { - controller_->AttachVideoView(videoView); + controller_->AttachVideoView([videoView getSink]); } void setAudioOutputGainControlEnabled(bool enabled) override { @@ -303,6 +288,10 @@ public: onStateUpdated_(mappedState); } } + + void candidatesGathered(const std::vector &candidates) { + onCandidatesGathered_(candidates); + } private: #ifdef TGVOIP_USE_CALLBACK_AUDIO_IO @@ -334,6 +323,7 @@ private: Controller *controller_; std::function onStateUpdated_; std::function onSignalBarsUpdated_; + std::function &)> onCandidatesGathered_; std::mutex m_onStateUpdated, m_onSignalBarsUpdated; }; @@ -379,14 +369,6 @@ TgVoip *TgVoip::makeInstance( std::unique_ptr const &proxy, TgVoipNetworkType initialNetworkType, TgVoipEncryptionKey const &encryptionKey -#ifdef TGVOIP_USE_CUSTOM_CRYPTO -, - TgVoipCrypto const &crypto -#endif -#ifdef TGVOIP_USE_CALLBACK_AUDIO_IO - , - TgVoipAudioDataCallbacks const &audioDataCallbacks -#endif ) { return new TgVoipImpl( endpoints, @@ -395,14 +377,6 @@ TgVoip *TgVoip::makeInstance( config, encryptionKey, initialNetworkType -#ifdef TGVOIP_USE_CUSTOM_CRYPTO - , - crypto -#endif -#ifdef TGVOIP_USE_CALLBACK_AUDIO_IO - , - audioDataCallbacks -#endif ); } diff --git a/submodules/TgVoipWebrtc/PublicHeaders/TgVoip/OngoingCallThreadLocalContext.h b/submodules/TgVoipWebrtc/PublicHeaders/TgVoip/OngoingCallThreadLocalContext.h index 0ba7cb28da..6ecd994552 100644 --- a/submodules/TgVoipWebrtc/PublicHeaders/TgVoip/OngoingCallThreadLocalContext.h +++ b/submodules/TgVoipWebrtc/PublicHeaders/TgVoip/OngoingCallThreadLocalContext.h @@ -65,7 +65,7 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtc) { @property (nonatomic, copy) void (^ _Nullable stateChanged)(OngoingCallStateWebrtc); @property (nonatomic, copy) void (^ _Nullable signalBarsChanged)(int32_t); -- (instancetype _Nonnull)initWithQueue:(id _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtc * _Nonnull)primaryConnection alternativeConnections:(NSArray * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath; +- (instancetype _Nonnull)initWithQueue:(id _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtc * _Nonnull)primaryConnection alternativeConnections:(NSArray * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath sendSignalingData:(void (^)(NSData * _Nonnull))sendSignalingData; - (void)stop:(void (^_Nullable)(NSString * _Nullable debugLog, int64_t bytesSentWifi, int64_t bytesReceivedWifi, int64_t bytesSentMobile, int64_t bytesReceivedMobile))completion; - (bool)needRate; @@ -77,6 +77,7 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtc) { - (void)setIsMuted:(bool)isMuted; - (void)setNetworkType:(OngoingCallNetworkTypeWebrtc)networkType; - (void)getRemoteCameraView:(void (^_Nonnull)(UIView * _Nullable))completion; +- (void)addSignalingData:(NSData * _Nonnull)data; @end diff --git a/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm b/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm index d019867d6b..f8fd37445e 100644 --- a/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm +++ b/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm @@ -35,6 +35,8 @@ using namespace TGVOIP_NAMESPACE; OngoingCallStateWebrtc _state; int32_t _signalBars; NSData *_lastDerivedState; + + void (^_sendSignalingData)(NSData *); } - (void)controllerStateChanged:(TgVoipState)state; @@ -112,7 +114,7 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL; return @"2.7.7"; } -- (instancetype _Nonnull)initWithQueue:(id _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtc * _Nonnull)primaryConnection alternativeConnections:(NSArray * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath { +- (instancetype _Nonnull)initWithQueue:(id _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtc * _Nonnull)primaryConnection alternativeConnections:(NSArray * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath sendSignalingData:(void (^)(NSData * _Nonnull))sendSignalingData; { self = [super init]; if (self != nil) { _queue = queue; @@ -123,6 +125,7 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL; _callConnectTimeout = 30.0; _callPacketTimeout = 10.0; _networkType = networkType; + _sendSignalingData = [sendSignalingData copy]; std::vector derivedStateValue; derivedStateValue.resize(derivedState.length); @@ -211,6 +214,16 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL; [strongSelf signalBarsChanged:signalBars]; } }); + _tgVoip->setOnCandidatesGathered([weakSelf](const std::vector &candidates) { + __strong OngoingCallThreadLocalContextWebrtc *strongSelf = weakSelf; + if (strongSelf) { + NSMutableArray *mappedCandidates = [[NSMutableArray alloc] init]; + for (auto &candidate : candidates) { + [mappedCandidates addObject:[[NSString alloc] initWithCString:candidate.c_str() encoding:NSUTF8StringEncoding]]; + } + [strongSelf candidatesGathered:mappedCandidates]; + } + }); } return self; } @@ -307,6 +320,30 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL; } } +- (void)candidatesGathered:(NSArray *)candidates { + if (_sendSignalingData) { + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:@{ + @"type": @"candidates", + @"data": candidates + }]; + _sendSignalingData(data); + } +} + +- (void)addSignalingData:(NSData *)data { + NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithData:data]; + NSString *type = dict[@"type"]; + if ([type isEqualToString:@"candidates"]) { + if (_tgVoip) { + std::vector candidates; + for (NSString *string in dict[@"data"]) { + candidates.push_back([string UTF8String]); + } + _tgVoip->addRemoteCandidates(candidates); + } + } +} + - (void)setIsMuted:(bool)isMuted { if (_tgVoip) { _tgVoip->setMuteMicrophone(isMuted); @@ -324,13 +361,15 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL; - (void)getRemoteCameraView:(void (^_Nonnull)(UIView * _Nullable))completion { if (_tgVoip) { - VideoMetalView *remoteRenderer = [[VideoMetalView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 240.0f)]; - remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill; - - _tgVoip->AttachVideoView(remoteRenderer); - dispatch_async(dispatch_get_main_queue(), ^{ - completion(remoteRenderer); + VideoMetalView *remoteRenderer = [[VideoMetalView alloc] initWithFrame:CGRectZero]; + remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill; + + _tgVoip->AttachVideoView(remoteRenderer); + + dispatch_async(dispatch_get_main_queue(), ^{ + completion(remoteRenderer); + }); }); } } diff --git a/third-party/webrtc/build-webrtc-bazel.sh b/third-party/webrtc/build-webrtc-bazel.sh index a0cb411e82..0e076ccb1d 100755 --- a/third-party/webrtc/build-webrtc-bazel.sh +++ b/third-party/webrtc/build-webrtc-bazel.sh @@ -23,7 +23,7 @@ if [ "$ARCH" == "x64" ]; then OUT_DIR="ios_sim" fi -gn gen out/$OUT_DIR --args="use_xcode_clang=true "" target_cpu=\"$ARCH\""' target_os="ios" is_debug=true is_component_build=false rtc_include_tests=false use_rtti=true rtc_use_x11=false use_custom_libcxx=false use_custom_libcxx_for_host=false rtc_build_ssl=false rtc_build_examples=false rtc_build_tools=false ios_deployment_target="9.0" ios_enable_code_signing=false is_unsafe_developer_build=false rtc_enable_protobuf=false rtc_include_builtin_video_codecs=true rtc_build_libvpx=true rtc_libvpx_build_vp9=true rtc_use_gtk=false rtc_use_metal_rendering=true rtc_ssl_root="//openssl"' +gn gen out/$OUT_DIR --args="use_xcode_clang=true "" target_cpu=\"$ARCH\""' target_os="ios" is_debug=false is_component_build=false rtc_include_tests=false use_rtti=true rtc_use_x11=false use_custom_libcxx=false use_custom_libcxx_for_host=false rtc_build_ssl=false rtc_build_examples=false rtc_build_tools=false ios_deployment_target="9.0" ios_enable_code_signing=false is_unsafe_developer_build=false rtc_enable_protobuf=false rtc_include_builtin_video_codecs=true rtc_build_libvpx=true rtc_libvpx_build_vp9=true rtc_use_gtk=false rtc_use_metal_rendering=true rtc_ssl_root="//openssl"' ninja -C out/$OUT_DIR framework_objc_static popd