blob: 2d328dd3505140c03fe283b4d89954d1df42ef63 [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
Yves Gerey665174f2018-06-19 15:03:05 +020027#include <sys/ioctl.h>
28#include <sys/select.h>
29#include <sys/time.h>
30#include <unistd.h>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000031#endif
32
33#if defined(WEBRTC_WIN)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000034#include <windows.h>
35#include <winsock2.h>
36#include <ws2tcpip.h>
37#undef SetPort
38#endif
39
Patrik Höglunda8005cf2017-12-13 16:05:42 +010040#include <errno.h>
41
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000042#include <algorithm>
43#include <map>
44
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020045#include "rtc_base/arraysize.h"
Steve Anton10542f22019-01-11 09:11:00 -080046#include "rtc_base/byte_order.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020047#include "rtc_base/checks.h"
48#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080049#include "rtc_base/network_monitor.h"
50#include "rtc_base/null_socket_server.h"
51#include "rtc_base/time_utils.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000052
Emilio Cobos Álvarez68065502019-05-29 15:30:32 +020053#if defined(WEBRTC_LINUX)
54#include <linux/sockios.h>
55#endif
56
Patrik Höglunda8005cf2017-12-13 16:05:42 +010057#if defined(WEBRTC_WIN)
58#define LAST_SYSTEM_ERROR (::GetLastError())
59#elif defined(__native_client__) && __native_client__
60#define LAST_SYSTEM_ERROR (0)
61#elif defined(WEBRTC_POSIX)
62#define LAST_SYSTEM_ERROR (errno)
63#endif // WEBRTC_WIN
64
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000065#if defined(WEBRTC_POSIX)
66#include <netinet/tcp.h> // for TCP_NODELAY
Yves Gerey665174f2018-06-19 15:03:05 +020067#define IP_MTU 14 // Until this is integrated from linux/in.h to netinet/in.h
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000068typedef void* SockOptArg;
Stefan Holmer9131efd2016-05-23 18:19:26 +020069
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000070#endif // WEBRTC_POSIX
71
Stefan Holmer3ebb3ef2016-05-23 20:26:11 +020072#if defined(WEBRTC_POSIX) && !defined(WEBRTC_MAC) && !defined(__native_client__)
73
Stefan Holmer9131efd2016-05-23 18:19:26 +020074int64_t GetSocketRecvTimestamp(int socket) {
75 struct timeval tv_ioctl;
76 int ret = ioctl(socket, SIOCGSTAMP, &tv_ioctl);
77 if (ret != 0)
78 return -1;
79 int64_t timestamp =
80 rtc::kNumMicrosecsPerSec * static_cast<int64_t>(tv_ioctl.tv_sec) +
81 static_cast<int64_t>(tv_ioctl.tv_usec);
82 return timestamp;
83}
84
85#else
86
87int64_t GetSocketRecvTimestamp(int socket) {
88 return -1;
89}
90#endif
91
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000092#if defined(WEBRTC_WIN)
93typedef char* SockOptArg;
94#endif
95
jbauchde4db112017-05-31 13:09:18 -070096#if defined(WEBRTC_USE_EPOLL)
97// POLLRDHUP / EPOLLRDHUP are only defined starting with Linux 2.6.17.
98#if !defined(POLLRDHUP)
99#define POLLRDHUP 0x2000
100#endif
101#if !defined(EPOLLRDHUP)
102#define EPOLLRDHUP 0x2000
103#endif
104#endif
105
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000106namespace rtc {
107
danilchapbebf54c2016-04-28 01:32:48 -0700108std::unique_ptr<SocketServer> SocketServer::CreateDefault() {
109#if defined(__native_client__)
110 return std::unique_ptr<SocketServer>(new rtc::NullSocketServer);
111#else
112 return std::unique_ptr<SocketServer>(new rtc::PhysicalSocketServer);
113#endif
114}
115
jbauch095ae152015-12-18 01:39:55 -0800116PhysicalSocket::PhysicalSocket(PhysicalSocketServer* ss, SOCKET s)
Yves Gerey665174f2018-06-19 15:03:05 +0200117 : ss_(ss),
118 s_(s),
119 error_(0),
120 state_((s == INVALID_SOCKET) ? CS_CLOSED : CS_CONNECTED),
121 resolver_(nullptr) {
jbauch095ae152015-12-18 01:39:55 -0800122 if (s_ != INVALID_SOCKET) {
jbauch577f5dc2017-05-17 16:32:26 -0700123 SetEnabledEvents(DE_READ | DE_WRITE);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000124
jbauch095ae152015-12-18 01:39:55 -0800125 int type = SOCK_STREAM;
126 socklen_t len = sizeof(type);
nissec16fa5e2017-02-07 07:18:43 -0800127 const int res =
128 getsockopt(s_, SOL_SOCKET, SO_TYPE, (SockOptArg)&type, &len);
129 RTC_DCHECK_EQ(0, res);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000130 udp_ = (SOCK_DGRAM == type);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000131 }
jbauch095ae152015-12-18 01:39:55 -0800132}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000133
jbauch095ae152015-12-18 01:39:55 -0800134PhysicalSocket::~PhysicalSocket() {
135 Close();
136}
137
138bool PhysicalSocket::Create(int family, int type) {
139 Close();
140 s_ = ::socket(family, type, 0);
141 udp_ = (SOCK_DGRAM == type);
Taylor Brandstetterecd6fc82020-02-05 17:26:37 -0800142 family_ = family;
jbauch095ae152015-12-18 01:39:55 -0800143 UpdateLastError();
jbauch577f5dc2017-05-17 16:32:26 -0700144 if (udp_) {
145 SetEnabledEvents(DE_READ | DE_WRITE);
146 }
jbauch095ae152015-12-18 01:39:55 -0800147 return s_ != INVALID_SOCKET;
148}
149
150SocketAddress PhysicalSocket::GetLocalAddress() const {
Mirko Bonadei108a2f02019-11-20 19:43:38 +0100151 sockaddr_storage addr_storage = {};
jbauch095ae152015-12-18 01:39:55 -0800152 socklen_t addrlen = sizeof(addr_storage);
153 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
154 int result = ::getsockname(s_, addr, &addrlen);
155 SocketAddress address;
156 if (result >= 0) {
157 SocketAddressFromSockAddrStorage(addr_storage, &address);
158 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100159 RTC_LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket="
160 << s_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000161 }
jbauch095ae152015-12-18 01:39:55 -0800162 return address;
163}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000164
jbauch095ae152015-12-18 01:39:55 -0800165SocketAddress PhysicalSocket::GetRemoteAddress() const {
Mirko Bonadei108a2f02019-11-20 19:43:38 +0100166 sockaddr_storage addr_storage = {};
jbauch095ae152015-12-18 01:39:55 -0800167 socklen_t addrlen = sizeof(addr_storage);
168 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
169 int result = ::getpeername(s_, addr, &addrlen);
170 SocketAddress address;
171 if (result >= 0) {
172 SocketAddressFromSockAddrStorage(addr_storage, &address);
173 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100174 RTC_LOG(LS_WARNING)
175 << "GetRemoteAddress: unable to get remote addr, socket=" << s_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000176 }
jbauch095ae152015-12-18 01:39:55 -0800177 return address;
178}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000179
jbauch095ae152015-12-18 01:39:55 -0800180int PhysicalSocket::Bind(const SocketAddress& bind_addr) {
deadbeefc874d122017-02-13 15:41:59 -0800181 SocketAddress copied_bind_addr = bind_addr;
182 // If a network binder is available, use it to bind a socket to an interface
183 // instead of bind(), since this is more reliable on an OS with a weak host
184 // model.
deadbeef9ffa13f2017-02-21 16:18:00 -0800185 if (ss_->network_binder() && !bind_addr.IsAnyIP()) {
deadbeefc874d122017-02-13 15:41:59 -0800186 NetworkBindingResult result =
187 ss_->network_binder()->BindSocketToNetwork(s_, bind_addr.ipaddr());
188 if (result == NetworkBindingResult::SUCCESS) {
189 // Since the network binder handled binding the socket to the desired
190 // network interface, we don't need to (and shouldn't) include an IP in
191 // the bind() call; bind() just needs to assign a port.
192 copied_bind_addr.SetIP(GetAnyIP(copied_bind_addr.ipaddr().family()));
193 } else if (result == NetworkBindingResult::NOT_IMPLEMENTED) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100194 RTC_LOG(LS_INFO) << "Can't bind socket to network because "
195 "network binding is not implemented for this OS.";
deadbeefc874d122017-02-13 15:41:59 -0800196 } else {
197 if (bind_addr.IsLoopbackIP()) {
198 // If we couldn't bind to a loopback IP (which should only happen in
199 // test scenarios), continue on. This may be expected behavior.
Paulina Hensmanb239a2e2020-03-31 16:16:11 +0200200 RTC_LOG(LS_VERBOSE) << "Binding socket to loopback address"
Mirko Bonadei675513b2017-11-09 11:09:25 +0100201 << " failed; result: " << static_cast<int>(result);
deadbeefc874d122017-02-13 15:41:59 -0800202 } else {
Paulina Hensmanb239a2e2020-03-31 16:16:11 +0200203 RTC_LOG(LS_WARNING) << "Binding socket to network address"
Mirko Bonadei675513b2017-11-09 11:09:25 +0100204 << " failed; result: " << static_cast<int>(result);
deadbeefc874d122017-02-13 15:41:59 -0800205 // If a network binding was attempted and failed, we should stop here
206 // and not try to use the socket. Otherwise, we may end up sending
207 // packets with an invalid source address.
208 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7026
209 return -1;
210 }
211 }
212 }
jbauch095ae152015-12-18 01:39:55 -0800213 sockaddr_storage addr_storage;
deadbeefc874d122017-02-13 15:41:59 -0800214 size_t len = copied_bind_addr.ToSockAddrStorage(&addr_storage);
jbauch095ae152015-12-18 01:39:55 -0800215 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
216 int err = ::bind(s_, addr, static_cast<int>(len));
217 UpdateLastError();
tfarinaa41ab932015-10-30 16:08:48 -0700218#if !defined(NDEBUG)
jbauch095ae152015-12-18 01:39:55 -0800219 if (0 == err) {
220 dbg_addr_ = "Bound @ ";
221 dbg_addr_.append(GetLocalAddress().ToString());
222 }
tfarinaa41ab932015-10-30 16:08:48 -0700223#endif
jbauch095ae152015-12-18 01:39:55 -0800224 return err;
225}
226
227int PhysicalSocket::Connect(const SocketAddress& addr) {
228 // TODO(pthatcher): Implicit creation is required to reconnect...
229 // ...but should we make it more explicit?
230 if (state_ != CS_CLOSED) {
231 SetError(EALREADY);
232 return SOCKET_ERROR;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000233 }
jbauch095ae152015-12-18 01:39:55 -0800234 if (addr.IsUnresolvedIP()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100235 RTC_LOG(LS_VERBOSE) << "Resolving addr in PhysicalSocket::Connect";
jbauch095ae152015-12-18 01:39:55 -0800236 resolver_ = new AsyncResolver();
237 resolver_->SignalDone.connect(this, &PhysicalSocket::OnResolveResult);
238 resolver_->Start(addr);
239 state_ = CS_CONNECTING;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000240 return 0;
241 }
242
jbauch095ae152015-12-18 01:39:55 -0800243 return DoConnect(addr);
244}
245
246int PhysicalSocket::DoConnect(const SocketAddress& connect_addr) {
Yves Gerey665174f2018-06-19 15:03:05 +0200247 if ((s_ == INVALID_SOCKET) && !Create(connect_addr.family(), SOCK_STREAM)) {
jbauch095ae152015-12-18 01:39:55 -0800248 return SOCKET_ERROR;
249 }
250 sockaddr_storage addr_storage;
251 size_t len = connect_addr.ToSockAddrStorage(&addr_storage);
252 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
253 int err = ::connect(s_, addr, static_cast<int>(len));
254 UpdateLastError();
jbauch577f5dc2017-05-17 16:32:26 -0700255 uint8_t events = DE_READ | DE_WRITE;
jbauch095ae152015-12-18 01:39:55 -0800256 if (err == 0) {
257 state_ = CS_CONNECTED;
258 } else if (IsBlockingError(GetError())) {
259 state_ = CS_CONNECTING;
jbauch577f5dc2017-05-17 16:32:26 -0700260 events |= DE_CONNECT;
jbauch095ae152015-12-18 01:39:55 -0800261 } else {
262 return SOCKET_ERROR;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000263 }
264
jbauch577f5dc2017-05-17 16:32:26 -0700265 EnableEvents(events);
jbauch095ae152015-12-18 01:39:55 -0800266 return 0;
267}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000268
jbauch095ae152015-12-18 01:39:55 -0800269int PhysicalSocket::GetError() const {
270 CritScope cs(&crit_);
271 return error_;
272}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000273
jbauch095ae152015-12-18 01:39:55 -0800274void PhysicalSocket::SetError(int error) {
275 CritScope cs(&crit_);
276 error_ = error;
277}
278
279AsyncSocket::ConnState PhysicalSocket::GetState() const {
280 return state_;
281}
282
283int PhysicalSocket::GetOption(Option opt, int* value) {
284 int slevel;
285 int sopt;
286 if (TranslateOption(opt, &slevel, &sopt) == -1)
287 return -1;
288 socklen_t optlen = sizeof(*value);
289 int ret = ::getsockopt(s_, slevel, sopt, (SockOptArg)value, &optlen);
Taylor Brandstetterecd6fc82020-02-05 17:26:37 -0800290 if (ret == -1) {
291 return -1;
292 }
293 if (opt == OPT_DONTFRAGMENT) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000294#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
jbauch095ae152015-12-18 01:39:55 -0800295 *value = (*value != IP_PMTUDISC_DONT) ? 1 : 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000296#endif
Taylor Brandstetterecd6fc82020-02-05 17:26:37 -0800297 } else if (opt == OPT_DSCP) {
298#if defined(WEBRTC_POSIX)
299 // unshift DSCP value to get six most significant bits of IP DiffServ field
300 *value >>= 2;
301#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000302 }
jbauch095ae152015-12-18 01:39:55 -0800303 return ret;
304}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000305
jbauch095ae152015-12-18 01:39:55 -0800306int PhysicalSocket::SetOption(Option opt, int value) {
307 int slevel;
308 int sopt;
309 if (TranslateOption(opt, &slevel, &sopt) == -1)
310 return -1;
311 if (opt == OPT_DONTFRAGMENT) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000312#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
jbauch095ae152015-12-18 01:39:55 -0800313 value = (value) ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000314#endif
Taylor Brandstetterecd6fc82020-02-05 17:26:37 -0800315 } else if (opt == OPT_DSCP) {
316#if defined(WEBRTC_POSIX)
317 // shift DSCP value to fit six most significant bits of IP DiffServ field
318 value <<= 2;
319#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000320 }
Taylor Brandstetterecd6fc82020-02-05 17:26:37 -0800321#if defined(WEBRTC_POSIX)
322 if (sopt == IPV6_TCLASS) {
323 // Set the IPv4 option in all cases to support dual-stack sockets.
324 ::setsockopt(s_, IPPROTO_IP, IP_TOS, (SockOptArg)&value, sizeof(value));
325 }
326#endif
jbauch095ae152015-12-18 01:39:55 -0800327 return ::setsockopt(s_, slevel, sopt, (SockOptArg)&value, sizeof(value));
328}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000329
jbauch095ae152015-12-18 01:39:55 -0800330int PhysicalSocket::Send(const void* pv, size_t cb) {
Yves Gerey665174f2018-06-19 15:03:05 +0200331 int sent = DoSend(
332 s_, reinterpret_cast<const char*>(pv), static_cast<int>(cb),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000333#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
jbauch095ae152015-12-18 01:39:55 -0800334 // Suppress SIGPIPE. Without this, attempting to send on a socket whose
335 // other end is closed will result in a SIGPIPE signal being raised to
336 // our process, which by default will terminate the process, which we
337 // don't want. By specifying this flag, we'll just get the error EPIPE
338 // instead and can handle the error gracefully.
339 MSG_NOSIGNAL
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000340#else
jbauch095ae152015-12-18 01:39:55 -0800341 0
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000342#endif
Jonas Olssona4d87372019-07-05 19:08:33 +0200343 );
jbauch095ae152015-12-18 01:39:55 -0800344 UpdateLastError();
345 MaybeRemapSendError();
346 // We have seen minidumps where this may be false.
nisseede5da42017-01-12 05:15:36 -0800347 RTC_DCHECK(sent <= static_cast<int>(cb));
jbauchf2a2bf42016-02-03 16:45:32 -0800348 if ((sent > 0 && sent < static_cast<int>(cb)) ||
349 (sent < 0 && IsBlockingError(GetError()))) {
jbauch577f5dc2017-05-17 16:32:26 -0700350 EnableEvents(DE_WRITE);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000351 }
jbauch095ae152015-12-18 01:39:55 -0800352 return sent;
353}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000354
jbauch095ae152015-12-18 01:39:55 -0800355int PhysicalSocket::SendTo(const void* buffer,
356 size_t length,
357 const SocketAddress& addr) {
358 sockaddr_storage saddr;
359 size_t len = addr.ToSockAddrStorage(&saddr);
Yves Gerey665174f2018-06-19 15:03:05 +0200360 int sent =
361 DoSendTo(s_, static_cast<const char*>(buffer), static_cast<int>(length),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000362#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
Yves Gerey665174f2018-06-19 15:03:05 +0200363 // Suppress SIGPIPE. See above for explanation.
364 MSG_NOSIGNAL,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000365#else
Yves Gerey665174f2018-06-19 15:03:05 +0200366 0,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000367#endif
Yves Gerey665174f2018-06-19 15:03:05 +0200368 reinterpret_cast<sockaddr*>(&saddr), static_cast<int>(len));
jbauch095ae152015-12-18 01:39:55 -0800369 UpdateLastError();
370 MaybeRemapSendError();
371 // We have seen minidumps where this may be false.
nisseede5da42017-01-12 05:15:36 -0800372 RTC_DCHECK(sent <= static_cast<int>(length));
jbauchf2a2bf42016-02-03 16:45:32 -0800373 if ((sent > 0 && sent < static_cast<int>(length)) ||
374 (sent < 0 && IsBlockingError(GetError()))) {
jbauch577f5dc2017-05-17 16:32:26 -0700375 EnableEvents(DE_WRITE);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000376 }
jbauch095ae152015-12-18 01:39:55 -0800377 return sent;
378}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000379
Stefan Holmer9131efd2016-05-23 18:19:26 +0200380int PhysicalSocket::Recv(void* buffer, size_t length, int64_t* timestamp) {
Yves Gerey665174f2018-06-19 15:03:05 +0200381 int received =
382 ::recv(s_, static_cast<char*>(buffer), static_cast<int>(length), 0);
jbauch095ae152015-12-18 01:39:55 -0800383 if ((received == 0) && (length != 0)) {
384 // Note: on graceful shutdown, recv can return 0. In this case, we
385 // pretend it is blocking, and then signal close, so that simplifying
386 // assumptions can be made about Recv.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100387 RTC_LOG(LS_WARNING) << "EOF from socket; deferring close event";
jbauch095ae152015-12-18 01:39:55 -0800388 // Must turn this back on so that the select() loop will notice the close
389 // event.
jbauch577f5dc2017-05-17 16:32:26 -0700390 EnableEvents(DE_READ);
jbauch095ae152015-12-18 01:39:55 -0800391 SetError(EWOULDBLOCK);
392 return SOCKET_ERROR;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000393 }
Stefan Holmer9131efd2016-05-23 18:19:26 +0200394 if (timestamp) {
395 *timestamp = GetSocketRecvTimestamp(s_);
396 }
jbauch095ae152015-12-18 01:39:55 -0800397 UpdateLastError();
398 int error = GetError();
399 bool success = (received >= 0) || IsBlockingError(error);
400 if (udp_ || success) {
jbauch577f5dc2017-05-17 16:32:26 -0700401 EnableEvents(DE_READ);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000402 }
jbauch095ae152015-12-18 01:39:55 -0800403 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100404 RTC_LOG_F(LS_VERBOSE) << "Error = " << error;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000405 }
jbauch095ae152015-12-18 01:39:55 -0800406 return received;
407}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000408
jbauch095ae152015-12-18 01:39:55 -0800409int PhysicalSocket::RecvFrom(void* buffer,
410 size_t length,
Stefan Holmer9131efd2016-05-23 18:19:26 +0200411 SocketAddress* out_addr,
412 int64_t* timestamp) {
jbauch095ae152015-12-18 01:39:55 -0800413 sockaddr_storage addr_storage;
414 socklen_t addr_len = sizeof(addr_storage);
415 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
416 int received = ::recvfrom(s_, static_cast<char*>(buffer),
417 static_cast<int>(length), 0, addr, &addr_len);
Stefan Holmer9131efd2016-05-23 18:19:26 +0200418 if (timestamp) {
419 *timestamp = GetSocketRecvTimestamp(s_);
420 }
jbauch095ae152015-12-18 01:39:55 -0800421 UpdateLastError();
422 if ((received >= 0) && (out_addr != nullptr))
423 SocketAddressFromSockAddrStorage(addr_storage, out_addr);
424 int error = GetError();
425 bool success = (received >= 0) || IsBlockingError(error);
426 if (udp_ || success) {
jbauch577f5dc2017-05-17 16:32:26 -0700427 EnableEvents(DE_READ);
jbauch095ae152015-12-18 01:39:55 -0800428 }
429 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100430 RTC_LOG_F(LS_VERBOSE) << "Error = " << error;
jbauch095ae152015-12-18 01:39:55 -0800431 }
432 return received;
433}
434
435int PhysicalSocket::Listen(int backlog) {
436 int err = ::listen(s_, backlog);
437 UpdateLastError();
438 if (err == 0) {
439 state_ = CS_CONNECTING;
jbauch577f5dc2017-05-17 16:32:26 -0700440 EnableEvents(DE_ACCEPT);
jbauch095ae152015-12-18 01:39:55 -0800441#if !defined(NDEBUG)
442 dbg_addr_ = "Listening @ ";
443 dbg_addr_.append(GetLocalAddress().ToString());
444#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000445 }
jbauch095ae152015-12-18 01:39:55 -0800446 return err;
447}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000448
jbauch095ae152015-12-18 01:39:55 -0800449AsyncSocket* PhysicalSocket::Accept(SocketAddress* out_addr) {
450 // Always re-subscribe DE_ACCEPT to make sure new incoming connections will
451 // trigger an event even if DoAccept returns an error here.
jbauch577f5dc2017-05-17 16:32:26 -0700452 EnableEvents(DE_ACCEPT);
jbauch095ae152015-12-18 01:39:55 -0800453 sockaddr_storage addr_storage;
454 socklen_t addr_len = sizeof(addr_storage);
455 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
456 SOCKET s = DoAccept(s_, addr, &addr_len);
457 UpdateLastError();
458 if (s == INVALID_SOCKET)
459 return nullptr;
460 if (out_addr != nullptr)
461 SocketAddressFromSockAddrStorage(addr_storage, out_addr);
462 return ss_->WrapSocket(s);
463}
464
465int PhysicalSocket::Close() {
466 if (s_ == INVALID_SOCKET)
467 return 0;
468 int err = ::closesocket(s_);
469 UpdateLastError();
470 s_ = INVALID_SOCKET;
471 state_ = CS_CLOSED;
jbauch577f5dc2017-05-17 16:32:26 -0700472 SetEnabledEvents(0);
jbauch095ae152015-12-18 01:39:55 -0800473 if (resolver_) {
474 resolver_->Destroy(false);
475 resolver_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000476 }
jbauch095ae152015-12-18 01:39:55 -0800477 return err;
478}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000479
jbauch095ae152015-12-18 01:39:55 -0800480SOCKET PhysicalSocket::DoAccept(SOCKET socket,
481 sockaddr* addr,
482 socklen_t* addrlen) {
483 return ::accept(socket, addr, addrlen);
484}
485
jbauchf2a2bf42016-02-03 16:45:32 -0800486int PhysicalSocket::DoSend(SOCKET socket, const char* buf, int len, int flags) {
487 return ::send(socket, buf, len, flags);
488}
489
490int PhysicalSocket::DoSendTo(SOCKET socket,
491 const char* buf,
492 int len,
493 int flags,
494 const struct sockaddr* dest_addr,
495 socklen_t addrlen) {
496 return ::sendto(socket, buf, len, flags, dest_addr, addrlen);
497}
498
jbauch095ae152015-12-18 01:39:55 -0800499void PhysicalSocket::OnResolveResult(AsyncResolverInterface* resolver) {
500 if (resolver != resolver_) {
501 return;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000502 }
503
jbauch095ae152015-12-18 01:39:55 -0800504 int error = resolver_->GetError();
505 if (error == 0) {
506 error = DoConnect(resolver_->address());
507 } else {
508 Close();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000509 }
510
jbauch095ae152015-12-18 01:39:55 -0800511 if (error) {
512 SetError(error);
513 SignalCloseEvent(this, error);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000514 }
jbauch095ae152015-12-18 01:39:55 -0800515}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000516
jbauch095ae152015-12-18 01:39:55 -0800517void PhysicalSocket::UpdateLastError() {
Patrik Höglunda8005cf2017-12-13 16:05:42 +0100518 SetError(LAST_SYSTEM_ERROR);
jbauch095ae152015-12-18 01:39:55 -0800519}
520
521void PhysicalSocket::MaybeRemapSendError() {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000522#if defined(WEBRTC_MAC)
jbauch095ae152015-12-18 01:39:55 -0800523 // https://developer.apple.com/library/mac/documentation/Darwin/
524 // Reference/ManPages/man2/sendto.2.html
525 // ENOBUFS - The output queue for a network interface is full.
526 // This generally indicates that the interface has stopped sending,
527 // but may be caused by transient congestion.
528 if (GetError() == ENOBUFS) {
529 SetError(EWOULDBLOCK);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000530 }
jbauch095ae152015-12-18 01:39:55 -0800531#endif
532}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000533
jbauch577f5dc2017-05-17 16:32:26 -0700534void PhysicalSocket::SetEnabledEvents(uint8_t events) {
535 enabled_events_ = events;
536}
537
538void PhysicalSocket::EnableEvents(uint8_t events) {
539 enabled_events_ |= events;
540}
541
542void PhysicalSocket::DisableEvents(uint8_t events) {
543 enabled_events_ &= ~events;
544}
545
jbauch095ae152015-12-18 01:39:55 -0800546int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
547 switch (opt) {
548 case OPT_DONTFRAGMENT:
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000549#if defined(WEBRTC_WIN)
jbauch095ae152015-12-18 01:39:55 -0800550 *slevel = IPPROTO_IP;
551 *sopt = IP_DONTFRAGMENT;
552 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000553#elif defined(WEBRTC_MAC) || defined(BSD) || defined(__native_client__)
Mirko Bonadei675513b2017-11-09 11:09:25 +0100554 RTC_LOG(LS_WARNING) << "Socket::OPT_DONTFRAGMENT not supported.";
jbauch095ae152015-12-18 01:39:55 -0800555 return -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000556#elif defined(WEBRTC_POSIX)
jbauch095ae152015-12-18 01:39:55 -0800557 *slevel = IPPROTO_IP;
558 *sopt = IP_MTU_DISCOVER;
559 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000560#endif
jbauch095ae152015-12-18 01:39:55 -0800561 case OPT_RCVBUF:
562 *slevel = SOL_SOCKET;
563 *sopt = SO_RCVBUF;
564 break;
565 case OPT_SNDBUF:
566 *slevel = SOL_SOCKET;
567 *sopt = SO_SNDBUF;
568 break;
569 case OPT_NODELAY:
570 *slevel = IPPROTO_TCP;
571 *sopt = TCP_NODELAY;
572 break;
573 case OPT_DSCP:
Taylor Brandstetterecd6fc82020-02-05 17:26:37 -0800574#if defined(WEBRTC_POSIX)
575 if (family_ == AF_INET6) {
576 *slevel = IPPROTO_IPV6;
577 *sopt = IPV6_TCLASS;
578 } else {
579 *slevel = IPPROTO_IP;
580 *sopt = IP_TOS;
581 }
582 break;
583#else
Mirko Bonadei675513b2017-11-09 11:09:25 +0100584 RTC_LOG(LS_WARNING) << "Socket::OPT_DSCP not supported.";
jbauch095ae152015-12-18 01:39:55 -0800585 return -1;
Taylor Brandstetterecd6fc82020-02-05 17:26:37 -0800586#endif
jbauch095ae152015-12-18 01:39:55 -0800587 case OPT_RTP_SENDTIME_EXTN_ID:
588 return -1; // No logging is necessary as this not a OS socket option.
589 default:
nissec80e7412017-01-11 05:56:46 -0800590 RTC_NOTREACHED();
jbauch095ae152015-12-18 01:39:55 -0800591 return -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000592 }
jbauch095ae152015-12-18 01:39:55 -0800593 return 0;
594}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000595
Yves Gerey665174f2018-06-19 15:03:05 +0200596SocketDispatcher::SocketDispatcher(PhysicalSocketServer* ss)
jbauch4331fcd2016-01-06 22:20:28 -0800597#if defined(WEBRTC_WIN)
Yves Gerey665174f2018-06-19 15:03:05 +0200598 : PhysicalSocket(ss),
599 id_(0),
600 signal_close_(false)
jbauch4331fcd2016-01-06 22:20:28 -0800601#else
Yves Gerey665174f2018-06-19 15:03:05 +0200602 : PhysicalSocket(ss)
jbauch4331fcd2016-01-06 22:20:28 -0800603#endif
604{
605}
606
Yves Gerey665174f2018-06-19 15:03:05 +0200607SocketDispatcher::SocketDispatcher(SOCKET s, PhysicalSocketServer* ss)
jbauch4331fcd2016-01-06 22:20:28 -0800608#if defined(WEBRTC_WIN)
Yves Gerey665174f2018-06-19 15:03:05 +0200609 : PhysicalSocket(ss, s),
610 id_(0),
611 signal_close_(false)
jbauch4331fcd2016-01-06 22:20:28 -0800612#else
Yves Gerey665174f2018-06-19 15:03:05 +0200613 : PhysicalSocket(ss, s)
jbauch4331fcd2016-01-06 22:20:28 -0800614#endif
615{
616}
617
618SocketDispatcher::~SocketDispatcher() {
619 Close();
620}
621
622bool SocketDispatcher::Initialize() {
nisseede5da42017-01-12 05:15:36 -0800623 RTC_DCHECK(s_ != INVALID_SOCKET);
Yves Gerey665174f2018-06-19 15:03:05 +0200624// Must be a non-blocking
jbauch4331fcd2016-01-06 22:20:28 -0800625#if defined(WEBRTC_WIN)
626 u_long argp = 1;
627 ioctlsocket(s_, FIONBIO, &argp);
628#elif defined(WEBRTC_POSIX)
629 fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK);
630#endif
deadbeefeae45642017-05-26 16:27:09 -0700631#if defined(WEBRTC_IOS)
632 // iOS may kill sockets when the app is moved to the background
633 // (specifically, if the app doesn't use the "voip" UIBackgroundMode). When
634 // we attempt to write to such a socket, SIGPIPE will be raised, which by
635 // default will terminate the process, which we don't want. By specifying
636 // this socket option, SIGPIPE will be disabled for the socket.
637 int value = 1;
638 ::setsockopt(s_, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value));
639#endif
jbauch4331fcd2016-01-06 22:20:28 -0800640 ss_->Add(this);
641 return true;
642}
643
644bool SocketDispatcher::Create(int type) {
645 return Create(AF_INET, type);
646}
647
648bool SocketDispatcher::Create(int family, int type) {
649 // Change the socket to be non-blocking.
650 if (!PhysicalSocket::Create(family, type))
651 return false;
652
653 if (!Initialize())
654 return false;
655
656#if defined(WEBRTC_WIN)
Yves Gerey665174f2018-06-19 15:03:05 +0200657 do {
658 id_ = ++next_id_;
659 } while (id_ == 0);
jbauch4331fcd2016-01-06 22:20:28 -0800660#endif
661 return true;
662}
663
664#if defined(WEBRTC_WIN)
665
666WSAEVENT SocketDispatcher::GetWSAEvent() {
667 return WSA_INVALID_EVENT;
668}
669
670SOCKET SocketDispatcher::GetSocket() {
671 return s_;
672}
673
674bool SocketDispatcher::CheckSignalClose() {
675 if (!signal_close_)
676 return false;
677
678 char ch;
679 if (recv(s_, &ch, 1, MSG_PEEK) > 0)
680 return false;
681
682 state_ = CS_CLOSED;
683 signal_close_ = false;
684 SignalCloseEvent(this, signal_err_);
685 return true;
686}
687
688int SocketDispatcher::next_id_ = 0;
689
690#elif defined(WEBRTC_POSIX)
691
692int SocketDispatcher::GetDescriptor() {
693 return s_;
694}
695
696bool SocketDispatcher::IsDescriptorClosed() {
deadbeeffaedf7f2017-02-09 15:09:22 -0800697 if (udp_) {
698 // The MSG_PEEK trick doesn't work for UDP, since (at least in some
699 // circumstances) it requires reading an entire UDP packet, which would be
700 // bad for performance here. So, just check whether |s_| has been closed,
701 // which should be sufficient.
702 return s_ == INVALID_SOCKET;
703 }
jbauch4331fcd2016-01-06 22:20:28 -0800704 // We don't have a reliable way of distinguishing end-of-stream
705 // from readability. So test on each readable call. Is this
706 // inefficient? Probably.
707 char ch;
708 ssize_t res = ::recv(s_, &ch, 1, MSG_PEEK);
709 if (res > 0) {
710 // Data available, so not closed.
711 return false;
712 } else if (res == 0) {
713 // EOF, so closed.
714 return true;
715 } else { // error
716 switch (errno) {
717 // Returned if we've already closed s_.
718 case EBADF:
719 // Returned during ungraceful peer shutdown.
720 case ECONNRESET:
721 return true;
deadbeeffaedf7f2017-02-09 15:09:22 -0800722 // The normal blocking error; don't log anything.
723 case EWOULDBLOCK:
724 // Interrupted system call.
725 case EINTR:
726 return false;
jbauch4331fcd2016-01-06 22:20:28 -0800727 default:
728 // Assume that all other errors are just blocking errors, meaning the
729 // connection is still good but we just can't read from it right now.
730 // This should only happen when connecting (and at most once), because
731 // in all other cases this function is only called if the file
732 // descriptor is already known to be in the readable state. However,
733 // it's not necessary a problem if we spuriously interpret a
734 // "connection lost"-type error as a blocking error, because typically
735 // the next recv() will get EOF, so we'll still eventually notice that
736 // the socket is closed.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100737 RTC_LOG_ERR(LS_WARNING) << "Assuming benign blocking error";
jbauch4331fcd2016-01-06 22:20:28 -0800738 return false;
739 }
740 }
741}
742
Yves Gerey665174f2018-06-19 15:03:05 +0200743#endif // WEBRTC_POSIX
jbauch4331fcd2016-01-06 22:20:28 -0800744
745uint32_t SocketDispatcher::GetRequestedEvents() {
jbauch577f5dc2017-05-17 16:32:26 -0700746 return enabled_events();
jbauch4331fcd2016-01-06 22:20:28 -0800747}
748
749void SocketDispatcher::OnPreEvent(uint32_t ff) {
750 if ((ff & DE_CONNECT) != 0)
751 state_ = CS_CONNECTED;
752
753#if defined(WEBRTC_WIN)
Yves Gerey665174f2018-06-19 15:03:05 +0200754// We set CS_CLOSED from CheckSignalClose.
jbauch4331fcd2016-01-06 22:20:28 -0800755#elif defined(WEBRTC_POSIX)
756 if ((ff & DE_CLOSE) != 0)
757 state_ = CS_CLOSED;
758#endif
759}
760
761#if defined(WEBRTC_WIN)
762
763void SocketDispatcher::OnEvent(uint32_t ff, int err) {
764 int cache_id = id_;
765 // Make sure we deliver connect/accept first. Otherwise, consumers may see
766 // something like a READ followed by a CONNECT, which would be odd.
767 if (((ff & DE_CONNECT) != 0) && (id_ == cache_id)) {
768 if (ff != DE_CONNECT)
Mirko Bonadei675513b2017-11-09 11:09:25 +0100769 RTC_LOG(LS_VERBOSE) << "Signalled with DE_CONNECT: " << ff;
jbauch577f5dc2017-05-17 16:32:26 -0700770 DisableEvents(DE_CONNECT);
jbauch4331fcd2016-01-06 22:20:28 -0800771#if !defined(NDEBUG)
772 dbg_addr_ = "Connected @ ";
773 dbg_addr_.append(GetRemoteAddress().ToString());
774#endif
775 SignalConnectEvent(this);
776 }
777 if (((ff & DE_ACCEPT) != 0) && (id_ == cache_id)) {
jbauch577f5dc2017-05-17 16:32:26 -0700778 DisableEvents(DE_ACCEPT);
jbauch4331fcd2016-01-06 22:20:28 -0800779 SignalReadEvent(this);
780 }
781 if ((ff & DE_READ) != 0) {
jbauch577f5dc2017-05-17 16:32:26 -0700782 DisableEvents(DE_READ);
jbauch4331fcd2016-01-06 22:20:28 -0800783 SignalReadEvent(this);
784 }
785 if (((ff & DE_WRITE) != 0) && (id_ == cache_id)) {
jbauch577f5dc2017-05-17 16:32:26 -0700786 DisableEvents(DE_WRITE);
jbauch4331fcd2016-01-06 22:20:28 -0800787 SignalWriteEvent(this);
788 }
789 if (((ff & DE_CLOSE) != 0) && (id_ == cache_id)) {
790 signal_close_ = true;
791 signal_err_ = err;
792 }
793}
794
795#elif defined(WEBRTC_POSIX)
796
797void SocketDispatcher::OnEvent(uint32_t ff, int err) {
jbauchde4db112017-05-31 13:09:18 -0700798#if defined(WEBRTC_USE_EPOLL)
799 // Remember currently enabled events so we can combine multiple changes
800 // into one update call later.
801 // The signal handlers might re-enable events disabled here, so we can't
802 // keep a list of events to disable at the end of the method. This list
803 // would not be updated with the events enabled by the signal handlers.
804 StartBatchedEventUpdates();
805#endif
jbauch4331fcd2016-01-06 22:20:28 -0800806 // Make sure we deliver connect/accept first. Otherwise, consumers may see
807 // something like a READ followed by a CONNECT, which would be odd.
808 if ((ff & DE_CONNECT) != 0) {
jbauch577f5dc2017-05-17 16:32:26 -0700809 DisableEvents(DE_CONNECT);
jbauch4331fcd2016-01-06 22:20:28 -0800810 SignalConnectEvent(this);
811 }
812 if ((ff & DE_ACCEPT) != 0) {
jbauch577f5dc2017-05-17 16:32:26 -0700813 DisableEvents(DE_ACCEPT);
jbauch4331fcd2016-01-06 22:20:28 -0800814 SignalReadEvent(this);
815 }
816 if ((ff & DE_READ) != 0) {
jbauch577f5dc2017-05-17 16:32:26 -0700817 DisableEvents(DE_READ);
jbauch4331fcd2016-01-06 22:20:28 -0800818 SignalReadEvent(this);
819 }
820 if ((ff & DE_WRITE) != 0) {
jbauch577f5dc2017-05-17 16:32:26 -0700821 DisableEvents(DE_WRITE);
jbauch4331fcd2016-01-06 22:20:28 -0800822 SignalWriteEvent(this);
823 }
824 if ((ff & DE_CLOSE) != 0) {
825 // The socket is now dead to us, so stop checking it.
jbauch577f5dc2017-05-17 16:32:26 -0700826 SetEnabledEvents(0);
jbauch4331fcd2016-01-06 22:20:28 -0800827 SignalCloseEvent(this, err);
828 }
jbauchde4db112017-05-31 13:09:18 -0700829#if defined(WEBRTC_USE_EPOLL)
830 FinishBatchedEventUpdates();
831#endif
jbauch4331fcd2016-01-06 22:20:28 -0800832}
833
Yves Gerey665174f2018-06-19 15:03:05 +0200834#endif // WEBRTC_POSIX
jbauch4331fcd2016-01-06 22:20:28 -0800835
jbauchde4db112017-05-31 13:09:18 -0700836#if defined(WEBRTC_USE_EPOLL)
837
838static int GetEpollEvents(uint32_t ff) {
839 int events = 0;
840 if (ff & (DE_READ | DE_ACCEPT)) {
841 events |= EPOLLIN;
842 }
843 if (ff & (DE_WRITE | DE_CONNECT)) {
844 events |= EPOLLOUT;
845 }
846 return events;
847}
848
849void SocketDispatcher::StartBatchedEventUpdates() {
850 RTC_DCHECK_EQ(saved_enabled_events_, -1);
851 saved_enabled_events_ = enabled_events();
852}
853
854void SocketDispatcher::FinishBatchedEventUpdates() {
855 RTC_DCHECK_NE(saved_enabled_events_, -1);
856 uint8_t old_events = static_cast<uint8_t>(saved_enabled_events_);
857 saved_enabled_events_ = -1;
858 MaybeUpdateDispatcher(old_events);
859}
860
861void SocketDispatcher::MaybeUpdateDispatcher(uint8_t old_events) {
862 if (GetEpollEvents(enabled_events()) != GetEpollEvents(old_events) &&
863 saved_enabled_events_ == -1) {
864 ss_->Update(this);
865 }
866}
867
868void SocketDispatcher::SetEnabledEvents(uint8_t events) {
869 uint8_t old_events = enabled_events();
870 PhysicalSocket::SetEnabledEvents(events);
871 MaybeUpdateDispatcher(old_events);
872}
873
874void SocketDispatcher::EnableEvents(uint8_t events) {
875 uint8_t old_events = enabled_events();
876 PhysicalSocket::EnableEvents(events);
877 MaybeUpdateDispatcher(old_events);
878}
879
880void SocketDispatcher::DisableEvents(uint8_t events) {
881 uint8_t old_events = enabled_events();
882 PhysicalSocket::DisableEvents(events);
883 MaybeUpdateDispatcher(old_events);
884}
885
886#endif // WEBRTC_USE_EPOLL
887
jbauch4331fcd2016-01-06 22:20:28 -0800888int SocketDispatcher::Close() {
889 if (s_ == INVALID_SOCKET)
890 return 0;
891
892#if defined(WEBRTC_WIN)
893 id_ = 0;
894 signal_close_ = false;
895#endif
mmorrison25eeda12020-04-07 16:13:13 -0600896#if defined(WEBRTC_USE_EPOLL)
897 // If we're batching events, the socket can be closed and reopened
898 // during the batch. Set saved_enabled_events_ to 0 here so the new
899 // socket, if any, has the correct old events bitfield
900 if (saved_enabled_events_ != -1) {
901 saved_enabled_events_ = 0;
902 }
903#endif
jbauch4331fcd2016-01-06 22:20:28 -0800904 ss_->Remove(this);
905 return PhysicalSocket::Close();
906}
907
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000908#if defined(WEBRTC_POSIX)
909class EventDispatcher : public Dispatcher {
910 public:
911 EventDispatcher(PhysicalSocketServer* ss) : ss_(ss), fSignaled_(false) {
912 if (pipe(afd_) < 0)
Mirko Bonadei675513b2017-11-09 11:09:25 +0100913 RTC_LOG(LERROR) << "pipe failed";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000914 ss_->Add(this);
915 }
916
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000917 ~EventDispatcher() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000918 ss_->Remove(this);
919 close(afd_[0]);
920 close(afd_[1]);
921 }
922
923 virtual void Signal() {
924 CritScope cs(&crit_);
925 if (!fSignaled_) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200926 const uint8_t b[1] = {0};
nissec16fa5e2017-02-07 07:18:43 -0800927 const ssize_t res = write(afd_[1], b, sizeof(b));
928 RTC_DCHECK_EQ(1, res);
929 fSignaled_ = true;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000930 }
931 }
932
Peter Boström0c4e06b2015-10-07 12:23:21 +0200933 uint32_t GetRequestedEvents() override { return DE_READ; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000934
Peter Boström0c4e06b2015-10-07 12:23:21 +0200935 void OnPreEvent(uint32_t ff) override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000936 // It is not possible to perfectly emulate an auto-resetting event with
937 // pipes. This simulates it by resetting before the event is handled.
938
939 CritScope cs(&crit_);
940 if (fSignaled_) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200941 uint8_t b[4]; // Allow for reading more than 1 byte, but expect 1.
nissec16fa5e2017-02-07 07:18:43 -0800942 const ssize_t res = read(afd_[0], b, sizeof(b));
943 RTC_DCHECK_EQ(1, res);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000944 fSignaled_ = false;
945 }
946 }
947
nissec80e7412017-01-11 05:56:46 -0800948 void OnEvent(uint32_t ff, int err) override { RTC_NOTREACHED(); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000949
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000950 int GetDescriptor() override { return afd_[0]; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000951
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000952 bool IsDescriptorClosed() override { return false; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000953
954 private:
Yves Gerey665174f2018-06-19 15:03:05 +0200955 PhysicalSocketServer* ss_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000956 int afd_[2];
957 bool fSignaled_;
958 CriticalSection crit_;
959};
960
Yves Gerey665174f2018-06-19 15:03:05 +0200961#endif // WEBRTC_POSIX
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000962
963#if defined(WEBRTC_WIN)
Peter Boström0c4e06b2015-10-07 12:23:21 +0200964static uint32_t FlagsToEvents(uint32_t events) {
965 uint32_t ffFD = FD_CLOSE;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000966 if (events & DE_READ)
967 ffFD |= FD_READ;
968 if (events & DE_WRITE)
969 ffFD |= FD_WRITE;
970 if (events & DE_CONNECT)
971 ffFD |= FD_CONNECT;
972 if (events & DE_ACCEPT)
973 ffFD |= FD_ACCEPT;
974 return ffFD;
975}
976
977class EventDispatcher : public Dispatcher {
978 public:
Yves Gerey665174f2018-06-19 15:03:05 +0200979 EventDispatcher(PhysicalSocketServer* ss) : ss_(ss) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000980 hev_ = WSACreateEvent();
981 if (hev_) {
982 ss_->Add(this);
983 }
984 }
985
Steve Anton9de3aac2017-10-24 10:08:26 -0700986 ~EventDispatcher() override {
deadbeef37f5ecf2017-02-27 14:06:41 -0800987 if (hev_ != nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000988 ss_->Remove(this);
989 WSACloseEvent(hev_);
deadbeef37f5ecf2017-02-27 14:06:41 -0800990 hev_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000991 }
992 }
993
994 virtual void Signal() {
deadbeef37f5ecf2017-02-27 14:06:41 -0800995 if (hev_ != nullptr)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000996 WSASetEvent(hev_);
997 }
998
Steve Anton9de3aac2017-10-24 10:08:26 -0700999 uint32_t GetRequestedEvents() override { return 0; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001000
Steve Anton9de3aac2017-10-24 10:08:26 -07001001 void OnPreEvent(uint32_t ff) override { WSAResetEvent(hev_); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001002
Steve Anton9de3aac2017-10-24 10:08:26 -07001003 void OnEvent(uint32_t ff, int err) override {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001004
Steve Anton9de3aac2017-10-24 10:08:26 -07001005 WSAEVENT GetWSAEvent() override { return hev_; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001006
Steve Anton9de3aac2017-10-24 10:08:26 -07001007 SOCKET GetSocket() override { return INVALID_SOCKET; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001008
Steve Anton9de3aac2017-10-24 10:08:26 -07001009 bool CheckSignalClose() override { return false; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001010
Steve Anton9de3aac2017-10-24 10:08:26 -07001011 private:
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001012 PhysicalSocketServer* ss_;
1013 WSAEVENT hev_;
1014};
honghaizcec0a082016-01-15 14:49:09 -08001015#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001016
1017// Sets the value of a boolean value to false when signaled.
1018class Signaler : public EventDispatcher {
1019 public:
Yves Gerey665174f2018-06-19 15:03:05 +02001020 Signaler(PhysicalSocketServer* ss, bool* pf) : EventDispatcher(ss), pf_(pf) {}
1021 ~Signaler() override {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001022
Peter Boström0c4e06b2015-10-07 12:23:21 +02001023 void OnEvent(uint32_t ff, int err) override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001024 if (pf_)
1025 *pf_ = false;
1026 }
1027
1028 private:
Yves Gerey665174f2018-06-19 15:03:05 +02001029 bool* pf_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001030};
1031
Yves Gerey665174f2018-06-19 15:03:05 +02001032PhysicalSocketServer::PhysicalSocketServer() : fWait_(false) {
jbauchde4db112017-05-31 13:09:18 -07001033#if defined(WEBRTC_USE_EPOLL)
1034 // Since Linux 2.6.8, the size argument is ignored, but must be greater than
1035 // zero. Before that the size served as hint to the kernel for the amount of
1036 // space to initially allocate in internal data structures.
1037 epoll_fd_ = epoll_create(FD_SETSIZE);
1038 if (epoll_fd_ == -1) {
1039 // Not an error, will fall back to "select" below.
Mirko Bonadei675513b2017-11-09 11:09:25 +01001040 RTC_LOG_E(LS_WARNING, EN, errno) << "epoll_create";
jbauchde4db112017-05-31 13:09:18 -07001041 epoll_fd_ = INVALID_SOCKET;
1042 }
1043#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001044 signal_wakeup_ = new Signaler(this, &fWait_);
1045#if defined(WEBRTC_WIN)
1046 socket_ev_ = WSACreateEvent();
1047#endif
1048}
1049
1050PhysicalSocketServer::~PhysicalSocketServer() {
1051#if defined(WEBRTC_WIN)
1052 WSACloseEvent(socket_ev_);
1053#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001054 delete signal_wakeup_;
jbauchde4db112017-05-31 13:09:18 -07001055#if defined(WEBRTC_USE_EPOLL)
1056 if (epoll_fd_ != INVALID_SOCKET) {
1057 close(epoll_fd_);
1058 }
1059#endif
nisseede5da42017-01-12 05:15:36 -08001060 RTC_DCHECK(dispatchers_.empty());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001061}
1062
1063void PhysicalSocketServer::WakeUp() {
1064 signal_wakeup_->Signal();
1065}
1066
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001067Socket* PhysicalSocketServer::CreateSocket(int family, int type) {
1068 PhysicalSocket* socket = new PhysicalSocket(this);
1069 if (socket->Create(family, type)) {
1070 return socket;
1071 } else {
1072 delete socket;
jbauch095ae152015-12-18 01:39:55 -08001073 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001074 }
1075}
1076
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001077AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int family, int type) {
1078 SocketDispatcher* dispatcher = new SocketDispatcher(this);
1079 if (dispatcher->Create(family, type)) {
1080 return dispatcher;
1081 } else {
1082 delete dispatcher;
jbauch095ae152015-12-18 01:39:55 -08001083 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001084 }
1085}
1086
1087AsyncSocket* PhysicalSocketServer::WrapSocket(SOCKET s) {
1088 SocketDispatcher* dispatcher = new SocketDispatcher(s, this);
1089 if (dispatcher->Initialize()) {
1090 return dispatcher;
1091 } else {
1092 delete dispatcher;
jbauch095ae152015-12-18 01:39:55 -08001093 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001094 }
1095}
1096
Yves Gerey665174f2018-06-19 15:03:05 +02001097void PhysicalSocketServer::Add(Dispatcher* pdispatcher) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001098 CritScope cs(&crit_);
jbauchde4db112017-05-31 13:09:18 -07001099 if (processing_dispatchers_) {
1100 // A dispatcher is being added while a "Wait" call is processing the
1101 // list of socket events.
1102 // Defer adding to "dispatchers_" set until processing is done to avoid
1103 // invalidating the iterator in "Wait".
1104 pending_remove_dispatchers_.erase(pdispatcher);
1105 pending_add_dispatchers_.insert(pdispatcher);
1106 } else {
1107 dispatchers_.insert(pdispatcher);
1108 }
1109#if defined(WEBRTC_USE_EPOLL)
1110 if (epoll_fd_ != INVALID_SOCKET) {
1111 AddEpoll(pdispatcher);
1112 }
1113#endif // WEBRTC_USE_EPOLL
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001114}
1115
Yves Gerey665174f2018-06-19 15:03:05 +02001116void PhysicalSocketServer::Remove(Dispatcher* pdispatcher) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001117 CritScope cs(&crit_);
jbauchde4db112017-05-31 13:09:18 -07001118 if (processing_dispatchers_) {
1119 // A dispatcher is being removed while a "Wait" call is processing the
1120 // list of socket events.
1121 // Defer removal from "dispatchers_" set until processing is done to avoid
1122 // invalidating the iterator in "Wait".
1123 if (!pending_add_dispatchers_.erase(pdispatcher) &&
1124 dispatchers_.find(pdispatcher) == dispatchers_.end()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001125 RTC_LOG(LS_WARNING) << "PhysicalSocketServer asked to remove a unknown "
Jonas Olssonb2b20312020-01-14 12:11:31 +01001126 "dispatcher, potentially from a duplicate call to "
1127 "Add.";
jbauchde4db112017-05-31 13:09:18 -07001128 return;
1129 }
1130
1131 pending_remove_dispatchers_.insert(pdispatcher);
1132 } else if (!dispatchers_.erase(pdispatcher)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001133 RTC_LOG(LS_WARNING)
1134 << "PhysicalSocketServer asked to remove a unknown "
Jonas Olssonb2b20312020-01-14 12:11:31 +01001135 "dispatcher, potentially from a duplicate call to Add.";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001136 return;
1137 }
jbauchde4db112017-05-31 13:09:18 -07001138#if defined(WEBRTC_USE_EPOLL)
1139 if (epoll_fd_ != INVALID_SOCKET) {
1140 RemoveEpoll(pdispatcher);
1141 }
1142#endif // WEBRTC_USE_EPOLL
1143}
1144
1145void PhysicalSocketServer::Update(Dispatcher* pdispatcher) {
1146#if defined(WEBRTC_USE_EPOLL)
1147 if (epoll_fd_ == INVALID_SOCKET) {
1148 return;
1149 }
1150
1151 CritScope cs(&crit_);
1152 if (dispatchers_.find(pdispatcher) == dispatchers_.end()) {
1153 return;
1154 }
1155
1156 UpdateEpoll(pdispatcher);
1157#endif
1158}
1159
1160void PhysicalSocketServer::AddRemovePendingDispatchers() {
1161 if (!pending_add_dispatchers_.empty()) {
1162 for (Dispatcher* pdispatcher : pending_add_dispatchers_) {
1163 dispatchers_.insert(pdispatcher);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001164 }
jbauchde4db112017-05-31 13:09:18 -07001165 pending_add_dispatchers_.clear();
1166 }
1167
1168 if (!pending_remove_dispatchers_.empty()) {
1169 for (Dispatcher* pdispatcher : pending_remove_dispatchers_) {
1170 dispatchers_.erase(pdispatcher);
1171 }
1172 pending_remove_dispatchers_.clear();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001173 }
1174}
1175
1176#if defined(WEBRTC_POSIX)
jbauchde4db112017-05-31 13:09:18 -07001177
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001178bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
jbauchde4db112017-05-31 13:09:18 -07001179#if defined(WEBRTC_USE_EPOLL)
1180 // We don't keep a dedicated "epoll" descriptor containing only the non-IO
1181 // (i.e. signaling) dispatcher, so "poll" will be used instead of the default
1182 // "select" to support sockets larger than FD_SETSIZE.
1183 if (!process_io) {
1184 return WaitPoll(cmsWait, signal_wakeup_);
1185 } else if (epoll_fd_ != INVALID_SOCKET) {
1186 return WaitEpoll(cmsWait);
1187 }
1188#endif
1189 return WaitSelect(cmsWait, process_io);
1190}
1191
1192static void ProcessEvents(Dispatcher* dispatcher,
1193 bool readable,
1194 bool writable,
1195 bool check_error) {
1196 int errcode = 0;
1197 // TODO(pthatcher): Should we set errcode if getsockopt fails?
1198 if (check_error) {
1199 socklen_t len = sizeof(errcode);
1200 ::getsockopt(dispatcher->GetDescriptor(), SOL_SOCKET, SO_ERROR, &errcode,
1201 &len);
1202 }
1203
1204 uint32_t ff = 0;
1205
1206 // Check readable descriptors. If we're waiting on an accept, signal
1207 // that. Otherwise we're waiting for data, check to see if we're
1208 // readable or really closed.
1209 // TODO(pthatcher): Only peek at TCP descriptors.
1210 if (readable) {
1211 if (dispatcher->GetRequestedEvents() & DE_ACCEPT) {
1212 ff |= DE_ACCEPT;
1213 } else if (errcode || dispatcher->IsDescriptorClosed()) {
1214 ff |= DE_CLOSE;
1215 } else {
1216 ff |= DE_READ;
1217 }
1218 }
1219
1220 // Check writable descriptors. If we're waiting on a connect, detect
1221 // success versus failure by the reaped error code.
1222 if (writable) {
1223 if (dispatcher->GetRequestedEvents() & DE_CONNECT) {
1224 if (!errcode) {
1225 ff |= DE_CONNECT;
1226 } else {
1227 ff |= DE_CLOSE;
1228 }
1229 } else {
1230 ff |= DE_WRITE;
1231 }
1232 }
1233
1234 // Tell the descriptor about the event.
1235 if (ff != 0) {
1236 dispatcher->OnPreEvent(ff);
1237 dispatcher->OnEvent(ff, errcode);
1238 }
1239}
1240
1241bool PhysicalSocketServer::WaitSelect(int cmsWait, bool process_io) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001242 // Calculate timing information
1243
deadbeef37f5ecf2017-02-27 14:06:41 -08001244 struct timeval* ptvWait = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001245 struct timeval tvWait;
Niels Möller689b5872018-08-29 09:55:44 +02001246 int64_t stop_us;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001247 if (cmsWait != kForever) {
1248 // Calculate wait timeval
1249 tvWait.tv_sec = cmsWait / 1000;
1250 tvWait.tv_usec = (cmsWait % 1000) * 1000;
1251 ptvWait = &tvWait;
1252
Niels Möller689b5872018-08-29 09:55:44 +02001253 // Calculate when to return
1254 stop_us = rtc::TimeMicros() + cmsWait * 1000;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001255 }
1256
1257 // Zero all fd_sets. Don't need to do this inside the loop since
1258 // select() zeros the descriptors not signaled
1259
1260 fd_set fdsRead;
1261 FD_ZERO(&fdsRead);
1262 fd_set fdsWrite;
1263 FD_ZERO(&fdsWrite);
Yves Gerey665174f2018-06-19 15:03:05 +02001264// Explicitly unpoison these FDs on MemorySanitizer which doesn't handle the
1265// inline assembly in FD_ZERO.
1266// http://crbug.com/344505
pbos@webrtc.org27e58982014-10-07 17:56:53 +00001267#ifdef MEMORY_SANITIZER
1268 __msan_unpoison(&fdsRead, sizeof(fdsRead));
1269 __msan_unpoison(&fdsWrite, sizeof(fdsWrite));
1270#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001271
1272 fWait_ = true;
1273
1274 while (fWait_) {
1275 int fdmax = -1;
1276 {
1277 CritScope cr(&crit_);
jbauchde4db112017-05-31 13:09:18 -07001278 // TODO(jbauch): Support re-entrant waiting.
1279 RTC_DCHECK(!processing_dispatchers_);
1280 for (Dispatcher* pdispatcher : dispatchers_) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001281 // Query dispatchers for read and write wait state
nisseede5da42017-01-12 05:15:36 -08001282 RTC_DCHECK(pdispatcher);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001283 if (!process_io && (pdispatcher != signal_wakeup_))
1284 continue;
1285 int fd = pdispatcher->GetDescriptor();
jbauchde4db112017-05-31 13:09:18 -07001286 // "select"ing a file descriptor that is equal to or larger than
1287 // FD_SETSIZE will result in undefined behavior.
1288 RTC_DCHECK_LT(fd, FD_SETSIZE);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001289 if (fd > fdmax)
1290 fdmax = fd;
1291
Peter Boström0c4e06b2015-10-07 12:23:21 +02001292 uint32_t ff = pdispatcher->GetRequestedEvents();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001293 if (ff & (DE_READ | DE_ACCEPT))
1294 FD_SET(fd, &fdsRead);
1295 if (ff & (DE_WRITE | DE_CONNECT))
1296 FD_SET(fd, &fdsWrite);
1297 }
1298 }
1299
1300 // Wait then call handlers as appropriate
1301 // < 0 means error
1302 // 0 means timeout
1303 // > 0 means count of descriptors ready
deadbeef37f5ecf2017-02-27 14:06:41 -08001304 int n = select(fdmax + 1, &fdsRead, &fdsWrite, nullptr, ptvWait);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001305
1306 // If error, return error.
1307 if (n < 0) {
1308 if (errno != EINTR) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001309 RTC_LOG_E(LS_ERROR, EN, errno) << "select";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001310 return false;
1311 }
1312 // Else ignore the error and keep going. If this EINTR was for one of the
1313 // signals managed by this PhysicalSocketServer, the
1314 // PosixSignalDeliveryDispatcher will be in the signaled state in the next
1315 // iteration.
1316 } else if (n == 0) {
1317 // If timeout, return success
1318 return true;
1319 } else {
1320 // We have signaled descriptors
1321 CritScope cr(&crit_);
jbauchde4db112017-05-31 13:09:18 -07001322 processing_dispatchers_ = true;
1323 for (Dispatcher* pdispatcher : dispatchers_) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001324 int fd = pdispatcher->GetDescriptor();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001325
jbauchde4db112017-05-31 13:09:18 -07001326 bool readable = FD_ISSET(fd, &fdsRead);
1327 if (readable) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001328 FD_CLR(fd, &fdsRead);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001329 }
1330
jbauchde4db112017-05-31 13:09:18 -07001331 bool writable = FD_ISSET(fd, &fdsWrite);
1332 if (writable) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001333 FD_CLR(fd, &fdsWrite);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001334 }
1335
jbauchde4db112017-05-31 13:09:18 -07001336 // The error code can be signaled through reads or writes.
1337 ProcessEvents(pdispatcher, readable, writable, readable || writable);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001338 }
jbauchde4db112017-05-31 13:09:18 -07001339
1340 processing_dispatchers_ = false;
1341 // Process deferred dispatchers that have been added/removed while the
1342 // events were handled above.
1343 AddRemovePendingDispatchers();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001344 }
1345
1346 // Recalc the time remaining to wait. Doing it here means it doesn't get
1347 // calced twice the first time through the loop
1348 if (ptvWait) {
1349 ptvWait->tv_sec = 0;
1350 ptvWait->tv_usec = 0;
Niels Möller689b5872018-08-29 09:55:44 +02001351 int64_t time_left_us = stop_us - rtc::TimeMicros();
1352 if (time_left_us > 0) {
1353 ptvWait->tv_sec = time_left_us / rtc::kNumMicrosecsPerSec;
1354 ptvWait->tv_usec = time_left_us % rtc::kNumMicrosecsPerSec;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001355 }
1356 }
1357 }
1358
1359 return true;
1360}
1361
jbauchde4db112017-05-31 13:09:18 -07001362#if defined(WEBRTC_USE_EPOLL)
1363
1364// Initial number of events to process with one call to "epoll_wait".
1365static const size_t kInitialEpollEvents = 128;
1366
1367// Maximum number of events to process with one call to "epoll_wait".
1368static const size_t kMaxEpollEvents = 8192;
1369
1370void PhysicalSocketServer::AddEpoll(Dispatcher* pdispatcher) {
1371 RTC_DCHECK(epoll_fd_ != INVALID_SOCKET);
1372 int fd = pdispatcher->GetDescriptor();
1373 RTC_DCHECK(fd != INVALID_SOCKET);
1374 if (fd == INVALID_SOCKET) {
1375 return;
1376 }
1377
1378 struct epoll_event event = {0};
1379 event.events = GetEpollEvents(pdispatcher->GetRequestedEvents());
1380 event.data.ptr = pdispatcher;
1381 int err = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &event);
1382 RTC_DCHECK_EQ(err, 0);
1383 if (err == -1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001384 RTC_LOG_E(LS_ERROR, EN, errno) << "epoll_ctl EPOLL_CTL_ADD";
jbauchde4db112017-05-31 13:09:18 -07001385 }
1386}
1387
1388void PhysicalSocketServer::RemoveEpoll(Dispatcher* pdispatcher) {
1389 RTC_DCHECK(epoll_fd_ != INVALID_SOCKET);
1390 int fd = pdispatcher->GetDescriptor();
1391 RTC_DCHECK(fd != INVALID_SOCKET);
1392 if (fd == INVALID_SOCKET) {
1393 return;
1394 }
1395
1396 struct epoll_event event = {0};
1397 int err = epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &event);
1398 RTC_DCHECK(err == 0 || errno == ENOENT);
1399 if (err == -1) {
1400 if (errno == ENOENT) {
1401 // Socket has already been closed.
Mirko Bonadei675513b2017-11-09 11:09:25 +01001402 RTC_LOG_E(LS_VERBOSE, EN, errno) << "epoll_ctl EPOLL_CTL_DEL";
jbauchde4db112017-05-31 13:09:18 -07001403 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001404 RTC_LOG_E(LS_ERROR, EN, errno) << "epoll_ctl EPOLL_CTL_DEL";
jbauchde4db112017-05-31 13:09:18 -07001405 }
1406 }
1407}
1408
1409void PhysicalSocketServer::UpdateEpoll(Dispatcher* pdispatcher) {
1410 RTC_DCHECK(epoll_fd_ != INVALID_SOCKET);
1411 int fd = pdispatcher->GetDescriptor();
1412 RTC_DCHECK(fd != INVALID_SOCKET);
1413 if (fd == INVALID_SOCKET) {
1414 return;
1415 }
1416
1417 struct epoll_event event = {0};
1418 event.events = GetEpollEvents(pdispatcher->GetRequestedEvents());
1419 event.data.ptr = pdispatcher;
1420 int err = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &event);
1421 RTC_DCHECK_EQ(err, 0);
1422 if (err == -1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001423 RTC_LOG_E(LS_ERROR, EN, errno) << "epoll_ctl EPOLL_CTL_MOD";
jbauchde4db112017-05-31 13:09:18 -07001424 }
1425}
1426
1427bool PhysicalSocketServer::WaitEpoll(int cmsWait) {
1428 RTC_DCHECK(epoll_fd_ != INVALID_SOCKET);
1429 int64_t tvWait = -1;
1430 int64_t tvStop = -1;
1431 if (cmsWait != kForever) {
1432 tvWait = cmsWait;
1433 tvStop = TimeAfter(cmsWait);
1434 }
1435
1436 if (epoll_events_.empty()) {
1437 // The initial space to receive events is created only if epoll is used.
1438 epoll_events_.resize(kInitialEpollEvents);
1439 }
1440
1441 fWait_ = true;
1442
1443 while (fWait_) {
1444 // Wait then call handlers as appropriate
1445 // < 0 means error
1446 // 0 means timeout
1447 // > 0 means count of descriptors ready
1448 int n = epoll_wait(epoll_fd_, &epoll_events_[0],
1449 static_cast<int>(epoll_events_.size()),
1450 static_cast<int>(tvWait));
1451 if (n < 0) {
1452 if (errno != EINTR) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001453 RTC_LOG_E(LS_ERROR, EN, errno) << "epoll";
jbauchde4db112017-05-31 13:09:18 -07001454 return false;
1455 }
1456 // Else ignore the error and keep going. If this EINTR was for one of the
1457 // signals managed by this PhysicalSocketServer, the
1458 // PosixSignalDeliveryDispatcher will be in the signaled state in the next
1459 // iteration.
1460 } else if (n == 0) {
1461 // If timeout, return success
1462 return true;
1463 } else {
1464 // We have signaled descriptors
1465 CritScope cr(&crit_);
1466 for (int i = 0; i < n; ++i) {
1467 const epoll_event& event = epoll_events_[i];
1468 Dispatcher* pdispatcher = static_cast<Dispatcher*>(event.data.ptr);
1469 if (dispatchers_.find(pdispatcher) == dispatchers_.end()) {
1470 // The dispatcher for this socket no longer exists.
1471 continue;
1472 }
1473
1474 bool readable = (event.events & (EPOLLIN | EPOLLPRI));
1475 bool writable = (event.events & EPOLLOUT);
1476 bool check_error = (event.events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP));
1477
1478 ProcessEvents(pdispatcher, readable, writable, check_error);
1479 }
1480 }
1481
1482 if (static_cast<size_t>(n) == epoll_events_.size() &&
1483 epoll_events_.size() < kMaxEpollEvents) {
1484 // We used the complete space to receive events, increase size for future
1485 // iterations.
1486 epoll_events_.resize(std::max(epoll_events_.size() * 2, kMaxEpollEvents));
1487 }
1488
1489 if (cmsWait != kForever) {
1490 tvWait = TimeDiff(tvStop, TimeMillis());
1491 if (tvWait < 0) {
1492 // Return success on timeout.
1493 return true;
1494 }
1495 }
1496 }
1497
1498 return true;
1499}
1500
1501bool PhysicalSocketServer::WaitPoll(int cmsWait, Dispatcher* dispatcher) {
1502 RTC_DCHECK(dispatcher);
1503 int64_t tvWait = -1;
1504 int64_t tvStop = -1;
1505 if (cmsWait != kForever) {
1506 tvWait = cmsWait;
1507 tvStop = TimeAfter(cmsWait);
1508 }
1509
1510 fWait_ = true;
1511
1512 struct pollfd fds = {0};
1513 int fd = dispatcher->GetDescriptor();
1514 fds.fd = fd;
1515
1516 while (fWait_) {
1517 uint32_t ff = dispatcher->GetRequestedEvents();
1518 fds.events = 0;
1519 if (ff & (DE_READ | DE_ACCEPT)) {
1520 fds.events |= POLLIN;
1521 }
1522 if (ff & (DE_WRITE | DE_CONNECT)) {
1523 fds.events |= POLLOUT;
1524 }
1525 fds.revents = 0;
1526
1527 // Wait then call handlers as appropriate
1528 // < 0 means error
1529 // 0 means timeout
1530 // > 0 means count of descriptors ready
1531 int n = poll(&fds, 1, static_cast<int>(tvWait));
1532 if (n < 0) {
1533 if (errno != EINTR) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001534 RTC_LOG_E(LS_ERROR, EN, errno) << "poll";
jbauchde4db112017-05-31 13:09:18 -07001535 return false;
1536 }
1537 // Else ignore the error and keep going. If this EINTR was for one of the
1538 // signals managed by this PhysicalSocketServer, the
1539 // PosixSignalDeliveryDispatcher will be in the signaled state in the next
1540 // iteration.
1541 } else if (n == 0) {
1542 // If timeout, return success
1543 return true;
1544 } else {
1545 // We have signaled descriptors (should only be the passed dispatcher).
1546 RTC_DCHECK_EQ(n, 1);
1547 RTC_DCHECK_EQ(fds.fd, fd);
1548
1549 bool readable = (fds.revents & (POLLIN | POLLPRI));
1550 bool writable = (fds.revents & POLLOUT);
1551 bool check_error = (fds.revents & (POLLRDHUP | POLLERR | POLLHUP));
1552
1553 ProcessEvents(dispatcher, readable, writable, check_error);
1554 }
1555
1556 if (cmsWait != kForever) {
1557 tvWait = TimeDiff(tvStop, TimeMillis());
1558 if (tvWait < 0) {
1559 // Return success on timeout.
1560 return true;
1561 }
1562 }
1563 }
1564
1565 return true;
1566}
1567
1568#endif // WEBRTC_USE_EPOLL
1569
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001570#endif // WEBRTC_POSIX
1571
1572#if defined(WEBRTC_WIN)
1573bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
Honghai Zhang82d78622016-05-06 11:29:15 -07001574 int64_t cmsTotal = cmsWait;
1575 int64_t cmsElapsed = 0;
1576 int64_t msStart = Time();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001577
1578 fWait_ = true;
1579 while (fWait_) {
1580 std::vector<WSAEVENT> events;
Yves Gerey665174f2018-06-19 15:03:05 +02001581 std::vector<Dispatcher*> event_owners;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001582
1583 events.push_back(socket_ev_);
1584
1585 {
1586 CritScope cr(&crit_);
jbauchde4db112017-05-31 13:09:18 -07001587 // TODO(jbauch): Support re-entrant waiting.
1588 RTC_DCHECK(!processing_dispatchers_);
1589
1590 // Calling "CheckSignalClose" might remove a closed dispatcher from the
1591 // set. This must be deferred to prevent invalidating the iterator.
1592 processing_dispatchers_ = true;
1593 for (Dispatcher* disp : dispatchers_) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001594 if (!process_io && (disp != signal_wakeup_))
1595 continue;
1596 SOCKET s = disp->GetSocket();
1597 if (disp->CheckSignalClose()) {
1598 // We just signalled close, don't poll this socket
1599 } else if (s != INVALID_SOCKET) {
Yves Gerey665174f2018-06-19 15:03:05 +02001600 WSAEventSelect(s, events[0],
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001601 FlagsToEvents(disp->GetRequestedEvents()));
1602 } else {
1603 events.push_back(disp->GetWSAEvent());
1604 event_owners.push_back(disp);
1605 }
1606 }
jbauchde4db112017-05-31 13:09:18 -07001607
1608 processing_dispatchers_ = false;
1609 // Process deferred dispatchers that have been added/removed while the
1610 // events were handled above.
1611 AddRemovePendingDispatchers();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001612 }
1613
1614 // Which is shorter, the delay wait or the asked wait?
1615
Honghai Zhang82d78622016-05-06 11:29:15 -07001616 int64_t cmsNext;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001617 if (cmsWait == kForever) {
1618 cmsNext = cmsWait;
1619 } else {
Honghai Zhang82d78622016-05-06 11:29:15 -07001620 cmsNext = std::max<int64_t>(0, cmsTotal - cmsElapsed);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001621 }
1622
1623 // Wait for one of the events to signal
Yves Gerey665174f2018-06-19 15:03:05 +02001624 DWORD dw =
1625 WSAWaitForMultipleEvents(static_cast<DWORD>(events.size()), &events[0],
1626 false, static_cast<DWORD>(cmsNext), false);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001627
1628 if (dw == WSA_WAIT_FAILED) {
1629 // Failed?
jbauch095ae152015-12-18 01:39:55 -08001630 // TODO(pthatcher): need a better strategy than this!
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001631 WSAGetLastError();
nissec80e7412017-01-11 05:56:46 -08001632 RTC_NOTREACHED();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001633 return false;
1634 } else if (dw == WSA_WAIT_TIMEOUT) {
1635 // Timeout?
1636 return true;
1637 } else {
1638 // Figure out which one it is and call it
1639 CritScope cr(&crit_);
1640 int index = dw - WSA_WAIT_EVENT_0;
1641 if (index > 0) {
Yves Gerey665174f2018-06-19 15:03:05 +02001642 --index; // The first event is the socket event
jbauchde4db112017-05-31 13:09:18 -07001643 Dispatcher* disp = event_owners[index];
1644 // The dispatcher could have been removed while waiting for events.
1645 if (dispatchers_.find(disp) != dispatchers_.end()) {
1646 disp->OnPreEvent(0);
1647 disp->OnEvent(0, 0);
1648 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001649 } else if (process_io) {
jbauchde4db112017-05-31 13:09:18 -07001650 processing_dispatchers_ = true;
1651 for (Dispatcher* disp : dispatchers_) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001652 SOCKET s = disp->GetSocket();
1653 if (s == INVALID_SOCKET)
1654 continue;
1655
1656 WSANETWORKEVENTS wsaEvents;
1657 int err = WSAEnumNetworkEvents(s, events[0], &wsaEvents);
1658 if (err == 0) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001659 {
1660 if ((wsaEvents.lNetworkEvents & FD_READ) &&
1661 wsaEvents.iErrorCode[FD_READ_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001662 RTC_LOG(WARNING)
1663 << "PhysicalSocketServer got FD_READ_BIT error "
1664 << wsaEvents.iErrorCode[FD_READ_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001665 }
1666 if ((wsaEvents.lNetworkEvents & FD_WRITE) &&
1667 wsaEvents.iErrorCode[FD_WRITE_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001668 RTC_LOG(WARNING)
1669 << "PhysicalSocketServer got FD_WRITE_BIT error "
1670 << wsaEvents.iErrorCode[FD_WRITE_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001671 }
1672 if ((wsaEvents.lNetworkEvents & FD_CONNECT) &&
1673 wsaEvents.iErrorCode[FD_CONNECT_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001674 RTC_LOG(WARNING)
1675 << "PhysicalSocketServer got FD_CONNECT_BIT error "
1676 << wsaEvents.iErrorCode[FD_CONNECT_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001677 }
1678 if ((wsaEvents.lNetworkEvents & FD_ACCEPT) &&
1679 wsaEvents.iErrorCode[FD_ACCEPT_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001680 RTC_LOG(WARNING)
1681 << "PhysicalSocketServer got FD_ACCEPT_BIT error "
1682 << wsaEvents.iErrorCode[FD_ACCEPT_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001683 }
1684 if ((wsaEvents.lNetworkEvents & FD_CLOSE) &&
1685 wsaEvents.iErrorCode[FD_CLOSE_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001686 RTC_LOG(WARNING)
1687 << "PhysicalSocketServer got FD_CLOSE_BIT error "
1688 << wsaEvents.iErrorCode[FD_CLOSE_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001689 }
1690 }
Peter Boström0c4e06b2015-10-07 12:23:21 +02001691 uint32_t ff = 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001692 int errcode = 0;
1693 if (wsaEvents.lNetworkEvents & FD_READ)
1694 ff |= DE_READ;
1695 if (wsaEvents.lNetworkEvents & FD_WRITE)
1696 ff |= DE_WRITE;
1697 if (wsaEvents.lNetworkEvents & FD_CONNECT) {
1698 if (wsaEvents.iErrorCode[FD_CONNECT_BIT] == 0) {
1699 ff |= DE_CONNECT;
1700 } else {
1701 ff |= DE_CLOSE;
1702 errcode = wsaEvents.iErrorCode[FD_CONNECT_BIT];
1703 }
1704 }
1705 if (wsaEvents.lNetworkEvents & FD_ACCEPT)
1706 ff |= DE_ACCEPT;
1707 if (wsaEvents.lNetworkEvents & FD_CLOSE) {
1708 ff |= DE_CLOSE;
1709 errcode = wsaEvents.iErrorCode[FD_CLOSE_BIT];
1710 }
1711 if (ff != 0) {
1712 disp->OnPreEvent(ff);
1713 disp->OnEvent(ff, errcode);
1714 }
1715 }
1716 }
jbauchde4db112017-05-31 13:09:18 -07001717
1718 processing_dispatchers_ = false;
1719 // Process deferred dispatchers that have been added/removed while the
1720 // events were handled above.
1721 AddRemovePendingDispatchers();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001722 }
1723
1724 // Reset the network event until new activity occurs
1725 WSAResetEvent(socket_ev_);
1726 }
1727
1728 // Break?
1729 if (!fWait_)
1730 break;
1731 cmsElapsed = TimeSince(msStart);
1732 if ((cmsWait != kForever) && (cmsElapsed >= cmsWait)) {
Yves Gerey665174f2018-06-19 15:03:05 +02001733 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001734 }
1735 }
1736
1737 // Done
1738 return true;
1739}
honghaizcec0a082016-01-15 14:49:09 -08001740#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001741
1742} // namespace rtc