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