blob: 08947e16e46c8d0f52644c58bdcd32873adef9fc [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2004 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 */
Steve Anton10542f22019-01-11 09:11:00 -080010#include "rtc_base/physical_socket_server.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000011
12#if defined(_MSC_VER) && _MSC_VER < 1300
Yves Gerey665174f2018-06-19 15:03:05 +020013#pragma warning(disable : 4786)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000014#endif
15
pbos@webrtc.org27e58982014-10-07 17:56:53 +000016#ifdef MEMORY_SANITIZER
17#include <sanitizer/msan_interface.h>
18#endif
19
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000020#if defined(WEBRTC_POSIX)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000021#include <fcntl.h>
Yves Gerey665174f2018-06-19 15:03:05 +020022#include <string.h>
jbauchde4db112017-05-31 13:09:18 -070023#if defined(WEBRTC_USE_EPOLL)
24// "poll" will be used to wait for the signal dispatcher.
25#include <poll.h>
26#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000027#include <signal.h>
Yves Gerey665174f2018-06-19 15:03:05 +020028#include <sys/ioctl.h>
29#include <sys/select.h>
30#include <sys/time.h>
31#include <unistd.h>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000032#endif
33
34#if defined(WEBRTC_WIN)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000035#include <windows.h>
36#include <winsock2.h>
37#include <ws2tcpip.h>
38#undef SetPort
39#endif
40
Patrik Höglunda8005cf2017-12-13 16:05:42 +010041#include <errno.h>
42
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000043#include <algorithm>
44#include <map>
45
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020046#include "rtc_base/arraysize.h"
Steve Anton10542f22019-01-11 09:11:00 -080047#include "rtc_base/byte_order.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020048#include "rtc_base/checks.h"
49#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080050#include "rtc_base/network_monitor.h"
51#include "rtc_base/null_socket_server.h"
52#include "rtc_base/time_utils.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000053
Emilio Cobos Álvarez68065502019-05-29 15:30:32 +020054#if defined(WEBRTC_LINUX)
55#include <linux/sockios.h>
56#endif
57
Patrik Höglunda8005cf2017-12-13 16:05:42 +010058#if defined(WEBRTC_WIN)
59#define LAST_SYSTEM_ERROR (::GetLastError())
60#elif defined(__native_client__) && __native_client__
61#define LAST_SYSTEM_ERROR (0)
62#elif defined(WEBRTC_POSIX)
63#define LAST_SYSTEM_ERROR (errno)
64#endif // WEBRTC_WIN
65
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000066#if defined(WEBRTC_POSIX)
67#include <netinet/tcp.h> // for TCP_NODELAY
Yves Gerey665174f2018-06-19 15:03:05 +020068#define IP_MTU 14 // Until this is integrated from linux/in.h to netinet/in.h
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000069typedef void* SockOptArg;
Stefan Holmer9131efd2016-05-23 18:19:26 +020070
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000071#endif // WEBRTC_POSIX
72
Stefan Holmer3ebb3ef2016-05-23 20:26:11 +020073#if defined(WEBRTC_POSIX) && !defined(WEBRTC_MAC) && !defined(__native_client__)
74
Stefan Holmer9131efd2016-05-23 18:19:26 +020075int64_t GetSocketRecvTimestamp(int socket) {
76 struct timeval tv_ioctl;
77 int ret = ioctl(socket, SIOCGSTAMP, &tv_ioctl);
78 if (ret != 0)
79 return -1;
80 int64_t timestamp =
81 rtc::kNumMicrosecsPerSec * static_cast<int64_t>(tv_ioctl.tv_sec) +
82 static_cast<int64_t>(tv_ioctl.tv_usec);
83 return timestamp;
84}
85
86#else
87
88int64_t GetSocketRecvTimestamp(int socket) {
89 return -1;
90}
91#endif
92
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000093#if defined(WEBRTC_WIN)
94typedef char* SockOptArg;
95#endif
96
jbauchde4db112017-05-31 13:09:18 -070097#if defined(WEBRTC_USE_EPOLL)
98// POLLRDHUP / EPOLLRDHUP are only defined starting with Linux 2.6.17.
99#if !defined(POLLRDHUP)
100#define POLLRDHUP 0x2000
101#endif
102#if !defined(EPOLLRDHUP)
103#define EPOLLRDHUP 0x2000
104#endif
105#endif
106
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000107namespace rtc {
108
danilchapbebf54c2016-04-28 01:32:48 -0700109std::unique_ptr<SocketServer> SocketServer::CreateDefault() {
110#if defined(__native_client__)
111 return std::unique_ptr<SocketServer>(new rtc::NullSocketServer);
112#else
113 return std::unique_ptr<SocketServer>(new rtc::PhysicalSocketServer);
114#endif
115}
116
jbauch095ae152015-12-18 01:39:55 -0800117PhysicalSocket::PhysicalSocket(PhysicalSocketServer* ss, SOCKET s)
Yves Gerey665174f2018-06-19 15:03:05 +0200118 : ss_(ss),
119 s_(s),
120 error_(0),
121 state_((s == INVALID_SOCKET) ? CS_CLOSED : CS_CONNECTED),
122 resolver_(nullptr) {
jbauch095ae152015-12-18 01:39:55 -0800123 if (s_ != INVALID_SOCKET) {
jbauch577f5dc2017-05-17 16:32:26 -0700124 SetEnabledEvents(DE_READ | DE_WRITE);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000125
jbauch095ae152015-12-18 01:39:55 -0800126 int type = SOCK_STREAM;
127 socklen_t len = sizeof(type);
nissec16fa5e2017-02-07 07:18:43 -0800128 const int res =
129 getsockopt(s_, SOL_SOCKET, SO_TYPE, (SockOptArg)&type, &len);
130 RTC_DCHECK_EQ(0, res);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000131 udp_ = (SOCK_DGRAM == type);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000132 }
jbauch095ae152015-12-18 01:39:55 -0800133}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000134
jbauch095ae152015-12-18 01:39:55 -0800135PhysicalSocket::~PhysicalSocket() {
136 Close();
137}
138
139bool PhysicalSocket::Create(int family, int type) {
140 Close();
141 s_ = ::socket(family, type, 0);
142 udp_ = (SOCK_DGRAM == type);
Taylor Brandstetterecd6fc82020-02-05 17:26:37 -0800143 family_ = family;
jbauch095ae152015-12-18 01:39:55 -0800144 UpdateLastError();
jbauch577f5dc2017-05-17 16:32:26 -0700145 if (udp_) {
146 SetEnabledEvents(DE_READ | DE_WRITE);
147 }
jbauch095ae152015-12-18 01:39:55 -0800148 return s_ != INVALID_SOCKET;
149}
150
151SocketAddress PhysicalSocket::GetLocalAddress() const {
Mirko Bonadei108a2f02019-11-20 19:43:38 +0100152 sockaddr_storage addr_storage = {};
jbauch095ae152015-12-18 01:39:55 -0800153 socklen_t addrlen = sizeof(addr_storage);
154 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
155 int result = ::getsockname(s_, addr, &addrlen);
156 SocketAddress address;
157 if (result >= 0) {
158 SocketAddressFromSockAddrStorage(addr_storage, &address);
159 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100160 RTC_LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket="
161 << s_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000162 }
jbauch095ae152015-12-18 01:39:55 -0800163 return address;
164}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000165
jbauch095ae152015-12-18 01:39:55 -0800166SocketAddress PhysicalSocket::GetRemoteAddress() const {
Mirko Bonadei108a2f02019-11-20 19:43:38 +0100167 sockaddr_storage addr_storage = {};
jbauch095ae152015-12-18 01:39:55 -0800168 socklen_t addrlen = sizeof(addr_storage);
169 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
170 int result = ::getpeername(s_, addr, &addrlen);
171 SocketAddress address;
172 if (result >= 0) {
173 SocketAddressFromSockAddrStorage(addr_storage, &address);
174 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100175 RTC_LOG(LS_WARNING)
176 << "GetRemoteAddress: unable to get remote addr, socket=" << s_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000177 }
jbauch095ae152015-12-18 01:39:55 -0800178 return address;
179}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000180
jbauch095ae152015-12-18 01:39:55 -0800181int PhysicalSocket::Bind(const SocketAddress& bind_addr) {
deadbeefc874d122017-02-13 15:41:59 -0800182 SocketAddress copied_bind_addr = bind_addr;
183 // If a network binder is available, use it to bind a socket to an interface
184 // instead of bind(), since this is more reliable on an OS with a weak host
185 // model.
deadbeef9ffa13f2017-02-21 16:18:00 -0800186 if (ss_->network_binder() && !bind_addr.IsAnyIP()) {
deadbeefc874d122017-02-13 15:41:59 -0800187 NetworkBindingResult result =
188 ss_->network_binder()->BindSocketToNetwork(s_, bind_addr.ipaddr());
189 if (result == NetworkBindingResult::SUCCESS) {
190 // Since the network binder handled binding the socket to the desired
191 // network interface, we don't need to (and shouldn't) include an IP in
192 // the bind() call; bind() just needs to assign a port.
193 copied_bind_addr.SetIP(GetAnyIP(copied_bind_addr.ipaddr().family()));
194 } else if (result == NetworkBindingResult::NOT_IMPLEMENTED) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100195 RTC_LOG(LS_INFO) << "Can't bind socket to network because "
196 "network binding is not implemented for this OS.";
deadbeefc874d122017-02-13 15:41:59 -0800197 } else {
198 if (bind_addr.IsLoopbackIP()) {
199 // If we couldn't bind to a loopback IP (which should only happen in
200 // test scenarios), continue on. This may be expected behavior.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100201 RTC_LOG(LS_VERBOSE) << "Binding socket to loopback address "
202 << bind_addr.ipaddr().ToString()
203 << " failed; result: " << static_cast<int>(result);
deadbeefc874d122017-02-13 15:41:59 -0800204 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100205 RTC_LOG(LS_WARNING) << "Binding socket to network address "
206 << bind_addr.ipaddr().ToString()
207 << " failed; result: " << static_cast<int>(result);
deadbeefc874d122017-02-13 15:41:59 -0800208 // If a network binding was attempted and failed, we should stop here
209 // and not try to use the socket. Otherwise, we may end up sending
210 // packets with an invalid source address.
211 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7026
212 return -1;
213 }
214 }
215 }
jbauch095ae152015-12-18 01:39:55 -0800216 sockaddr_storage addr_storage;
deadbeefc874d122017-02-13 15:41:59 -0800217 size_t len = copied_bind_addr.ToSockAddrStorage(&addr_storage);
jbauch095ae152015-12-18 01:39:55 -0800218 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
219 int err = ::bind(s_, addr, static_cast<int>(len));
220 UpdateLastError();
tfarinaa41ab932015-10-30 16:08:48 -0700221#if !defined(NDEBUG)
jbauch095ae152015-12-18 01:39:55 -0800222 if (0 == err) {
223 dbg_addr_ = "Bound @ ";
224 dbg_addr_.append(GetLocalAddress().ToString());
225 }
tfarinaa41ab932015-10-30 16:08:48 -0700226#endif
jbauch095ae152015-12-18 01:39:55 -0800227 return err;
228}
229
230int PhysicalSocket::Connect(const SocketAddress& addr) {
231 // TODO(pthatcher): Implicit creation is required to reconnect...
232 // ...but should we make it more explicit?
233 if (state_ != CS_CLOSED) {
234 SetError(EALREADY);
235 return SOCKET_ERROR;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000236 }
jbauch095ae152015-12-18 01:39:55 -0800237 if (addr.IsUnresolvedIP()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100238 RTC_LOG(LS_VERBOSE) << "Resolving addr in PhysicalSocket::Connect";
jbauch095ae152015-12-18 01:39:55 -0800239 resolver_ = new AsyncResolver();
240 resolver_->SignalDone.connect(this, &PhysicalSocket::OnResolveResult);
241 resolver_->Start(addr);
242 state_ = CS_CONNECTING;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000243 return 0;
244 }
245
jbauch095ae152015-12-18 01:39:55 -0800246 return DoConnect(addr);
247}
248
249int PhysicalSocket::DoConnect(const SocketAddress& connect_addr) {
Yves Gerey665174f2018-06-19 15:03:05 +0200250 if ((s_ == INVALID_SOCKET) && !Create(connect_addr.family(), SOCK_STREAM)) {
jbauch095ae152015-12-18 01:39:55 -0800251 return SOCKET_ERROR;
252 }
253 sockaddr_storage addr_storage;
254 size_t len = connect_addr.ToSockAddrStorage(&addr_storage);
255 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
256 int err = ::connect(s_, addr, static_cast<int>(len));
257 UpdateLastError();
jbauch577f5dc2017-05-17 16:32:26 -0700258 uint8_t events = DE_READ | DE_WRITE;
jbauch095ae152015-12-18 01:39:55 -0800259 if (err == 0) {
260 state_ = CS_CONNECTED;
261 } else if (IsBlockingError(GetError())) {
262 state_ = CS_CONNECTING;
jbauch577f5dc2017-05-17 16:32:26 -0700263 events |= DE_CONNECT;
jbauch095ae152015-12-18 01:39:55 -0800264 } else {
265 return SOCKET_ERROR;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000266 }
267
jbauch577f5dc2017-05-17 16:32:26 -0700268 EnableEvents(events);
jbauch095ae152015-12-18 01:39:55 -0800269 return 0;
270}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000271
jbauch095ae152015-12-18 01:39:55 -0800272int PhysicalSocket::GetError() const {
273 CritScope cs(&crit_);
274 return error_;
275}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000276
jbauch095ae152015-12-18 01:39:55 -0800277void PhysicalSocket::SetError(int error) {
278 CritScope cs(&crit_);
279 error_ = error;
280}
281
282AsyncSocket::ConnState PhysicalSocket::GetState() const {
283 return state_;
284}
285
286int PhysicalSocket::GetOption(Option opt, int* value) {
287 int slevel;
288 int sopt;
289 if (TranslateOption(opt, &slevel, &sopt) == -1)
290 return -1;
291 socklen_t optlen = sizeof(*value);
292 int ret = ::getsockopt(s_, slevel, sopt, (SockOptArg)value, &optlen);
Taylor Brandstetterecd6fc82020-02-05 17:26:37 -0800293 if (ret == -1) {
294 return -1;
295 }
296 if (opt == OPT_DONTFRAGMENT) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000297#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
jbauch095ae152015-12-18 01:39:55 -0800298 *value = (*value != IP_PMTUDISC_DONT) ? 1 : 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000299#endif
Taylor Brandstetterecd6fc82020-02-05 17:26:37 -0800300 } else if (opt == OPT_DSCP) {
301#if defined(WEBRTC_POSIX)
302 // unshift DSCP value to get six most significant bits of IP DiffServ field
303 *value >>= 2;
304#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000305 }
jbauch095ae152015-12-18 01:39:55 -0800306 return ret;
307}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000308
jbauch095ae152015-12-18 01:39:55 -0800309int PhysicalSocket::SetOption(Option opt, int value) {
310 int slevel;
311 int sopt;
312 if (TranslateOption(opt, &slevel, &sopt) == -1)
313 return -1;
314 if (opt == OPT_DONTFRAGMENT) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000315#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
jbauch095ae152015-12-18 01:39:55 -0800316 value = (value) ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000317#endif
Taylor Brandstetterecd6fc82020-02-05 17:26:37 -0800318 } else if (opt == OPT_DSCP) {
319#if defined(WEBRTC_POSIX)
320 // shift DSCP value to fit six most significant bits of IP DiffServ field
321 value <<= 2;
322#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000323 }
Taylor Brandstetterecd6fc82020-02-05 17:26:37 -0800324#if defined(WEBRTC_POSIX)
325 if (sopt == IPV6_TCLASS) {
326 // Set the IPv4 option in all cases to support dual-stack sockets.
327 ::setsockopt(s_, IPPROTO_IP, IP_TOS, (SockOptArg)&value, sizeof(value));
328 }
329#endif
jbauch095ae152015-12-18 01:39:55 -0800330 return ::setsockopt(s_, slevel, sopt, (SockOptArg)&value, sizeof(value));
331}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000332
jbauch095ae152015-12-18 01:39:55 -0800333int PhysicalSocket::Send(const void* pv, size_t cb) {
Yves Gerey665174f2018-06-19 15:03:05 +0200334 int sent = DoSend(
335 s_, reinterpret_cast<const char*>(pv), static_cast<int>(cb),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000336#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
jbauch095ae152015-12-18 01:39:55 -0800337 // Suppress SIGPIPE. Without this, attempting to send on a socket whose
338 // other end is closed will result in a SIGPIPE signal being raised to
339 // our process, which by default will terminate the process, which we
340 // don't want. By specifying this flag, we'll just get the error EPIPE
341 // instead and can handle the error gracefully.
342 MSG_NOSIGNAL
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000343#else
jbauch095ae152015-12-18 01:39:55 -0800344 0
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000345#endif
Jonas Olssona4d87372019-07-05 19:08:33 +0200346 );
jbauch095ae152015-12-18 01:39:55 -0800347 UpdateLastError();
348 MaybeRemapSendError();
349 // We have seen minidumps where this may be false.
nisseede5da42017-01-12 05:15:36 -0800350 RTC_DCHECK(sent <= static_cast<int>(cb));
jbauchf2a2bf42016-02-03 16:45:32 -0800351 if ((sent > 0 && sent < static_cast<int>(cb)) ||
352 (sent < 0 && IsBlockingError(GetError()))) {
jbauch577f5dc2017-05-17 16:32:26 -0700353 EnableEvents(DE_WRITE);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000354 }
jbauch095ae152015-12-18 01:39:55 -0800355 return sent;
356}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000357
jbauch095ae152015-12-18 01:39:55 -0800358int PhysicalSocket::SendTo(const void* buffer,
359 size_t length,
360 const SocketAddress& addr) {
361 sockaddr_storage saddr;
362 size_t len = addr.ToSockAddrStorage(&saddr);
Yves Gerey665174f2018-06-19 15:03:05 +0200363 int sent =
364 DoSendTo(s_, static_cast<const char*>(buffer), static_cast<int>(length),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000365#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
Yves Gerey665174f2018-06-19 15:03:05 +0200366 // Suppress SIGPIPE. See above for explanation.
367 MSG_NOSIGNAL,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000368#else
Yves Gerey665174f2018-06-19 15:03:05 +0200369 0,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000370#endif
Yves Gerey665174f2018-06-19 15:03:05 +0200371 reinterpret_cast<sockaddr*>(&saddr), static_cast<int>(len));
jbauch095ae152015-12-18 01:39:55 -0800372 UpdateLastError();
373 MaybeRemapSendError();
374 // We have seen minidumps where this may be false.
nisseede5da42017-01-12 05:15:36 -0800375 RTC_DCHECK(sent <= static_cast<int>(length));
jbauchf2a2bf42016-02-03 16:45:32 -0800376 if ((sent > 0 && sent < static_cast<int>(length)) ||
377 (sent < 0 && IsBlockingError(GetError()))) {
jbauch577f5dc2017-05-17 16:32:26 -0700378 EnableEvents(DE_WRITE);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000379 }
jbauch095ae152015-12-18 01:39:55 -0800380 return sent;
381}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000382
Stefan Holmer9131efd2016-05-23 18:19:26 +0200383int PhysicalSocket::Recv(void* buffer, size_t length, int64_t* timestamp) {
Yves Gerey665174f2018-06-19 15:03:05 +0200384 int received =
385 ::recv(s_, static_cast<char*>(buffer), static_cast<int>(length), 0);
jbauch095ae152015-12-18 01:39:55 -0800386 if ((received == 0) && (length != 0)) {
387 // Note: on graceful shutdown, recv can return 0. In this case, we
388 // pretend it is blocking, and then signal close, so that simplifying
389 // assumptions can be made about Recv.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100390 RTC_LOG(LS_WARNING) << "EOF from socket; deferring close event";
jbauch095ae152015-12-18 01:39:55 -0800391 // Must turn this back on so that the select() loop will notice the close
392 // event.
jbauch577f5dc2017-05-17 16:32:26 -0700393 EnableEvents(DE_READ);
jbauch095ae152015-12-18 01:39:55 -0800394 SetError(EWOULDBLOCK);
395 return SOCKET_ERROR;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000396 }
Stefan Holmer9131efd2016-05-23 18:19:26 +0200397 if (timestamp) {
398 *timestamp = GetSocketRecvTimestamp(s_);
399 }
jbauch095ae152015-12-18 01:39:55 -0800400 UpdateLastError();
401 int error = GetError();
402 bool success = (received >= 0) || IsBlockingError(error);
403 if (udp_ || success) {
jbauch577f5dc2017-05-17 16:32:26 -0700404 EnableEvents(DE_READ);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000405 }
jbauch095ae152015-12-18 01:39:55 -0800406 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100407 RTC_LOG_F(LS_VERBOSE) << "Error = " << error;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000408 }
jbauch095ae152015-12-18 01:39:55 -0800409 return received;
410}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000411
jbauch095ae152015-12-18 01:39:55 -0800412int PhysicalSocket::RecvFrom(void* buffer,
413 size_t length,
Stefan Holmer9131efd2016-05-23 18:19:26 +0200414 SocketAddress* out_addr,
415 int64_t* timestamp) {
jbauch095ae152015-12-18 01:39:55 -0800416 sockaddr_storage addr_storage;
417 socklen_t addr_len = sizeof(addr_storage);
418 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
419 int received = ::recvfrom(s_, static_cast<char*>(buffer),
420 static_cast<int>(length), 0, addr, &addr_len);
Stefan Holmer9131efd2016-05-23 18:19:26 +0200421 if (timestamp) {
422 *timestamp = GetSocketRecvTimestamp(s_);
423 }
jbauch095ae152015-12-18 01:39:55 -0800424 UpdateLastError();
425 if ((received >= 0) && (out_addr != nullptr))
426 SocketAddressFromSockAddrStorage(addr_storage, out_addr);
427 int error = GetError();
428 bool success = (received >= 0) || IsBlockingError(error);
429 if (udp_ || success) {
jbauch577f5dc2017-05-17 16:32:26 -0700430 EnableEvents(DE_READ);
jbauch095ae152015-12-18 01:39:55 -0800431 }
432 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100433 RTC_LOG_F(LS_VERBOSE) << "Error = " << error;
jbauch095ae152015-12-18 01:39:55 -0800434 }
435 return received;
436}
437
438int PhysicalSocket::Listen(int backlog) {
439 int err = ::listen(s_, backlog);
440 UpdateLastError();
441 if (err == 0) {
442 state_ = CS_CONNECTING;
jbauch577f5dc2017-05-17 16:32:26 -0700443 EnableEvents(DE_ACCEPT);
jbauch095ae152015-12-18 01:39:55 -0800444#if !defined(NDEBUG)
445 dbg_addr_ = "Listening @ ";
446 dbg_addr_.append(GetLocalAddress().ToString());
447#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000448 }
jbauch095ae152015-12-18 01:39:55 -0800449 return err;
450}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000451
jbauch095ae152015-12-18 01:39:55 -0800452AsyncSocket* PhysicalSocket::Accept(SocketAddress* out_addr) {
453 // Always re-subscribe DE_ACCEPT to make sure new incoming connections will
454 // trigger an event even if DoAccept returns an error here.
jbauch577f5dc2017-05-17 16:32:26 -0700455 EnableEvents(DE_ACCEPT);
jbauch095ae152015-12-18 01:39:55 -0800456 sockaddr_storage addr_storage;
457 socklen_t addr_len = sizeof(addr_storage);
458 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
459 SOCKET s = DoAccept(s_, addr, &addr_len);
460 UpdateLastError();
461 if (s == INVALID_SOCKET)
462 return nullptr;
463 if (out_addr != nullptr)
464 SocketAddressFromSockAddrStorage(addr_storage, out_addr);
465 return ss_->WrapSocket(s);
466}
467
468int PhysicalSocket::Close() {
469 if (s_ == INVALID_SOCKET)
470 return 0;
471 int err = ::closesocket(s_);
472 UpdateLastError();
473 s_ = INVALID_SOCKET;
474 state_ = CS_CLOSED;
jbauch577f5dc2017-05-17 16:32:26 -0700475 SetEnabledEvents(0);
jbauch095ae152015-12-18 01:39:55 -0800476 if (resolver_) {
477 resolver_->Destroy(false);
478 resolver_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000479 }
jbauch095ae152015-12-18 01:39:55 -0800480 return err;
481}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000482
jbauch095ae152015-12-18 01:39:55 -0800483SOCKET PhysicalSocket::DoAccept(SOCKET socket,
484 sockaddr* addr,
485 socklen_t* addrlen) {
486 return ::accept(socket, addr, addrlen);
487}
488
jbauchf2a2bf42016-02-03 16:45:32 -0800489int PhysicalSocket::DoSend(SOCKET socket, const char* buf, int len, int flags) {
490 return ::send(socket, buf, len, flags);
491}
492
493int PhysicalSocket::DoSendTo(SOCKET socket,
494 const char* buf,
495 int len,
496 int flags,
497 const struct sockaddr* dest_addr,
498 socklen_t addrlen) {
499 return ::sendto(socket, buf, len, flags, dest_addr, addrlen);
500}
501
jbauch095ae152015-12-18 01:39:55 -0800502void PhysicalSocket::OnResolveResult(AsyncResolverInterface* resolver) {
503 if (resolver != resolver_) {
504 return;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000505 }
506
jbauch095ae152015-12-18 01:39:55 -0800507 int error = resolver_->GetError();
508 if (error == 0) {
509 error = DoConnect(resolver_->address());
510 } else {
511 Close();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000512 }
513
jbauch095ae152015-12-18 01:39:55 -0800514 if (error) {
515 SetError(error);
516 SignalCloseEvent(this, error);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000517 }
jbauch095ae152015-12-18 01:39:55 -0800518}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000519
jbauch095ae152015-12-18 01:39:55 -0800520void PhysicalSocket::UpdateLastError() {
Patrik Höglunda8005cf2017-12-13 16:05:42 +0100521 SetError(LAST_SYSTEM_ERROR);
jbauch095ae152015-12-18 01:39:55 -0800522}
523
524void PhysicalSocket::MaybeRemapSendError() {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000525#if defined(WEBRTC_MAC)
jbauch095ae152015-12-18 01:39:55 -0800526 // https://developer.apple.com/library/mac/documentation/Darwin/
527 // Reference/ManPages/man2/sendto.2.html
528 // ENOBUFS - The output queue for a network interface is full.
529 // This generally indicates that the interface has stopped sending,
530 // but may be caused by transient congestion.
531 if (GetError() == ENOBUFS) {
532 SetError(EWOULDBLOCK);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000533 }
jbauch095ae152015-12-18 01:39:55 -0800534#endif
535}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000536
jbauch577f5dc2017-05-17 16:32:26 -0700537void PhysicalSocket::SetEnabledEvents(uint8_t events) {
538 enabled_events_ = events;
539}
540
541void PhysicalSocket::EnableEvents(uint8_t events) {
542 enabled_events_ |= events;
543}
544
545void PhysicalSocket::DisableEvents(uint8_t events) {
546 enabled_events_ &= ~events;
547}
548
jbauch095ae152015-12-18 01:39:55 -0800549int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
550 switch (opt) {
551 case OPT_DONTFRAGMENT:
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000552#if defined(WEBRTC_WIN)
jbauch095ae152015-12-18 01:39:55 -0800553 *slevel = IPPROTO_IP;
554 *sopt = IP_DONTFRAGMENT;
555 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000556#elif defined(WEBRTC_MAC) || defined(BSD) || defined(__native_client__)
Mirko Bonadei675513b2017-11-09 11:09:25 +0100557 RTC_LOG(LS_WARNING) << "Socket::OPT_DONTFRAGMENT not supported.";
jbauch095ae152015-12-18 01:39:55 -0800558 return -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000559#elif defined(WEBRTC_POSIX)
jbauch095ae152015-12-18 01:39:55 -0800560 *slevel = IPPROTO_IP;
561 *sopt = IP_MTU_DISCOVER;
562 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000563#endif
jbauch095ae152015-12-18 01:39:55 -0800564 case OPT_RCVBUF:
565 *slevel = SOL_SOCKET;
566 *sopt = SO_RCVBUF;
567 break;
568 case OPT_SNDBUF:
569 *slevel = SOL_SOCKET;
570 *sopt = SO_SNDBUF;
571 break;
572 case OPT_NODELAY:
573 *slevel = IPPROTO_TCP;
574 *sopt = TCP_NODELAY;
575 break;
576 case OPT_DSCP:
Taylor Brandstetterecd6fc82020-02-05 17:26:37 -0800577#if defined(WEBRTC_POSIX)
578 if (family_ == AF_INET6) {
579 *slevel = IPPROTO_IPV6;
580 *sopt = IPV6_TCLASS;
581 } else {
582 *slevel = IPPROTO_IP;
583 *sopt = IP_TOS;
584 }
585 break;
586#else
Mirko Bonadei675513b2017-11-09 11:09:25 +0100587 RTC_LOG(LS_WARNING) << "Socket::OPT_DSCP not supported.";
jbauch095ae152015-12-18 01:39:55 -0800588 return -1;
Taylor Brandstetterecd6fc82020-02-05 17:26:37 -0800589#endif
jbauch095ae152015-12-18 01:39:55 -0800590 case OPT_RTP_SENDTIME_EXTN_ID:
591 return -1; // No logging is necessary as this not a OS socket option.
592 default:
nissec80e7412017-01-11 05:56:46 -0800593 RTC_NOTREACHED();
jbauch095ae152015-12-18 01:39:55 -0800594 return -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000595 }
jbauch095ae152015-12-18 01:39:55 -0800596 return 0;
597}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000598
Yves Gerey665174f2018-06-19 15:03:05 +0200599SocketDispatcher::SocketDispatcher(PhysicalSocketServer* ss)
jbauch4331fcd2016-01-06 22:20:28 -0800600#if defined(WEBRTC_WIN)
Yves Gerey665174f2018-06-19 15:03:05 +0200601 : PhysicalSocket(ss),
602 id_(0),
603 signal_close_(false)
jbauch4331fcd2016-01-06 22:20:28 -0800604#else
Yves Gerey665174f2018-06-19 15:03:05 +0200605 : PhysicalSocket(ss)
jbauch4331fcd2016-01-06 22:20:28 -0800606#endif
607{
608}
609
Yves Gerey665174f2018-06-19 15:03:05 +0200610SocketDispatcher::SocketDispatcher(SOCKET s, PhysicalSocketServer* ss)
jbauch4331fcd2016-01-06 22:20:28 -0800611#if defined(WEBRTC_WIN)
Yves Gerey665174f2018-06-19 15:03:05 +0200612 : PhysicalSocket(ss, s),
613 id_(0),
614 signal_close_(false)
jbauch4331fcd2016-01-06 22:20:28 -0800615#else
Yves Gerey665174f2018-06-19 15:03:05 +0200616 : PhysicalSocket(ss, s)
jbauch4331fcd2016-01-06 22:20:28 -0800617#endif
618{
619}
620
621SocketDispatcher::~SocketDispatcher() {
622 Close();
623}
624
625bool SocketDispatcher::Initialize() {
nisseede5da42017-01-12 05:15:36 -0800626 RTC_DCHECK(s_ != INVALID_SOCKET);
Yves Gerey665174f2018-06-19 15:03:05 +0200627// Must be a non-blocking
jbauch4331fcd2016-01-06 22:20:28 -0800628#if defined(WEBRTC_WIN)
629 u_long argp = 1;
630 ioctlsocket(s_, FIONBIO, &argp);
631#elif defined(WEBRTC_POSIX)
632 fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK);
633#endif
deadbeefeae45642017-05-26 16:27:09 -0700634#if defined(WEBRTC_IOS)
635 // iOS may kill sockets when the app is moved to the background
636 // (specifically, if the app doesn't use the "voip" UIBackgroundMode). When
637 // we attempt to write to such a socket, SIGPIPE will be raised, which by
638 // default will terminate the process, which we don't want. By specifying
639 // this socket option, SIGPIPE will be disabled for the socket.
640 int value = 1;
641 ::setsockopt(s_, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value));
642#endif
jbauch4331fcd2016-01-06 22:20:28 -0800643 ss_->Add(this);
644 return true;
645}
646
647bool SocketDispatcher::Create(int type) {
648 return Create(AF_INET, type);
649}
650
651bool SocketDispatcher::Create(int family, int type) {
652 // Change the socket to be non-blocking.
653 if (!PhysicalSocket::Create(family, type))
654 return false;
655
656 if (!Initialize())
657 return false;
658
659#if defined(WEBRTC_WIN)
Yves Gerey665174f2018-06-19 15:03:05 +0200660 do {
661 id_ = ++next_id_;
662 } while (id_ == 0);
jbauch4331fcd2016-01-06 22:20:28 -0800663#endif
664 return true;
665}
666
667#if defined(WEBRTC_WIN)
668
669WSAEVENT SocketDispatcher::GetWSAEvent() {
670 return WSA_INVALID_EVENT;
671}
672
673SOCKET SocketDispatcher::GetSocket() {
674 return s_;
675}
676
677bool SocketDispatcher::CheckSignalClose() {
678 if (!signal_close_)
679 return false;
680
681 char ch;
682 if (recv(s_, &ch, 1, MSG_PEEK) > 0)
683 return false;
684
685 state_ = CS_CLOSED;
686 signal_close_ = false;
687 SignalCloseEvent(this, signal_err_);
688 return true;
689}
690
691int SocketDispatcher::next_id_ = 0;
692
693#elif defined(WEBRTC_POSIX)
694
695int SocketDispatcher::GetDescriptor() {
696 return s_;
697}
698
699bool SocketDispatcher::IsDescriptorClosed() {
deadbeeffaedf7f2017-02-09 15:09:22 -0800700 if (udp_) {
701 // The MSG_PEEK trick doesn't work for UDP, since (at least in some
702 // circumstances) it requires reading an entire UDP packet, which would be
703 // bad for performance here. So, just check whether |s_| has been closed,
704 // which should be sufficient.
705 return s_ == INVALID_SOCKET;
706 }
jbauch4331fcd2016-01-06 22:20:28 -0800707 // We don't have a reliable way of distinguishing end-of-stream
708 // from readability. So test on each readable call. Is this
709 // inefficient? Probably.
710 char ch;
711 ssize_t res = ::recv(s_, &ch, 1, MSG_PEEK);
712 if (res > 0) {
713 // Data available, so not closed.
714 return false;
715 } else if (res == 0) {
716 // EOF, so closed.
717 return true;
718 } else { // error
719 switch (errno) {
720 // Returned if we've already closed s_.
721 case EBADF:
722 // Returned during ungraceful peer shutdown.
723 case ECONNRESET:
724 return true;
deadbeeffaedf7f2017-02-09 15:09:22 -0800725 // The normal blocking error; don't log anything.
726 case EWOULDBLOCK:
727 // Interrupted system call.
728 case EINTR:
729 return false;
jbauch4331fcd2016-01-06 22:20:28 -0800730 default:
731 // Assume that all other errors are just blocking errors, meaning the
732 // connection is still good but we just can't read from it right now.
733 // This should only happen when connecting (and at most once), because
734 // in all other cases this function is only called if the file
735 // descriptor is already known to be in the readable state. However,
736 // it's not necessary a problem if we spuriously interpret a
737 // "connection lost"-type error as a blocking error, because typically
738 // the next recv() will get EOF, so we'll still eventually notice that
739 // the socket is closed.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100740 RTC_LOG_ERR(LS_WARNING) << "Assuming benign blocking error";
jbauch4331fcd2016-01-06 22:20:28 -0800741 return false;
742 }
743 }
744}
745
Yves Gerey665174f2018-06-19 15:03:05 +0200746#endif // WEBRTC_POSIX
jbauch4331fcd2016-01-06 22:20:28 -0800747
748uint32_t SocketDispatcher::GetRequestedEvents() {
jbauch577f5dc2017-05-17 16:32:26 -0700749 return enabled_events();
jbauch4331fcd2016-01-06 22:20:28 -0800750}
751
752void SocketDispatcher::OnPreEvent(uint32_t ff) {
753 if ((ff & DE_CONNECT) != 0)
754 state_ = CS_CONNECTED;
755
756#if defined(WEBRTC_WIN)
Yves Gerey665174f2018-06-19 15:03:05 +0200757// We set CS_CLOSED from CheckSignalClose.
jbauch4331fcd2016-01-06 22:20:28 -0800758#elif defined(WEBRTC_POSIX)
759 if ((ff & DE_CLOSE) != 0)
760 state_ = CS_CLOSED;
761#endif
762}
763
764#if defined(WEBRTC_WIN)
765
766void SocketDispatcher::OnEvent(uint32_t ff, int err) {
767 int cache_id = id_;
768 // Make sure we deliver connect/accept first. Otherwise, consumers may see
769 // something like a READ followed by a CONNECT, which would be odd.
770 if (((ff & DE_CONNECT) != 0) && (id_ == cache_id)) {
771 if (ff != DE_CONNECT)
Mirko Bonadei675513b2017-11-09 11:09:25 +0100772 RTC_LOG(LS_VERBOSE) << "Signalled with DE_CONNECT: " << ff;
jbauch577f5dc2017-05-17 16:32:26 -0700773 DisableEvents(DE_CONNECT);
jbauch4331fcd2016-01-06 22:20:28 -0800774#if !defined(NDEBUG)
775 dbg_addr_ = "Connected @ ";
776 dbg_addr_.append(GetRemoteAddress().ToString());
777#endif
778 SignalConnectEvent(this);
779 }
780 if (((ff & DE_ACCEPT) != 0) && (id_ == cache_id)) {
jbauch577f5dc2017-05-17 16:32:26 -0700781 DisableEvents(DE_ACCEPT);
jbauch4331fcd2016-01-06 22:20:28 -0800782 SignalReadEvent(this);
783 }
784 if ((ff & DE_READ) != 0) {
jbauch577f5dc2017-05-17 16:32:26 -0700785 DisableEvents(DE_READ);
jbauch4331fcd2016-01-06 22:20:28 -0800786 SignalReadEvent(this);
787 }
788 if (((ff & DE_WRITE) != 0) && (id_ == cache_id)) {
jbauch577f5dc2017-05-17 16:32:26 -0700789 DisableEvents(DE_WRITE);
jbauch4331fcd2016-01-06 22:20:28 -0800790 SignalWriteEvent(this);
791 }
792 if (((ff & DE_CLOSE) != 0) && (id_ == cache_id)) {
793 signal_close_ = true;
794 signal_err_ = err;
795 }
796}
797
798#elif defined(WEBRTC_POSIX)
799
800void SocketDispatcher::OnEvent(uint32_t ff, int err) {
jbauchde4db112017-05-31 13:09:18 -0700801#if defined(WEBRTC_USE_EPOLL)
802 // Remember currently enabled events so we can combine multiple changes
803 // into one update call later.
804 // The signal handlers might re-enable events disabled here, so we can't
805 // keep a list of events to disable at the end of the method. This list
806 // would not be updated with the events enabled by the signal handlers.
807 StartBatchedEventUpdates();
808#endif
jbauch4331fcd2016-01-06 22:20:28 -0800809 // Make sure we deliver connect/accept first. Otherwise, consumers may see
810 // something like a READ followed by a CONNECT, which would be odd.
811 if ((ff & DE_CONNECT) != 0) {
jbauch577f5dc2017-05-17 16:32:26 -0700812 DisableEvents(DE_CONNECT);
jbauch4331fcd2016-01-06 22:20:28 -0800813 SignalConnectEvent(this);
814 }
815 if ((ff & DE_ACCEPT) != 0) {
jbauch577f5dc2017-05-17 16:32:26 -0700816 DisableEvents(DE_ACCEPT);
jbauch4331fcd2016-01-06 22:20:28 -0800817 SignalReadEvent(this);
818 }
819 if ((ff & DE_READ) != 0) {
jbauch577f5dc2017-05-17 16:32:26 -0700820 DisableEvents(DE_READ);
jbauch4331fcd2016-01-06 22:20:28 -0800821 SignalReadEvent(this);
822 }
823 if ((ff & DE_WRITE) != 0) {
jbauch577f5dc2017-05-17 16:32:26 -0700824 DisableEvents(DE_WRITE);
jbauch4331fcd2016-01-06 22:20:28 -0800825 SignalWriteEvent(this);
826 }
827 if ((ff & DE_CLOSE) != 0) {
828 // The socket is now dead to us, so stop checking it.
jbauch577f5dc2017-05-17 16:32:26 -0700829 SetEnabledEvents(0);
jbauch4331fcd2016-01-06 22:20:28 -0800830 SignalCloseEvent(this, err);
831 }
jbauchde4db112017-05-31 13:09:18 -0700832#if defined(WEBRTC_USE_EPOLL)
833 FinishBatchedEventUpdates();
834#endif
jbauch4331fcd2016-01-06 22:20:28 -0800835}
836
Yves Gerey665174f2018-06-19 15:03:05 +0200837#endif // WEBRTC_POSIX
jbauch4331fcd2016-01-06 22:20:28 -0800838
jbauchde4db112017-05-31 13:09:18 -0700839#if defined(WEBRTC_USE_EPOLL)
840
841static int GetEpollEvents(uint32_t ff) {
842 int events = 0;
843 if (ff & (DE_READ | DE_ACCEPT)) {
844 events |= EPOLLIN;
845 }
846 if (ff & (DE_WRITE | DE_CONNECT)) {
847 events |= EPOLLOUT;
848 }
849 return events;
850}
851
852void SocketDispatcher::StartBatchedEventUpdates() {
853 RTC_DCHECK_EQ(saved_enabled_events_, -1);
854 saved_enabled_events_ = enabled_events();
855}
856
857void SocketDispatcher::FinishBatchedEventUpdates() {
858 RTC_DCHECK_NE(saved_enabled_events_, -1);
859 uint8_t old_events = static_cast<uint8_t>(saved_enabled_events_);
860 saved_enabled_events_ = -1;
861 MaybeUpdateDispatcher(old_events);
862}
863
864void SocketDispatcher::MaybeUpdateDispatcher(uint8_t old_events) {
865 if (GetEpollEvents(enabled_events()) != GetEpollEvents(old_events) &&
866 saved_enabled_events_ == -1) {
867 ss_->Update(this);
868 }
869}
870
871void SocketDispatcher::SetEnabledEvents(uint8_t events) {
872 uint8_t old_events = enabled_events();
873 PhysicalSocket::SetEnabledEvents(events);
874 MaybeUpdateDispatcher(old_events);
875}
876
877void SocketDispatcher::EnableEvents(uint8_t events) {
878 uint8_t old_events = enabled_events();
879 PhysicalSocket::EnableEvents(events);
880 MaybeUpdateDispatcher(old_events);
881}
882
883void SocketDispatcher::DisableEvents(uint8_t events) {
884 uint8_t old_events = enabled_events();
885 PhysicalSocket::DisableEvents(events);
886 MaybeUpdateDispatcher(old_events);
887}
888
889#endif // WEBRTC_USE_EPOLL
890
jbauch4331fcd2016-01-06 22:20:28 -0800891int SocketDispatcher::Close() {
892 if (s_ == INVALID_SOCKET)
893 return 0;
894
895#if defined(WEBRTC_WIN)
896 id_ = 0;
897 signal_close_ = false;
898#endif
899 ss_->Remove(this);
900 return PhysicalSocket::Close();
901}
902
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000903#if defined(WEBRTC_POSIX)
904class EventDispatcher : public Dispatcher {
905 public:
906 EventDispatcher(PhysicalSocketServer* ss) : ss_(ss), fSignaled_(false) {
907 if (pipe(afd_) < 0)
Mirko Bonadei675513b2017-11-09 11:09:25 +0100908 RTC_LOG(LERROR) << "pipe failed";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000909 ss_->Add(this);
910 }
911
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000912 ~EventDispatcher() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000913 ss_->Remove(this);
914 close(afd_[0]);
915 close(afd_[1]);
916 }
917
918 virtual void Signal() {
919 CritScope cs(&crit_);
920 if (!fSignaled_) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200921 const uint8_t b[1] = {0};
nissec16fa5e2017-02-07 07:18:43 -0800922 const ssize_t res = write(afd_[1], b, sizeof(b));
923 RTC_DCHECK_EQ(1, res);
924 fSignaled_ = true;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000925 }
926 }
927
Peter Boström0c4e06b2015-10-07 12:23:21 +0200928 uint32_t GetRequestedEvents() override { return DE_READ; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000929
Peter Boström0c4e06b2015-10-07 12:23:21 +0200930 void OnPreEvent(uint32_t ff) override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000931 // It is not possible to perfectly emulate an auto-resetting event with
932 // pipes. This simulates it by resetting before the event is handled.
933
934 CritScope cs(&crit_);
935 if (fSignaled_) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200936 uint8_t b[4]; // Allow for reading more than 1 byte, but expect 1.
nissec16fa5e2017-02-07 07:18:43 -0800937 const ssize_t res = read(afd_[0], b, sizeof(b));
938 RTC_DCHECK_EQ(1, res);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000939 fSignaled_ = false;
940 }
941 }
942
nissec80e7412017-01-11 05:56:46 -0800943 void OnEvent(uint32_t ff, int err) override { RTC_NOTREACHED(); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000944
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000945 int GetDescriptor() override { return afd_[0]; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000946
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000947 bool IsDescriptorClosed() override { return false; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000948
949 private:
Yves Gerey665174f2018-06-19 15:03:05 +0200950 PhysicalSocketServer* ss_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000951 int afd_[2];
952 bool fSignaled_;
953 CriticalSection crit_;
954};
955
956// These two classes use the self-pipe trick to deliver POSIX signals to our
957// select loop. This is the only safe, reliable, cross-platform way to do
958// non-trivial things with a POSIX signal in an event-driven program (until
959// proper pselect() implementations become ubiquitous).
960
961class PosixSignalHandler {
962 public:
963 // POSIX only specifies 32 signals, but in principle the system might have
964 // more and the programmer might choose to use them, so we size our array
965 // for 128.
966 static const int kNumPosixSignals = 128;
967
968 // There is just a single global instance. (Signal handlers do not get any
969 // sort of user-defined void * parameter, so they can't access anything that
970 // isn't global.)
971 static PosixSignalHandler* Instance() {
Niels Möller14682a32018-05-24 08:54:25 +0200972 static PosixSignalHandler* const instance = new PosixSignalHandler();
973 return instance;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000974 }
975
976 // Returns true if the given signal number is set.
977 bool IsSignalSet(int signum) const {
nisseede5da42017-01-12 05:15:36 -0800978 RTC_DCHECK(signum < static_cast<int>(arraysize(received_signal_)));
tfarina5237aaf2015-11-10 23:44:30 -0800979 if (signum < static_cast<int>(arraysize(received_signal_))) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000980 return received_signal_[signum];
981 } else {
982 return false;
983 }
984 }
985
986 // Clears the given signal number.
987 void ClearSignal(int signum) {
nisseede5da42017-01-12 05:15:36 -0800988 RTC_DCHECK(signum < static_cast<int>(arraysize(received_signal_)));
tfarina5237aaf2015-11-10 23:44:30 -0800989 if (signum < static_cast<int>(arraysize(received_signal_))) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000990 received_signal_[signum] = false;
991 }
992 }
993
994 // Returns the file descriptor to monitor for signal events.
Yves Gerey665174f2018-06-19 15:03:05 +0200995 int GetDescriptor() const { return afd_[0]; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000996
997 // This is called directly from our real signal handler, so it must be
998 // signal-handler-safe. That means it cannot assume anything about the
999 // user-level state of the process, since the handler could be executed at any
1000 // time on any thread.
1001 void OnPosixSignalReceived(int signum) {
tfarina5237aaf2015-11-10 23:44:30 -08001002 if (signum >= static_cast<int>(arraysize(received_signal_))) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001003 // We don't have space in our array for this.
1004 return;
1005 }
1006 // Set a flag saying we've seen this signal.
1007 received_signal_[signum] = true;
1008 // Notify application code that we got a signal.
Peter Boström0c4e06b2015-10-07 12:23:21 +02001009 const uint8_t b[1] = {0};
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001010 if (-1 == write(afd_[1], b, sizeof(b))) {
1011 // Nothing we can do here. If there's an error somehow then there's
1012 // nothing we can safely do from a signal handler.
1013 // No, we can't even safely log it.
1014 // But, we still have to check the return value here. Otherwise,
1015 // GCC 4.4.1 complains ignoring return value. Even (void) doesn't help.
1016 return;
1017 }
1018 }
1019
1020 private:
1021 PosixSignalHandler() {
1022 if (pipe(afd_) < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001023 RTC_LOG_ERR(LS_ERROR) << "pipe failed";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001024 return;
1025 }
1026 if (fcntl(afd_[0], F_SETFL, O_NONBLOCK) < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001027 RTC_LOG_ERR(LS_WARNING) << "fcntl #1 failed";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001028 }
1029 if (fcntl(afd_[1], F_SETFL, O_NONBLOCK) < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001030 RTC_LOG_ERR(LS_WARNING) << "fcntl #2 failed";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001031 }
Yves Gerey665174f2018-06-19 15:03:05 +02001032 memset(const_cast<void*>(static_cast<volatile void*>(received_signal_)), 0,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001033 sizeof(received_signal_));
1034 }
1035
1036 ~PosixSignalHandler() {
1037 int fd1 = afd_[0];
1038 int fd2 = afd_[1];
1039 // We clobber the stored file descriptor numbers here or else in principle
1040 // a signal that happens to be delivered during application termination
1041 // could erroneously write a zero byte to an unrelated file handle in
1042 // OnPosixSignalReceived() if some other file happens to be opened later
1043 // during shutdown and happens to be given the same file descriptor number
1044 // as our pipe had. Unfortunately even with this precaution there is still a
1045 // race where that could occur if said signal happens to be handled
1046 // concurrently with this code and happens to have already read the value of
1047 // afd_[1] from memory before we clobber it, but that's unlikely.
1048 afd_[0] = -1;
1049 afd_[1] = -1;
1050 close(fd1);
1051 close(fd2);
1052 }
1053
1054 int afd_[2];
1055 // These are boolean flags that will be set in our signal handler and read
1056 // and cleared from Wait(). There is a race involved in this, but it is
1057 // benign. The signal handler sets the flag before signaling the pipe, so
1058 // we'll never end up blocking in select() while a flag is still true.
1059 // However, if two of the same signal arrive close to each other then it's
1060 // possible that the second time the handler may set the flag while it's still
1061 // true, meaning that signal will be missed. But the first occurrence of it
1062 // will still be handled, so this isn't a problem.
1063 // Volatile is not necessary here for correctness, but this data _is_ volatile
1064 // so I've marked it as such.
Peter Boström0c4e06b2015-10-07 12:23:21 +02001065 volatile uint8_t received_signal_[kNumPosixSignals];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001066};
1067
1068class PosixSignalDispatcher : public Dispatcher {
1069 public:
Yves Gerey665174f2018-06-19 15:03:05 +02001070 PosixSignalDispatcher(PhysicalSocketServer* owner) : owner_(owner) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001071 owner_->Add(this);
1072 }
1073
Yves Gerey665174f2018-06-19 15:03:05 +02001074 ~PosixSignalDispatcher() override { owner_->Remove(this); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001075
Peter Boström0c4e06b2015-10-07 12:23:21 +02001076 uint32_t GetRequestedEvents() override { return DE_READ; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001077
Peter Boström0c4e06b2015-10-07 12:23:21 +02001078 void OnPreEvent(uint32_t ff) override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001079 // Events might get grouped if signals come very fast, so we read out up to
1080 // 16 bytes to make sure we keep the pipe empty.
Peter Boström0c4e06b2015-10-07 12:23:21 +02001081 uint8_t b[16];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001082 ssize_t ret = read(GetDescriptor(), b, sizeof(b));
1083 if (ret < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001084 RTC_LOG_ERR(LS_WARNING) << "Error in read()";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001085 } else if (ret == 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001086 RTC_LOG(LS_WARNING) << "Should have read at least one byte";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001087 }
1088 }
1089
Peter Boström0c4e06b2015-10-07 12:23:21 +02001090 void OnEvent(uint32_t ff, int err) override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001091 for (int signum = 0; signum < PosixSignalHandler::kNumPosixSignals;
1092 ++signum) {
1093 if (PosixSignalHandler::Instance()->IsSignalSet(signum)) {
1094 PosixSignalHandler::Instance()->ClearSignal(signum);
1095 HandlerMap::iterator i = handlers_.find(signum);
1096 if (i == handlers_.end()) {
1097 // This can happen if a signal is delivered to our process at around
1098 // the same time as we unset our handler for it. It is not an error
1099 // condition, but it's unusual enough to be worth logging.
Mirko Bonadei675513b2017-11-09 11:09:25 +01001100 RTC_LOG(LS_INFO) << "Received signal with no handler: " << signum;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001101 } else {
1102 // Otherwise, execute our handler.
1103 (*i->second)(signum);
1104 }
1105 }
1106 }
1107 }
1108
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +00001109 int GetDescriptor() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001110 return PosixSignalHandler::Instance()->GetDescriptor();
1111 }
1112
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +00001113 bool IsDescriptorClosed() override { return false; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001114
1115 void SetHandler(int signum, void (*handler)(int)) {
1116 handlers_[signum] = handler;
1117 }
1118
Yves Gerey665174f2018-06-19 15:03:05 +02001119 void ClearHandler(int signum) { handlers_.erase(signum); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001120
Yves Gerey665174f2018-06-19 15:03:05 +02001121 bool HasHandlers() { return !handlers_.empty(); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001122
1123 private:
1124 typedef std::map<int, void (*)(int)> HandlerMap;
1125
1126 HandlerMap handlers_;
1127 // Our owner.
Yves Gerey665174f2018-06-19 15:03:05 +02001128 PhysicalSocketServer* owner_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001129};
1130
Yves Gerey665174f2018-06-19 15:03:05 +02001131#endif // WEBRTC_POSIX
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001132
1133#if defined(WEBRTC_WIN)
Peter Boström0c4e06b2015-10-07 12:23:21 +02001134static uint32_t FlagsToEvents(uint32_t events) {
1135 uint32_t ffFD = FD_CLOSE;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001136 if (events & DE_READ)
1137 ffFD |= FD_READ;
1138 if (events & DE_WRITE)
1139 ffFD |= FD_WRITE;
1140 if (events & DE_CONNECT)
1141 ffFD |= FD_CONNECT;
1142 if (events & DE_ACCEPT)
1143 ffFD |= FD_ACCEPT;
1144 return ffFD;
1145}
1146
1147class EventDispatcher : public Dispatcher {
1148 public:
Yves Gerey665174f2018-06-19 15:03:05 +02001149 EventDispatcher(PhysicalSocketServer* ss) : ss_(ss) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001150 hev_ = WSACreateEvent();
1151 if (hev_) {
1152 ss_->Add(this);
1153 }
1154 }
1155
Steve Anton9de3aac2017-10-24 10:08:26 -07001156 ~EventDispatcher() override {
deadbeef37f5ecf2017-02-27 14:06:41 -08001157 if (hev_ != nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001158 ss_->Remove(this);
1159 WSACloseEvent(hev_);
deadbeef37f5ecf2017-02-27 14:06:41 -08001160 hev_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001161 }
1162 }
1163
1164 virtual void Signal() {
deadbeef37f5ecf2017-02-27 14:06:41 -08001165 if (hev_ != nullptr)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001166 WSASetEvent(hev_);
1167 }
1168
Steve Anton9de3aac2017-10-24 10:08:26 -07001169 uint32_t GetRequestedEvents() override { return 0; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001170
Steve Anton9de3aac2017-10-24 10:08:26 -07001171 void OnPreEvent(uint32_t ff) override { WSAResetEvent(hev_); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001172
Steve Anton9de3aac2017-10-24 10:08:26 -07001173 void OnEvent(uint32_t ff, int err) override {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001174
Steve Anton9de3aac2017-10-24 10:08:26 -07001175 WSAEVENT GetWSAEvent() override { return hev_; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001176
Steve Anton9de3aac2017-10-24 10:08:26 -07001177 SOCKET GetSocket() override { return INVALID_SOCKET; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001178
Steve Anton9de3aac2017-10-24 10:08:26 -07001179 bool CheckSignalClose() override { return false; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001180
Steve Anton9de3aac2017-10-24 10:08:26 -07001181 private:
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001182 PhysicalSocketServer* ss_;
1183 WSAEVENT hev_;
1184};
honghaizcec0a082016-01-15 14:49:09 -08001185#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001186
1187// Sets the value of a boolean value to false when signaled.
1188class Signaler : public EventDispatcher {
1189 public:
Yves Gerey665174f2018-06-19 15:03:05 +02001190 Signaler(PhysicalSocketServer* ss, bool* pf) : EventDispatcher(ss), pf_(pf) {}
1191 ~Signaler() override {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001192
Peter Boström0c4e06b2015-10-07 12:23:21 +02001193 void OnEvent(uint32_t ff, int err) override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001194 if (pf_)
1195 *pf_ = false;
1196 }
1197
1198 private:
Yves Gerey665174f2018-06-19 15:03:05 +02001199 bool* pf_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001200};
1201
Yves Gerey665174f2018-06-19 15:03:05 +02001202PhysicalSocketServer::PhysicalSocketServer() : fWait_(false) {
jbauchde4db112017-05-31 13:09:18 -07001203#if defined(WEBRTC_USE_EPOLL)
1204 // Since Linux 2.6.8, the size argument is ignored, but must be greater than
1205 // zero. Before that the size served as hint to the kernel for the amount of
1206 // space to initially allocate in internal data structures.
1207 epoll_fd_ = epoll_create(FD_SETSIZE);
1208 if (epoll_fd_ == -1) {
1209 // Not an error, will fall back to "select" below.
Mirko Bonadei675513b2017-11-09 11:09:25 +01001210 RTC_LOG_E(LS_WARNING, EN, errno) << "epoll_create";
jbauchde4db112017-05-31 13:09:18 -07001211 epoll_fd_ = INVALID_SOCKET;
1212 }
1213#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001214 signal_wakeup_ = new Signaler(this, &fWait_);
1215#if defined(WEBRTC_WIN)
1216 socket_ev_ = WSACreateEvent();
1217#endif
1218}
1219
1220PhysicalSocketServer::~PhysicalSocketServer() {
1221#if defined(WEBRTC_WIN)
1222 WSACloseEvent(socket_ev_);
1223#endif
1224#if defined(WEBRTC_POSIX)
1225 signal_dispatcher_.reset();
1226#endif
1227 delete signal_wakeup_;
jbauchde4db112017-05-31 13:09:18 -07001228#if defined(WEBRTC_USE_EPOLL)
1229 if (epoll_fd_ != INVALID_SOCKET) {
1230 close(epoll_fd_);
1231 }
1232#endif
nisseede5da42017-01-12 05:15:36 -08001233 RTC_DCHECK(dispatchers_.empty());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001234}
1235
1236void PhysicalSocketServer::WakeUp() {
1237 signal_wakeup_->Signal();
1238}
1239
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001240Socket* PhysicalSocketServer::CreateSocket(int family, int type) {
1241 PhysicalSocket* socket = new PhysicalSocket(this);
1242 if (socket->Create(family, type)) {
1243 return socket;
1244 } else {
1245 delete socket;
jbauch095ae152015-12-18 01:39:55 -08001246 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001247 }
1248}
1249
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001250AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int family, int type) {
1251 SocketDispatcher* dispatcher = new SocketDispatcher(this);
1252 if (dispatcher->Create(family, type)) {
1253 return dispatcher;
1254 } else {
1255 delete dispatcher;
jbauch095ae152015-12-18 01:39:55 -08001256 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001257 }
1258}
1259
1260AsyncSocket* PhysicalSocketServer::WrapSocket(SOCKET s) {
1261 SocketDispatcher* dispatcher = new SocketDispatcher(s, this);
1262 if (dispatcher->Initialize()) {
1263 return dispatcher;
1264 } else {
1265 delete dispatcher;
jbauch095ae152015-12-18 01:39:55 -08001266 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001267 }
1268}
1269
Yves Gerey665174f2018-06-19 15:03:05 +02001270void PhysicalSocketServer::Add(Dispatcher* pdispatcher) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001271 CritScope cs(&crit_);
jbauchde4db112017-05-31 13:09:18 -07001272 if (processing_dispatchers_) {
1273 // A dispatcher is being added while a "Wait" call is processing the
1274 // list of socket events.
1275 // Defer adding to "dispatchers_" set until processing is done to avoid
1276 // invalidating the iterator in "Wait".
1277 pending_remove_dispatchers_.erase(pdispatcher);
1278 pending_add_dispatchers_.insert(pdispatcher);
1279 } else {
1280 dispatchers_.insert(pdispatcher);
1281 }
1282#if defined(WEBRTC_USE_EPOLL)
1283 if (epoll_fd_ != INVALID_SOCKET) {
1284 AddEpoll(pdispatcher);
1285 }
1286#endif // WEBRTC_USE_EPOLL
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001287}
1288
Yves Gerey665174f2018-06-19 15:03:05 +02001289void PhysicalSocketServer::Remove(Dispatcher* pdispatcher) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001290 CritScope cs(&crit_);
jbauchde4db112017-05-31 13:09:18 -07001291 if (processing_dispatchers_) {
1292 // A dispatcher is being removed while a "Wait" call is processing the
1293 // list of socket events.
1294 // Defer removal from "dispatchers_" set until processing is done to avoid
1295 // invalidating the iterator in "Wait".
1296 if (!pending_add_dispatchers_.erase(pdispatcher) &&
1297 dispatchers_.find(pdispatcher) == dispatchers_.end()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001298 RTC_LOG(LS_WARNING) << "PhysicalSocketServer asked to remove a unknown "
Jonas Olssonb2b20312020-01-14 12:11:31 +01001299 "dispatcher, potentially from a duplicate call to "
1300 "Add.";
jbauchde4db112017-05-31 13:09:18 -07001301 return;
1302 }
1303
1304 pending_remove_dispatchers_.insert(pdispatcher);
1305 } else if (!dispatchers_.erase(pdispatcher)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001306 RTC_LOG(LS_WARNING)
1307 << "PhysicalSocketServer asked to remove a unknown "
Jonas Olssonb2b20312020-01-14 12:11:31 +01001308 "dispatcher, potentially from a duplicate call to Add.";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001309 return;
1310 }
jbauchde4db112017-05-31 13:09:18 -07001311#if defined(WEBRTC_USE_EPOLL)
1312 if (epoll_fd_ != INVALID_SOCKET) {
1313 RemoveEpoll(pdispatcher);
1314 }
1315#endif // WEBRTC_USE_EPOLL
1316}
1317
1318void PhysicalSocketServer::Update(Dispatcher* pdispatcher) {
1319#if defined(WEBRTC_USE_EPOLL)
1320 if (epoll_fd_ == INVALID_SOCKET) {
1321 return;
1322 }
1323
1324 CritScope cs(&crit_);
1325 if (dispatchers_.find(pdispatcher) == dispatchers_.end()) {
1326 return;
1327 }
1328
1329 UpdateEpoll(pdispatcher);
1330#endif
1331}
1332
1333void PhysicalSocketServer::AddRemovePendingDispatchers() {
1334 if (!pending_add_dispatchers_.empty()) {
1335 for (Dispatcher* pdispatcher : pending_add_dispatchers_) {
1336 dispatchers_.insert(pdispatcher);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001337 }
jbauchde4db112017-05-31 13:09:18 -07001338 pending_add_dispatchers_.clear();
1339 }
1340
1341 if (!pending_remove_dispatchers_.empty()) {
1342 for (Dispatcher* pdispatcher : pending_remove_dispatchers_) {
1343 dispatchers_.erase(pdispatcher);
1344 }
1345 pending_remove_dispatchers_.clear();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001346 }
1347}
1348
1349#if defined(WEBRTC_POSIX)
jbauchde4db112017-05-31 13:09:18 -07001350
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001351bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
jbauchde4db112017-05-31 13:09:18 -07001352#if defined(WEBRTC_USE_EPOLL)
1353 // We don't keep a dedicated "epoll" descriptor containing only the non-IO
1354 // (i.e. signaling) dispatcher, so "poll" will be used instead of the default
1355 // "select" to support sockets larger than FD_SETSIZE.
1356 if (!process_io) {
1357 return WaitPoll(cmsWait, signal_wakeup_);
1358 } else if (epoll_fd_ != INVALID_SOCKET) {
1359 return WaitEpoll(cmsWait);
1360 }
1361#endif
1362 return WaitSelect(cmsWait, process_io);
1363}
1364
1365static void ProcessEvents(Dispatcher* dispatcher,
1366 bool readable,
1367 bool writable,
1368 bool check_error) {
1369 int errcode = 0;
1370 // TODO(pthatcher): Should we set errcode if getsockopt fails?
1371 if (check_error) {
1372 socklen_t len = sizeof(errcode);
1373 ::getsockopt(dispatcher->GetDescriptor(), SOL_SOCKET, SO_ERROR, &errcode,
1374 &len);
1375 }
1376
1377 uint32_t ff = 0;
1378
1379 // Check readable descriptors. If we're waiting on an accept, signal
1380 // that. Otherwise we're waiting for data, check to see if we're
1381 // readable or really closed.
1382 // TODO(pthatcher): Only peek at TCP descriptors.
1383 if (readable) {
1384 if (dispatcher->GetRequestedEvents() & DE_ACCEPT) {
1385 ff |= DE_ACCEPT;
1386 } else if (errcode || dispatcher->IsDescriptorClosed()) {
1387 ff |= DE_CLOSE;
1388 } else {
1389 ff |= DE_READ;
1390 }
1391 }
1392
1393 // Check writable descriptors. If we're waiting on a connect, detect
1394 // success versus failure by the reaped error code.
1395 if (writable) {
1396 if (dispatcher->GetRequestedEvents() & DE_CONNECT) {
1397 if (!errcode) {
1398 ff |= DE_CONNECT;
1399 } else {
1400 ff |= DE_CLOSE;
1401 }
1402 } else {
1403 ff |= DE_WRITE;
1404 }
1405 }
1406
1407 // Tell the descriptor about the event.
1408 if (ff != 0) {
1409 dispatcher->OnPreEvent(ff);
1410 dispatcher->OnEvent(ff, errcode);
1411 }
1412}
1413
1414bool PhysicalSocketServer::WaitSelect(int cmsWait, bool process_io) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001415 // Calculate timing information
1416
deadbeef37f5ecf2017-02-27 14:06:41 -08001417 struct timeval* ptvWait = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001418 struct timeval tvWait;
Niels Möller689b5872018-08-29 09:55:44 +02001419 int64_t stop_us;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001420 if (cmsWait != kForever) {
1421 // Calculate wait timeval
1422 tvWait.tv_sec = cmsWait / 1000;
1423 tvWait.tv_usec = (cmsWait % 1000) * 1000;
1424 ptvWait = &tvWait;
1425
Niels Möller689b5872018-08-29 09:55:44 +02001426 // Calculate when to return
1427 stop_us = rtc::TimeMicros() + cmsWait * 1000;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001428 }
1429
1430 // Zero all fd_sets. Don't need to do this inside the loop since
1431 // select() zeros the descriptors not signaled
1432
1433 fd_set fdsRead;
1434 FD_ZERO(&fdsRead);
1435 fd_set fdsWrite;
1436 FD_ZERO(&fdsWrite);
Yves Gerey665174f2018-06-19 15:03:05 +02001437// Explicitly unpoison these FDs on MemorySanitizer which doesn't handle the
1438// inline assembly in FD_ZERO.
1439// http://crbug.com/344505
pbos@webrtc.org27e58982014-10-07 17:56:53 +00001440#ifdef MEMORY_SANITIZER
1441 __msan_unpoison(&fdsRead, sizeof(fdsRead));
1442 __msan_unpoison(&fdsWrite, sizeof(fdsWrite));
1443#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001444
1445 fWait_ = true;
1446
1447 while (fWait_) {
1448 int fdmax = -1;
1449 {
1450 CritScope cr(&crit_);
jbauchde4db112017-05-31 13:09:18 -07001451 // TODO(jbauch): Support re-entrant waiting.
1452 RTC_DCHECK(!processing_dispatchers_);
1453 for (Dispatcher* pdispatcher : dispatchers_) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001454 // Query dispatchers for read and write wait state
nisseede5da42017-01-12 05:15:36 -08001455 RTC_DCHECK(pdispatcher);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001456 if (!process_io && (pdispatcher != signal_wakeup_))
1457 continue;
1458 int fd = pdispatcher->GetDescriptor();
jbauchde4db112017-05-31 13:09:18 -07001459 // "select"ing a file descriptor that is equal to or larger than
1460 // FD_SETSIZE will result in undefined behavior.
1461 RTC_DCHECK_LT(fd, FD_SETSIZE);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001462 if (fd > fdmax)
1463 fdmax = fd;
1464
Peter Boström0c4e06b2015-10-07 12:23:21 +02001465 uint32_t ff = pdispatcher->GetRequestedEvents();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001466 if (ff & (DE_READ | DE_ACCEPT))
1467 FD_SET(fd, &fdsRead);
1468 if (ff & (DE_WRITE | DE_CONNECT))
1469 FD_SET(fd, &fdsWrite);
1470 }
1471 }
1472
1473 // Wait then call handlers as appropriate
1474 // < 0 means error
1475 // 0 means timeout
1476 // > 0 means count of descriptors ready
deadbeef37f5ecf2017-02-27 14:06:41 -08001477 int n = select(fdmax + 1, &fdsRead, &fdsWrite, nullptr, ptvWait);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001478
1479 // If error, return error.
1480 if (n < 0) {
1481 if (errno != EINTR) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001482 RTC_LOG_E(LS_ERROR, EN, errno) << "select";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001483 return false;
1484 }
1485 // Else ignore the error and keep going. If this EINTR was for one of the
1486 // signals managed by this PhysicalSocketServer, the
1487 // PosixSignalDeliveryDispatcher will be in the signaled state in the next
1488 // iteration.
1489 } else if (n == 0) {
1490 // If timeout, return success
1491 return true;
1492 } else {
1493 // We have signaled descriptors
1494 CritScope cr(&crit_);
jbauchde4db112017-05-31 13:09:18 -07001495 processing_dispatchers_ = true;
1496 for (Dispatcher* pdispatcher : dispatchers_) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001497 int fd = pdispatcher->GetDescriptor();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001498
jbauchde4db112017-05-31 13:09:18 -07001499 bool readable = FD_ISSET(fd, &fdsRead);
1500 if (readable) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001501 FD_CLR(fd, &fdsRead);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001502 }
1503
jbauchde4db112017-05-31 13:09:18 -07001504 bool writable = FD_ISSET(fd, &fdsWrite);
1505 if (writable) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001506 FD_CLR(fd, &fdsWrite);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001507 }
1508
jbauchde4db112017-05-31 13:09:18 -07001509 // The error code can be signaled through reads or writes.
1510 ProcessEvents(pdispatcher, readable, writable, readable || writable);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001511 }
jbauchde4db112017-05-31 13:09:18 -07001512
1513 processing_dispatchers_ = false;
1514 // Process deferred dispatchers that have been added/removed while the
1515 // events were handled above.
1516 AddRemovePendingDispatchers();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001517 }
1518
1519 // Recalc the time remaining to wait. Doing it here means it doesn't get
1520 // calced twice the first time through the loop
1521 if (ptvWait) {
1522 ptvWait->tv_sec = 0;
1523 ptvWait->tv_usec = 0;
Niels Möller689b5872018-08-29 09:55:44 +02001524 int64_t time_left_us = stop_us - rtc::TimeMicros();
1525 if (time_left_us > 0) {
1526 ptvWait->tv_sec = time_left_us / rtc::kNumMicrosecsPerSec;
1527 ptvWait->tv_usec = time_left_us % rtc::kNumMicrosecsPerSec;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001528 }
1529 }
1530 }
1531
1532 return true;
1533}
1534
jbauchde4db112017-05-31 13:09:18 -07001535#if defined(WEBRTC_USE_EPOLL)
1536
1537// Initial number of events to process with one call to "epoll_wait".
1538static const size_t kInitialEpollEvents = 128;
1539
1540// Maximum number of events to process with one call to "epoll_wait".
1541static const size_t kMaxEpollEvents = 8192;
1542
1543void PhysicalSocketServer::AddEpoll(Dispatcher* pdispatcher) {
1544 RTC_DCHECK(epoll_fd_ != INVALID_SOCKET);
1545 int fd = pdispatcher->GetDescriptor();
1546 RTC_DCHECK(fd != INVALID_SOCKET);
1547 if (fd == INVALID_SOCKET) {
1548 return;
1549 }
1550
1551 struct epoll_event event = {0};
1552 event.events = GetEpollEvents(pdispatcher->GetRequestedEvents());
1553 event.data.ptr = pdispatcher;
1554 int err = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &event);
1555 RTC_DCHECK_EQ(err, 0);
1556 if (err == -1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001557 RTC_LOG_E(LS_ERROR, EN, errno) << "epoll_ctl EPOLL_CTL_ADD";
jbauchde4db112017-05-31 13:09:18 -07001558 }
1559}
1560
1561void PhysicalSocketServer::RemoveEpoll(Dispatcher* pdispatcher) {
1562 RTC_DCHECK(epoll_fd_ != INVALID_SOCKET);
1563 int fd = pdispatcher->GetDescriptor();
1564 RTC_DCHECK(fd != INVALID_SOCKET);
1565 if (fd == INVALID_SOCKET) {
1566 return;
1567 }
1568
1569 struct epoll_event event = {0};
1570 int err = epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &event);
1571 RTC_DCHECK(err == 0 || errno == ENOENT);
1572 if (err == -1) {
1573 if (errno == ENOENT) {
1574 // Socket has already been closed.
Mirko Bonadei675513b2017-11-09 11:09:25 +01001575 RTC_LOG_E(LS_VERBOSE, EN, errno) << "epoll_ctl EPOLL_CTL_DEL";
jbauchde4db112017-05-31 13:09:18 -07001576 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001577 RTC_LOG_E(LS_ERROR, EN, errno) << "epoll_ctl EPOLL_CTL_DEL";
jbauchde4db112017-05-31 13:09:18 -07001578 }
1579 }
1580}
1581
1582void PhysicalSocketServer::UpdateEpoll(Dispatcher* pdispatcher) {
1583 RTC_DCHECK(epoll_fd_ != INVALID_SOCKET);
1584 int fd = pdispatcher->GetDescriptor();
1585 RTC_DCHECK(fd != INVALID_SOCKET);
1586 if (fd == INVALID_SOCKET) {
1587 return;
1588 }
1589
1590 struct epoll_event event = {0};
1591 event.events = GetEpollEvents(pdispatcher->GetRequestedEvents());
1592 event.data.ptr = pdispatcher;
1593 int err = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &event);
1594 RTC_DCHECK_EQ(err, 0);
1595 if (err == -1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001596 RTC_LOG_E(LS_ERROR, EN, errno) << "epoll_ctl EPOLL_CTL_MOD";
jbauchde4db112017-05-31 13:09:18 -07001597 }
1598}
1599
1600bool PhysicalSocketServer::WaitEpoll(int cmsWait) {
1601 RTC_DCHECK(epoll_fd_ != INVALID_SOCKET);
1602 int64_t tvWait = -1;
1603 int64_t tvStop = -1;
1604 if (cmsWait != kForever) {
1605 tvWait = cmsWait;
1606 tvStop = TimeAfter(cmsWait);
1607 }
1608
1609 if (epoll_events_.empty()) {
1610 // The initial space to receive events is created only if epoll is used.
1611 epoll_events_.resize(kInitialEpollEvents);
1612 }
1613
1614 fWait_ = true;
1615
1616 while (fWait_) {
1617 // Wait then call handlers as appropriate
1618 // < 0 means error
1619 // 0 means timeout
1620 // > 0 means count of descriptors ready
1621 int n = epoll_wait(epoll_fd_, &epoll_events_[0],
1622 static_cast<int>(epoll_events_.size()),
1623 static_cast<int>(tvWait));
1624 if (n < 0) {
1625 if (errno != EINTR) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001626 RTC_LOG_E(LS_ERROR, EN, errno) << "epoll";
jbauchde4db112017-05-31 13:09:18 -07001627 return false;
1628 }
1629 // Else ignore the error and keep going. If this EINTR was for one of the
1630 // signals managed by this PhysicalSocketServer, the
1631 // PosixSignalDeliveryDispatcher will be in the signaled state in the next
1632 // iteration.
1633 } else if (n == 0) {
1634 // If timeout, return success
1635 return true;
1636 } else {
1637 // We have signaled descriptors
1638 CritScope cr(&crit_);
1639 for (int i = 0; i < n; ++i) {
1640 const epoll_event& event = epoll_events_[i];
1641 Dispatcher* pdispatcher = static_cast<Dispatcher*>(event.data.ptr);
1642 if (dispatchers_.find(pdispatcher) == dispatchers_.end()) {
1643 // The dispatcher for this socket no longer exists.
1644 continue;
1645 }
1646
1647 bool readable = (event.events & (EPOLLIN | EPOLLPRI));
1648 bool writable = (event.events & EPOLLOUT);
1649 bool check_error = (event.events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP));
1650
1651 ProcessEvents(pdispatcher, readable, writable, check_error);
1652 }
1653 }
1654
1655 if (static_cast<size_t>(n) == epoll_events_.size() &&
1656 epoll_events_.size() < kMaxEpollEvents) {
1657 // We used the complete space to receive events, increase size for future
1658 // iterations.
1659 epoll_events_.resize(std::max(epoll_events_.size() * 2, kMaxEpollEvents));
1660 }
1661
1662 if (cmsWait != kForever) {
1663 tvWait = TimeDiff(tvStop, TimeMillis());
1664 if (tvWait < 0) {
1665 // Return success on timeout.
1666 return true;
1667 }
1668 }
1669 }
1670
1671 return true;
1672}
1673
1674bool PhysicalSocketServer::WaitPoll(int cmsWait, Dispatcher* dispatcher) {
1675 RTC_DCHECK(dispatcher);
1676 int64_t tvWait = -1;
1677 int64_t tvStop = -1;
1678 if (cmsWait != kForever) {
1679 tvWait = cmsWait;
1680 tvStop = TimeAfter(cmsWait);
1681 }
1682
1683 fWait_ = true;
1684
1685 struct pollfd fds = {0};
1686 int fd = dispatcher->GetDescriptor();
1687 fds.fd = fd;
1688
1689 while (fWait_) {
1690 uint32_t ff = dispatcher->GetRequestedEvents();
1691 fds.events = 0;
1692 if (ff & (DE_READ | DE_ACCEPT)) {
1693 fds.events |= POLLIN;
1694 }
1695 if (ff & (DE_WRITE | DE_CONNECT)) {
1696 fds.events |= POLLOUT;
1697 }
1698 fds.revents = 0;
1699
1700 // Wait then call handlers as appropriate
1701 // < 0 means error
1702 // 0 means timeout
1703 // > 0 means count of descriptors ready
1704 int n = poll(&fds, 1, static_cast<int>(tvWait));
1705 if (n < 0) {
1706 if (errno != EINTR) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001707 RTC_LOG_E(LS_ERROR, EN, errno) << "poll";
jbauchde4db112017-05-31 13:09:18 -07001708 return false;
1709 }
1710 // Else ignore the error and keep going. If this EINTR was for one of the
1711 // signals managed by this PhysicalSocketServer, the
1712 // PosixSignalDeliveryDispatcher will be in the signaled state in the next
1713 // iteration.
1714 } else if (n == 0) {
1715 // If timeout, return success
1716 return true;
1717 } else {
1718 // We have signaled descriptors (should only be the passed dispatcher).
1719 RTC_DCHECK_EQ(n, 1);
1720 RTC_DCHECK_EQ(fds.fd, fd);
1721
1722 bool readable = (fds.revents & (POLLIN | POLLPRI));
1723 bool writable = (fds.revents & POLLOUT);
1724 bool check_error = (fds.revents & (POLLRDHUP | POLLERR | POLLHUP));
1725
1726 ProcessEvents(dispatcher, readable, writable, check_error);
1727 }
1728
1729 if (cmsWait != kForever) {
1730 tvWait = TimeDiff(tvStop, TimeMillis());
1731 if (tvWait < 0) {
1732 // Return success on timeout.
1733 return true;
1734 }
1735 }
1736 }
1737
1738 return true;
1739}
1740
1741#endif // WEBRTC_USE_EPOLL
1742
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001743static void GlobalSignalHandler(int signum) {
1744 PosixSignalHandler::Instance()->OnPosixSignalReceived(signum);
1745}
1746
1747bool PhysicalSocketServer::SetPosixSignalHandler(int signum,
1748 void (*handler)(int)) {
1749 // If handler is SIG_IGN or SIG_DFL then clear our user-level handler,
1750 // otherwise set one.
1751 if (handler == SIG_IGN || handler == SIG_DFL) {
1752 if (!InstallSignal(signum, handler)) {
1753 return false;
1754 }
1755 if (signal_dispatcher_) {
1756 signal_dispatcher_->ClearHandler(signum);
1757 if (!signal_dispatcher_->HasHandlers()) {
1758 signal_dispatcher_.reset();
1759 }
1760 }
1761 } else {
1762 if (!signal_dispatcher_) {
1763 signal_dispatcher_.reset(new PosixSignalDispatcher(this));
1764 }
1765 signal_dispatcher_->SetHandler(signum, handler);
1766 if (!InstallSignal(signum, &GlobalSignalHandler)) {
1767 return false;
1768 }
1769 }
1770 return true;
1771}
1772
1773Dispatcher* PhysicalSocketServer::signal_dispatcher() {
1774 return signal_dispatcher_.get();
1775}
1776
1777bool PhysicalSocketServer::InstallSignal(int signum, void (*handler)(int)) {
1778 struct sigaction act;
1779 // It doesn't really matter what we set this mask to.
1780 if (sigemptyset(&act.sa_mask) != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001781 RTC_LOG_ERR(LS_ERROR) << "Couldn't set mask";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001782 return false;
1783 }
1784 act.sa_handler = handler;
1785#if !defined(__native_client__)
1786 // Use SA_RESTART so that our syscalls don't get EINTR, since we don't need it
1787 // and it's a nuisance. Though some syscalls still return EINTR and there's no
1788 // real standard for which ones. :(
1789 act.sa_flags = SA_RESTART;
1790#else
1791 act.sa_flags = 0;
1792#endif
deadbeef37f5ecf2017-02-27 14:06:41 -08001793 if (sigaction(signum, &act, nullptr) != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001794 RTC_LOG_ERR(LS_ERROR) << "Couldn't set sigaction";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001795 return false;
1796 }
1797 return true;
1798}
1799#endif // WEBRTC_POSIX
1800
1801#if defined(WEBRTC_WIN)
1802bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
Honghai Zhang82d78622016-05-06 11:29:15 -07001803 int64_t cmsTotal = cmsWait;
1804 int64_t cmsElapsed = 0;
1805 int64_t msStart = Time();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001806
1807 fWait_ = true;
1808 while (fWait_) {
1809 std::vector<WSAEVENT> events;
Yves Gerey665174f2018-06-19 15:03:05 +02001810 std::vector<Dispatcher*> event_owners;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001811
1812 events.push_back(socket_ev_);
1813
1814 {
1815 CritScope cr(&crit_);
jbauchde4db112017-05-31 13:09:18 -07001816 // TODO(jbauch): Support re-entrant waiting.
1817 RTC_DCHECK(!processing_dispatchers_);
1818
1819 // Calling "CheckSignalClose" might remove a closed dispatcher from the
1820 // set. This must be deferred to prevent invalidating the iterator.
1821 processing_dispatchers_ = true;
1822 for (Dispatcher* disp : dispatchers_) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001823 if (!process_io && (disp != signal_wakeup_))
1824 continue;
1825 SOCKET s = disp->GetSocket();
1826 if (disp->CheckSignalClose()) {
1827 // We just signalled close, don't poll this socket
1828 } else if (s != INVALID_SOCKET) {
Yves Gerey665174f2018-06-19 15:03:05 +02001829 WSAEventSelect(s, events[0],
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001830 FlagsToEvents(disp->GetRequestedEvents()));
1831 } else {
1832 events.push_back(disp->GetWSAEvent());
1833 event_owners.push_back(disp);
1834 }
1835 }
jbauchde4db112017-05-31 13:09:18 -07001836
1837 processing_dispatchers_ = false;
1838 // Process deferred dispatchers that have been added/removed while the
1839 // events were handled above.
1840 AddRemovePendingDispatchers();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001841 }
1842
1843 // Which is shorter, the delay wait or the asked wait?
1844
Honghai Zhang82d78622016-05-06 11:29:15 -07001845 int64_t cmsNext;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001846 if (cmsWait == kForever) {
1847 cmsNext = cmsWait;
1848 } else {
Honghai Zhang82d78622016-05-06 11:29:15 -07001849 cmsNext = std::max<int64_t>(0, cmsTotal - cmsElapsed);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001850 }
1851
1852 // Wait for one of the events to signal
Yves Gerey665174f2018-06-19 15:03:05 +02001853 DWORD dw =
1854 WSAWaitForMultipleEvents(static_cast<DWORD>(events.size()), &events[0],
1855 false, static_cast<DWORD>(cmsNext), false);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001856
1857 if (dw == WSA_WAIT_FAILED) {
1858 // Failed?
jbauch095ae152015-12-18 01:39:55 -08001859 // TODO(pthatcher): need a better strategy than this!
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001860 WSAGetLastError();
nissec80e7412017-01-11 05:56:46 -08001861 RTC_NOTREACHED();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001862 return false;
1863 } else if (dw == WSA_WAIT_TIMEOUT) {
1864 // Timeout?
1865 return true;
1866 } else {
1867 // Figure out which one it is and call it
1868 CritScope cr(&crit_);
1869 int index = dw - WSA_WAIT_EVENT_0;
1870 if (index > 0) {
Yves Gerey665174f2018-06-19 15:03:05 +02001871 --index; // The first event is the socket event
jbauchde4db112017-05-31 13:09:18 -07001872 Dispatcher* disp = event_owners[index];
1873 // The dispatcher could have been removed while waiting for events.
1874 if (dispatchers_.find(disp) != dispatchers_.end()) {
1875 disp->OnPreEvent(0);
1876 disp->OnEvent(0, 0);
1877 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001878 } else if (process_io) {
jbauchde4db112017-05-31 13:09:18 -07001879 processing_dispatchers_ = true;
1880 for (Dispatcher* disp : dispatchers_) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001881 SOCKET s = disp->GetSocket();
1882 if (s == INVALID_SOCKET)
1883 continue;
1884
1885 WSANETWORKEVENTS wsaEvents;
1886 int err = WSAEnumNetworkEvents(s, events[0], &wsaEvents);
1887 if (err == 0) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001888 {
1889 if ((wsaEvents.lNetworkEvents & FD_READ) &&
1890 wsaEvents.iErrorCode[FD_READ_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001891 RTC_LOG(WARNING)
1892 << "PhysicalSocketServer got FD_READ_BIT error "
1893 << wsaEvents.iErrorCode[FD_READ_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001894 }
1895 if ((wsaEvents.lNetworkEvents & FD_WRITE) &&
1896 wsaEvents.iErrorCode[FD_WRITE_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001897 RTC_LOG(WARNING)
1898 << "PhysicalSocketServer got FD_WRITE_BIT error "
1899 << wsaEvents.iErrorCode[FD_WRITE_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001900 }
1901 if ((wsaEvents.lNetworkEvents & FD_CONNECT) &&
1902 wsaEvents.iErrorCode[FD_CONNECT_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001903 RTC_LOG(WARNING)
1904 << "PhysicalSocketServer got FD_CONNECT_BIT error "
1905 << wsaEvents.iErrorCode[FD_CONNECT_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001906 }
1907 if ((wsaEvents.lNetworkEvents & FD_ACCEPT) &&
1908 wsaEvents.iErrorCode[FD_ACCEPT_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001909 RTC_LOG(WARNING)
1910 << "PhysicalSocketServer got FD_ACCEPT_BIT error "
1911 << wsaEvents.iErrorCode[FD_ACCEPT_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001912 }
1913 if ((wsaEvents.lNetworkEvents & FD_CLOSE) &&
1914 wsaEvents.iErrorCode[FD_CLOSE_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001915 RTC_LOG(WARNING)
1916 << "PhysicalSocketServer got FD_CLOSE_BIT error "
1917 << wsaEvents.iErrorCode[FD_CLOSE_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001918 }
1919 }
Peter Boström0c4e06b2015-10-07 12:23:21 +02001920 uint32_t ff = 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001921 int errcode = 0;
1922 if (wsaEvents.lNetworkEvents & FD_READ)
1923 ff |= DE_READ;
1924 if (wsaEvents.lNetworkEvents & FD_WRITE)
1925 ff |= DE_WRITE;
1926 if (wsaEvents.lNetworkEvents & FD_CONNECT) {
1927 if (wsaEvents.iErrorCode[FD_CONNECT_BIT] == 0) {
1928 ff |= DE_CONNECT;
1929 } else {
1930 ff |= DE_CLOSE;
1931 errcode = wsaEvents.iErrorCode[FD_CONNECT_BIT];
1932 }
1933 }
1934 if (wsaEvents.lNetworkEvents & FD_ACCEPT)
1935 ff |= DE_ACCEPT;
1936 if (wsaEvents.lNetworkEvents & FD_CLOSE) {
1937 ff |= DE_CLOSE;
1938 errcode = wsaEvents.iErrorCode[FD_CLOSE_BIT];
1939 }
1940 if (ff != 0) {
1941 disp->OnPreEvent(ff);
1942 disp->OnEvent(ff, errcode);
1943 }
1944 }
1945 }
jbauchde4db112017-05-31 13:09:18 -07001946
1947 processing_dispatchers_ = false;
1948 // Process deferred dispatchers that have been added/removed while the
1949 // events were handled above.
1950 AddRemovePendingDispatchers();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001951 }
1952
1953 // Reset the network event until new activity occurs
1954 WSAResetEvent(socket_ev_);
1955 }
1956
1957 // Break?
1958 if (!fWait_)
1959 break;
1960 cmsElapsed = TimeSince(msStart);
1961 if ((cmsWait != kForever) && (cmsElapsed >= cmsWait)) {
Yves Gerey665174f2018-06-19 15:03:05 +02001962 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001963 }
1964 }
1965
1966 // Done
1967 return true;
1968}
honghaizcec0a082016-01-15 14:49:09 -08001969#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001970
1971} // namespace rtc