diff options
Diffstat (limited to 'third_party/libwebrtc/test/network/emulated_turn_server.cc')
-rw-r--r-- | third_party/libwebrtc/test/network/emulated_turn_server.cc | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/third_party/libwebrtc/test/network/emulated_turn_server.cc b/third_party/libwebrtc/test/network/emulated_turn_server.cc new file mode 100644 index 0000000000..0bc7ec6e2a --- /dev/null +++ b/third_party/libwebrtc/test/network/emulated_turn_server.cc @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "test/network/emulated_turn_server.h" + +#include <string> +#include <utility> + +#include "api/packet_socket_factory.h" +#include "rtc_base/strings/string_builder.h" +#include "rtc_base/task_queue_for_test.h" + +namespace { + +static const char kTestRealm[] = "example.org"; +static const char kTestSoftware[] = "TestTurnServer"; + +// A wrapper class for copying data between an AsyncPacketSocket and a +// EmulatedEndpoint. This is used by the cricket::TurnServer when +// sending data back into the emulated network. +class AsyncPacketSocketWrapper : public rtc::AsyncPacketSocket { + public: + AsyncPacketSocketWrapper(webrtc::test::EmulatedTURNServer* turn_server, + webrtc::EmulatedEndpoint* endpoint, + uint16_t port) + : turn_server_(turn_server), + endpoint_(endpoint), + local_address_( + rtc::SocketAddress(endpoint_->GetPeerLocalAddress(), port)) {} + ~AsyncPacketSocketWrapper() { turn_server_->Unbind(local_address_); } + + rtc::SocketAddress GetLocalAddress() const override { return local_address_; } + rtc::SocketAddress GetRemoteAddress() const override { + return rtc::SocketAddress(); + } + int Send(const void* pv, + size_t cb, + const rtc::PacketOptions& options) override { + RTC_CHECK(false) << "TCP not implemented"; + return -1; + } + int SendTo(const void* pv, + size_t cb, + const rtc::SocketAddress& addr, + const rtc::PacketOptions& options) override { + // Copy from rtc::AsyncPacketSocket to EmulatedEndpoint. + rtc::CopyOnWriteBuffer buf(reinterpret_cast<const char*>(pv), cb); + endpoint_->SendPacket(local_address_, addr, buf); + return cb; + } + int Close() override { return 0; } + + rtc::AsyncPacketSocket::State GetState() const override { + return rtc::AsyncPacketSocket::STATE_BOUND; + } + int GetOption(rtc::Socket::Option opt, int* value) override { return 0; } + int SetOption(rtc::Socket::Option opt, int value) override { return 0; } + int GetError() const override { return 0; } + void SetError(int error) override {} + + private: + webrtc::test::EmulatedTURNServer* const turn_server_; + webrtc::EmulatedEndpoint* const endpoint_; + const rtc::SocketAddress local_address_; +}; + +// A wrapper class for cricket::TurnServer to allocate sockets. +class PacketSocketFactoryWrapper : public rtc::PacketSocketFactory { + public: + explicit PacketSocketFactoryWrapper( + webrtc::test::EmulatedTURNServer* turn_server) + : turn_server_(turn_server) {} + ~PacketSocketFactoryWrapper() override {} + + // This method is called from TurnServer when making a TURN ALLOCATION. + // It will create a socket on the `peer_` endpoint. + rtc::AsyncPacketSocket* CreateUdpSocket(const rtc::SocketAddress& address, + uint16_t min_port, + uint16_t max_port) override { + return turn_server_->CreatePeerSocket(); + } + + rtc::AsyncListenSocket* CreateServerTcpSocket( + const rtc::SocketAddress& local_address, + uint16_t min_port, + uint16_t max_port, + int opts) override { + return nullptr; + } + rtc::AsyncPacketSocket* CreateClientTcpSocket( + const rtc::SocketAddress& local_address, + const rtc::SocketAddress& remote_address, + const rtc::ProxyInfo& proxy_info, + const std::string& user_agent, + const rtc::PacketSocketTcpOptions& tcp_options) override { + return nullptr; + } + std::unique_ptr<webrtc::AsyncDnsResolverInterface> CreateAsyncDnsResolver() + override { + return nullptr; + } + + private: + webrtc::test::EmulatedTURNServer* turn_server_; +}; + +} // namespace + +namespace webrtc { +namespace test { + +EmulatedTURNServer::EmulatedTURNServer(std::unique_ptr<rtc::Thread> thread, + EmulatedEndpoint* client, + EmulatedEndpoint* peer) + : thread_(std::move(thread)), client_(client), peer_(peer) { + ice_config_.username = "keso"; + ice_config_.password = "keso"; + SendTask(thread_.get(), [=]() { + RTC_DCHECK_RUN_ON(thread_.get()); + turn_server_ = std::make_unique<cricket::TurnServer>(thread_.get()); + turn_server_->set_realm(kTestRealm); + turn_server_->set_realm(kTestSoftware); + turn_server_->set_auth_hook(this); + + auto client_socket = Wrap(client_); + turn_server_->AddInternalSocket(client_socket, cricket::PROTO_UDP); + turn_server_->SetExternalSocketFactory(new PacketSocketFactoryWrapper(this), + rtc::SocketAddress()); + client_address_ = client_socket->GetLocalAddress(); + char buf[256]; + rtc::SimpleStringBuilder str(buf); + str.AppendFormat("turn:%s?transport=udp", + client_address_.ToString().c_str()); + ice_config_.url = str.str(); + }); +} + +void EmulatedTURNServer::Stop() { + SendTask(thread_.get(), [=]() { + RTC_DCHECK_RUN_ON(thread_.get()); + sockets_.clear(); + }); +} + +EmulatedTURNServer::~EmulatedTURNServer() { + SendTask(thread_.get(), [=]() { + RTC_DCHECK_RUN_ON(thread_.get()); + turn_server_.reset(nullptr); + }); +} + +rtc::AsyncPacketSocket* EmulatedTURNServer::Wrap(EmulatedEndpoint* endpoint) { + RTC_DCHECK_RUN_ON(thread_.get()); + auto port = endpoint->BindReceiver(0, this).value(); + auto socket = new AsyncPacketSocketWrapper(this, endpoint, port); + sockets_[rtc::SocketAddress(endpoint->GetPeerLocalAddress(), port)] = socket; + return socket; +} + +void EmulatedTURNServer::OnPacketReceived(webrtc::EmulatedIpPacket packet) { + // Copy from EmulatedEndpoint to rtc::AsyncPacketSocket. + thread_->PostTask([this, packet(std::move(packet))]() { + RTC_DCHECK_RUN_ON(thread_.get()); + auto it = sockets_.find(packet.to); + if (it != sockets_.end()) { + it->second->SignalReadPacket( + it->second, reinterpret_cast<const char*>(packet.cdata()), + packet.size(), packet.from, packet.arrival_time.ms()); + } + }); +} + +void EmulatedTURNServer::Unbind(rtc::SocketAddress address) { + RTC_DCHECK_RUN_ON(thread_.get()); + if (GetClientEndpoint()->GetPeerLocalAddress() == address.ipaddr()) { + GetClientEndpoint()->UnbindReceiver(address.port()); + } else { + GetPeerEndpoint()->UnbindReceiver(address.port()); + } + sockets_.erase(address); +} + +} // namespace test +} // namespace webrtc |