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