blob: ca78499179a0b9718b02cf7522c26322971269b6 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:261/*
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 */
Mirko Bonadei92ea95e2017-09-15 04:47:3110#include "rtc_base/physicalsocketserver.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2611
12#if defined(_MSC_VER) && _MSC_VER < 1300
Yves Gerey665174f2018-06-19 13:03:0513#pragma warning(disable : 4786)
henrike@webrtc.orgf0488722014-05-13 18:00:2614#endif
15
pbos@webrtc.org27e58982014-10-07 17:56:5316#ifdef MEMORY_SANITIZER
17#include <sanitizer/msan_interface.h>
18#endif
19
henrike@webrtc.orgf0488722014-05-13 18:00:2620#if defined(WEBRTC_POSIX)
henrike@webrtc.orgf0488722014-05-13 18:00:2621#include <fcntl.h>
Yves Gerey665174f2018-06-19 13:03:0522#include <string.h>
jbauchde4db112017-05-31 20:09:1823#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:2627#include <signal.h>
Yves Gerey665174f2018-06-19 13:03:0528#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:2632#endif
33
34#if defined(WEBRTC_WIN)
henrike@webrtc.orgf0488722014-05-13 18:00:2635#include <windows.h>
36#include <winsock2.h>
37#include <ws2tcpip.h>
38#undef SetPort
39#endif
40
Patrik Höglunda8005cf2017-12-13 15:05:4241#include <errno.h>
42
henrike@webrtc.orgf0488722014-05-13 18:00:2643#include <algorithm>
44#include <map>
45
Mirko Bonadei92ea95e2017-09-15 04:47:3146#include "rtc_base/arraysize.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3147#include "rtc_base/byteorder.h"
48#include "rtc_base/checks.h"
49#include "rtc_base/logging.h"
50#include "rtc_base/networkmonitor.h"
51#include "rtc_base/nullsocketserver.h"
52#include "rtc_base/timeutils.h"
53#include "rtc_base/win32socketinit.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2654
Patrik Höglunda8005cf2017-12-13 15:05:4255#if defined(WEBRTC_WIN)
56#define LAST_SYSTEM_ERROR (::GetLastError())
57#elif defined(__native_client__) && __native_client__
58#define LAST_SYSTEM_ERROR (0)
59#elif defined(WEBRTC_POSIX)
60#define LAST_SYSTEM_ERROR (errno)
61#endif // WEBRTC_WIN
62
henrike@webrtc.orgf0488722014-05-13 18:00:2663#if defined(WEBRTC_POSIX)
64#include <netinet/tcp.h> // for TCP_NODELAY
Yves Gerey665174f2018-06-19 13:03:0565#define IP_MTU 14 // Until this is integrated from linux/in.h to netinet/in.h
henrike@webrtc.orgf0488722014-05-13 18:00:2666typedef void* SockOptArg;
Stefan Holmer9131efd2016-05-23 16:19:2667
henrike@webrtc.orgf0488722014-05-13 18:00:2668#endif // WEBRTC_POSIX
69
Stefan Holmer3ebb3ef2016-05-23 18:26:1170#if defined(WEBRTC_POSIX) && !defined(WEBRTC_MAC) && !defined(__native_client__)
71
Stefan Holmer9131efd2016-05-23 16:19:2672int64_t GetSocketRecvTimestamp(int socket) {
73 struct timeval tv_ioctl;
74 int ret = ioctl(socket, SIOCGSTAMP, &tv_ioctl);
75 if (ret != 0)
76 return -1;
77 int64_t timestamp =
78 rtc::kNumMicrosecsPerSec * static_cast<int64_t>(tv_ioctl.tv_sec) +
79 static_cast<int64_t>(tv_ioctl.tv_usec);
80 return timestamp;
81}
82
83#else
84
85int64_t GetSocketRecvTimestamp(int socket) {
86 return -1;
87}
88#endif
89
henrike@webrtc.orgf0488722014-05-13 18:00:2690#if defined(WEBRTC_WIN)
91typedef char* SockOptArg;
92#endif
93
jbauchde4db112017-05-31 20:09:1894#if defined(WEBRTC_USE_EPOLL)
95// POLLRDHUP / EPOLLRDHUP are only defined starting with Linux 2.6.17.
96#if !defined(POLLRDHUP)
97#define POLLRDHUP 0x2000
98#endif
99#if !defined(EPOLLRDHUP)
100#define EPOLLRDHUP 0x2000
101#endif
102#endif
103
henrike@webrtc.orgf0488722014-05-13 18:00:26104namespace rtc {
105
danilchapbebf54c2016-04-28 08:32:48106std::unique_ptr<SocketServer> SocketServer::CreateDefault() {
107#if defined(__native_client__)
108 return std::unique_ptr<SocketServer>(new rtc::NullSocketServer);
109#else
110 return std::unique_ptr<SocketServer>(new rtc::PhysicalSocketServer);
111#endif
112}
113
jbauch095ae152015-12-18 09:39:55114PhysicalSocket::PhysicalSocket(PhysicalSocketServer* ss, SOCKET s)
Yves Gerey665174f2018-06-19 13:03:05115 : ss_(ss),
116 s_(s),
117 error_(0),
118 state_((s == INVALID_SOCKET) ? CS_CLOSED : CS_CONNECTED),
119 resolver_(nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26120#if defined(WEBRTC_WIN)
jbauch095ae152015-12-18 09:39:55121 // EnsureWinsockInit() ensures that winsock is initialized. The default
122 // version of this function doesn't do anything because winsock is
123 // initialized by constructor of a static object. If neccessary libjingle
124 // users can link it with a different version of this function by replacing
125 // win32socketinit.cc. See win32socketinit.cc for more details.
126 EnsureWinsockInit();
henrike@webrtc.orgf0488722014-05-13 18:00:26127#endif
jbauch095ae152015-12-18 09:39:55128 if (s_ != INVALID_SOCKET) {
jbauch577f5dc2017-05-17 23:32:26129 SetEnabledEvents(DE_READ | DE_WRITE);
henrike@webrtc.orgf0488722014-05-13 18:00:26130
jbauch095ae152015-12-18 09:39:55131 int type = SOCK_STREAM;
132 socklen_t len = sizeof(type);
nissec16fa5e2017-02-07 15:18:43133 const int res =
134 getsockopt(s_, SOL_SOCKET, SO_TYPE, (SockOptArg)&type, &len);
135 RTC_DCHECK_EQ(0, res);
henrike@webrtc.orgf0488722014-05-13 18:00:26136 udp_ = (SOCK_DGRAM == type);
henrike@webrtc.orgf0488722014-05-13 18:00:26137 }
jbauch095ae152015-12-18 09:39:55138}
henrike@webrtc.orgf0488722014-05-13 18:00:26139
jbauch095ae152015-12-18 09:39:55140PhysicalSocket::~PhysicalSocket() {
141 Close();
142}
143
144bool PhysicalSocket::Create(int family, int type) {
145 Close();
146 s_ = ::socket(family, type, 0);
147 udp_ = (SOCK_DGRAM == type);
148 UpdateLastError();
jbauch577f5dc2017-05-17 23:32:26149 if (udp_) {
150 SetEnabledEvents(DE_READ | DE_WRITE);
151 }
jbauch095ae152015-12-18 09:39:55152 return s_ != INVALID_SOCKET;
153}
154
155SocketAddress PhysicalSocket::GetLocalAddress() const {
156 sockaddr_storage addr_storage = {0};
157 socklen_t addrlen = sizeof(addr_storage);
158 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
159 int result = ::getsockname(s_, addr, &addrlen);
160 SocketAddress address;
161 if (result >= 0) {
162 SocketAddressFromSockAddrStorage(addr_storage, &address);
163 } else {
Mirko Bonadei675513b2017-11-09 10:09:25164 RTC_LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket="
165 << s_;
henrike@webrtc.orgf0488722014-05-13 18:00:26166 }
jbauch095ae152015-12-18 09:39:55167 return address;
168}
henrike@webrtc.orgf0488722014-05-13 18:00:26169
jbauch095ae152015-12-18 09:39:55170SocketAddress PhysicalSocket::GetRemoteAddress() const {
171 sockaddr_storage addr_storage = {0};
172 socklen_t addrlen = sizeof(addr_storage);
173 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
174 int result = ::getpeername(s_, addr, &addrlen);
175 SocketAddress address;
176 if (result >= 0) {
177 SocketAddressFromSockAddrStorage(addr_storage, &address);
178 } else {
Mirko Bonadei675513b2017-11-09 10:09:25179 RTC_LOG(LS_WARNING)
180 << "GetRemoteAddress: unable to get remote addr, socket=" << s_;
henrike@webrtc.orgf0488722014-05-13 18:00:26181 }
jbauch095ae152015-12-18 09:39:55182 return address;
183}
henrike@webrtc.orgf0488722014-05-13 18:00:26184
jbauch095ae152015-12-18 09:39:55185int PhysicalSocket::Bind(const SocketAddress& bind_addr) {
deadbeefc874d122017-02-13 23:41:59186 SocketAddress copied_bind_addr = bind_addr;
187 // If a network binder is available, use it to bind a socket to an interface
188 // instead of bind(), since this is more reliable on an OS with a weak host
189 // model.
deadbeef9ffa13f2017-02-22 00:18:00190 if (ss_->network_binder() && !bind_addr.IsAnyIP()) {
deadbeefc874d122017-02-13 23:41:59191 NetworkBindingResult result =
192 ss_->network_binder()->BindSocketToNetwork(s_, bind_addr.ipaddr());
193 if (result == NetworkBindingResult::SUCCESS) {
194 // Since the network binder handled binding the socket to the desired
195 // network interface, we don't need to (and shouldn't) include an IP in
196 // the bind() call; bind() just needs to assign a port.
197 copied_bind_addr.SetIP(GetAnyIP(copied_bind_addr.ipaddr().family()));
198 } else if (result == NetworkBindingResult::NOT_IMPLEMENTED) {
Mirko Bonadei675513b2017-11-09 10:09:25199 RTC_LOG(LS_INFO) << "Can't bind socket to network because "
200 "network binding is not implemented for this OS.";
deadbeefc874d122017-02-13 23:41:59201 } else {
202 if (bind_addr.IsLoopbackIP()) {
203 // If we couldn't bind to a loopback IP (which should only happen in
204 // test scenarios), continue on. This may be expected behavior.
Mirko Bonadei675513b2017-11-09 10:09:25205 RTC_LOG(LS_VERBOSE) << "Binding socket to loopback address "
206 << bind_addr.ipaddr().ToString()
207 << " failed; result: " << static_cast<int>(result);
deadbeefc874d122017-02-13 23:41:59208 } else {
Mirko Bonadei675513b2017-11-09 10:09:25209 RTC_LOG(LS_WARNING) << "Binding socket to network address "
210 << bind_addr.ipaddr().ToString()
211 << " failed; result: " << static_cast<int>(result);
deadbeefc874d122017-02-13 23:41:59212 // If a network binding was attempted and failed, we should stop here
213 // and not try to use the socket. Otherwise, we may end up sending
214 // packets with an invalid source address.
215 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7026
216 return -1;
217 }
218 }
219 }
jbauch095ae152015-12-18 09:39:55220 sockaddr_storage addr_storage;
deadbeefc874d122017-02-13 23:41:59221 size_t len = copied_bind_addr.ToSockAddrStorage(&addr_storage);
jbauch095ae152015-12-18 09:39:55222 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
223 int err = ::bind(s_, addr, static_cast<int>(len));
224 UpdateLastError();
tfarinaa41ab932015-10-30 23:08:48225#if !defined(NDEBUG)
jbauch095ae152015-12-18 09:39:55226 if (0 == err) {
227 dbg_addr_ = "Bound @ ";
228 dbg_addr_.append(GetLocalAddress().ToString());
229 }
tfarinaa41ab932015-10-30 23:08:48230#endif
jbauch095ae152015-12-18 09:39:55231 return err;
232}
233
234int PhysicalSocket::Connect(const SocketAddress& addr) {
235 // TODO(pthatcher): Implicit creation is required to reconnect...
236 // ...but should we make it more explicit?
237 if (state_ != CS_CLOSED) {
238 SetError(EALREADY);
239 return SOCKET_ERROR;
henrike@webrtc.orgf0488722014-05-13 18:00:26240 }
jbauch095ae152015-12-18 09:39:55241 if (addr.IsUnresolvedIP()) {
Mirko Bonadei675513b2017-11-09 10:09:25242 RTC_LOG(LS_VERBOSE) << "Resolving addr in PhysicalSocket::Connect";
jbauch095ae152015-12-18 09:39:55243 resolver_ = new AsyncResolver();
244 resolver_->SignalDone.connect(this, &PhysicalSocket::OnResolveResult);
245 resolver_->Start(addr);
246 state_ = CS_CONNECTING;
henrike@webrtc.orgf0488722014-05-13 18:00:26247 return 0;
248 }
249
jbauch095ae152015-12-18 09:39:55250 return DoConnect(addr);
251}
252
253int PhysicalSocket::DoConnect(const SocketAddress& connect_addr) {
Yves Gerey665174f2018-06-19 13:03:05254 if ((s_ == INVALID_SOCKET) && !Create(connect_addr.family(), SOCK_STREAM)) {
jbauch095ae152015-12-18 09:39:55255 return SOCKET_ERROR;
256 }
257 sockaddr_storage addr_storage;
258 size_t len = connect_addr.ToSockAddrStorage(&addr_storage);
259 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
260 int err = ::connect(s_, addr, static_cast<int>(len));
261 UpdateLastError();
jbauch577f5dc2017-05-17 23:32:26262 uint8_t events = DE_READ | DE_WRITE;
jbauch095ae152015-12-18 09:39:55263 if (err == 0) {
264 state_ = CS_CONNECTED;
265 } else if (IsBlockingError(GetError())) {
266 state_ = CS_CONNECTING;
jbauch577f5dc2017-05-17 23:32:26267 events |= DE_CONNECT;
jbauch095ae152015-12-18 09:39:55268 } else {
269 return SOCKET_ERROR;
henrike@webrtc.orgf0488722014-05-13 18:00:26270 }
271
jbauch577f5dc2017-05-17 23:32:26272 EnableEvents(events);
jbauch095ae152015-12-18 09:39:55273 return 0;
274}
henrike@webrtc.orgf0488722014-05-13 18:00:26275
jbauch095ae152015-12-18 09:39:55276int PhysicalSocket::GetError() const {
277 CritScope cs(&crit_);
278 return error_;
279}
henrike@webrtc.orgf0488722014-05-13 18:00:26280
jbauch095ae152015-12-18 09:39:55281void PhysicalSocket::SetError(int error) {
282 CritScope cs(&crit_);
283 error_ = error;
284}
285
286AsyncSocket::ConnState PhysicalSocket::GetState() const {
287 return state_;
288}
289
290int PhysicalSocket::GetOption(Option opt, int* value) {
291 int slevel;
292 int sopt;
293 if (TranslateOption(opt, &slevel, &sopt) == -1)
294 return -1;
295 socklen_t optlen = sizeof(*value);
296 int ret = ::getsockopt(s_, slevel, sopt, (SockOptArg)value, &optlen);
297 if (ret != -1 && opt == OPT_DONTFRAGMENT) {
henrike@webrtc.orgf0488722014-05-13 18:00:26298#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
jbauch095ae152015-12-18 09:39:55299 *value = (*value != IP_PMTUDISC_DONT) ? 1 : 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26300#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26301 }
jbauch095ae152015-12-18 09:39:55302 return ret;
303}
henrike@webrtc.orgf0488722014-05-13 18:00:26304
jbauch095ae152015-12-18 09:39:55305int PhysicalSocket::SetOption(Option opt, int value) {
306 int slevel;
307 int sopt;
308 if (TranslateOption(opt, &slevel, &sopt) == -1)
309 return -1;
310 if (opt == OPT_DONTFRAGMENT) {
henrike@webrtc.orgf0488722014-05-13 18:00:26311#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
jbauch095ae152015-12-18 09:39:55312 value = (value) ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
henrike@webrtc.orgf0488722014-05-13 18:00:26313#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26314 }
jbauch095ae152015-12-18 09:39:55315 return ::setsockopt(s_, slevel, sopt, (SockOptArg)&value, sizeof(value));
316}
henrike@webrtc.orgf0488722014-05-13 18:00:26317
jbauch095ae152015-12-18 09:39:55318int PhysicalSocket::Send(const void* pv, size_t cb) {
Yves Gerey665174f2018-06-19 13:03:05319 int sent = DoSend(
320 s_, reinterpret_cast<const char*>(pv), static_cast<int>(cb),
henrike@webrtc.orgf0488722014-05-13 18:00:26321#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
jbauch095ae152015-12-18 09:39:55322 // Suppress SIGPIPE. Without this, attempting to send on a socket whose
323 // other end is closed will result in a SIGPIPE signal being raised to
324 // our process, which by default will terminate the process, which we
325 // don't want. By specifying this flag, we'll just get the error EPIPE
326 // instead and can handle the error gracefully.
327 MSG_NOSIGNAL
henrike@webrtc.orgf0488722014-05-13 18:00:26328#else
jbauch095ae152015-12-18 09:39:55329 0
henrike@webrtc.orgf0488722014-05-13 18:00:26330#endif
jbauch095ae152015-12-18 09:39:55331 );
332 UpdateLastError();
333 MaybeRemapSendError();
334 // We have seen minidumps where this may be false.
nisseede5da42017-01-12 13:15:36335 RTC_DCHECK(sent <= static_cast<int>(cb));
jbauchf2a2bf42016-02-04 00:45:32336 if ((sent > 0 && sent < static_cast<int>(cb)) ||
337 (sent < 0 && IsBlockingError(GetError()))) {
jbauch577f5dc2017-05-17 23:32:26338 EnableEvents(DE_WRITE);
henrike@webrtc.orgf0488722014-05-13 18:00:26339 }
jbauch095ae152015-12-18 09:39:55340 return sent;
341}
henrike@webrtc.orgf0488722014-05-13 18:00:26342
jbauch095ae152015-12-18 09:39:55343int PhysicalSocket::SendTo(const void* buffer,
344 size_t length,
345 const SocketAddress& addr) {
346 sockaddr_storage saddr;
347 size_t len = addr.ToSockAddrStorage(&saddr);
Yves Gerey665174f2018-06-19 13:03:05348 int sent =
349 DoSendTo(s_, static_cast<const char*>(buffer), static_cast<int>(length),
henrike@webrtc.orgf0488722014-05-13 18:00:26350#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
Yves Gerey665174f2018-06-19 13:03:05351 // Suppress SIGPIPE. See above for explanation.
352 MSG_NOSIGNAL,
henrike@webrtc.orgf0488722014-05-13 18:00:26353#else
Yves Gerey665174f2018-06-19 13:03:05354 0,
henrike@webrtc.orgf0488722014-05-13 18:00:26355#endif
Yves Gerey665174f2018-06-19 13:03:05356 reinterpret_cast<sockaddr*>(&saddr), static_cast<int>(len));
jbauch095ae152015-12-18 09:39:55357 UpdateLastError();
358 MaybeRemapSendError();
359 // We have seen minidumps where this may be false.
nisseede5da42017-01-12 13:15:36360 RTC_DCHECK(sent <= static_cast<int>(length));
jbauchf2a2bf42016-02-04 00:45:32361 if ((sent > 0 && sent < static_cast<int>(length)) ||
362 (sent < 0 && IsBlockingError(GetError()))) {
jbauch577f5dc2017-05-17 23:32:26363 EnableEvents(DE_WRITE);
henrike@webrtc.orgf0488722014-05-13 18:00:26364 }
jbauch095ae152015-12-18 09:39:55365 return sent;
366}
henrike@webrtc.orgf0488722014-05-13 18:00:26367
Stefan Holmer9131efd2016-05-23 16:19:26368int PhysicalSocket::Recv(void* buffer, size_t length, int64_t* timestamp) {
Yves Gerey665174f2018-06-19 13:03:05369 int received =
370 ::recv(s_, static_cast<char*>(buffer), static_cast<int>(length), 0);
jbauch095ae152015-12-18 09:39:55371 if ((received == 0) && (length != 0)) {
372 // Note: on graceful shutdown, recv can return 0. In this case, we
373 // pretend it is blocking, and then signal close, so that simplifying
374 // assumptions can be made about Recv.
Mirko Bonadei675513b2017-11-09 10:09:25375 RTC_LOG(LS_WARNING) << "EOF from socket; deferring close event";
jbauch095ae152015-12-18 09:39:55376 // Must turn this back on so that the select() loop will notice the close
377 // event.
jbauch577f5dc2017-05-17 23:32:26378 EnableEvents(DE_READ);
jbauch095ae152015-12-18 09:39:55379 SetError(EWOULDBLOCK);
380 return SOCKET_ERROR;
henrike@webrtc.orgf0488722014-05-13 18:00:26381 }
Stefan Holmer9131efd2016-05-23 16:19:26382 if (timestamp) {
383 *timestamp = GetSocketRecvTimestamp(s_);
384 }
jbauch095ae152015-12-18 09:39:55385 UpdateLastError();
386 int error = GetError();
387 bool success = (received >= 0) || IsBlockingError(error);
388 if (udp_ || success) {
jbauch577f5dc2017-05-17 23:32:26389 EnableEvents(DE_READ);
henrike@webrtc.orgf0488722014-05-13 18:00:26390 }
jbauch095ae152015-12-18 09:39:55391 if (!success) {
Mirko Bonadei675513b2017-11-09 10:09:25392 RTC_LOG_F(LS_VERBOSE) << "Error = " << error;
henrike@webrtc.orgf0488722014-05-13 18:00:26393 }
jbauch095ae152015-12-18 09:39:55394 return received;
395}
henrike@webrtc.orgf0488722014-05-13 18:00:26396
jbauch095ae152015-12-18 09:39:55397int PhysicalSocket::RecvFrom(void* buffer,
398 size_t length,
Stefan Holmer9131efd2016-05-23 16:19:26399 SocketAddress* out_addr,
400 int64_t* timestamp) {
jbauch095ae152015-12-18 09:39:55401 sockaddr_storage addr_storage;
402 socklen_t addr_len = sizeof(addr_storage);
403 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
404 int received = ::recvfrom(s_, static_cast<char*>(buffer),
405 static_cast<int>(length), 0, addr, &addr_len);
Stefan Holmer9131efd2016-05-23 16:19:26406 if (timestamp) {
407 *timestamp = GetSocketRecvTimestamp(s_);
408 }
jbauch095ae152015-12-18 09:39:55409 UpdateLastError();
410 if ((received >= 0) && (out_addr != nullptr))
411 SocketAddressFromSockAddrStorage(addr_storage, out_addr);
412 int error = GetError();
413 bool success = (received >= 0) || IsBlockingError(error);
414 if (udp_ || success) {
jbauch577f5dc2017-05-17 23:32:26415 EnableEvents(DE_READ);
jbauch095ae152015-12-18 09:39:55416 }
417 if (!success) {
Mirko Bonadei675513b2017-11-09 10:09:25418 RTC_LOG_F(LS_VERBOSE) << "Error = " << error;
jbauch095ae152015-12-18 09:39:55419 }
420 return received;
421}
422
423int PhysicalSocket::Listen(int backlog) {
424 int err = ::listen(s_, backlog);
425 UpdateLastError();
426 if (err == 0) {
427 state_ = CS_CONNECTING;
jbauch577f5dc2017-05-17 23:32:26428 EnableEvents(DE_ACCEPT);
jbauch095ae152015-12-18 09:39:55429#if !defined(NDEBUG)
430 dbg_addr_ = "Listening @ ";
431 dbg_addr_.append(GetLocalAddress().ToString());
432#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26433 }
jbauch095ae152015-12-18 09:39:55434 return err;
435}
henrike@webrtc.orgf0488722014-05-13 18:00:26436
jbauch095ae152015-12-18 09:39:55437AsyncSocket* PhysicalSocket::Accept(SocketAddress* out_addr) {
438 // Always re-subscribe DE_ACCEPT to make sure new incoming connections will
439 // trigger an event even if DoAccept returns an error here.
jbauch577f5dc2017-05-17 23:32:26440 EnableEvents(DE_ACCEPT);
jbauch095ae152015-12-18 09:39:55441 sockaddr_storage addr_storage;
442 socklen_t addr_len = sizeof(addr_storage);
443 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
444 SOCKET s = DoAccept(s_, addr, &addr_len);
445 UpdateLastError();
446 if (s == INVALID_SOCKET)
447 return nullptr;
448 if (out_addr != nullptr)
449 SocketAddressFromSockAddrStorage(addr_storage, out_addr);
450 return ss_->WrapSocket(s);
451}
452
453int PhysicalSocket::Close() {
454 if (s_ == INVALID_SOCKET)
455 return 0;
456 int err = ::closesocket(s_);
457 UpdateLastError();
458 s_ = INVALID_SOCKET;
459 state_ = CS_CLOSED;
jbauch577f5dc2017-05-17 23:32:26460 SetEnabledEvents(0);
jbauch095ae152015-12-18 09:39:55461 if (resolver_) {
462 resolver_->Destroy(false);
463 resolver_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26464 }
jbauch095ae152015-12-18 09:39:55465 return err;
466}
henrike@webrtc.orgf0488722014-05-13 18:00:26467
jbauch095ae152015-12-18 09:39:55468SOCKET PhysicalSocket::DoAccept(SOCKET socket,
469 sockaddr* addr,
470 socklen_t* addrlen) {
471 return ::accept(socket, addr, addrlen);
472}
473
jbauchf2a2bf42016-02-04 00:45:32474int PhysicalSocket::DoSend(SOCKET socket, const char* buf, int len, int flags) {
475 return ::send(socket, buf, len, flags);
476}
477
478int PhysicalSocket::DoSendTo(SOCKET socket,
479 const char* buf,
480 int len,
481 int flags,
482 const struct sockaddr* dest_addr,
483 socklen_t addrlen) {
484 return ::sendto(socket, buf, len, flags, dest_addr, addrlen);
485}
486
jbauch095ae152015-12-18 09:39:55487void PhysicalSocket::OnResolveResult(AsyncResolverInterface* resolver) {
488 if (resolver != resolver_) {
489 return;
henrike@webrtc.orgf0488722014-05-13 18:00:26490 }
491
jbauch095ae152015-12-18 09:39:55492 int error = resolver_->GetError();
493 if (error == 0) {
494 error = DoConnect(resolver_->address());
495 } else {
496 Close();
henrike@webrtc.orgf0488722014-05-13 18:00:26497 }
498
jbauch095ae152015-12-18 09:39:55499 if (error) {
500 SetError(error);
501 SignalCloseEvent(this, error);
henrike@webrtc.orgf0488722014-05-13 18:00:26502 }
jbauch095ae152015-12-18 09:39:55503}
henrike@webrtc.orgf0488722014-05-13 18:00:26504
jbauch095ae152015-12-18 09:39:55505void PhysicalSocket::UpdateLastError() {
Patrik Höglunda8005cf2017-12-13 15:05:42506 SetError(LAST_SYSTEM_ERROR);
jbauch095ae152015-12-18 09:39:55507}
508
509void PhysicalSocket::MaybeRemapSendError() {
henrike@webrtc.orgf0488722014-05-13 18:00:26510#if defined(WEBRTC_MAC)
jbauch095ae152015-12-18 09:39:55511 // https://developer.apple.com/library/mac/documentation/Darwin/
512 // Reference/ManPages/man2/sendto.2.html
513 // ENOBUFS - The output queue for a network interface is full.
514 // This generally indicates that the interface has stopped sending,
515 // but may be caused by transient congestion.
516 if (GetError() == ENOBUFS) {
517 SetError(EWOULDBLOCK);
henrike@webrtc.orgf0488722014-05-13 18:00:26518 }
jbauch095ae152015-12-18 09:39:55519#endif
520}
henrike@webrtc.orgf0488722014-05-13 18:00:26521
jbauch577f5dc2017-05-17 23:32:26522void PhysicalSocket::SetEnabledEvents(uint8_t events) {
523 enabled_events_ = events;
524}
525
526void PhysicalSocket::EnableEvents(uint8_t events) {
527 enabled_events_ |= events;
528}
529
530void PhysicalSocket::DisableEvents(uint8_t events) {
531 enabled_events_ &= ~events;
532}
533
jbauch095ae152015-12-18 09:39:55534int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
535 switch (opt) {
536 case OPT_DONTFRAGMENT:
henrike@webrtc.orgf0488722014-05-13 18:00:26537#if defined(WEBRTC_WIN)
jbauch095ae152015-12-18 09:39:55538 *slevel = IPPROTO_IP;
539 *sopt = IP_DONTFRAGMENT;
540 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26541#elif defined(WEBRTC_MAC) || defined(BSD) || defined(__native_client__)
Mirko Bonadei675513b2017-11-09 10:09:25542 RTC_LOG(LS_WARNING) << "Socket::OPT_DONTFRAGMENT not supported.";
jbauch095ae152015-12-18 09:39:55543 return -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26544#elif defined(WEBRTC_POSIX)
jbauch095ae152015-12-18 09:39:55545 *slevel = IPPROTO_IP;
546 *sopt = IP_MTU_DISCOVER;
547 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26548#endif
jbauch095ae152015-12-18 09:39:55549 case OPT_RCVBUF:
550 *slevel = SOL_SOCKET;
551 *sopt = SO_RCVBUF;
552 break;
553 case OPT_SNDBUF:
554 *slevel = SOL_SOCKET;
555 *sopt = SO_SNDBUF;
556 break;
557 case OPT_NODELAY:
558 *slevel = IPPROTO_TCP;
559 *sopt = TCP_NODELAY;
560 break;
561 case OPT_DSCP:
Mirko Bonadei675513b2017-11-09 10:09:25562 RTC_LOG(LS_WARNING) << "Socket::OPT_DSCP not supported.";
jbauch095ae152015-12-18 09:39:55563 return -1;
564 case OPT_RTP_SENDTIME_EXTN_ID:
565 return -1; // No logging is necessary as this not a OS socket option.
566 default:
nissec80e7412017-01-11 13:56:46567 RTC_NOTREACHED();
jbauch095ae152015-12-18 09:39:55568 return -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26569 }
jbauch095ae152015-12-18 09:39:55570 return 0;
571}
henrike@webrtc.orgf0488722014-05-13 18:00:26572
Yves Gerey665174f2018-06-19 13:03:05573SocketDispatcher::SocketDispatcher(PhysicalSocketServer* ss)
jbauch4331fcd2016-01-07 06:20:28574#if defined(WEBRTC_WIN)
Yves Gerey665174f2018-06-19 13:03:05575 : PhysicalSocket(ss),
576 id_(0),
577 signal_close_(false)
jbauch4331fcd2016-01-07 06:20:28578#else
Yves Gerey665174f2018-06-19 13:03:05579 : PhysicalSocket(ss)
jbauch4331fcd2016-01-07 06:20:28580#endif
581{
582}
583
Yves Gerey665174f2018-06-19 13:03:05584SocketDispatcher::SocketDispatcher(SOCKET s, PhysicalSocketServer* ss)
jbauch4331fcd2016-01-07 06:20:28585#if defined(WEBRTC_WIN)
Yves Gerey665174f2018-06-19 13:03:05586 : PhysicalSocket(ss, s),
587 id_(0),
588 signal_close_(false)
jbauch4331fcd2016-01-07 06:20:28589#else
Yves Gerey665174f2018-06-19 13:03:05590 : PhysicalSocket(ss, s)
jbauch4331fcd2016-01-07 06:20:28591#endif
592{
593}
594
595SocketDispatcher::~SocketDispatcher() {
596 Close();
597}
598
599bool SocketDispatcher::Initialize() {
nisseede5da42017-01-12 13:15:36600 RTC_DCHECK(s_ != INVALID_SOCKET);
Yves Gerey665174f2018-06-19 13:03:05601// Must be a non-blocking
jbauch4331fcd2016-01-07 06:20:28602#if defined(WEBRTC_WIN)
603 u_long argp = 1;
604 ioctlsocket(s_, FIONBIO, &argp);
605#elif defined(WEBRTC_POSIX)
606 fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK);
607#endif
deadbeefeae45642017-05-26 23:27:09608#if defined(WEBRTC_IOS)
609 // iOS may kill sockets when the app is moved to the background
610 // (specifically, if the app doesn't use the "voip" UIBackgroundMode). When
611 // we attempt to write to such a socket, SIGPIPE will be raised, which by
612 // default will terminate the process, which we don't want. By specifying
613 // this socket option, SIGPIPE will be disabled for the socket.
614 int value = 1;
615 ::setsockopt(s_, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value));
616#endif
jbauch4331fcd2016-01-07 06:20:28617 ss_->Add(this);
618 return true;
619}
620
621bool SocketDispatcher::Create(int type) {
622 return Create(AF_INET, type);
623}
624
625bool SocketDispatcher::Create(int family, int type) {
626 // Change the socket to be non-blocking.
627 if (!PhysicalSocket::Create(family, type))
628 return false;
629
630 if (!Initialize())
631 return false;
632
633#if defined(WEBRTC_WIN)
Yves Gerey665174f2018-06-19 13:03:05634 do {
635 id_ = ++next_id_;
636 } while (id_ == 0);
jbauch4331fcd2016-01-07 06:20:28637#endif
638 return true;
639}
640
641#if defined(WEBRTC_WIN)
642
643WSAEVENT SocketDispatcher::GetWSAEvent() {
644 return WSA_INVALID_EVENT;
645}
646
647SOCKET SocketDispatcher::GetSocket() {
648 return s_;
649}
650
651bool SocketDispatcher::CheckSignalClose() {
652 if (!signal_close_)
653 return false;
654
655 char ch;
656 if (recv(s_, &ch, 1, MSG_PEEK) > 0)
657 return false;
658
659 state_ = CS_CLOSED;
660 signal_close_ = false;
661 SignalCloseEvent(this, signal_err_);
662 return true;
663}
664
665int SocketDispatcher::next_id_ = 0;
666
667#elif defined(WEBRTC_POSIX)
668
669int SocketDispatcher::GetDescriptor() {
670 return s_;
671}
672
673bool SocketDispatcher::IsDescriptorClosed() {
deadbeeffaedf7f2017-02-09 23:09:22674 if (udp_) {
675 // The MSG_PEEK trick doesn't work for UDP, since (at least in some
676 // circumstances) it requires reading an entire UDP packet, which would be
677 // bad for performance here. So, just check whether |s_| has been closed,
678 // which should be sufficient.
679 return s_ == INVALID_SOCKET;
680 }
jbauch4331fcd2016-01-07 06:20:28681 // We don't have a reliable way of distinguishing end-of-stream
682 // from readability. So test on each readable call. Is this
683 // inefficient? Probably.
684 char ch;
685 ssize_t res = ::recv(s_, &ch, 1, MSG_PEEK);
686 if (res > 0) {
687 // Data available, so not closed.
688 return false;
689 } else if (res == 0) {
690 // EOF, so closed.
691 return true;
692 } else { // error
693 switch (errno) {
694 // Returned if we've already closed s_.
695 case EBADF:
696 // Returned during ungraceful peer shutdown.
697 case ECONNRESET:
698 return true;
deadbeeffaedf7f2017-02-09 23:09:22699 // The normal blocking error; don't log anything.
700 case EWOULDBLOCK:
701 // Interrupted system call.
702 case EINTR:
703 return false;
jbauch4331fcd2016-01-07 06:20:28704 default:
705 // Assume that all other errors are just blocking errors, meaning the
706 // connection is still good but we just can't read from it right now.
707 // This should only happen when connecting (and at most once), because
708 // in all other cases this function is only called if the file
709 // descriptor is already known to be in the readable state. However,
710 // it's not necessary a problem if we spuriously interpret a
711 // "connection lost"-type error as a blocking error, because typically
712 // the next recv() will get EOF, so we'll still eventually notice that
713 // the socket is closed.
Mirko Bonadei675513b2017-11-09 10:09:25714 RTC_LOG_ERR(LS_WARNING) << "Assuming benign blocking error";
jbauch4331fcd2016-01-07 06:20:28715 return false;
716 }
717 }
718}
719
Yves Gerey665174f2018-06-19 13:03:05720#endif // WEBRTC_POSIX
jbauch4331fcd2016-01-07 06:20:28721
722uint32_t SocketDispatcher::GetRequestedEvents() {
jbauch577f5dc2017-05-17 23:32:26723 return enabled_events();
jbauch4331fcd2016-01-07 06:20:28724}
725
726void SocketDispatcher::OnPreEvent(uint32_t ff) {
727 if ((ff & DE_CONNECT) != 0)
728 state_ = CS_CONNECTED;
729
730#if defined(WEBRTC_WIN)
Yves Gerey665174f2018-06-19 13:03:05731// We set CS_CLOSED from CheckSignalClose.
jbauch4331fcd2016-01-07 06:20:28732#elif defined(WEBRTC_POSIX)
733 if ((ff & DE_CLOSE) != 0)
734 state_ = CS_CLOSED;
735#endif
736}
737
738#if defined(WEBRTC_WIN)
739
740void SocketDispatcher::OnEvent(uint32_t ff, int err) {
741 int cache_id = id_;
742 // Make sure we deliver connect/accept first. Otherwise, consumers may see
743 // something like a READ followed by a CONNECT, which would be odd.
744 if (((ff & DE_CONNECT) != 0) && (id_ == cache_id)) {
745 if (ff != DE_CONNECT)
Mirko Bonadei675513b2017-11-09 10:09:25746 RTC_LOG(LS_VERBOSE) << "Signalled with DE_CONNECT: " << ff;
jbauch577f5dc2017-05-17 23:32:26747 DisableEvents(DE_CONNECT);
jbauch4331fcd2016-01-07 06:20:28748#if !defined(NDEBUG)
749 dbg_addr_ = "Connected @ ";
750 dbg_addr_.append(GetRemoteAddress().ToString());
751#endif
752 SignalConnectEvent(this);
753 }
754 if (((ff & DE_ACCEPT) != 0) && (id_ == cache_id)) {
jbauch577f5dc2017-05-17 23:32:26755 DisableEvents(DE_ACCEPT);
jbauch4331fcd2016-01-07 06:20:28756 SignalReadEvent(this);
757 }
758 if ((ff & DE_READ) != 0) {
jbauch577f5dc2017-05-17 23:32:26759 DisableEvents(DE_READ);
jbauch4331fcd2016-01-07 06:20:28760 SignalReadEvent(this);
761 }
762 if (((ff & DE_WRITE) != 0) && (id_ == cache_id)) {
jbauch577f5dc2017-05-17 23:32:26763 DisableEvents(DE_WRITE);
jbauch4331fcd2016-01-07 06:20:28764 SignalWriteEvent(this);
765 }
766 if (((ff & DE_CLOSE) != 0) && (id_ == cache_id)) {
767 signal_close_ = true;
768 signal_err_ = err;
769 }
770}
771
772#elif defined(WEBRTC_POSIX)
773
774void SocketDispatcher::OnEvent(uint32_t ff, int err) {
jbauchde4db112017-05-31 20:09:18775#if defined(WEBRTC_USE_EPOLL)
776 // Remember currently enabled events so we can combine multiple changes
777 // into one update call later.
778 // The signal handlers might re-enable events disabled here, so we can't
779 // keep a list of events to disable at the end of the method. This list
780 // would not be updated with the events enabled by the signal handlers.
781 StartBatchedEventUpdates();
782#endif
jbauch4331fcd2016-01-07 06:20:28783 // Make sure we deliver connect/accept first. Otherwise, consumers may see
784 // something like a READ followed by a CONNECT, which would be odd.
785 if ((ff & DE_CONNECT) != 0) {
jbauch577f5dc2017-05-17 23:32:26786 DisableEvents(DE_CONNECT);
jbauch4331fcd2016-01-07 06:20:28787 SignalConnectEvent(this);
788 }
789 if ((ff & DE_ACCEPT) != 0) {
jbauch577f5dc2017-05-17 23:32:26790 DisableEvents(DE_ACCEPT);
jbauch4331fcd2016-01-07 06:20:28791 SignalReadEvent(this);
792 }
793 if ((ff & DE_READ) != 0) {
jbauch577f5dc2017-05-17 23:32:26794 DisableEvents(DE_READ);
jbauch4331fcd2016-01-07 06:20:28795 SignalReadEvent(this);
796 }
797 if ((ff & DE_WRITE) != 0) {
jbauch577f5dc2017-05-17 23:32:26798 DisableEvents(DE_WRITE);
jbauch4331fcd2016-01-07 06:20:28799 SignalWriteEvent(this);
800 }
801 if ((ff & DE_CLOSE) != 0) {
802 // The socket is now dead to us, so stop checking it.
jbauch577f5dc2017-05-17 23:32:26803 SetEnabledEvents(0);
jbauch4331fcd2016-01-07 06:20:28804 SignalCloseEvent(this, err);
805 }
jbauchde4db112017-05-31 20:09:18806#if defined(WEBRTC_USE_EPOLL)
807 FinishBatchedEventUpdates();
808#endif
jbauch4331fcd2016-01-07 06:20:28809}
810
Yves Gerey665174f2018-06-19 13:03:05811#endif // WEBRTC_POSIX
jbauch4331fcd2016-01-07 06:20:28812
jbauchde4db112017-05-31 20:09:18813#if defined(WEBRTC_USE_EPOLL)
814
815static int GetEpollEvents(uint32_t ff) {
816 int events = 0;
817 if (ff & (DE_READ | DE_ACCEPT)) {
818 events |= EPOLLIN;
819 }
820 if (ff & (DE_WRITE | DE_CONNECT)) {
821 events |= EPOLLOUT;
822 }
823 return events;
824}
825
826void SocketDispatcher::StartBatchedEventUpdates() {
827 RTC_DCHECK_EQ(saved_enabled_events_, -1);
828 saved_enabled_events_ = enabled_events();
829}
830
831void SocketDispatcher::FinishBatchedEventUpdates() {
832 RTC_DCHECK_NE(saved_enabled_events_, -1);
833 uint8_t old_events = static_cast<uint8_t>(saved_enabled_events_);
834 saved_enabled_events_ = -1;
835 MaybeUpdateDispatcher(old_events);
836}
837
838void SocketDispatcher::MaybeUpdateDispatcher(uint8_t old_events) {
839 if (GetEpollEvents(enabled_events()) != GetEpollEvents(old_events) &&
840 saved_enabled_events_ == -1) {
841 ss_->Update(this);
842 }
843}
844
845void SocketDispatcher::SetEnabledEvents(uint8_t events) {
846 uint8_t old_events = enabled_events();
847 PhysicalSocket::SetEnabledEvents(events);
848 MaybeUpdateDispatcher(old_events);
849}
850
851void SocketDispatcher::EnableEvents(uint8_t events) {
852 uint8_t old_events = enabled_events();
853 PhysicalSocket::EnableEvents(events);
854 MaybeUpdateDispatcher(old_events);
855}
856
857void SocketDispatcher::DisableEvents(uint8_t events) {
858 uint8_t old_events = enabled_events();
859 PhysicalSocket::DisableEvents(events);
860 MaybeUpdateDispatcher(old_events);
861}
862
863#endif // WEBRTC_USE_EPOLL
864
jbauch4331fcd2016-01-07 06:20:28865int SocketDispatcher::Close() {
866 if (s_ == INVALID_SOCKET)
867 return 0;
868
869#if defined(WEBRTC_WIN)
870 id_ = 0;
871 signal_close_ = false;
872#endif
873 ss_->Remove(this);
874 return PhysicalSocket::Close();
875}
876
henrike@webrtc.orgf0488722014-05-13 18:00:26877#if defined(WEBRTC_POSIX)
878class EventDispatcher : public Dispatcher {
879 public:
880 EventDispatcher(PhysicalSocketServer* ss) : ss_(ss), fSignaled_(false) {
881 if (pipe(afd_) < 0)
Mirko Bonadei675513b2017-11-09 10:09:25882 RTC_LOG(LERROR) << "pipe failed";
henrike@webrtc.orgf0488722014-05-13 18:00:26883 ss_->Add(this);
884 }
885
kwiberg@webrtc.org67186fe2015-03-09 22:21:53886 ~EventDispatcher() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26887 ss_->Remove(this);
888 close(afd_[0]);
889 close(afd_[1]);
890 }
891
892 virtual void Signal() {
893 CritScope cs(&crit_);
894 if (!fSignaled_) {
Peter Boström0c4e06b2015-10-07 10:23:21895 const uint8_t b[1] = {0};
nissec16fa5e2017-02-07 15:18:43896 const ssize_t res = write(afd_[1], b, sizeof(b));
897 RTC_DCHECK_EQ(1, res);
898 fSignaled_ = true;
henrike@webrtc.orgf0488722014-05-13 18:00:26899 }
900 }
901
Peter Boström0c4e06b2015-10-07 10:23:21902 uint32_t GetRequestedEvents() override { return DE_READ; }
henrike@webrtc.orgf0488722014-05-13 18:00:26903
Peter Boström0c4e06b2015-10-07 10:23:21904 void OnPreEvent(uint32_t ff) override {
henrike@webrtc.orgf0488722014-05-13 18:00:26905 // It is not possible to perfectly emulate an auto-resetting event with
906 // pipes. This simulates it by resetting before the event is handled.
907
908 CritScope cs(&crit_);
909 if (fSignaled_) {
Peter Boström0c4e06b2015-10-07 10:23:21910 uint8_t b[4]; // Allow for reading more than 1 byte, but expect 1.
nissec16fa5e2017-02-07 15:18:43911 const ssize_t res = read(afd_[0], b, sizeof(b));
912 RTC_DCHECK_EQ(1, res);
henrike@webrtc.orgf0488722014-05-13 18:00:26913 fSignaled_ = false;
914 }
915 }
916
nissec80e7412017-01-11 13:56:46917 void OnEvent(uint32_t ff, int err) override { RTC_NOTREACHED(); }
henrike@webrtc.orgf0488722014-05-13 18:00:26918
kwiberg@webrtc.org67186fe2015-03-09 22:21:53919 int GetDescriptor() override { return afd_[0]; }
henrike@webrtc.orgf0488722014-05-13 18:00:26920
kwiberg@webrtc.org67186fe2015-03-09 22:21:53921 bool IsDescriptorClosed() override { return false; }
henrike@webrtc.orgf0488722014-05-13 18:00:26922
923 private:
Yves Gerey665174f2018-06-19 13:03:05924 PhysicalSocketServer* ss_;
henrike@webrtc.orgf0488722014-05-13 18:00:26925 int afd_[2];
926 bool fSignaled_;
927 CriticalSection crit_;
928};
929
930// These two classes use the self-pipe trick to deliver POSIX signals to our
931// select loop. This is the only safe, reliable, cross-platform way to do
932// non-trivial things with a POSIX signal in an event-driven program (until
933// proper pselect() implementations become ubiquitous).
934
935class PosixSignalHandler {
936 public:
937 // POSIX only specifies 32 signals, but in principle the system might have
938 // more and the programmer might choose to use them, so we size our array
939 // for 128.
940 static const int kNumPosixSignals = 128;
941
942 // There is just a single global instance. (Signal handlers do not get any
943 // sort of user-defined void * parameter, so they can't access anything that
944 // isn't global.)
945 static PosixSignalHandler* Instance() {
Niels Möller14682a32018-05-24 06:54:25946 static PosixSignalHandler* const instance = new PosixSignalHandler();
947 return instance;
henrike@webrtc.orgf0488722014-05-13 18:00:26948 }
949
950 // Returns true if the given signal number is set.
951 bool IsSignalSet(int signum) const {
nisseede5da42017-01-12 13:15:36952 RTC_DCHECK(signum < static_cast<int>(arraysize(received_signal_)));
tfarina5237aaf2015-11-11 07:44:30953 if (signum < static_cast<int>(arraysize(received_signal_))) {
henrike@webrtc.orgf0488722014-05-13 18:00:26954 return received_signal_[signum];
955 } else {
956 return false;
957 }
958 }
959
960 // Clears the given signal number.
961 void ClearSignal(int signum) {
nisseede5da42017-01-12 13:15:36962 RTC_DCHECK(signum < static_cast<int>(arraysize(received_signal_)));
tfarina5237aaf2015-11-11 07:44:30963 if (signum < static_cast<int>(arraysize(received_signal_))) {
henrike@webrtc.orgf0488722014-05-13 18:00:26964 received_signal_[signum] = false;
965 }
966 }
967
968 // Returns the file descriptor to monitor for signal events.
Yves Gerey665174f2018-06-19 13:03:05969 int GetDescriptor() const { return afd_[0]; }
henrike@webrtc.orgf0488722014-05-13 18:00:26970
971 // This is called directly from our real signal handler, so it must be
972 // signal-handler-safe. That means it cannot assume anything about the
973 // user-level state of the process, since the handler could be executed at any
974 // time on any thread.
975 void OnPosixSignalReceived(int signum) {
tfarina5237aaf2015-11-11 07:44:30976 if (signum >= static_cast<int>(arraysize(received_signal_))) {
henrike@webrtc.orgf0488722014-05-13 18:00:26977 // We don't have space in our array for this.
978 return;
979 }
980 // Set a flag saying we've seen this signal.
981 received_signal_[signum] = true;
982 // Notify application code that we got a signal.
Peter Boström0c4e06b2015-10-07 10:23:21983 const uint8_t b[1] = {0};
henrike@webrtc.orgf0488722014-05-13 18:00:26984 if (-1 == write(afd_[1], b, sizeof(b))) {
985 // Nothing we can do here. If there's an error somehow then there's
986 // nothing we can safely do from a signal handler.
987 // No, we can't even safely log it.
988 // But, we still have to check the return value here. Otherwise,
989 // GCC 4.4.1 complains ignoring return value. Even (void) doesn't help.
990 return;
991 }
992 }
993
994 private:
995 PosixSignalHandler() {
996 if (pipe(afd_) < 0) {
Mirko Bonadei675513b2017-11-09 10:09:25997 RTC_LOG_ERR(LS_ERROR) << "pipe failed";
henrike@webrtc.orgf0488722014-05-13 18:00:26998 return;
999 }
1000 if (fcntl(afd_[0], F_SETFL, O_NONBLOCK) < 0) {
Mirko Bonadei675513b2017-11-09 10:09:251001 RTC_LOG_ERR(LS_WARNING) << "fcntl #1 failed";
henrike@webrtc.orgf0488722014-05-13 18:00:261002 }
1003 if (fcntl(afd_[1], F_SETFL, O_NONBLOCK) < 0) {
Mirko Bonadei675513b2017-11-09 10:09:251004 RTC_LOG_ERR(LS_WARNING) << "fcntl #2 failed";
henrike@webrtc.orgf0488722014-05-13 18:00:261005 }
Yves Gerey665174f2018-06-19 13:03:051006 memset(const_cast<void*>(static_cast<volatile void*>(received_signal_)), 0,
henrike@webrtc.orgf0488722014-05-13 18:00:261007 sizeof(received_signal_));
1008 }
1009
1010 ~PosixSignalHandler() {
1011 int fd1 = afd_[0];
1012 int fd2 = afd_[1];
1013 // We clobber the stored file descriptor numbers here or else in principle
1014 // a signal that happens to be delivered during application termination
1015 // could erroneously write a zero byte to an unrelated file handle in
1016 // OnPosixSignalReceived() if some other file happens to be opened later
1017 // during shutdown and happens to be given the same file descriptor number
1018 // as our pipe had. Unfortunately even with this precaution there is still a
1019 // race where that could occur if said signal happens to be handled
1020 // concurrently with this code and happens to have already read the value of
1021 // afd_[1] from memory before we clobber it, but that's unlikely.
1022 afd_[0] = -1;
1023 afd_[1] = -1;
1024 close(fd1);
1025 close(fd2);
1026 }
1027
1028 int afd_[2];
1029 // These are boolean flags that will be set in our signal handler and read
1030 // and cleared from Wait(). There is a race involved in this, but it is
1031 // benign. The signal handler sets the flag before signaling the pipe, so
1032 // we'll never end up blocking in select() while a flag is still true.
1033 // However, if two of the same signal arrive close to each other then it's
1034 // possible that the second time the handler may set the flag while it's still
1035 // true, meaning that signal will be missed. But the first occurrence of it
1036 // will still be handled, so this isn't a problem.
1037 // Volatile is not necessary here for correctness, but this data _is_ volatile
1038 // so I've marked it as such.
Peter Boström0c4e06b2015-10-07 10:23:211039 volatile uint8_t received_signal_[kNumPosixSignals];
henrike@webrtc.orgf0488722014-05-13 18:00:261040};
1041
1042class PosixSignalDispatcher : public Dispatcher {
1043 public:
Yves Gerey665174f2018-06-19 13:03:051044 PosixSignalDispatcher(PhysicalSocketServer* owner) : owner_(owner) {
henrike@webrtc.orgf0488722014-05-13 18:00:261045 owner_->Add(this);
1046 }
1047
Yves Gerey665174f2018-06-19 13:03:051048 ~PosixSignalDispatcher() override { owner_->Remove(this); }
henrike@webrtc.orgf0488722014-05-13 18:00:261049
Peter Boström0c4e06b2015-10-07 10:23:211050 uint32_t GetRequestedEvents() override { return DE_READ; }
henrike@webrtc.orgf0488722014-05-13 18:00:261051
Peter Boström0c4e06b2015-10-07 10:23:211052 void OnPreEvent(uint32_t ff) override {
henrike@webrtc.orgf0488722014-05-13 18:00:261053 // Events might get grouped if signals come very fast, so we read out up to
1054 // 16 bytes to make sure we keep the pipe empty.
Peter Boström0c4e06b2015-10-07 10:23:211055 uint8_t b[16];
henrike@webrtc.orgf0488722014-05-13 18:00:261056 ssize_t ret = read(GetDescriptor(), b, sizeof(b));
1057 if (ret < 0) {
Mirko Bonadei675513b2017-11-09 10:09:251058 RTC_LOG_ERR(LS_WARNING) << "Error in read()";
henrike@webrtc.orgf0488722014-05-13 18:00:261059 } else if (ret == 0) {
Mirko Bonadei675513b2017-11-09 10:09:251060 RTC_LOG(LS_WARNING) << "Should have read at least one byte";
henrike@webrtc.orgf0488722014-05-13 18:00:261061 }
1062 }
1063
Peter Boström0c4e06b2015-10-07 10:23:211064 void OnEvent(uint32_t ff, int err) override {
henrike@webrtc.orgf0488722014-05-13 18:00:261065 for (int signum = 0; signum < PosixSignalHandler::kNumPosixSignals;
1066 ++signum) {
1067 if (PosixSignalHandler::Instance()->IsSignalSet(signum)) {
1068 PosixSignalHandler::Instance()->ClearSignal(signum);
1069 HandlerMap::iterator i = handlers_.find(signum);
1070 if (i == handlers_.end()) {
1071 // This can happen if a signal is delivered to our process at around
1072 // the same time as we unset our handler for it. It is not an error
1073 // condition, but it's unusual enough to be worth logging.
Mirko Bonadei675513b2017-11-09 10:09:251074 RTC_LOG(LS_INFO) << "Received signal with no handler: " << signum;
henrike@webrtc.orgf0488722014-05-13 18:00:261075 } else {
1076 // Otherwise, execute our handler.
1077 (*i->second)(signum);
1078 }
1079 }
1080 }
1081 }
1082
kwiberg@webrtc.org67186fe2015-03-09 22:21:531083 int GetDescriptor() override {
henrike@webrtc.orgf0488722014-05-13 18:00:261084 return PosixSignalHandler::Instance()->GetDescriptor();
1085 }
1086
kwiberg@webrtc.org67186fe2015-03-09 22:21:531087 bool IsDescriptorClosed() override { return false; }
henrike@webrtc.orgf0488722014-05-13 18:00:261088
1089 void SetHandler(int signum, void (*handler)(int)) {
1090 handlers_[signum] = handler;
1091 }
1092
Yves Gerey665174f2018-06-19 13:03:051093 void ClearHandler(int signum) { handlers_.erase(signum); }
henrike@webrtc.orgf0488722014-05-13 18:00:261094
Yves Gerey665174f2018-06-19 13:03:051095 bool HasHandlers() { return !handlers_.empty(); }
henrike@webrtc.orgf0488722014-05-13 18:00:261096
1097 private:
1098 typedef std::map<int, void (*)(int)> HandlerMap;
1099
1100 HandlerMap handlers_;
1101 // Our owner.
Yves Gerey665174f2018-06-19 13:03:051102 PhysicalSocketServer* owner_;
henrike@webrtc.orgf0488722014-05-13 18:00:261103};
1104
Yves Gerey665174f2018-06-19 13:03:051105#endif // WEBRTC_POSIX
henrike@webrtc.orgf0488722014-05-13 18:00:261106
1107#if defined(WEBRTC_WIN)
Peter Boström0c4e06b2015-10-07 10:23:211108static uint32_t FlagsToEvents(uint32_t events) {
1109 uint32_t ffFD = FD_CLOSE;
henrike@webrtc.orgf0488722014-05-13 18:00:261110 if (events & DE_READ)
1111 ffFD |= FD_READ;
1112 if (events & DE_WRITE)
1113 ffFD |= FD_WRITE;
1114 if (events & DE_CONNECT)
1115 ffFD |= FD_CONNECT;
1116 if (events & DE_ACCEPT)
1117 ffFD |= FD_ACCEPT;
1118 return ffFD;
1119}
1120
1121class EventDispatcher : public Dispatcher {
1122 public:
Yves Gerey665174f2018-06-19 13:03:051123 EventDispatcher(PhysicalSocketServer* ss) : ss_(ss) {
henrike@webrtc.orgf0488722014-05-13 18:00:261124 hev_ = WSACreateEvent();
1125 if (hev_) {
1126 ss_->Add(this);
1127 }
1128 }
1129
Steve Anton9de3aac2017-10-24 17:08:261130 ~EventDispatcher() override {
deadbeef37f5ecf2017-02-27 22:06:411131 if (hev_ != nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:261132 ss_->Remove(this);
1133 WSACloseEvent(hev_);
deadbeef37f5ecf2017-02-27 22:06:411134 hev_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:261135 }
1136 }
1137
1138 virtual void Signal() {
deadbeef37f5ecf2017-02-27 22:06:411139 if (hev_ != nullptr)
henrike@webrtc.orgf0488722014-05-13 18:00:261140 WSASetEvent(hev_);
1141 }
1142
Steve Anton9de3aac2017-10-24 17:08:261143 uint32_t GetRequestedEvents() override { return 0; }
henrike@webrtc.orgf0488722014-05-13 18:00:261144
Steve Anton9de3aac2017-10-24 17:08:261145 void OnPreEvent(uint32_t ff) override { WSAResetEvent(hev_); }
henrike@webrtc.orgf0488722014-05-13 18:00:261146
Steve Anton9de3aac2017-10-24 17:08:261147 void OnEvent(uint32_t ff, int err) override {}
henrike@webrtc.orgf0488722014-05-13 18:00:261148
Steve Anton9de3aac2017-10-24 17:08:261149 WSAEVENT GetWSAEvent() override { return hev_; }
henrike@webrtc.orgf0488722014-05-13 18:00:261150
Steve Anton9de3aac2017-10-24 17:08:261151 SOCKET GetSocket() override { return INVALID_SOCKET; }
henrike@webrtc.orgf0488722014-05-13 18:00:261152
Steve Anton9de3aac2017-10-24 17:08:261153 bool CheckSignalClose() override { return false; }
henrike@webrtc.orgf0488722014-05-13 18:00:261154
Steve Anton9de3aac2017-10-24 17:08:261155 private:
henrike@webrtc.orgf0488722014-05-13 18:00:261156 PhysicalSocketServer* ss_;
1157 WSAEVENT hev_;
1158};
honghaizcec0a082016-01-15 22:49:091159#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:261160
1161// Sets the value of a boolean value to false when signaled.
1162class Signaler : public EventDispatcher {
1163 public:
Yves Gerey665174f2018-06-19 13:03:051164 Signaler(PhysicalSocketServer* ss, bool* pf) : EventDispatcher(ss), pf_(pf) {}
1165 ~Signaler() override {}
henrike@webrtc.orgf0488722014-05-13 18:00:261166
Peter Boström0c4e06b2015-10-07 10:23:211167 void OnEvent(uint32_t ff, int err) override {
henrike@webrtc.orgf0488722014-05-13 18:00:261168 if (pf_)
1169 *pf_ = false;
1170 }
1171
1172 private:
Yves Gerey665174f2018-06-19 13:03:051173 bool* pf_;
henrike@webrtc.orgf0488722014-05-13 18:00:261174};
1175
Yves Gerey665174f2018-06-19 13:03:051176PhysicalSocketServer::PhysicalSocketServer() : fWait_(false) {
jbauchde4db112017-05-31 20:09:181177#if defined(WEBRTC_USE_EPOLL)
1178 // Since Linux 2.6.8, the size argument is ignored, but must be greater than
1179 // zero. Before that the size served as hint to the kernel for the amount of
1180 // space to initially allocate in internal data structures.
1181 epoll_fd_ = epoll_create(FD_SETSIZE);
1182 if (epoll_fd_ == -1) {
1183 // Not an error, will fall back to "select" below.
Mirko Bonadei675513b2017-11-09 10:09:251184 RTC_LOG_E(LS_WARNING, EN, errno) << "epoll_create";
jbauchde4db112017-05-31 20:09:181185 epoll_fd_ = INVALID_SOCKET;
1186 }
1187#endif
henrike@webrtc.orgf0488722014-05-13 18:00:261188 signal_wakeup_ = new Signaler(this, &fWait_);
1189#if defined(WEBRTC_WIN)
1190 socket_ev_ = WSACreateEvent();
1191#endif
1192}
1193
1194PhysicalSocketServer::~PhysicalSocketServer() {
1195#if defined(WEBRTC_WIN)
1196 WSACloseEvent(socket_ev_);
1197#endif
1198#if defined(WEBRTC_POSIX)
1199 signal_dispatcher_.reset();
1200#endif
1201 delete signal_wakeup_;
jbauchde4db112017-05-31 20:09:181202#if defined(WEBRTC_USE_EPOLL)
1203 if (epoll_fd_ != INVALID_SOCKET) {
1204 close(epoll_fd_);
1205 }
1206#endif
nisseede5da42017-01-12 13:15:361207 RTC_DCHECK(dispatchers_.empty());
henrike@webrtc.orgf0488722014-05-13 18:00:261208}
1209
1210void PhysicalSocketServer::WakeUp() {
1211 signal_wakeup_->Signal();
1212}
1213
henrike@webrtc.orgf0488722014-05-13 18:00:261214Socket* PhysicalSocketServer::CreateSocket(int family, int type) {
1215 PhysicalSocket* socket = new PhysicalSocket(this);
1216 if (socket->Create(family, type)) {
1217 return socket;
1218 } else {
1219 delete socket;
jbauch095ae152015-12-18 09:39:551220 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:261221 }
1222}
1223
henrike@webrtc.orgf0488722014-05-13 18:00:261224AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int family, int type) {
1225 SocketDispatcher* dispatcher = new SocketDispatcher(this);
1226 if (dispatcher->Create(family, type)) {
1227 return dispatcher;
1228 } else {
1229 delete dispatcher;
jbauch095ae152015-12-18 09:39:551230 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:261231 }
1232}
1233
1234AsyncSocket* PhysicalSocketServer::WrapSocket(SOCKET s) {
1235 SocketDispatcher* dispatcher = new SocketDispatcher(s, this);
1236 if (dispatcher->Initialize()) {
1237 return dispatcher;
1238 } else {
1239 delete dispatcher;
jbauch095ae152015-12-18 09:39:551240 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:261241 }
1242}
1243
Yves Gerey665174f2018-06-19 13:03:051244void PhysicalSocketServer::Add(Dispatcher* pdispatcher) {
henrike@webrtc.orgf0488722014-05-13 18:00:261245 CritScope cs(&crit_);
jbauchde4db112017-05-31 20:09:181246 if (processing_dispatchers_) {
1247 // A dispatcher is being added while a "Wait" call is processing the
1248 // list of socket events.
1249 // Defer adding to "dispatchers_" set until processing is done to avoid
1250 // invalidating the iterator in "Wait".
1251 pending_remove_dispatchers_.erase(pdispatcher);
1252 pending_add_dispatchers_.insert(pdispatcher);
1253 } else {
1254 dispatchers_.insert(pdispatcher);
1255 }
1256#if defined(WEBRTC_USE_EPOLL)
1257 if (epoll_fd_ != INVALID_SOCKET) {
1258 AddEpoll(pdispatcher);
1259 }
1260#endif // WEBRTC_USE_EPOLL
henrike@webrtc.orgf0488722014-05-13 18:00:261261}
1262
Yves Gerey665174f2018-06-19 13:03:051263void PhysicalSocketServer::Remove(Dispatcher* pdispatcher) {
henrike@webrtc.orgf0488722014-05-13 18:00:261264 CritScope cs(&crit_);
jbauchde4db112017-05-31 20:09:181265 if (processing_dispatchers_) {
1266 // A dispatcher is being removed while a "Wait" call is processing the
1267 // list of socket events.
1268 // Defer removal from "dispatchers_" set until processing is done to avoid
1269 // invalidating the iterator in "Wait".
1270 if (!pending_add_dispatchers_.erase(pdispatcher) &&
1271 dispatchers_.find(pdispatcher) == dispatchers_.end()) {
Mirko Bonadei675513b2017-11-09 10:09:251272 RTC_LOG(LS_WARNING) << "PhysicalSocketServer asked to remove a unknown "
1273 << "dispatcher, potentially from a duplicate call to "
1274 << "Add.";
jbauchde4db112017-05-31 20:09:181275 return;
1276 }
1277
1278 pending_remove_dispatchers_.insert(pdispatcher);
1279 } else if (!dispatchers_.erase(pdispatcher)) {
Mirko Bonadei675513b2017-11-09 10:09:251280 RTC_LOG(LS_WARNING)
1281 << "PhysicalSocketServer asked to remove a unknown "
1282 << "dispatcher, potentially from a duplicate call to Add.";
henrike@webrtc.orgf0488722014-05-13 18:00:261283 return;
1284 }
jbauchde4db112017-05-31 20:09:181285#if defined(WEBRTC_USE_EPOLL)
1286 if (epoll_fd_ != INVALID_SOCKET) {
1287 RemoveEpoll(pdispatcher);
1288 }
1289#endif // WEBRTC_USE_EPOLL
1290}
1291
1292void PhysicalSocketServer::Update(Dispatcher* pdispatcher) {
1293#if defined(WEBRTC_USE_EPOLL)
1294 if (epoll_fd_ == INVALID_SOCKET) {
1295 return;
1296 }
1297
1298 CritScope cs(&crit_);
1299 if (dispatchers_.find(pdispatcher) == dispatchers_.end()) {
1300 return;
1301 }
1302
1303 UpdateEpoll(pdispatcher);
1304#endif
1305}
1306
1307void PhysicalSocketServer::AddRemovePendingDispatchers() {
1308 if (!pending_add_dispatchers_.empty()) {
1309 for (Dispatcher* pdispatcher : pending_add_dispatchers_) {
1310 dispatchers_.insert(pdispatcher);
henrike@webrtc.orgf0488722014-05-13 18:00:261311 }
jbauchde4db112017-05-31 20:09:181312 pending_add_dispatchers_.clear();
1313 }
1314
1315 if (!pending_remove_dispatchers_.empty()) {
1316 for (Dispatcher* pdispatcher : pending_remove_dispatchers_) {
1317 dispatchers_.erase(pdispatcher);
1318 }
1319 pending_remove_dispatchers_.clear();
henrike@webrtc.orgf0488722014-05-13 18:00:261320 }
1321}
1322
1323#if defined(WEBRTC_POSIX)
jbauchde4db112017-05-31 20:09:181324
henrike@webrtc.orgf0488722014-05-13 18:00:261325bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
jbauchde4db112017-05-31 20:09:181326#if defined(WEBRTC_USE_EPOLL)
1327 // We don't keep a dedicated "epoll" descriptor containing only the non-IO
1328 // (i.e. signaling) dispatcher, so "poll" will be used instead of the default
1329 // "select" to support sockets larger than FD_SETSIZE.
1330 if (!process_io) {
1331 return WaitPoll(cmsWait, signal_wakeup_);
1332 } else if (epoll_fd_ != INVALID_SOCKET) {
1333 return WaitEpoll(cmsWait);
1334 }
1335#endif
1336 return WaitSelect(cmsWait, process_io);
1337}
1338
1339static void ProcessEvents(Dispatcher* dispatcher,
1340 bool readable,
1341 bool writable,
1342 bool check_error) {
1343 int errcode = 0;
1344 // TODO(pthatcher): Should we set errcode if getsockopt fails?
1345 if (check_error) {
1346 socklen_t len = sizeof(errcode);
1347 ::getsockopt(dispatcher->GetDescriptor(), SOL_SOCKET, SO_ERROR, &errcode,
1348 &len);
1349 }
1350
1351 uint32_t ff = 0;
1352
1353 // Check readable descriptors. If we're waiting on an accept, signal
1354 // that. Otherwise we're waiting for data, check to see if we're
1355 // readable or really closed.
1356 // TODO(pthatcher): Only peek at TCP descriptors.
1357 if (readable) {
1358 if (dispatcher->GetRequestedEvents() & DE_ACCEPT) {
1359 ff |= DE_ACCEPT;
1360 } else if (errcode || dispatcher->IsDescriptorClosed()) {
1361 ff |= DE_CLOSE;
1362 } else {
1363 ff |= DE_READ;
1364 }
1365 }
1366
1367 // Check writable descriptors. If we're waiting on a connect, detect
1368 // success versus failure by the reaped error code.
1369 if (writable) {
1370 if (dispatcher->GetRequestedEvents() & DE_CONNECT) {
1371 if (!errcode) {
1372 ff |= DE_CONNECT;
1373 } else {
1374 ff |= DE_CLOSE;
1375 }
1376 } else {
1377 ff |= DE_WRITE;
1378 }
1379 }
1380
1381 // Tell the descriptor about the event.
1382 if (ff != 0) {
1383 dispatcher->OnPreEvent(ff);
1384 dispatcher->OnEvent(ff, errcode);
1385 }
1386}
1387
1388bool PhysicalSocketServer::WaitSelect(int cmsWait, bool process_io) {
henrike@webrtc.orgf0488722014-05-13 18:00:261389 // Calculate timing information
1390
deadbeef37f5ecf2017-02-27 22:06:411391 struct timeval* ptvWait = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:261392 struct timeval tvWait;
1393 struct timeval tvStop;
1394 if (cmsWait != kForever) {
1395 // Calculate wait timeval
1396 tvWait.tv_sec = cmsWait / 1000;
1397 tvWait.tv_usec = (cmsWait % 1000) * 1000;
1398 ptvWait = &tvWait;
1399
1400 // Calculate when to return in a timeval
deadbeef37f5ecf2017-02-27 22:06:411401 gettimeofday(&tvStop, nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:261402 tvStop.tv_sec += tvWait.tv_sec;
1403 tvStop.tv_usec += tvWait.tv_usec;
1404 if (tvStop.tv_usec >= 1000000) {
1405 tvStop.tv_usec -= 1000000;
1406 tvStop.tv_sec += 1;
1407 }
1408 }
1409
1410 // Zero all fd_sets. Don't need to do this inside the loop since
1411 // select() zeros the descriptors not signaled
1412
1413 fd_set fdsRead;
1414 FD_ZERO(&fdsRead);
1415 fd_set fdsWrite;
1416 FD_ZERO(&fdsWrite);
Yves Gerey665174f2018-06-19 13:03:051417// Explicitly unpoison these FDs on MemorySanitizer which doesn't handle the
1418// inline assembly in FD_ZERO.
1419// http://crbug.com/344505
pbos@webrtc.org27e58982014-10-07 17:56:531420#ifdef MEMORY_SANITIZER
1421 __msan_unpoison(&fdsRead, sizeof(fdsRead));
1422 __msan_unpoison(&fdsWrite, sizeof(fdsWrite));
1423#endif
henrike@webrtc.orgf0488722014-05-13 18:00:261424
1425 fWait_ = true;
1426
1427 while (fWait_) {
1428 int fdmax = -1;
1429 {
1430 CritScope cr(&crit_);
jbauchde4db112017-05-31 20:09:181431 // TODO(jbauch): Support re-entrant waiting.
1432 RTC_DCHECK(!processing_dispatchers_);
1433 for (Dispatcher* pdispatcher : dispatchers_) {
henrike@webrtc.orgf0488722014-05-13 18:00:261434 // Query dispatchers for read and write wait state
nisseede5da42017-01-12 13:15:361435 RTC_DCHECK(pdispatcher);
henrike@webrtc.orgf0488722014-05-13 18:00:261436 if (!process_io && (pdispatcher != signal_wakeup_))
1437 continue;
1438 int fd = pdispatcher->GetDescriptor();
jbauchde4db112017-05-31 20:09:181439 // "select"ing a file descriptor that is equal to or larger than
1440 // FD_SETSIZE will result in undefined behavior.
1441 RTC_DCHECK_LT(fd, FD_SETSIZE);
henrike@webrtc.orgf0488722014-05-13 18:00:261442 if (fd > fdmax)
1443 fdmax = fd;
1444
Peter Boström0c4e06b2015-10-07 10:23:211445 uint32_t ff = pdispatcher->GetRequestedEvents();
henrike@webrtc.orgf0488722014-05-13 18:00:261446 if (ff & (DE_READ | DE_ACCEPT))
1447 FD_SET(fd, &fdsRead);
1448 if (ff & (DE_WRITE | DE_CONNECT))
1449 FD_SET(fd, &fdsWrite);
1450 }
1451 }
1452
1453 // Wait then call handlers as appropriate
1454 // < 0 means error
1455 // 0 means timeout
1456 // > 0 means count of descriptors ready
deadbeef37f5ecf2017-02-27 22:06:411457 int n = select(fdmax + 1, &fdsRead, &fdsWrite, nullptr, ptvWait);
henrike@webrtc.orgf0488722014-05-13 18:00:261458
1459 // If error, return error.
1460 if (n < 0) {
1461 if (errno != EINTR) {
Mirko Bonadei675513b2017-11-09 10:09:251462 RTC_LOG_E(LS_ERROR, EN, errno) << "select";
henrike@webrtc.orgf0488722014-05-13 18:00:261463 return false;
1464 }
1465 // Else ignore the error and keep going. If this EINTR was for one of the
1466 // signals managed by this PhysicalSocketServer, the
1467 // PosixSignalDeliveryDispatcher will be in the signaled state in the next
1468 // iteration.
1469 } else if (n == 0) {
1470 // If timeout, return success
1471 return true;
1472 } else {
1473 // We have signaled descriptors
1474 CritScope cr(&crit_);
jbauchde4db112017-05-31 20:09:181475 processing_dispatchers_ = true;
1476 for (Dispatcher* pdispatcher : dispatchers_) {
henrike@webrtc.orgf0488722014-05-13 18:00:261477 int fd = pdispatcher->GetDescriptor();
henrike@webrtc.orgf0488722014-05-13 18:00:261478
jbauchde4db112017-05-31 20:09:181479 bool readable = FD_ISSET(fd, &fdsRead);
1480 if (readable) {
henrike@webrtc.orgf0488722014-05-13 18:00:261481 FD_CLR(fd, &fdsRead);
henrike@webrtc.orgf0488722014-05-13 18:00:261482 }
1483
jbauchde4db112017-05-31 20:09:181484 bool writable = FD_ISSET(fd, &fdsWrite);
1485 if (writable) {
henrike@webrtc.orgf0488722014-05-13 18:00:261486 FD_CLR(fd, &fdsWrite);
henrike@webrtc.orgf0488722014-05-13 18:00:261487 }
1488
jbauchde4db112017-05-31 20:09:181489 // The error code can be signaled through reads or writes.
1490 ProcessEvents(pdispatcher, readable, writable, readable || writable);
henrike@webrtc.orgf0488722014-05-13 18:00:261491 }
jbauchde4db112017-05-31 20:09:181492
1493 processing_dispatchers_ = false;
1494 // Process deferred dispatchers that have been added/removed while the
1495 // events were handled above.
1496 AddRemovePendingDispatchers();
henrike@webrtc.orgf0488722014-05-13 18:00:261497 }
1498
1499 // Recalc the time remaining to wait. Doing it here means it doesn't get
1500 // calced twice the first time through the loop
1501 if (ptvWait) {
1502 ptvWait->tv_sec = 0;
1503 ptvWait->tv_usec = 0;
1504 struct timeval tvT;
deadbeef37f5ecf2017-02-27 22:06:411505 gettimeofday(&tvT, nullptr);
Yves Gerey665174f2018-06-19 13:03:051506 if ((tvStop.tv_sec > tvT.tv_sec) ||
1507 ((tvStop.tv_sec == tvT.tv_sec) && (tvStop.tv_usec > tvT.tv_usec))) {
henrike@webrtc.orgf0488722014-05-13 18:00:261508 ptvWait->tv_sec = tvStop.tv_sec - tvT.tv_sec;
1509 ptvWait->tv_usec = tvStop.tv_usec - tvT.tv_usec;
1510 if (ptvWait->tv_usec < 0) {
nisseede5da42017-01-12 13:15:361511 RTC_DCHECK(ptvWait->tv_sec > 0);
henrike@webrtc.orgf0488722014-05-13 18:00:261512 ptvWait->tv_usec += 1000000;
1513 ptvWait->tv_sec -= 1;
1514 }
1515 }
1516 }
1517 }
1518
1519 return true;
1520}
1521
jbauchde4db112017-05-31 20:09:181522#if defined(WEBRTC_USE_EPOLL)
1523
1524// Initial number of events to process with one call to "epoll_wait".
1525static const size_t kInitialEpollEvents = 128;
1526
1527// Maximum number of events to process with one call to "epoll_wait".
1528static const size_t kMaxEpollEvents = 8192;
1529
1530void PhysicalSocketServer::AddEpoll(Dispatcher* pdispatcher) {
1531 RTC_DCHECK(epoll_fd_ != INVALID_SOCKET);
1532 int fd = pdispatcher->GetDescriptor();
1533 RTC_DCHECK(fd != INVALID_SOCKET);
1534 if (fd == INVALID_SOCKET) {
1535 return;
1536 }
1537
1538 struct epoll_event event = {0};
1539 event.events = GetEpollEvents(pdispatcher->GetRequestedEvents());
1540 event.data.ptr = pdispatcher;
1541 int err = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &event);
1542 RTC_DCHECK_EQ(err, 0);
1543 if (err == -1) {
Mirko Bonadei675513b2017-11-09 10:09:251544 RTC_LOG_E(LS_ERROR, EN, errno) << "epoll_ctl EPOLL_CTL_ADD";
jbauchde4db112017-05-31 20:09:181545 }
1546}
1547
1548void PhysicalSocketServer::RemoveEpoll(Dispatcher* pdispatcher) {
1549 RTC_DCHECK(epoll_fd_ != INVALID_SOCKET);
1550 int fd = pdispatcher->GetDescriptor();
1551 RTC_DCHECK(fd != INVALID_SOCKET);
1552 if (fd == INVALID_SOCKET) {
1553 return;
1554 }
1555
1556 struct epoll_event event = {0};
1557 int err = epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &event);
1558 RTC_DCHECK(err == 0 || errno == ENOENT);
1559 if (err == -1) {
1560 if (errno == ENOENT) {
1561 // Socket has already been closed.
Mirko Bonadei675513b2017-11-09 10:09:251562 RTC_LOG_E(LS_VERBOSE, EN, errno) << "epoll_ctl EPOLL_CTL_DEL";
jbauchde4db112017-05-31 20:09:181563 } else {
Mirko Bonadei675513b2017-11-09 10:09:251564 RTC_LOG_E(LS_ERROR, EN, errno) << "epoll_ctl EPOLL_CTL_DEL";
jbauchde4db112017-05-31 20:09:181565 }
1566 }
1567}
1568
1569void PhysicalSocketServer::UpdateEpoll(Dispatcher* pdispatcher) {
1570 RTC_DCHECK(epoll_fd_ != INVALID_SOCKET);
1571 int fd = pdispatcher->GetDescriptor();
1572 RTC_DCHECK(fd != INVALID_SOCKET);
1573 if (fd == INVALID_SOCKET) {
1574 return;
1575 }
1576
1577 struct epoll_event event = {0};
1578 event.events = GetEpollEvents(pdispatcher->GetRequestedEvents());
1579 event.data.ptr = pdispatcher;
1580 int err = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &event);
1581 RTC_DCHECK_EQ(err, 0);
1582 if (err == -1) {
Mirko Bonadei675513b2017-11-09 10:09:251583 RTC_LOG_E(LS_ERROR, EN, errno) << "epoll_ctl EPOLL_CTL_MOD";
jbauchde4db112017-05-31 20:09:181584 }
1585}
1586
1587bool PhysicalSocketServer::WaitEpoll(int cmsWait) {
1588 RTC_DCHECK(epoll_fd_ != INVALID_SOCKET);
1589 int64_t tvWait = -1;
1590 int64_t tvStop = -1;
1591 if (cmsWait != kForever) {
1592 tvWait = cmsWait;
1593 tvStop = TimeAfter(cmsWait);
1594 }
1595
1596 if (epoll_events_.empty()) {
1597 // The initial space to receive events is created only if epoll is used.
1598 epoll_events_.resize(kInitialEpollEvents);
1599 }
1600
1601 fWait_ = true;
1602
1603 while (fWait_) {
1604 // Wait then call handlers as appropriate
1605 // < 0 means error
1606 // 0 means timeout
1607 // > 0 means count of descriptors ready
1608 int n = epoll_wait(epoll_fd_, &epoll_events_[0],
1609 static_cast<int>(epoll_events_.size()),
1610 static_cast<int>(tvWait));
1611 if (n < 0) {
1612 if (errno != EINTR) {
Mirko Bonadei675513b2017-11-09 10:09:251613 RTC_LOG_E(LS_ERROR, EN, errno) << "epoll";
jbauchde4db112017-05-31 20:09:181614 return false;
1615 }
1616 // Else ignore the error and keep going. If this EINTR was for one of the
1617 // signals managed by this PhysicalSocketServer, the
1618 // PosixSignalDeliveryDispatcher will be in the signaled state in the next
1619 // iteration.
1620 } else if (n == 0) {
1621 // If timeout, return success
1622 return true;
1623 } else {
1624 // We have signaled descriptors
1625 CritScope cr(&crit_);
1626 for (int i = 0; i < n; ++i) {
1627 const epoll_event& event = epoll_events_[i];
1628 Dispatcher* pdispatcher = static_cast<Dispatcher*>(event.data.ptr);
1629 if (dispatchers_.find(pdispatcher) == dispatchers_.end()) {
1630 // The dispatcher for this socket no longer exists.
1631 continue;
1632 }
1633
1634 bool readable = (event.events & (EPOLLIN | EPOLLPRI));
1635 bool writable = (event.events & EPOLLOUT);
1636 bool check_error = (event.events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP));
1637
1638 ProcessEvents(pdispatcher, readable, writable, check_error);
1639 }
1640 }
1641
1642 if (static_cast<size_t>(n) == epoll_events_.size() &&
1643 epoll_events_.size() < kMaxEpollEvents) {
1644 // We used the complete space to receive events, increase size for future
1645 // iterations.
1646 epoll_events_.resize(std::max(epoll_events_.size() * 2, kMaxEpollEvents));
1647 }
1648
1649 if (cmsWait != kForever) {
1650 tvWait = TimeDiff(tvStop, TimeMillis());
1651 if (tvWait < 0) {
1652 // Return success on timeout.
1653 return true;
1654 }
1655 }
1656 }
1657
1658 return true;
1659}
1660
1661bool PhysicalSocketServer::WaitPoll(int cmsWait, Dispatcher* dispatcher) {
1662 RTC_DCHECK(dispatcher);
1663 int64_t tvWait = -1;
1664 int64_t tvStop = -1;
1665 if (cmsWait != kForever) {
1666 tvWait = cmsWait;
1667 tvStop = TimeAfter(cmsWait);
1668 }
1669
1670 fWait_ = true;
1671
1672 struct pollfd fds = {0};
1673 int fd = dispatcher->GetDescriptor();
1674 fds.fd = fd;
1675
1676 while (fWait_) {
1677 uint32_t ff = dispatcher->GetRequestedEvents();
1678 fds.events = 0;
1679 if (ff & (DE_READ | DE_ACCEPT)) {
1680 fds.events |= POLLIN;
1681 }
1682 if (ff & (DE_WRITE | DE_CONNECT)) {
1683 fds.events |= POLLOUT;
1684 }
1685 fds.revents = 0;
1686
1687 // Wait then call handlers as appropriate
1688 // < 0 means error
1689 // 0 means timeout
1690 // > 0 means count of descriptors ready
1691 int n = poll(&fds, 1, static_cast<int>(tvWait));
1692 if (n < 0) {
1693 if (errno != EINTR) {
Mirko Bonadei675513b2017-11-09 10:09:251694 RTC_LOG_E(LS_ERROR, EN, errno) << "poll";
jbauchde4db112017-05-31 20:09:181695 return false;
1696 }
1697 // Else ignore the error and keep going. If this EINTR was for one of the
1698 // signals managed by this PhysicalSocketServer, the
1699 // PosixSignalDeliveryDispatcher will be in the signaled state in the next
1700 // iteration.
1701 } else if (n == 0) {
1702 // If timeout, return success
1703 return true;
1704 } else {
1705 // We have signaled descriptors (should only be the passed dispatcher).
1706 RTC_DCHECK_EQ(n, 1);
1707 RTC_DCHECK_EQ(fds.fd, fd);
1708
1709 bool readable = (fds.revents & (POLLIN | POLLPRI));
1710 bool writable = (fds.revents & POLLOUT);
1711 bool check_error = (fds.revents & (POLLRDHUP | POLLERR | POLLHUP));
1712
1713 ProcessEvents(dispatcher, readable, writable, check_error);
1714 }
1715
1716 if (cmsWait != kForever) {
1717 tvWait = TimeDiff(tvStop, TimeMillis());
1718 if (tvWait < 0) {
1719 // Return success on timeout.
1720 return true;
1721 }
1722 }
1723 }
1724
1725 return true;
1726}
1727
1728#endif // WEBRTC_USE_EPOLL
1729
henrike@webrtc.orgf0488722014-05-13 18:00:261730static void GlobalSignalHandler(int signum) {
1731 PosixSignalHandler::Instance()->OnPosixSignalReceived(signum);
1732}
1733
1734bool PhysicalSocketServer::SetPosixSignalHandler(int signum,
1735 void (*handler)(int)) {
1736 // If handler is SIG_IGN or SIG_DFL then clear our user-level handler,
1737 // otherwise set one.
1738 if (handler == SIG_IGN || handler == SIG_DFL) {
1739 if (!InstallSignal(signum, handler)) {
1740 return false;
1741 }
1742 if (signal_dispatcher_) {
1743 signal_dispatcher_->ClearHandler(signum);
1744 if (!signal_dispatcher_->HasHandlers()) {
1745 signal_dispatcher_.reset();
1746 }
1747 }
1748 } else {
1749 if (!signal_dispatcher_) {
1750 signal_dispatcher_.reset(new PosixSignalDispatcher(this));
1751 }
1752 signal_dispatcher_->SetHandler(signum, handler);
1753 if (!InstallSignal(signum, &GlobalSignalHandler)) {
1754 return false;
1755 }
1756 }
1757 return true;
1758}
1759
1760Dispatcher* PhysicalSocketServer::signal_dispatcher() {
1761 return signal_dispatcher_.get();
1762}
1763
1764bool PhysicalSocketServer::InstallSignal(int signum, void (*handler)(int)) {
1765 struct sigaction act;
1766 // It doesn't really matter what we set this mask to.
1767 if (sigemptyset(&act.sa_mask) != 0) {
Mirko Bonadei675513b2017-11-09 10:09:251768 RTC_LOG_ERR(LS_ERROR) << "Couldn't set mask";
henrike@webrtc.orgf0488722014-05-13 18:00:261769 return false;
1770 }
1771 act.sa_handler = handler;
1772#if !defined(__native_client__)
1773 // Use SA_RESTART so that our syscalls don't get EINTR, since we don't need it
1774 // and it's a nuisance. Though some syscalls still return EINTR and there's no
1775 // real standard for which ones. :(
1776 act.sa_flags = SA_RESTART;
1777#else
1778 act.sa_flags = 0;
1779#endif
deadbeef37f5ecf2017-02-27 22:06:411780 if (sigaction(signum, &act, nullptr) != 0) {
Mirko Bonadei675513b2017-11-09 10:09:251781 RTC_LOG_ERR(LS_ERROR) << "Couldn't set sigaction";
henrike@webrtc.orgf0488722014-05-13 18:00:261782 return false;
1783 }
1784 return true;
1785}
1786#endif // WEBRTC_POSIX
1787
1788#if defined(WEBRTC_WIN)
1789bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
Honghai Zhang82d78622016-05-06 18:29:151790 int64_t cmsTotal = cmsWait;
1791 int64_t cmsElapsed = 0;
1792 int64_t msStart = Time();
henrike@webrtc.orgf0488722014-05-13 18:00:261793
1794 fWait_ = true;
1795 while (fWait_) {
1796 std::vector<WSAEVENT> events;
Yves Gerey665174f2018-06-19 13:03:051797 std::vector<Dispatcher*> event_owners;
henrike@webrtc.orgf0488722014-05-13 18:00:261798
1799 events.push_back(socket_ev_);
1800
1801 {
1802 CritScope cr(&crit_);
jbauchde4db112017-05-31 20:09:181803 // TODO(jbauch): Support re-entrant waiting.
1804 RTC_DCHECK(!processing_dispatchers_);
1805
1806 // Calling "CheckSignalClose" might remove a closed dispatcher from the
1807 // set. This must be deferred to prevent invalidating the iterator.
1808 processing_dispatchers_ = true;
1809 for (Dispatcher* disp : dispatchers_) {
henrike@webrtc.orgf0488722014-05-13 18:00:261810 if (!process_io && (disp != signal_wakeup_))
1811 continue;
1812 SOCKET s = disp->GetSocket();
1813 if (disp->CheckSignalClose()) {
1814 // We just signalled close, don't poll this socket
1815 } else if (s != INVALID_SOCKET) {
Yves Gerey665174f2018-06-19 13:03:051816 WSAEventSelect(s, events[0],
henrike@webrtc.orgf0488722014-05-13 18:00:261817 FlagsToEvents(disp->GetRequestedEvents()));
1818 } else {
1819 events.push_back(disp->GetWSAEvent());
1820 event_owners.push_back(disp);
1821 }
1822 }
jbauchde4db112017-05-31 20:09:181823
1824 processing_dispatchers_ = false;
1825 // Process deferred dispatchers that have been added/removed while the
1826 // events were handled above.
1827 AddRemovePendingDispatchers();
henrike@webrtc.orgf0488722014-05-13 18:00:261828 }
1829
1830 // Which is shorter, the delay wait or the asked wait?
1831
Honghai Zhang82d78622016-05-06 18:29:151832 int64_t cmsNext;
henrike@webrtc.orgf0488722014-05-13 18:00:261833 if (cmsWait == kForever) {
1834 cmsNext = cmsWait;
1835 } else {
Honghai Zhang82d78622016-05-06 18:29:151836 cmsNext = std::max<int64_t>(0, cmsTotal - cmsElapsed);
henrike@webrtc.orgf0488722014-05-13 18:00:261837 }
1838
1839 // Wait for one of the events to signal
Yves Gerey665174f2018-06-19 13:03:051840 DWORD dw =
1841 WSAWaitForMultipleEvents(static_cast<DWORD>(events.size()), &events[0],
1842 false, static_cast<DWORD>(cmsNext), false);
henrike@webrtc.orgf0488722014-05-13 18:00:261843
1844 if (dw == WSA_WAIT_FAILED) {
1845 // Failed?
jbauch095ae152015-12-18 09:39:551846 // TODO(pthatcher): need a better strategy than this!
henrike@webrtc.orgf0488722014-05-13 18:00:261847 WSAGetLastError();
nissec80e7412017-01-11 13:56:461848 RTC_NOTREACHED();
henrike@webrtc.orgf0488722014-05-13 18:00:261849 return false;
1850 } else if (dw == WSA_WAIT_TIMEOUT) {
1851 // Timeout?
1852 return true;
1853 } else {
1854 // Figure out which one it is and call it
1855 CritScope cr(&crit_);
1856 int index = dw - WSA_WAIT_EVENT_0;
1857 if (index > 0) {
Yves Gerey665174f2018-06-19 13:03:051858 --index; // The first event is the socket event
jbauchde4db112017-05-31 20:09:181859 Dispatcher* disp = event_owners[index];
1860 // The dispatcher could have been removed while waiting for events.
1861 if (dispatchers_.find(disp) != dispatchers_.end()) {
1862 disp->OnPreEvent(0);
1863 disp->OnEvent(0, 0);
1864 }
henrike@webrtc.orgf0488722014-05-13 18:00:261865 } else if (process_io) {
jbauchde4db112017-05-31 20:09:181866 processing_dispatchers_ = true;
1867 for (Dispatcher* disp : dispatchers_) {
henrike@webrtc.orgf0488722014-05-13 18:00:261868 SOCKET s = disp->GetSocket();
1869 if (s == INVALID_SOCKET)
1870 continue;
1871
1872 WSANETWORKEVENTS wsaEvents;
1873 int err = WSAEnumNetworkEvents(s, events[0], &wsaEvents);
1874 if (err == 0) {
henrike@webrtc.orgf0488722014-05-13 18:00:261875 {
1876 if ((wsaEvents.lNetworkEvents & FD_READ) &&
1877 wsaEvents.iErrorCode[FD_READ_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 10:09:251878 RTC_LOG(WARNING)
1879 << "PhysicalSocketServer got FD_READ_BIT error "
1880 << wsaEvents.iErrorCode[FD_READ_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:261881 }
1882 if ((wsaEvents.lNetworkEvents & FD_WRITE) &&
1883 wsaEvents.iErrorCode[FD_WRITE_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 10:09:251884 RTC_LOG(WARNING)
1885 << "PhysicalSocketServer got FD_WRITE_BIT error "
1886 << wsaEvents.iErrorCode[FD_WRITE_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:261887 }
1888 if ((wsaEvents.lNetworkEvents & FD_CONNECT) &&
1889 wsaEvents.iErrorCode[FD_CONNECT_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 10:09:251890 RTC_LOG(WARNING)
1891 << "PhysicalSocketServer got FD_CONNECT_BIT error "
1892 << wsaEvents.iErrorCode[FD_CONNECT_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:261893 }
1894 if ((wsaEvents.lNetworkEvents & FD_ACCEPT) &&
1895 wsaEvents.iErrorCode[FD_ACCEPT_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 10:09:251896 RTC_LOG(WARNING)
1897 << "PhysicalSocketServer got FD_ACCEPT_BIT error "
1898 << wsaEvents.iErrorCode[FD_ACCEPT_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:261899 }
1900 if ((wsaEvents.lNetworkEvents & FD_CLOSE) &&
1901 wsaEvents.iErrorCode[FD_CLOSE_BIT] != 0) {
Mirko Bonadei675513b2017-11-09 10:09:251902 RTC_LOG(WARNING)
1903 << "PhysicalSocketServer got FD_CLOSE_BIT error "
1904 << wsaEvents.iErrorCode[FD_CLOSE_BIT];
henrike@webrtc.orgf0488722014-05-13 18:00:261905 }
1906 }
Peter Boström0c4e06b2015-10-07 10:23:211907 uint32_t ff = 0;
henrike@webrtc.orgf0488722014-05-13 18:00:261908 int errcode = 0;
1909 if (wsaEvents.lNetworkEvents & FD_READ)
1910 ff |= DE_READ;
1911 if (wsaEvents.lNetworkEvents & FD_WRITE)
1912 ff |= DE_WRITE;
1913 if (wsaEvents.lNetworkEvents & FD_CONNECT) {
1914 if (wsaEvents.iErrorCode[FD_CONNECT_BIT] == 0) {
1915 ff |= DE_CONNECT;
1916 } else {
1917 ff |= DE_CLOSE;
1918 errcode = wsaEvents.iErrorCode[FD_CONNECT_BIT];
1919 }
1920 }
1921 if (wsaEvents.lNetworkEvents & FD_ACCEPT)
1922 ff |= DE_ACCEPT;
1923 if (wsaEvents.lNetworkEvents & FD_CLOSE) {
1924 ff |= DE_CLOSE;
1925 errcode = wsaEvents.iErrorCode[FD_CLOSE_BIT];
1926 }
1927 if (ff != 0) {
1928 disp->OnPreEvent(ff);
1929 disp->OnEvent(ff, errcode);
1930 }
1931 }
1932 }
jbauchde4db112017-05-31 20:09:181933
1934 processing_dispatchers_ = false;
1935 // Process deferred dispatchers that have been added/removed while the
1936 // events were handled above.
1937 AddRemovePendingDispatchers();
henrike@webrtc.orgf0488722014-05-13 18:00:261938 }
1939
1940 // Reset the network event until new activity occurs
1941 WSAResetEvent(socket_ev_);
1942 }
1943
1944 // Break?
1945 if (!fWait_)
1946 break;
1947 cmsElapsed = TimeSince(msStart);
1948 if ((cmsWait != kForever) && (cmsElapsed >= cmsWait)) {
Yves Gerey665174f2018-06-19 13:03:051949 break;
henrike@webrtc.orgf0488722014-05-13 18:00:261950 }
1951 }
1952
1953 // Done
1954 return true;
1955}
honghaizcec0a082016-01-15 22:49:091956#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:261957
1958} // namespace rtc