xref: /aosp_15_r20/external/webrtc/test/network/fake_network_socket_server.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2019 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/fake_network_socket_server.h"
12 
13 #include <algorithm>
14 #include <string>
15 #include <utility>
16 #include <vector>
17 
18 #include "absl/algorithm/container.h"
19 #include "api/scoped_refptr.h"
20 #include "api/task_queue/pending_task_safety_flag.h"
21 #include "rtc_base/event.h"
22 #include "rtc_base/logging.h"
23 #include "rtc_base/thread.h"
24 
25 namespace webrtc {
26 namespace test {
27 namespace {
ToString(const rtc::SocketAddress & addr)28 std::string ToString(const rtc::SocketAddress& addr) {
29   return addr.HostAsURIString() + ":" + std::to_string(addr.port());
30 }
31 
32 }  // namespace
33 
34 // Represents a socket, which will operate with emulated network.
35 class FakeNetworkSocket : public rtc::Socket,
36                           public EmulatedNetworkReceiverInterface {
37  public:
38   explicit FakeNetworkSocket(FakeNetworkSocketServer* scoket_manager,
39                              rtc::Thread* thread);
40   ~FakeNetworkSocket() override;
41 
42   // Will be invoked by EmulatedEndpoint to deliver packets into this socket.
43   void OnPacketReceived(EmulatedIpPacket packet) override;
44 
45   // rtc::Socket methods:
46   rtc::SocketAddress GetLocalAddress() const override;
47   rtc::SocketAddress GetRemoteAddress() const override;
48   int Bind(const rtc::SocketAddress& addr) override;
49   int Connect(const rtc::SocketAddress& addr) override;
50   int Close() override;
51   int Send(const void* pv, size_t cb) override;
52   int SendTo(const void* pv,
53              size_t cb,
54              const rtc::SocketAddress& addr) override;
55   int Recv(void* pv, size_t cb, int64_t* timestamp) override;
56   int RecvFrom(void* pv,
57                size_t cb,
58                rtc::SocketAddress* paddr,
59                int64_t* timestamp) override;
60   int Listen(int backlog) override;
61   rtc::Socket* Accept(rtc::SocketAddress* paddr) override;
62   int GetError() const override;
63   void SetError(int error) override;
64   ConnState GetState() const override;
65   int GetOption(Option opt, int* value) override;
66   int SetOption(Option opt, int value) override;
67 
68  private:
69   FakeNetworkSocketServer* const socket_server_;
70   rtc::Thread* const thread_;
71   EmulatedEndpointImpl* endpoint_ RTC_GUARDED_BY(&thread_);
72   rtc::SocketAddress local_addr_ RTC_GUARDED_BY(&thread_);
73   rtc::SocketAddress remote_addr_ RTC_GUARDED_BY(&thread_);
74   ConnState state_ RTC_GUARDED_BY(&thread_);
75   int error_ RTC_GUARDED_BY(&thread_);
76   std::map<Option, int> options_map_ RTC_GUARDED_BY(&thread_);
77 
78   absl::optional<EmulatedIpPacket> pending_ RTC_GUARDED_BY(thread_);
79   rtc::scoped_refptr<PendingTaskSafetyFlag> alive_;
80 };
81 
FakeNetworkSocket(FakeNetworkSocketServer * socket_server,rtc::Thread * thread)82 FakeNetworkSocket::FakeNetworkSocket(FakeNetworkSocketServer* socket_server,
83                                      rtc::Thread* thread)
84     : socket_server_(socket_server),
85       thread_(thread),
86       state_(CS_CLOSED),
87       error_(0),
88       alive_(PendingTaskSafetyFlag::Create()) {}
89 
~FakeNetworkSocket()90 FakeNetworkSocket::~FakeNetworkSocket() {
91   // Abandon all pending packets.
92   alive_->SetNotAlive();
93 
94   Close();
95   socket_server_->Unregister(this);
96 }
97 
OnPacketReceived(EmulatedIpPacket packet)98 void FakeNetworkSocket::OnPacketReceived(EmulatedIpPacket packet) {
99   auto task = [this, packet = std::move(packet)]() mutable {
100     RTC_DCHECK_RUN_ON(thread_);
101     if (!endpoint_->Enabled())
102       return;
103     RTC_DCHECK(!pending_);
104     pending_ = std::move(packet);
105     // Note that we expect that this will trigger exactly one call to RecvFrom()
106     // where pending_packet will be read and reset. This call is done without
107     // any thread switch (see AsyncUDPSocket::OnReadEvent) so it's safe to
108     // assume that SignalReadEvent() will block until the packet has been read.
109     SignalReadEvent(this);
110     RTC_DCHECK(!pending_);
111   };
112   thread_->PostTask(SafeTask(alive_, std::move(task)));
113   socket_server_->WakeUp();
114 }
115 
116 
GetLocalAddress() const117 rtc::SocketAddress FakeNetworkSocket::GetLocalAddress() const {
118   RTC_DCHECK_RUN_ON(thread_);
119   return local_addr_;
120 }
121 
GetRemoteAddress() const122 rtc::SocketAddress FakeNetworkSocket::GetRemoteAddress() const {
123   RTC_DCHECK_RUN_ON(thread_);
124   return remote_addr_;
125 }
126 
Bind(const rtc::SocketAddress & addr)127 int FakeNetworkSocket::Bind(const rtc::SocketAddress& addr) {
128   RTC_DCHECK_RUN_ON(thread_);
129   RTC_CHECK(local_addr_.IsNil())
130       << "Socket already bound to address: " << ToString(local_addr_);
131   local_addr_ = addr;
132   endpoint_ = socket_server_->GetEndpointNode(local_addr_.ipaddr());
133   if (!endpoint_) {
134     local_addr_.Clear();
135     RTC_LOG(LS_INFO) << "No endpoint for address: " << ToString(addr);
136     error_ = EADDRNOTAVAIL;
137     return 2;
138   }
139   absl::optional<uint16_t> port =
140       endpoint_->BindReceiver(local_addr_.port(), this);
141   if (!port) {
142     local_addr_.Clear();
143     RTC_LOG(LS_INFO) << "Cannot bind to in-use address: " << ToString(addr);
144     error_ = EADDRINUSE;
145     return 1;
146   }
147   local_addr_.SetPort(port.value());
148   return 0;
149 }
150 
Connect(const rtc::SocketAddress & addr)151 int FakeNetworkSocket::Connect(const rtc::SocketAddress& addr) {
152   RTC_DCHECK_RUN_ON(thread_);
153   RTC_CHECK(remote_addr_.IsNil())
154       << "Socket already connected to address: " << ToString(remote_addr_);
155   RTC_CHECK(!local_addr_.IsNil())
156       << "Socket have to be bind to some local address";
157   remote_addr_ = addr;
158   state_ = CS_CONNECTED;
159   return 0;
160 }
161 
Send(const void * pv,size_t cb)162 int FakeNetworkSocket::Send(const void* pv, size_t cb) {
163   RTC_DCHECK_RUN_ON(thread_);
164   RTC_CHECK(state_ == CS_CONNECTED) << "Socket cannot send: not connected";
165   return SendTo(pv, cb, remote_addr_);
166 }
167 
SendTo(const void * pv,size_t cb,const rtc::SocketAddress & addr)168 int FakeNetworkSocket::SendTo(const void* pv,
169                               size_t cb,
170                               const rtc::SocketAddress& addr) {
171   RTC_DCHECK_RUN_ON(thread_);
172   RTC_CHECK(!local_addr_.IsNil())
173       << "Socket have to be bind to some local address";
174   if (!endpoint_->Enabled()) {
175     error_ = ENETDOWN;
176     return -1;
177   }
178   rtc::CopyOnWriteBuffer packet(static_cast<const uint8_t*>(pv), cb);
179   endpoint_->SendPacket(local_addr_, addr, packet);
180   return cb;
181 }
182 
Recv(void * pv,size_t cb,int64_t * timestamp)183 int FakeNetworkSocket::Recv(void* pv, size_t cb, int64_t* timestamp) {
184   rtc::SocketAddress paddr;
185   return RecvFrom(pv, cb, &paddr, timestamp);
186 }
187 
188 // Reads 1 packet from internal queue. Reads up to `cb` bytes into `pv`
189 // and returns the length of received packet.
RecvFrom(void * pv,size_t cb,rtc::SocketAddress * paddr,int64_t * timestamp)190 int FakeNetworkSocket::RecvFrom(void* pv,
191                                 size_t cb,
192                                 rtc::SocketAddress* paddr,
193                                 int64_t* timestamp) {
194   RTC_DCHECK_RUN_ON(thread_);
195 
196   if (timestamp) {
197     *timestamp = -1;
198   }
199   RTC_CHECK(pending_);
200 
201   *paddr = pending_->from;
202   size_t data_read = std::min(cb, pending_->size());
203   memcpy(pv, pending_->cdata(), data_read);
204   *timestamp = pending_->arrival_time.us();
205 
206   // According to RECV(2) Linux Man page
207   // real socket will discard data, that won't fit into provided buffer,
208   // but we won't to skip such error, so we will assert here.
209   RTC_CHECK(data_read == pending_->size())
210       << "Too small buffer is provided for socket read. "
211          "Received data size: "
212       << pending_->size() << "; Provided buffer size: " << cb;
213 
214   pending_.reset();
215 
216   // According to RECV(2) Linux Man page
217   // real socket will return message length, not data read. In our case it is
218   // actually the same value.
219   return static_cast<int>(data_read);
220 }
221 
Listen(int backlog)222 int FakeNetworkSocket::Listen(int backlog) {
223   RTC_CHECK(false) << "Listen() isn't valid for SOCK_DGRAM";
224 }
225 
Accept(rtc::SocketAddress *)226 rtc::Socket* FakeNetworkSocket::Accept(rtc::SocketAddress* /*paddr*/) {
227   RTC_CHECK(false) << "Accept() isn't valid for SOCK_DGRAM";
228 }
229 
Close()230 int FakeNetworkSocket::Close() {
231   RTC_DCHECK_RUN_ON(thread_);
232   state_ = CS_CLOSED;
233   if (!local_addr_.IsNil()) {
234     endpoint_->UnbindReceiver(local_addr_.port());
235   }
236   local_addr_.Clear();
237   remote_addr_.Clear();
238   return 0;
239 }
240 
GetError() const241 int FakeNetworkSocket::GetError() const {
242   RTC_DCHECK_RUN_ON(thread_);
243   return error_;
244 }
245 
SetError(int error)246 void FakeNetworkSocket::SetError(int error) {
247   RTC_DCHECK_RUN_ON(thread_);
248   RTC_CHECK(error == 0);
249   error_ = error;
250 }
251 
GetState() const252 rtc::Socket::ConnState FakeNetworkSocket::GetState() const {
253   RTC_DCHECK_RUN_ON(thread_);
254   return state_;
255 }
256 
GetOption(Option opt,int * value)257 int FakeNetworkSocket::GetOption(Option opt, int* value) {
258   RTC_DCHECK_RUN_ON(thread_);
259   auto it = options_map_.find(opt);
260   if (it == options_map_.end()) {
261     return -1;
262   }
263   *value = it->second;
264   return 0;
265 }
266 
SetOption(Option opt,int value)267 int FakeNetworkSocket::SetOption(Option opt, int value) {
268   RTC_DCHECK_RUN_ON(thread_);
269   options_map_[opt] = value;
270   return 0;
271 }
272 
FakeNetworkSocketServer(EndpointsContainer * endpoints_container)273 FakeNetworkSocketServer::FakeNetworkSocketServer(
274     EndpointsContainer* endpoints_container)
275     : endpoints_container_(endpoints_container),
276       wakeup_(/*manual_reset=*/false, /*initially_signaled=*/false) {}
277 FakeNetworkSocketServer::~FakeNetworkSocketServer() = default;
278 
GetEndpointNode(const rtc::IPAddress & ip)279 EmulatedEndpointImpl* FakeNetworkSocketServer::GetEndpointNode(
280     const rtc::IPAddress& ip) {
281   return endpoints_container_->LookupByLocalAddress(ip);
282 }
283 
Unregister(FakeNetworkSocket * socket)284 void FakeNetworkSocketServer::Unregister(FakeNetworkSocket* socket) {
285   MutexLock lock(&lock_);
286   sockets_.erase(absl::c_find(sockets_, socket));
287 }
288 
CreateSocket(int family,int type)289 rtc::Socket* FakeNetworkSocketServer::CreateSocket(int family, int type) {
290   RTC_DCHECK(family == AF_INET || family == AF_INET6);
291   // We support only UDP sockets for now.
292   RTC_DCHECK(type == SOCK_DGRAM) << "Only UDP sockets are supported";
293   RTC_DCHECK(thread_) << "must be attached to thread before creating sockets";
294   FakeNetworkSocket* out = new FakeNetworkSocket(this, thread_);
295   {
296     MutexLock lock(&lock_);
297     sockets_.push_back(out);
298   }
299   return out;
300 }
301 
SetMessageQueue(rtc::Thread * thread)302 void FakeNetworkSocketServer::SetMessageQueue(rtc::Thread* thread) {
303   thread_ = thread;
304 }
305 
306 // Always returns true (if return false, it won't be invoked again...)
Wait(webrtc::TimeDelta max_wait_duration,bool process_io)307 bool FakeNetworkSocketServer::Wait(webrtc::TimeDelta max_wait_duration,
308                                    bool process_io) {
309   RTC_DCHECK(thread_ == rtc::Thread::Current());
310   if (!max_wait_duration.IsZero())
311     wakeup_.Wait(max_wait_duration);
312 
313   return true;
314 }
315 
WakeUp()316 void FakeNetworkSocketServer::WakeUp() {
317   wakeup_.Set();
318 }
319 
320 
321 }  // namespace test
322 }  // namespace webrtc
323