xref: /aosp_15_r20/external/webrtc/test/network/emulated_turn_server.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "test/network/emulated_turn_server.h"
12 
13 #include <string>
14 #include <utility>
15 
16 #include "api/packet_socket_factory.h"
17 #include "rtc_base/strings/string_builder.h"
18 #include "rtc_base/task_queue_for_test.h"
19 
20 namespace {
21 
22 static const char kTestRealm[] = "example.org";
23 static const char kTestSoftware[] = "TestTurnServer";
24 
25 // A wrapper class for copying data between an AsyncPacketSocket and a
26 // EmulatedEndpoint. This is used by the cricket::TurnServer when
27 // sending data back into the emulated network.
28 class AsyncPacketSocketWrapper : public rtc::AsyncPacketSocket {
29  public:
AsyncPacketSocketWrapper(webrtc::test::EmulatedTURNServer * turn_server,webrtc::EmulatedEndpoint * endpoint,uint16_t port)30   AsyncPacketSocketWrapper(webrtc::test::EmulatedTURNServer* turn_server,
31                            webrtc::EmulatedEndpoint* endpoint,
32                            uint16_t port)
33       : turn_server_(turn_server),
34         endpoint_(endpoint),
35         local_address_(
36             rtc::SocketAddress(endpoint_->GetPeerLocalAddress(), port)) {}
~AsyncPacketSocketWrapper()37   ~AsyncPacketSocketWrapper() { turn_server_->Unbind(local_address_); }
38 
GetLocalAddress() const39   rtc::SocketAddress GetLocalAddress() const override { return local_address_; }
GetRemoteAddress() const40   rtc::SocketAddress GetRemoteAddress() const override {
41     return rtc::SocketAddress();
42   }
Send(const void * pv,size_t cb,const rtc::PacketOptions & options)43   int Send(const void* pv,
44            size_t cb,
45            const rtc::PacketOptions& options) override {
46     RTC_CHECK(false) << "TCP not implemented";
47     return -1;
48   }
SendTo(const void * pv,size_t cb,const rtc::SocketAddress & addr,const rtc::PacketOptions & options)49   int SendTo(const void* pv,
50              size_t cb,
51              const rtc::SocketAddress& addr,
52              const rtc::PacketOptions& options) override {
53     // Copy from rtc::AsyncPacketSocket to EmulatedEndpoint.
54     rtc::CopyOnWriteBuffer buf(reinterpret_cast<const char*>(pv), cb);
55     endpoint_->SendPacket(local_address_, addr, buf);
56     return cb;
57   }
Close()58   int Close() override { return 0; }
59 
GetState() const60   rtc::AsyncPacketSocket::State GetState() const override {
61     return rtc::AsyncPacketSocket::STATE_BOUND;
62   }
GetOption(rtc::Socket::Option opt,int * value)63   int GetOption(rtc::Socket::Option opt, int* value) override { return 0; }
SetOption(rtc::Socket::Option opt,int value)64   int SetOption(rtc::Socket::Option opt, int value) override { return 0; }
GetError() const65   int GetError() const override { return 0; }
SetError(int error)66   void SetError(int error) override {}
67 
68  private:
69   webrtc::test::EmulatedTURNServer* const turn_server_;
70   webrtc::EmulatedEndpoint* const endpoint_;
71   const rtc::SocketAddress local_address_;
72 };
73 
74 // A wrapper class for cricket::TurnServer to allocate sockets.
75 class PacketSocketFactoryWrapper : public rtc::PacketSocketFactory {
76  public:
PacketSocketFactoryWrapper(webrtc::test::EmulatedTURNServer * turn_server)77   explicit PacketSocketFactoryWrapper(
78       webrtc::test::EmulatedTURNServer* turn_server)
79       : turn_server_(turn_server) {}
~PacketSocketFactoryWrapper()80   ~PacketSocketFactoryWrapper() override {}
81 
82   // This method is called from TurnServer when making a TURN ALLOCATION.
83   // It will create a socket on the `peer_` endpoint.
CreateUdpSocket(const rtc::SocketAddress & address,uint16_t min_port,uint16_t max_port)84   rtc::AsyncPacketSocket* CreateUdpSocket(const rtc::SocketAddress& address,
85                                           uint16_t min_port,
86                                           uint16_t max_port) override {
87     return turn_server_->CreatePeerSocket();
88   }
89 
CreateServerTcpSocket(const rtc::SocketAddress & local_address,uint16_t min_port,uint16_t max_port,int opts)90   rtc::AsyncListenSocket* CreateServerTcpSocket(
91       const rtc::SocketAddress& local_address,
92       uint16_t min_port,
93       uint16_t max_port,
94       int opts) override {
95     return nullptr;
96   }
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)97   rtc::AsyncPacketSocket* CreateClientTcpSocket(
98       const rtc::SocketAddress& local_address,
99       const rtc::SocketAddress& remote_address,
100       const rtc::ProxyInfo& proxy_info,
101       const std::string& user_agent,
102       const rtc::PacketSocketTcpOptions& tcp_options) override {
103     return nullptr;
104   }
CreateAsyncDnsResolver()105   std::unique_ptr<webrtc::AsyncDnsResolverInterface> CreateAsyncDnsResolver()
106       override {
107     return nullptr;
108   }
109 
110  private:
111   webrtc::test::EmulatedTURNServer* turn_server_;
112 };
113 
114 }  //  namespace
115 
116 namespace webrtc {
117 namespace test {
118 
EmulatedTURNServer(std::unique_ptr<rtc::Thread> thread,EmulatedEndpoint * client,EmulatedEndpoint * peer)119 EmulatedTURNServer::EmulatedTURNServer(std::unique_ptr<rtc::Thread> thread,
120                                        EmulatedEndpoint* client,
121                                        EmulatedEndpoint* peer)
122     : thread_(std::move(thread)), client_(client), peer_(peer) {
123   ice_config_.username = "keso";
124   ice_config_.password = "keso";
125   SendTask(thread_.get(), [=]() {
126     RTC_DCHECK_RUN_ON(thread_.get());
127     turn_server_ = std::make_unique<cricket::TurnServer>(thread_.get());
128     turn_server_->set_realm(kTestRealm);
129     turn_server_->set_realm(kTestSoftware);
130     turn_server_->set_auth_hook(this);
131 
132     auto client_socket = Wrap(client_);
133     turn_server_->AddInternalSocket(client_socket, cricket::PROTO_UDP);
134     turn_server_->SetExternalSocketFactory(new PacketSocketFactoryWrapper(this),
135                                            rtc::SocketAddress());
136     client_address_ = client_socket->GetLocalAddress();
137     char buf[256];
138     rtc::SimpleStringBuilder str(buf);
139     str.AppendFormat("turn:%s?transport=udp",
140                      client_address_.ToString().c_str());
141     ice_config_.url = str.str();
142   });
143 }
144 
Stop()145 void EmulatedTURNServer::Stop() {
146   SendTask(thread_.get(), [=]() {
147     RTC_DCHECK_RUN_ON(thread_.get());
148     sockets_.clear();
149   });
150 }
151 
~EmulatedTURNServer()152 EmulatedTURNServer::~EmulatedTURNServer() {
153   SendTask(thread_.get(), [=]() {
154     RTC_DCHECK_RUN_ON(thread_.get());
155     turn_server_.reset(nullptr);
156   });
157 }
158 
Wrap(EmulatedEndpoint * endpoint)159 rtc::AsyncPacketSocket* EmulatedTURNServer::Wrap(EmulatedEndpoint* endpoint) {
160   RTC_DCHECK_RUN_ON(thread_.get());
161   auto port = endpoint->BindReceiver(0, this).value();
162   auto socket = new AsyncPacketSocketWrapper(this, endpoint, port);
163   sockets_[rtc::SocketAddress(endpoint->GetPeerLocalAddress(), port)] = socket;
164   return socket;
165 }
166 
OnPacketReceived(webrtc::EmulatedIpPacket packet)167 void EmulatedTURNServer::OnPacketReceived(webrtc::EmulatedIpPacket packet) {
168   // Copy from EmulatedEndpoint to rtc::AsyncPacketSocket.
169   thread_->PostTask([this, packet(std::move(packet))]() {
170     RTC_DCHECK_RUN_ON(thread_.get());
171     auto it = sockets_.find(packet.to);
172     if (it != sockets_.end()) {
173       it->second->SignalReadPacket(
174           it->second, reinterpret_cast<const char*>(packet.cdata()),
175           packet.size(), packet.from, packet.arrival_time.ms());
176     }
177   });
178 }
179 
Unbind(rtc::SocketAddress address)180 void EmulatedTURNServer::Unbind(rtc::SocketAddress address) {
181   RTC_DCHECK_RUN_ON(thread_.get());
182   if (GetClientEndpoint()->GetPeerLocalAddress() == address.ipaddr()) {
183     GetClientEndpoint()->UnbindReceiver(address.port());
184   } else {
185     GetPeerEndpoint()->UnbindReceiver(address.port());
186   }
187   sockets_.erase(address);
188 }
189 
190 }  // namespace test
191 }  // namespace webrtc
192