blob: 07591e8ad332b534516fdb0f27ed21c7fe9f55ec [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 */
honghaizcec0a082016-01-15 14:49:09 -080010#include "webrtc/base/physicalsocketserver.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000011
12#if defined(_MSC_VER) && _MSC_VER < 1300
13#pragma warning(disable:4786)
14#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)
21#include <string.h>
22#include <errno.h>
23#include <fcntl.h>
Stefan Holmer9131efd2016-05-23 18:19:26 +020024#include <sys/ioctl.h>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000025#include <sys/time.h>
26#include <sys/select.h>
27#include <unistd.h>
28#include <signal.h>
29#endif
30
31#if defined(WEBRTC_WIN)
32#define WIN32_LEAN_AND_MEAN
33#include <windows.h>
34#include <winsock2.h>
35#include <ws2tcpip.h>
36#undef SetPort
37#endif
38
39#include <algorithm>
40#include <map>
41
tfarina5237aaf2015-11-10 23:44:30 -080042#include "webrtc/base/arraysize.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000043#include "webrtc/base/basictypes.h"
44#include "webrtc/base/byteorder.h"
nissec80e7412017-01-11 05:56:46 -080045#include "webrtc/base/checks.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000046#include "webrtc/base/logging.h"
honghaizcec0a082016-01-15 14:49:09 -080047#include "webrtc/base/networkmonitor.h"
danilchapbebf54c2016-04-28 01:32:48 -070048#include "webrtc/base/nullsocketserver.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000049#include "webrtc/base/timeutils.h"
50#include "webrtc/base/winping.h"
51#include "webrtc/base/win32socketinit.h"
52
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000053#if defined(WEBRTC_POSIX)
54#include <netinet/tcp.h> // for TCP_NODELAY
55#define IP_MTU 14 // Until this is integrated from linux/in.h to netinet/in.h
56typedef void* SockOptArg;
Stefan Holmer9131efd2016-05-23 18:19:26 +020057
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000058#endif // WEBRTC_POSIX
59
Stefan Holmer3ebb3ef2016-05-23 20:26:11 +020060#if defined(WEBRTC_POSIX) && !defined(WEBRTC_MAC) && !defined(__native_client__)
61
Stefan Holmer9131efd2016-05-23 18:19:26 +020062int64_t GetSocketRecvTimestamp(int socket) {
63 struct timeval tv_ioctl;
64 int ret = ioctl(socket, SIOCGSTAMP, &tv_ioctl);
65 if (ret != 0)
66 return -1;
67 int64_t timestamp =
68 rtc::kNumMicrosecsPerSec * static_cast<int64_t>(tv_ioctl.tv_sec) +
69 static_cast<int64_t>(tv_ioctl.tv_usec);
70 return timestamp;
71}
72
73#else
74
75int64_t GetSocketRecvTimestamp(int socket) {
76 return -1;
77}
78#endif
79
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000080#if defined(WEBRTC_WIN)
81typedef char* SockOptArg;
82#endif
83
84namespace rtc {
85
danilchapbebf54c2016-04-28 01:32:48 -070086std::unique_ptr<SocketServer> SocketServer::CreateDefault() {
87#if defined(__native_client__)
88 return std::unique_ptr<SocketServer>(new rtc::NullSocketServer);
89#else
90 return std::unique_ptr<SocketServer>(new rtc::PhysicalSocketServer);
91#endif
92}
93
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000094#if defined(WEBRTC_WIN)
95// Standard MTUs, from RFC 1191
Peter Boström0c4e06b2015-10-07 12:23:21 +020096const uint16_t PACKET_MAXIMUMS[] = {
97 65535, // Theoretical maximum, Hyperchannel
98 32000, // Nothing
99 17914, // 16Mb IBM Token Ring
100 8166, // IEEE 802.4
101 // 4464, // IEEE 802.5 (4Mb max)
102 4352, // FDDI
103 // 2048, // Wideband Network
104 2002, // IEEE 802.5 (4Mb recommended)
105 // 1536, // Expermental Ethernet Networks
106 // 1500, // Ethernet, Point-to-Point (default)
107 1492, // IEEE 802.3
108 1006, // SLIP, ARPANET
109 // 576, // X.25 Networks
110 // 544, // DEC IP Portal
111 // 512, // NETBIOS
112 508, // IEEE 802/Source-Rt Bridge, ARCNET
113 296, // Point-to-Point (low delay)
114 68, // Official minimum
115 0, // End of list marker
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000116};
117
118static const int IP_HEADER_SIZE = 20u;
119static const int IPV6_HEADER_SIZE = 40u;
120static const int ICMP_HEADER_SIZE = 8u;
121static const int ICMP_PING_TIMEOUT_MILLIS = 10000u;
122#endif
123
jbauch095ae152015-12-18 01:39:55 -0800124PhysicalSocket::PhysicalSocket(PhysicalSocketServer* ss, SOCKET s)
125 : ss_(ss), s_(s), enabled_events_(0), error_(0),
126 state_((s == INVALID_SOCKET) ? CS_CLOSED : CS_CONNECTED),
127 resolver_(nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000128#if defined(WEBRTC_WIN)
jbauch095ae152015-12-18 01:39:55 -0800129 // EnsureWinsockInit() ensures that winsock is initialized. The default
130 // version of this function doesn't do anything because winsock is
131 // initialized by constructor of a static object. If neccessary libjingle
132 // users can link it with a different version of this function by replacing
133 // win32socketinit.cc. See win32socketinit.cc for more details.
134 EnsureWinsockInit();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000135#endif
jbauch095ae152015-12-18 01:39:55 -0800136 if (s_ != INVALID_SOCKET) {
137 enabled_events_ = DE_READ | DE_WRITE;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000138
jbauch095ae152015-12-18 01:39:55 -0800139 int type = SOCK_STREAM;
140 socklen_t len = sizeof(type);
nissec16fa5e2017-02-07 07:18:43 -0800141 const int res =
142 getsockopt(s_, SOL_SOCKET, SO_TYPE, (SockOptArg)&type, &len);
143 RTC_DCHECK_EQ(0, res);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000144 udp_ = (SOCK_DGRAM == type);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000145 }
jbauch095ae152015-12-18 01:39:55 -0800146}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000147
jbauch095ae152015-12-18 01:39:55 -0800148PhysicalSocket::~PhysicalSocket() {
149 Close();
150}
151
152bool PhysicalSocket::Create(int family, int type) {
153 Close();
154 s_ = ::socket(family, type, 0);
155 udp_ = (SOCK_DGRAM == type);
156 UpdateLastError();
157 if (udp_)
158 enabled_events_ = DE_READ | DE_WRITE;
159 return s_ != INVALID_SOCKET;
160}
161
162SocketAddress PhysicalSocket::GetLocalAddress() const {
163 sockaddr_storage addr_storage = {0};
164 socklen_t addrlen = sizeof(addr_storage);
165 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
166 int result = ::getsockname(s_, addr, &addrlen);
167 SocketAddress address;
168 if (result >= 0) {
169 SocketAddressFromSockAddrStorage(addr_storage, &address);
170 } else {
171 LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket="
172 << s_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000173 }
jbauch095ae152015-12-18 01:39:55 -0800174 return address;
175}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000176
jbauch095ae152015-12-18 01:39:55 -0800177SocketAddress PhysicalSocket::GetRemoteAddress() const {
178 sockaddr_storage addr_storage = {0};
179 socklen_t addrlen = sizeof(addr_storage);
180 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
181 int result = ::getpeername(s_, addr, &addrlen);
182 SocketAddress address;
183 if (result >= 0) {
184 SocketAddressFromSockAddrStorage(addr_storage, &address);
185 } else {
186 LOG(LS_WARNING) << "GetRemoteAddress: unable to get remote addr, socket="
187 << s_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000188 }
jbauch095ae152015-12-18 01:39:55 -0800189 return address;
190}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000191
jbauch095ae152015-12-18 01:39:55 -0800192int PhysicalSocket::Bind(const SocketAddress& bind_addr) {
193 sockaddr_storage addr_storage;
194 size_t len = bind_addr.ToSockAddrStorage(&addr_storage);
195 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
196 int err = ::bind(s_, addr, static_cast<int>(len));
197 UpdateLastError();
tfarinaa41ab932015-10-30 16:08:48 -0700198#if !defined(NDEBUG)
jbauch095ae152015-12-18 01:39:55 -0800199 if (0 == err) {
200 dbg_addr_ = "Bound @ ";
201 dbg_addr_.append(GetLocalAddress().ToString());
202 }
tfarinaa41ab932015-10-30 16:08:48 -0700203#endif
honghaizcec0a082016-01-15 14:49:09 -0800204 if (ss_->network_binder()) {
205 int result =
206 ss_->network_binder()->BindSocketToNetwork(s_, bind_addr.ipaddr());
207 if (result < 0) {
208 LOG(LS_INFO) << "Binding socket to network address "
209 << bind_addr.ipaddr().ToString() << " result " << result;
210 }
211 }
jbauch095ae152015-12-18 01:39:55 -0800212 return err;
213}
214
215int PhysicalSocket::Connect(const SocketAddress& addr) {
216 // TODO(pthatcher): Implicit creation is required to reconnect...
217 // ...but should we make it more explicit?
218 if (state_ != CS_CLOSED) {
219 SetError(EALREADY);
220 return SOCKET_ERROR;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000221 }
jbauch095ae152015-12-18 01:39:55 -0800222 if (addr.IsUnresolvedIP()) {
223 LOG(LS_VERBOSE) << "Resolving addr in PhysicalSocket::Connect";
224 resolver_ = new AsyncResolver();
225 resolver_->SignalDone.connect(this, &PhysicalSocket::OnResolveResult);
226 resolver_->Start(addr);
227 state_ = CS_CONNECTING;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000228 return 0;
229 }
230
jbauch095ae152015-12-18 01:39:55 -0800231 return DoConnect(addr);
232}
233
234int PhysicalSocket::DoConnect(const SocketAddress& connect_addr) {
235 if ((s_ == INVALID_SOCKET) &&
236 !Create(connect_addr.family(), SOCK_STREAM)) {
237 return SOCKET_ERROR;
238 }
239 sockaddr_storage addr_storage;
240 size_t len = connect_addr.ToSockAddrStorage(&addr_storage);
241 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
242 int err = ::connect(s_, addr, static_cast<int>(len));
243 UpdateLastError();
244 if (err == 0) {
245 state_ = CS_CONNECTED;
246 } else if (IsBlockingError(GetError())) {
247 state_ = CS_CONNECTING;
248 enabled_events_ |= DE_CONNECT;
249 } else {
250 return SOCKET_ERROR;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000251 }
252
jbauch095ae152015-12-18 01:39:55 -0800253 enabled_events_ |= DE_READ | DE_WRITE;
254 return 0;
255}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000256
jbauch095ae152015-12-18 01:39:55 -0800257int PhysicalSocket::GetError() const {
258 CritScope cs(&crit_);
259 return error_;
260}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000261
jbauch095ae152015-12-18 01:39:55 -0800262void PhysicalSocket::SetError(int error) {
263 CritScope cs(&crit_);
264 error_ = error;
265}
266
267AsyncSocket::ConnState PhysicalSocket::GetState() const {
268 return state_;
269}
270
271int PhysicalSocket::GetOption(Option opt, int* value) {
272 int slevel;
273 int sopt;
274 if (TranslateOption(opt, &slevel, &sopt) == -1)
275 return -1;
276 socklen_t optlen = sizeof(*value);
277 int ret = ::getsockopt(s_, slevel, sopt, (SockOptArg)value, &optlen);
278 if (ret != -1 && opt == OPT_DONTFRAGMENT) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000279#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
jbauch095ae152015-12-18 01:39:55 -0800280 *value = (*value != IP_PMTUDISC_DONT) ? 1 : 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000281#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000282 }
jbauch095ae152015-12-18 01:39:55 -0800283 return ret;
284}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000285
jbauch095ae152015-12-18 01:39:55 -0800286int PhysicalSocket::SetOption(Option opt, int value) {
287 int slevel;
288 int sopt;
289 if (TranslateOption(opt, &slevel, &sopt) == -1)
290 return -1;
291 if (opt == OPT_DONTFRAGMENT) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000292#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
jbauch095ae152015-12-18 01:39:55 -0800293 value = (value) ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000294#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000295 }
jbauch095ae152015-12-18 01:39:55 -0800296 return ::setsockopt(s_, slevel, sopt, (SockOptArg)&value, sizeof(value));
297}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000298
jbauch095ae152015-12-18 01:39:55 -0800299int PhysicalSocket::Send(const void* pv, size_t cb) {
jbauchf2a2bf42016-02-03 16:45:32 -0800300 int sent = DoSend(s_, reinterpret_cast<const char *>(pv),
301 static_cast<int>(cb),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000302#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
jbauch095ae152015-12-18 01:39:55 -0800303 // Suppress SIGPIPE. Without this, attempting to send on a socket whose
304 // other end is closed will result in a SIGPIPE signal being raised to
305 // our process, which by default will terminate the process, which we
306 // don't want. By specifying this flag, we'll just get the error EPIPE
307 // instead and can handle the error gracefully.
308 MSG_NOSIGNAL
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000309#else
jbauch095ae152015-12-18 01:39:55 -0800310 0
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000311#endif
jbauch095ae152015-12-18 01:39:55 -0800312 );
313 UpdateLastError();
314 MaybeRemapSendError();
315 // We have seen minidumps where this may be false.
nisseede5da42017-01-12 05:15:36 -0800316 RTC_DCHECK(sent <= static_cast<int>(cb));
jbauchf2a2bf42016-02-03 16:45:32 -0800317 if ((sent > 0 && sent < static_cast<int>(cb)) ||
318 (sent < 0 && IsBlockingError(GetError()))) {
jbauch095ae152015-12-18 01:39:55 -0800319 enabled_events_ |= DE_WRITE;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000320 }
jbauch095ae152015-12-18 01:39:55 -0800321 return sent;
322}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000323
jbauch095ae152015-12-18 01:39:55 -0800324int PhysicalSocket::SendTo(const void* buffer,
325 size_t length,
326 const SocketAddress& addr) {
327 sockaddr_storage saddr;
328 size_t len = addr.ToSockAddrStorage(&saddr);
jbauchf2a2bf42016-02-03 16:45:32 -0800329 int sent = DoSendTo(
jbauch095ae152015-12-18 01:39:55 -0800330 s_, static_cast<const char *>(buffer), static_cast<int>(length),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000331#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
jbauch095ae152015-12-18 01:39:55 -0800332 // Suppress SIGPIPE. See above for explanation.
333 MSG_NOSIGNAL,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000334#else
jbauch095ae152015-12-18 01:39:55 -0800335 0,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000336#endif
jbauch095ae152015-12-18 01:39:55 -0800337 reinterpret_cast<sockaddr*>(&saddr), static_cast<int>(len));
338 UpdateLastError();
339 MaybeRemapSendError();
340 // We have seen minidumps where this may be false.
nisseede5da42017-01-12 05:15:36 -0800341 RTC_DCHECK(sent <= static_cast<int>(length));
jbauchf2a2bf42016-02-03 16:45:32 -0800342 if ((sent > 0 && sent < static_cast<int>(length)) ||
343 (sent < 0 && IsBlockingError(GetError()))) {
jbauch095ae152015-12-18 01:39:55 -0800344 enabled_events_ |= DE_WRITE;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000345 }
jbauch095ae152015-12-18 01:39:55 -0800346 return sent;
347}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000348
Stefan Holmer9131efd2016-05-23 18:19:26 +0200349int PhysicalSocket::Recv(void* buffer, size_t length, int64_t* timestamp) {
jbauch095ae152015-12-18 01:39:55 -0800350 int received = ::recv(s_, static_cast<char*>(buffer),
351 static_cast<int>(length), 0);
352 if ((received == 0) && (length != 0)) {
353 // Note: on graceful shutdown, recv can return 0. In this case, we
354 // pretend it is blocking, and then signal close, so that simplifying
355 // assumptions can be made about Recv.
356 LOG(LS_WARNING) << "EOF from socket; deferring close event";
357 // Must turn this back on so that the select() loop will notice the close
358 // event.
359 enabled_events_ |= DE_READ;
360 SetError(EWOULDBLOCK);
361 return SOCKET_ERROR;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000362 }
Stefan Holmer9131efd2016-05-23 18:19:26 +0200363 if (timestamp) {
364 *timestamp = GetSocketRecvTimestamp(s_);
365 }
jbauch095ae152015-12-18 01:39:55 -0800366 UpdateLastError();
367 int error = GetError();
368 bool success = (received >= 0) || IsBlockingError(error);
369 if (udp_ || success) {
370 enabled_events_ |= DE_READ;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000371 }
jbauch095ae152015-12-18 01:39:55 -0800372 if (!success) {
373 LOG_F(LS_VERBOSE) << "Error = " << error;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000374 }
jbauch095ae152015-12-18 01:39:55 -0800375 return received;
376}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000377
jbauch095ae152015-12-18 01:39:55 -0800378int PhysicalSocket::RecvFrom(void* buffer,
379 size_t length,
Stefan Holmer9131efd2016-05-23 18:19:26 +0200380 SocketAddress* out_addr,
381 int64_t* timestamp) {
jbauch095ae152015-12-18 01:39:55 -0800382 sockaddr_storage addr_storage;
383 socklen_t addr_len = sizeof(addr_storage);
384 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
385 int received = ::recvfrom(s_, static_cast<char*>(buffer),
386 static_cast<int>(length), 0, addr, &addr_len);
Stefan Holmer9131efd2016-05-23 18:19:26 +0200387 if (timestamp) {
388 *timestamp = GetSocketRecvTimestamp(s_);
389 }
jbauch095ae152015-12-18 01:39:55 -0800390 UpdateLastError();
391 if ((received >= 0) && (out_addr != nullptr))
392 SocketAddressFromSockAddrStorage(addr_storage, out_addr);
393 int error = GetError();
394 bool success = (received >= 0) || IsBlockingError(error);
395 if (udp_ || success) {
396 enabled_events_ |= DE_READ;
397 }
398 if (!success) {
399 LOG_F(LS_VERBOSE) << "Error = " << error;
400 }
401 return received;
402}
403
404int PhysicalSocket::Listen(int backlog) {
405 int err = ::listen(s_, backlog);
406 UpdateLastError();
407 if (err == 0) {
408 state_ = CS_CONNECTING;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000409 enabled_events_ |= DE_ACCEPT;
jbauch095ae152015-12-18 01:39:55 -0800410#if !defined(NDEBUG)
411 dbg_addr_ = "Listening @ ";
412 dbg_addr_.append(GetLocalAddress().ToString());
413#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000414 }
jbauch095ae152015-12-18 01:39:55 -0800415 return err;
416}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000417
jbauch095ae152015-12-18 01:39:55 -0800418AsyncSocket* PhysicalSocket::Accept(SocketAddress* out_addr) {
419 // Always re-subscribe DE_ACCEPT to make sure new incoming connections will
420 // trigger an event even if DoAccept returns an error here.
421 enabled_events_ |= DE_ACCEPT;
422 sockaddr_storage addr_storage;
423 socklen_t addr_len = sizeof(addr_storage);
424 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
425 SOCKET s = DoAccept(s_, addr, &addr_len);
426 UpdateLastError();
427 if (s == INVALID_SOCKET)
428 return nullptr;
429 if (out_addr != nullptr)
430 SocketAddressFromSockAddrStorage(addr_storage, out_addr);
431 return ss_->WrapSocket(s);
432}
433
434int PhysicalSocket::Close() {
435 if (s_ == INVALID_SOCKET)
436 return 0;
437 int err = ::closesocket(s_);
438 UpdateLastError();
439 s_ = INVALID_SOCKET;
440 state_ = CS_CLOSED;
441 enabled_events_ = 0;
442 if (resolver_) {
443 resolver_->Destroy(false);
444 resolver_ = nullptr;
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 -0800449int PhysicalSocket::EstimateMTU(uint16_t* mtu) {
450 SocketAddress addr = GetRemoteAddress();
451 if (addr.IsAnyIP()) {
452 SetError(ENOTCONN);
453 return -1;
454 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000455
456#if defined(WEBRTC_WIN)
jbauch095ae152015-12-18 01:39:55 -0800457 // Gets the interface MTU (TTL=1) for the interface used to reach |addr|.
458 WinPing ping;
459 if (!ping.IsValid()) {
460 SetError(EINVAL); // can't think of a better error ID
461 return -1;
462 }
463 int header_size = ICMP_HEADER_SIZE;
464 if (addr.family() == AF_INET6) {
465 header_size += IPV6_HEADER_SIZE;
466 } else if (addr.family() == AF_INET) {
467 header_size += IP_HEADER_SIZE;
468 }
469
470 for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) {
471 int32_t size = PACKET_MAXIMUMS[level] - header_size;
472 WinPing::PingResult result = ping.Ping(addr.ipaddr(), size,
473 ICMP_PING_TIMEOUT_MILLIS,
474 1, false);
475 if (result == WinPing::PING_FAIL) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000476 SetError(EINVAL); // can't think of a better error ID
477 return -1;
jbauch095ae152015-12-18 01:39:55 -0800478 } else if (result != WinPing::PING_TOO_LARGE) {
479 *mtu = PACKET_MAXIMUMS[level];
480 return 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000481 }
jbauch095ae152015-12-18 01:39:55 -0800482 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000483
nissec80e7412017-01-11 05:56:46 -0800484 RTC_NOTREACHED();
jbauch095ae152015-12-18 01:39:55 -0800485 return -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000486#elif defined(WEBRTC_MAC)
jbauch095ae152015-12-18 01:39:55 -0800487 // No simple way to do this on Mac OS X.
488 // SIOCGIFMTU would work if we knew which interface would be used, but
489 // figuring that out is pretty complicated. For now we'll return an error
490 // and let the caller pick a default MTU.
491 SetError(EINVAL);
492 return -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000493#elif defined(WEBRTC_LINUX)
jbauch095ae152015-12-18 01:39:55 -0800494 // Gets the path MTU.
495 int value;
496 socklen_t vlen = sizeof(value);
497 int err = getsockopt(s_, IPPROTO_IP, IP_MTU, &value, &vlen);
498 if (err < 0) {
499 UpdateLastError();
500 return err;
501 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000502
nisseede5da42017-01-12 05:15:36 -0800503 RTC_DCHECK((0 <= value) && (value <= 65536));
jbauch095ae152015-12-18 01:39:55 -0800504 *mtu = value;
505 return 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000506#elif defined(__native_client__)
jbauch095ae152015-12-18 01:39:55 -0800507 // Most socket operations, including this, will fail in NaCl's sandbox.
508 error_ = EACCES;
509 return -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000510#endif
jbauch095ae152015-12-18 01:39:55 -0800511}
512
jbauch095ae152015-12-18 01:39:55 -0800513SOCKET PhysicalSocket::DoAccept(SOCKET socket,
514 sockaddr* addr,
515 socklen_t* addrlen) {
516 return ::accept(socket, addr, addrlen);
517}
518
jbauchf2a2bf42016-02-03 16:45:32 -0800519int PhysicalSocket::DoSend(SOCKET socket, const char* buf, int len, int flags) {
520 return ::send(socket, buf, len, flags);
521}
522
523int PhysicalSocket::DoSendTo(SOCKET socket,
524 const char* buf,
525 int len,
526 int flags,
527 const struct sockaddr* dest_addr,
528 socklen_t addrlen) {
529 return ::sendto(socket, buf, len, flags, dest_addr, addrlen);
530}
531
jbauch095ae152015-12-18 01:39:55 -0800532void PhysicalSocket::OnResolveResult(AsyncResolverInterface* resolver) {
533 if (resolver != resolver_) {
534 return;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000535 }
536
jbauch095ae152015-12-18 01:39:55 -0800537 int error = resolver_->GetError();
538 if (error == 0) {
539 error = DoConnect(resolver_->address());
540 } else {
541 Close();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000542 }
543
jbauch095ae152015-12-18 01:39:55 -0800544 if (error) {
545 SetError(error);
546 SignalCloseEvent(this, error);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000547 }
jbauch095ae152015-12-18 01:39:55 -0800548}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000549
jbauch095ae152015-12-18 01:39:55 -0800550void PhysicalSocket::UpdateLastError() {
551 SetError(LAST_SYSTEM_ERROR);
552}
553
554void PhysicalSocket::MaybeRemapSendError() {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000555#if defined(WEBRTC_MAC)
jbauch095ae152015-12-18 01:39:55 -0800556 // https://developer.apple.com/library/mac/documentation/Darwin/
557 // Reference/ManPages/man2/sendto.2.html
558 // ENOBUFS - The output queue for a network interface is full.
559 // This generally indicates that the interface has stopped sending,
560 // but may be caused by transient congestion.
561 if (GetError() == ENOBUFS) {
562 SetError(EWOULDBLOCK);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000563 }
jbauch095ae152015-12-18 01:39:55 -0800564#endif
565}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000566
jbauch095ae152015-12-18 01:39:55 -0800567int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
568 switch (opt) {
569 case OPT_DONTFRAGMENT:
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000570#if defined(WEBRTC_WIN)
jbauch095ae152015-12-18 01:39:55 -0800571 *slevel = IPPROTO_IP;
572 *sopt = IP_DONTFRAGMENT;
573 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000574#elif defined(WEBRTC_MAC) || defined(BSD) || defined(__native_client__)
jbauch095ae152015-12-18 01:39:55 -0800575 LOG(LS_WARNING) << "Socket::OPT_DONTFRAGMENT not supported.";
576 return -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000577#elif defined(WEBRTC_POSIX)
jbauch095ae152015-12-18 01:39:55 -0800578 *slevel = IPPROTO_IP;
579 *sopt = IP_MTU_DISCOVER;
580 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000581#endif
jbauch095ae152015-12-18 01:39:55 -0800582 case OPT_RCVBUF:
583 *slevel = SOL_SOCKET;
584 *sopt = SO_RCVBUF;
585 break;
586 case OPT_SNDBUF:
587 *slevel = SOL_SOCKET;
588 *sopt = SO_SNDBUF;
589 break;
590 case OPT_NODELAY:
591 *slevel = IPPROTO_TCP;
592 *sopt = TCP_NODELAY;
593 break;
594 case OPT_DSCP:
595 LOG(LS_WARNING) << "Socket::OPT_DSCP not supported.";
596 return -1;
597 case OPT_RTP_SENDTIME_EXTN_ID:
598 return -1; // No logging is necessary as this not a OS socket option.
599 default:
nissec80e7412017-01-11 05:56:46 -0800600 RTC_NOTREACHED();
jbauch095ae152015-12-18 01:39:55 -0800601 return -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000602 }
jbauch095ae152015-12-18 01:39:55 -0800603 return 0;
604}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000605
jbauch4331fcd2016-01-06 22:20:28 -0800606SocketDispatcher::SocketDispatcher(PhysicalSocketServer *ss)
607#if defined(WEBRTC_WIN)
608 : PhysicalSocket(ss), id_(0), signal_close_(false)
609#else
610 : PhysicalSocket(ss)
611#endif
612{
613}
614
615SocketDispatcher::SocketDispatcher(SOCKET s, PhysicalSocketServer *ss)
616#if defined(WEBRTC_WIN)
617 : PhysicalSocket(ss, s), id_(0), signal_close_(false)
618#else
619 : PhysicalSocket(ss, s)
620#endif
621{
622}
623
624SocketDispatcher::~SocketDispatcher() {
625 Close();
626}
627
628bool SocketDispatcher::Initialize() {
nisseede5da42017-01-12 05:15:36 -0800629 RTC_DCHECK(s_ != INVALID_SOCKET);
jbauch4331fcd2016-01-06 22:20:28 -0800630 // Must be a non-blocking
631#if defined(WEBRTC_WIN)
632 u_long argp = 1;
633 ioctlsocket(s_, FIONBIO, &argp);
634#elif defined(WEBRTC_POSIX)
635 fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK);
636#endif
637 ss_->Add(this);
638 return true;
639}
640
641bool SocketDispatcher::Create(int type) {
642 return Create(AF_INET, type);
643}
644
645bool SocketDispatcher::Create(int family, int type) {
646 // Change the socket to be non-blocking.
647 if (!PhysicalSocket::Create(family, type))
648 return false;
649
650 if (!Initialize())
651 return false;
652
653#if defined(WEBRTC_WIN)
654 do { id_ = ++next_id_; } while (id_ == 0);
655#endif
656 return true;
657}
658
659#if defined(WEBRTC_WIN)
660
661WSAEVENT SocketDispatcher::GetWSAEvent() {
662 return WSA_INVALID_EVENT;
663}
664
665SOCKET SocketDispatcher::GetSocket() {
666 return s_;
667}
668
669bool SocketDispatcher::CheckSignalClose() {
670 if (!signal_close_)
671 return false;
672
673 char ch;
674 if (recv(s_, &ch, 1, MSG_PEEK) > 0)
675 return false;
676
677 state_ = CS_CLOSED;
678 signal_close_ = false;
679 SignalCloseEvent(this, signal_err_);
680 return true;
681}
682
683int SocketDispatcher::next_id_ = 0;
684
685#elif defined(WEBRTC_POSIX)
686
687int SocketDispatcher::GetDescriptor() {
688 return s_;
689}
690
691bool SocketDispatcher::IsDescriptorClosed() {
deadbeeffaedf7f2017-02-09 15:09:22 -0800692 if (udp_) {
693 // The MSG_PEEK trick doesn't work for UDP, since (at least in some
694 // circumstances) it requires reading an entire UDP packet, which would be
695 // bad for performance here. So, just check whether |s_| has been closed,
696 // which should be sufficient.
697 return s_ == INVALID_SOCKET;
698 }
jbauch4331fcd2016-01-06 22:20:28 -0800699 // We don't have a reliable way of distinguishing end-of-stream
700 // from readability. So test on each readable call. Is this
701 // inefficient? Probably.
702 char ch;
703 ssize_t res = ::recv(s_, &ch, 1, MSG_PEEK);
704 if (res > 0) {
705 // Data available, so not closed.
706 return false;
707 } else if (res == 0) {
708 // EOF, so closed.
709 return true;
710 } else { // error
711 switch (errno) {
712 // Returned if we've already closed s_.
713 case EBADF:
714 // Returned during ungraceful peer shutdown.
715 case ECONNRESET:
716 return true;
deadbeeffaedf7f2017-02-09 15:09:22 -0800717 // The normal blocking error; don't log anything.
718 case EWOULDBLOCK:
719 // Interrupted system call.
720 case EINTR:
721 return false;
jbauch4331fcd2016-01-06 22:20:28 -0800722 default:
723 // Assume that all other errors are just blocking errors, meaning the
724 // connection is still good but we just can't read from it right now.
725 // This should only happen when connecting (and at most once), because
726 // in all other cases this function is only called if the file
727 // descriptor is already known to be in the readable state. However,
728 // it's not necessary a problem if we spuriously interpret a
729 // "connection lost"-type error as a blocking error, because typically
730 // the next recv() will get EOF, so we'll still eventually notice that
731 // the socket is closed.
732 LOG_ERR(LS_WARNING) << "Assuming benign blocking error";
733 return false;
734 }
735 }
736}
737
738#endif // WEBRTC_POSIX
739
740uint32_t SocketDispatcher::GetRequestedEvents() {
741 return enabled_events_;
742}
743
744void SocketDispatcher::OnPreEvent(uint32_t ff) {
745 if ((ff & DE_CONNECT) != 0)
746 state_ = CS_CONNECTED;
747
748#if defined(WEBRTC_WIN)
749 // We set CS_CLOSED from CheckSignalClose.
750#elif defined(WEBRTC_POSIX)
751 if ((ff & DE_CLOSE) != 0)
752 state_ = CS_CLOSED;
753#endif
754}
755
756#if defined(WEBRTC_WIN)
757
758void SocketDispatcher::OnEvent(uint32_t ff, int err) {
759 int cache_id = id_;
760 // Make sure we deliver connect/accept first. Otherwise, consumers may see
761 // something like a READ followed by a CONNECT, which would be odd.
762 if (((ff & DE_CONNECT) != 0) && (id_ == cache_id)) {
763 if (ff != DE_CONNECT)
764 LOG(LS_VERBOSE) << "Signalled with DE_CONNECT: " << ff;
765 enabled_events_ &= ~DE_CONNECT;
766#if !defined(NDEBUG)
767 dbg_addr_ = "Connected @ ";
768 dbg_addr_.append(GetRemoteAddress().ToString());
769#endif
770 SignalConnectEvent(this);
771 }
772 if (((ff & DE_ACCEPT) != 0) && (id_ == cache_id)) {
773 enabled_events_ &= ~DE_ACCEPT;
774 SignalReadEvent(this);
775 }
776 if ((ff & DE_READ) != 0) {
777 enabled_events_ &= ~DE_READ;
778 SignalReadEvent(this);
779 }
780 if (((ff & DE_WRITE) != 0) && (id_ == cache_id)) {
781 enabled_events_ &= ~DE_WRITE;
782 SignalWriteEvent(this);
783 }
784 if (((ff & DE_CLOSE) != 0) && (id_ == cache_id)) {
785 signal_close_ = true;
786 signal_err_ = err;
787 }
788}
789
790#elif defined(WEBRTC_POSIX)
791
792void SocketDispatcher::OnEvent(uint32_t ff, int err) {
793 // Make sure we deliver connect/accept first. Otherwise, consumers may see
794 // something like a READ followed by a CONNECT, which would be odd.
795 if ((ff & DE_CONNECT) != 0) {
796 enabled_events_ &= ~DE_CONNECT;
797 SignalConnectEvent(this);
798 }
799 if ((ff & DE_ACCEPT) != 0) {
800 enabled_events_ &= ~DE_ACCEPT;
801 SignalReadEvent(this);
802 }
803 if ((ff & DE_READ) != 0) {
804 enabled_events_ &= ~DE_READ;
805 SignalReadEvent(this);
806 }
807 if ((ff & DE_WRITE) != 0) {
808 enabled_events_ &= ~DE_WRITE;
809 SignalWriteEvent(this);
810 }
811 if ((ff & DE_CLOSE) != 0) {
812 // The socket is now dead to us, so stop checking it.
813 enabled_events_ = 0;
814 SignalCloseEvent(this, err);
815 }
816}
817
818#endif // WEBRTC_POSIX
819
820int SocketDispatcher::Close() {
821 if (s_ == INVALID_SOCKET)
822 return 0;
823
824#if defined(WEBRTC_WIN)
825 id_ = 0;
826 signal_close_ = false;
827#endif
828 ss_->Remove(this);
829 return PhysicalSocket::Close();
830}
831
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000832#if defined(WEBRTC_POSIX)
833class EventDispatcher : public Dispatcher {
834 public:
835 EventDispatcher(PhysicalSocketServer* ss) : ss_(ss), fSignaled_(false) {
836 if (pipe(afd_) < 0)
837 LOG(LERROR) << "pipe failed";
838 ss_->Add(this);
839 }
840
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000841 ~EventDispatcher() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000842 ss_->Remove(this);
843 close(afd_[0]);
844 close(afd_[1]);
845 }
846
847 virtual void Signal() {
848 CritScope cs(&crit_);
849 if (!fSignaled_) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200850 const uint8_t b[1] = {0};
nissec16fa5e2017-02-07 07:18:43 -0800851 const ssize_t res = write(afd_[1], b, sizeof(b));
852 RTC_DCHECK_EQ(1, res);
853 fSignaled_ = true;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000854 }
855 }
856
Peter Boström0c4e06b2015-10-07 12:23:21 +0200857 uint32_t GetRequestedEvents() override { return DE_READ; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000858
Peter Boström0c4e06b2015-10-07 12:23:21 +0200859 void OnPreEvent(uint32_t ff) override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000860 // It is not possible to perfectly emulate an auto-resetting event with
861 // pipes. This simulates it by resetting before the event is handled.
862
863 CritScope cs(&crit_);
864 if (fSignaled_) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200865 uint8_t b[4]; // Allow for reading more than 1 byte, but expect 1.
nissec16fa5e2017-02-07 07:18:43 -0800866 const ssize_t res = read(afd_[0], b, sizeof(b));
867 RTC_DCHECK_EQ(1, res);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000868 fSignaled_ = false;
869 }
870 }
871
nissec80e7412017-01-11 05:56:46 -0800872 void OnEvent(uint32_t ff, int err) override { RTC_NOTREACHED(); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000873
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000874 int GetDescriptor() override { return afd_[0]; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000875
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000876 bool IsDescriptorClosed() override { return false; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000877
878 private:
879 PhysicalSocketServer *ss_;
880 int afd_[2];
881 bool fSignaled_;
882 CriticalSection crit_;
883};
884
885// These two classes use the self-pipe trick to deliver POSIX signals to our
886// select loop. This is the only safe, reliable, cross-platform way to do
887// non-trivial things with a POSIX signal in an event-driven program (until
888// proper pselect() implementations become ubiquitous).
889
890class PosixSignalHandler {
891 public:
892 // POSIX only specifies 32 signals, but in principle the system might have
893 // more and the programmer might choose to use them, so we size our array
894 // for 128.
895 static const int kNumPosixSignals = 128;
896
897 // There is just a single global instance. (Signal handlers do not get any
898 // sort of user-defined void * parameter, so they can't access anything that
899 // isn't global.)
900 static PosixSignalHandler* Instance() {
Andrew MacDonald469c2c02015-05-22 17:50:26 -0700901 RTC_DEFINE_STATIC_LOCAL(PosixSignalHandler, instance, ());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000902 return &instance;
903 }
904
905 // Returns true if the given signal number is set.
906 bool IsSignalSet(int signum) const {
nisseede5da42017-01-12 05:15:36 -0800907 RTC_DCHECK(signum < static_cast<int>(arraysize(received_signal_)));
tfarina5237aaf2015-11-10 23:44:30 -0800908 if (signum < static_cast<int>(arraysize(received_signal_))) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000909 return received_signal_[signum];
910 } else {
911 return false;
912 }
913 }
914
915 // Clears the given signal number.
916 void ClearSignal(int signum) {
nisseede5da42017-01-12 05:15:36 -0800917 RTC_DCHECK(signum < static_cast<int>(arraysize(received_signal_)));
tfarina5237aaf2015-11-10 23:44:30 -0800918 if (signum < static_cast<int>(arraysize(received_signal_))) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000919 received_signal_[signum] = false;
920 }
921 }
922
923 // Returns the file descriptor to monitor for signal events.
924 int GetDescriptor() const {
925 return afd_[0];
926 }
927
928 // This is called directly from our real signal handler, so it must be
929 // signal-handler-safe. That means it cannot assume anything about the
930 // user-level state of the process, since the handler could be executed at any
931 // time on any thread.
932 void OnPosixSignalReceived(int signum) {
tfarina5237aaf2015-11-10 23:44:30 -0800933 if (signum >= static_cast<int>(arraysize(received_signal_))) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000934 // We don't have space in our array for this.
935 return;
936 }
937 // Set a flag saying we've seen this signal.
938 received_signal_[signum] = true;
939 // Notify application code that we got a signal.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200940 const uint8_t b[1] = {0};
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000941 if (-1 == write(afd_[1], b, sizeof(b))) {
942 // Nothing we can do here. If there's an error somehow then there's
943 // nothing we can safely do from a signal handler.
944 // No, we can't even safely log it.
945 // But, we still have to check the return value here. Otherwise,
946 // GCC 4.4.1 complains ignoring return value. Even (void) doesn't help.
947 return;
948 }
949 }
950
951 private:
952 PosixSignalHandler() {
953 if (pipe(afd_) < 0) {
954 LOG_ERR(LS_ERROR) << "pipe failed";
955 return;
956 }
957 if (fcntl(afd_[0], F_SETFL, O_NONBLOCK) < 0) {
958 LOG_ERR(LS_WARNING) << "fcntl #1 failed";
959 }
960 if (fcntl(afd_[1], F_SETFL, O_NONBLOCK) < 0) {
961 LOG_ERR(LS_WARNING) << "fcntl #2 failed";
962 }
963 memset(const_cast<void *>(static_cast<volatile void *>(received_signal_)),
964 0,
965 sizeof(received_signal_));
966 }
967
968 ~PosixSignalHandler() {
969 int fd1 = afd_[0];
970 int fd2 = afd_[1];
971 // We clobber the stored file descriptor numbers here or else in principle
972 // a signal that happens to be delivered during application termination
973 // could erroneously write a zero byte to an unrelated file handle in
974 // OnPosixSignalReceived() if some other file happens to be opened later
975 // during shutdown and happens to be given the same file descriptor number
976 // as our pipe had. Unfortunately even with this precaution there is still a
977 // race where that could occur if said signal happens to be handled
978 // concurrently with this code and happens to have already read the value of
979 // afd_[1] from memory before we clobber it, but that's unlikely.
980 afd_[0] = -1;
981 afd_[1] = -1;
982 close(fd1);
983 close(fd2);
984 }
985
986 int afd_[2];
987 // These are boolean flags that will be set in our signal handler and read
988 // and cleared from Wait(). There is a race involved in this, but it is
989 // benign. The signal handler sets the flag before signaling the pipe, so
990 // we'll never end up blocking in select() while a flag is still true.
991 // However, if two of the same signal arrive close to each other then it's
992 // possible that the second time the handler may set the flag while it's still
993 // true, meaning that signal will be missed. But the first occurrence of it
994 // will still be handled, so this isn't a problem.
995 // Volatile is not necessary here for correctness, but this data _is_ volatile
996 // so I've marked it as such.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200997 volatile uint8_t received_signal_[kNumPosixSignals];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000998};
999
1000class PosixSignalDispatcher : public Dispatcher {
1001 public:
1002 PosixSignalDispatcher(PhysicalSocketServer *owner) : owner_(owner) {
1003 owner_->Add(this);
1004 }
1005
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +00001006 ~PosixSignalDispatcher() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001007 owner_->Remove(this);
1008 }
1009
Peter Boström0c4e06b2015-10-07 12:23:21 +02001010 uint32_t GetRequestedEvents() override { return DE_READ; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001011
Peter Boström0c4e06b2015-10-07 12:23:21 +02001012 void OnPreEvent(uint32_t ff) override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001013 // Events might get grouped if signals come very fast, so we read out up to
1014 // 16 bytes to make sure we keep the pipe empty.
Peter Boström0c4e06b2015-10-07 12:23:21 +02001015 uint8_t b[16];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001016 ssize_t ret = read(GetDescriptor(), b, sizeof(b));
1017 if (ret < 0) {
1018 LOG_ERR(LS_WARNING) << "Error in read()";
1019 } else if (ret == 0) {
1020 LOG(LS_WARNING) << "Should have read at least one byte";
1021 }
1022 }
1023
Peter Boström0c4e06b2015-10-07 12:23:21 +02001024 void OnEvent(uint32_t ff, int err) override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001025 for (int signum = 0; signum < PosixSignalHandler::kNumPosixSignals;
1026 ++signum) {
1027 if (PosixSignalHandler::Instance()->IsSignalSet(signum)) {
1028 PosixSignalHandler::Instance()->ClearSignal(signum);
1029 HandlerMap::iterator i = handlers_.find(signum);
1030 if (i == handlers_.end()) {
1031 // This can happen if a signal is delivered to our process at around
1032 // the same time as we unset our handler for it. It is not an error
1033 // condition, but it's unusual enough to be worth logging.
1034 LOG(LS_INFO) << "Received signal with no handler: " << signum;
1035 } else {
1036 // Otherwise, execute our handler.
1037 (*i->second)(signum);
1038 }
1039 }
1040 }
1041 }
1042
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +00001043 int GetDescriptor() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001044 return PosixSignalHandler::Instance()->GetDescriptor();
1045 }
1046
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +00001047 bool IsDescriptorClosed() override { return false; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001048
1049 void SetHandler(int signum, void (*handler)(int)) {
1050 handlers_[signum] = handler;
1051 }
1052
1053 void ClearHandler(int signum) {
1054 handlers_.erase(signum);
1055 }
1056
1057 bool HasHandlers() {
1058 return !handlers_.empty();
1059 }
1060
1061 private:
1062 typedef std::map<int, void (*)(int)> HandlerMap;
1063
1064 HandlerMap handlers_;
1065 // Our owner.
1066 PhysicalSocketServer *owner_;
1067};
1068
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001069#endif // WEBRTC_POSIX
1070
1071#if defined(WEBRTC_WIN)
Peter Boström0c4e06b2015-10-07 12:23:21 +02001072static uint32_t FlagsToEvents(uint32_t events) {
1073 uint32_t ffFD = FD_CLOSE;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001074 if (events & DE_READ)
1075 ffFD |= FD_READ;
1076 if (events & DE_WRITE)
1077 ffFD |= FD_WRITE;
1078 if (events & DE_CONNECT)
1079 ffFD |= FD_CONNECT;
1080 if (events & DE_ACCEPT)
1081 ffFD |= FD_ACCEPT;
1082 return ffFD;
1083}
1084
1085class EventDispatcher : public Dispatcher {
1086 public:
1087 EventDispatcher(PhysicalSocketServer *ss) : ss_(ss) {
1088 hev_ = WSACreateEvent();
1089 if (hev_) {
1090 ss_->Add(this);
1091 }
1092 }
1093
1094 ~EventDispatcher() {
1095 if (hev_ != NULL) {
1096 ss_->Remove(this);
1097 WSACloseEvent(hev_);
1098 hev_ = NULL;
1099 }
1100 }
1101
1102 virtual void Signal() {
1103 if (hev_ != NULL)
1104 WSASetEvent(hev_);
1105 }
1106
Peter Boström0c4e06b2015-10-07 12:23:21 +02001107 virtual uint32_t GetRequestedEvents() { return 0; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001108
Peter Boström0c4e06b2015-10-07 12:23:21 +02001109 virtual void OnPreEvent(uint32_t ff) { WSAResetEvent(hev_); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001110
Peter Boström0c4e06b2015-10-07 12:23:21 +02001111 virtual void OnEvent(uint32_t ff, int err) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001112
1113 virtual WSAEVENT GetWSAEvent() {
1114 return hev_;
1115 }
1116
1117 virtual SOCKET GetSocket() {
1118 return INVALID_SOCKET;
1119 }
1120
1121 virtual bool CheckSignalClose() { return false; }
1122
1123private:
1124 PhysicalSocketServer* ss_;
1125 WSAEVENT hev_;
1126};
honghaizcec0a082016-01-15 14:49:09 -08001127#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001128
1129// Sets the value of a boolean value to false when signaled.
1130class Signaler : public EventDispatcher {
1131 public:
1132 Signaler(PhysicalSocketServer* ss, bool* pf)
1133 : EventDispatcher(ss), pf_(pf) {
1134 }
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +00001135 ~Signaler() override { }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001136
Peter Boström0c4e06b2015-10-07 12:23:21 +02001137 void OnEvent(uint32_t ff, int err) override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001138 if (pf_)
1139 *pf_ = false;
1140 }
1141
1142 private:
1143 bool *pf_;
1144};
1145
1146PhysicalSocketServer::PhysicalSocketServer()
1147 : fWait_(false) {
1148 signal_wakeup_ = new Signaler(this, &fWait_);
1149#if defined(WEBRTC_WIN)
1150 socket_ev_ = WSACreateEvent();
1151#endif
1152}
1153
1154PhysicalSocketServer::~PhysicalSocketServer() {
1155#if defined(WEBRTC_WIN)
1156 WSACloseEvent(socket_ev_);
1157#endif
1158#if defined(WEBRTC_POSIX)
1159 signal_dispatcher_.reset();
1160#endif
1161 delete signal_wakeup_;
nisseede5da42017-01-12 05:15:36 -08001162 RTC_DCHECK(dispatchers_.empty());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001163}
1164
1165void PhysicalSocketServer::WakeUp() {
1166 signal_wakeup_->Signal();
1167}
1168
1169Socket* PhysicalSocketServer::CreateSocket(int type) {
1170 return CreateSocket(AF_INET, type);
1171}
1172
1173Socket* PhysicalSocketServer::CreateSocket(int family, int type) {
1174 PhysicalSocket* socket = new PhysicalSocket(this);
1175 if (socket->Create(family, type)) {
1176 return socket;
1177 } else {
1178 delete socket;
jbauch095ae152015-12-18 01:39:55 -08001179 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001180 }
1181}
1182
1183AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int type) {
1184 return CreateAsyncSocket(AF_INET, type);
1185}
1186
1187AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int family, int type) {
1188 SocketDispatcher* dispatcher = new SocketDispatcher(this);
1189 if (dispatcher->Create(family, type)) {
1190 return dispatcher;
1191 } else {
1192 delete dispatcher;
jbauch095ae152015-12-18 01:39:55 -08001193 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001194 }
1195}
1196
1197AsyncSocket* PhysicalSocketServer::WrapSocket(SOCKET s) {
1198 SocketDispatcher* dispatcher = new SocketDispatcher(s, this);
1199 if (dispatcher->Initialize()) {
1200 return dispatcher;
1201 } else {
1202 delete dispatcher;
jbauch095ae152015-12-18 01:39:55 -08001203 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001204 }
1205}
1206
1207void PhysicalSocketServer::Add(Dispatcher *pdispatcher) {
1208 CritScope cs(&crit_);
1209 // Prevent duplicates. This can cause dead dispatchers to stick around.
1210 DispatcherList::iterator pos = std::find(dispatchers_.begin(),
1211 dispatchers_.end(),
1212 pdispatcher);
1213 if (pos != dispatchers_.end())
1214 return;
1215 dispatchers_.push_back(pdispatcher);
1216}
1217
1218void PhysicalSocketServer::Remove(Dispatcher *pdispatcher) {
1219 CritScope cs(&crit_);
1220 DispatcherList::iterator pos = std::find(dispatchers_.begin(),
1221 dispatchers_.end(),
1222 pdispatcher);
1223 // We silently ignore duplicate calls to Add, so we should silently ignore
1224 // the (expected) symmetric calls to Remove. Note that this may still hide
1225 // a real issue, so we at least log a warning about it.
1226 if (pos == dispatchers_.end()) {
1227 LOG(LS_WARNING) << "PhysicalSocketServer asked to remove a unknown "
1228 << "dispatcher, potentially from a duplicate call to Add.";
1229 return;
1230 }
1231 size_t index = pos - dispatchers_.begin();
1232 dispatchers_.erase(pos);
1233 for (IteratorList::iterator it = iterators_.begin(); it != iterators_.end();
1234 ++it) {
1235 if (index < **it) {
1236 --**it;
1237 }
1238 }
1239}
1240
1241#if defined(WEBRTC_POSIX)
1242bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
1243 // Calculate timing information
1244
1245 struct timeval *ptvWait = NULL;
1246 struct timeval tvWait;
1247 struct timeval tvStop;
1248 if (cmsWait != kForever) {
1249 // Calculate wait timeval
1250 tvWait.tv_sec = cmsWait / 1000;
1251 tvWait.tv_usec = (cmsWait % 1000) * 1000;
1252 ptvWait = &tvWait;
1253
1254 // Calculate when to return in a timeval
1255 gettimeofday(&tvStop, NULL);
1256 tvStop.tv_sec += tvWait.tv_sec;
1257 tvStop.tv_usec += tvWait.tv_usec;
1258 if (tvStop.tv_usec >= 1000000) {
1259 tvStop.tv_usec -= 1000000;
1260 tvStop.tv_sec += 1;
1261 }
1262 }
1263
1264 // Zero all fd_sets. Don't need to do this inside the loop since
1265 // select() zeros the descriptors not signaled
1266
1267 fd_set fdsRead;
1268 FD_ZERO(&fdsRead);
1269 fd_set fdsWrite;
1270 FD_ZERO(&fdsWrite);
pbos@webrtc.org27e58982014-10-07 17:56:53 +00001271 // Explicitly unpoison these FDs on MemorySanitizer which doesn't handle the
1272 // inline assembly in FD_ZERO.
1273 // http://crbug.com/344505
1274#ifdef MEMORY_SANITIZER
1275 __msan_unpoison(&fdsRead, sizeof(fdsRead));
1276 __msan_unpoison(&fdsWrite, sizeof(fdsWrite));
1277#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001278
1279 fWait_ = true;
1280
1281 while (fWait_) {
1282 int fdmax = -1;
1283 {
1284 CritScope cr(&crit_);
1285 for (size_t i = 0; i < dispatchers_.size(); ++i) {
1286 // Query dispatchers for read and write wait state
1287 Dispatcher *pdispatcher = dispatchers_[i];
nisseede5da42017-01-12 05:15:36 -08001288 RTC_DCHECK(pdispatcher);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001289 if (!process_io && (pdispatcher != signal_wakeup_))
1290 continue;
1291 int fd = pdispatcher->GetDescriptor();
1292 if (fd > fdmax)
1293 fdmax = fd;
1294
Peter Boström0c4e06b2015-10-07 12:23:21 +02001295 uint32_t ff = pdispatcher->GetRequestedEvents();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001296 if (ff & (DE_READ | DE_ACCEPT))
1297 FD_SET(fd, &fdsRead);
1298 if (ff & (DE_WRITE | DE_CONNECT))
1299 FD_SET(fd, &fdsWrite);
1300 }
1301 }
1302
1303 // Wait then call handlers as appropriate
1304 // < 0 means error
1305 // 0 means timeout
1306 // > 0 means count of descriptors ready
1307 int n = select(fdmax + 1, &fdsRead, &fdsWrite, NULL, ptvWait);
1308
1309 // If error, return error.
1310 if (n < 0) {
1311 if (errno != EINTR) {
1312 LOG_E(LS_ERROR, EN, errno) << "select";
1313 return false;
1314 }
1315 // Else ignore the error and keep going. If this EINTR was for one of the
1316 // signals managed by this PhysicalSocketServer, the
1317 // PosixSignalDeliveryDispatcher will be in the signaled state in the next
1318 // iteration.
1319 } else if (n == 0) {
1320 // If timeout, return success
1321 return true;
1322 } else {
1323 // We have signaled descriptors
1324 CritScope cr(&crit_);
1325 for (size_t i = 0; i < dispatchers_.size(); ++i) {
1326 Dispatcher *pdispatcher = dispatchers_[i];
1327 int fd = pdispatcher->GetDescriptor();
Peter Boström0c4e06b2015-10-07 12:23:21 +02001328 uint32_t ff = 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001329 int errcode = 0;
1330
1331 // Reap any error code, which can be signaled through reads or writes.
jbauch095ae152015-12-18 01:39:55 -08001332 // TODO(pthatcher): Should we set errcode if getsockopt fails?
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001333 if (FD_ISSET(fd, &fdsRead) || FD_ISSET(fd, &fdsWrite)) {
1334 socklen_t len = sizeof(errcode);
1335 ::getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &len);
1336 }
1337
1338 // Check readable descriptors. If we're waiting on an accept, signal
1339 // that. Otherwise we're waiting for data, check to see if we're
1340 // readable or really closed.
jbauch095ae152015-12-18 01:39:55 -08001341 // TODO(pthatcher): Only peek at TCP descriptors.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001342 if (FD_ISSET(fd, &fdsRead)) {
1343 FD_CLR(fd, &fdsRead);
1344 if (pdispatcher->GetRequestedEvents() & DE_ACCEPT) {
1345 ff |= DE_ACCEPT;
1346 } else if (errcode || pdispatcher->IsDescriptorClosed()) {
1347 ff |= DE_CLOSE;
1348 } else {
1349 ff |= DE_READ;
1350 }
1351 }
1352
1353 // Check writable descriptors. If we're waiting on a connect, detect
1354 // success versus failure by the reaped error code.
1355 if (FD_ISSET(fd, &fdsWrite)) {
1356 FD_CLR(fd, &fdsWrite);
1357 if (pdispatcher->GetRequestedEvents() & DE_CONNECT) {
1358 if (!errcode) {
1359 ff |= DE_CONNECT;
1360 } else {
1361 ff |= DE_CLOSE;
1362 }
1363 } else {
1364 ff |= DE_WRITE;
1365 }
1366 }
1367
1368 // Tell the descriptor about the event.
1369 if (ff != 0) {
1370 pdispatcher->OnPreEvent(ff);
1371 pdispatcher->OnEvent(ff, errcode);
1372 }
1373 }
1374 }
1375
1376 // Recalc the time remaining to wait. Doing it here means it doesn't get
1377 // calced twice the first time through the loop
1378 if (ptvWait) {
1379 ptvWait->tv_sec = 0;
1380 ptvWait->tv_usec = 0;
1381 struct timeval tvT;
1382 gettimeofday(&tvT, NULL);
1383 if ((tvStop.tv_sec > tvT.tv_sec)
1384 || ((tvStop.tv_sec == tvT.tv_sec)
1385 && (tvStop.tv_usec > tvT.tv_usec))) {
1386 ptvWait->tv_sec = tvStop.tv_sec - tvT.tv_sec;
1387 ptvWait->tv_usec = tvStop.tv_usec - tvT.tv_usec;
1388 if (ptvWait->tv_usec < 0) {
nisseede5da42017-01-12 05:15:36 -08001389 RTC_DCHECK(ptvWait->tv_sec > 0);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001390 ptvWait->tv_usec += 1000000;
1391 ptvWait->tv_sec -= 1;
1392 }
1393 }
1394 }
1395 }
1396
1397 return true;
1398}
1399
1400static void GlobalSignalHandler(int signum) {
1401 PosixSignalHandler::Instance()->OnPosixSignalReceived(signum);
1402}
1403
1404bool PhysicalSocketServer::SetPosixSignalHandler(int signum,
1405 void (*handler)(int)) {
1406 // If handler is SIG_IGN or SIG_DFL then clear our user-level handler,
1407 // otherwise set one.
1408 if (handler == SIG_IGN || handler == SIG_DFL) {
1409 if (!InstallSignal(signum, handler)) {
1410 return false;
1411 }
1412 if (signal_dispatcher_) {
1413 signal_dispatcher_->ClearHandler(signum);
1414 if (!signal_dispatcher_->HasHandlers()) {
1415 signal_dispatcher_.reset();
1416 }
1417 }
1418 } else {
1419 if (!signal_dispatcher_) {
1420 signal_dispatcher_.reset(new PosixSignalDispatcher(this));
1421 }
1422 signal_dispatcher_->SetHandler(signum, handler);
1423 if (!InstallSignal(signum, &GlobalSignalHandler)) {
1424 return false;
1425 }
1426 }
1427 return true;
1428}
1429
1430Dispatcher* PhysicalSocketServer::signal_dispatcher() {
1431 return signal_dispatcher_.get();
1432}
1433
1434bool PhysicalSocketServer::InstallSignal(int signum, void (*handler)(int)) {
1435 struct sigaction act;
1436 // It doesn't really matter what we set this mask to.
1437 if (sigemptyset(&act.sa_mask) != 0) {
1438 LOG_ERR(LS_ERROR) << "Couldn't set mask";
1439 return false;
1440 }
1441 act.sa_handler = handler;
1442#if !defined(__native_client__)
1443 // Use SA_RESTART so that our syscalls don't get EINTR, since we don't need it
1444 // and it's a nuisance. Though some syscalls still return EINTR and there's no
1445 // real standard for which ones. :(
1446 act.sa_flags = SA_RESTART;
1447#else
1448 act.sa_flags = 0;
1449#endif
1450 if (sigaction(signum, &act, NULL) != 0) {
1451 LOG_ERR(LS_ERROR) << "Couldn't set sigaction";
1452 return false;
1453 }
1454 return true;
1455}
1456#endif // WEBRTC_POSIX
1457
1458#if defined(WEBRTC_WIN)
1459bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
Honghai Zhang82d78622016-05-06 11:29:15 -07001460 int64_t cmsTotal = cmsWait;
1461 int64_t cmsElapsed = 0;
1462 int64_t msStart = Time();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001463
1464 fWait_ = true;
1465 while (fWait_) {
1466 std::vector<WSAEVENT> events;
1467 std::vector<Dispatcher *> event_owners;
1468
1469 events.push_back(socket_ev_);
1470
1471 {
1472 CritScope cr(&crit_);
1473 size_t i = 0;
1474 iterators_.push_back(&i);
1475 // Don't track dispatchers_.size(), because we want to pick up any new
1476 // dispatchers that were added while processing the loop.
1477 while (i < dispatchers_.size()) {
1478 Dispatcher* disp = dispatchers_[i++];
1479 if (!process_io && (disp != signal_wakeup_))
1480 continue;
1481 SOCKET s = disp->GetSocket();
1482 if (disp->CheckSignalClose()) {
1483 // We just signalled close, don't poll this socket
1484 } else if (s != INVALID_SOCKET) {
1485 WSAEventSelect(s,
1486 events[0],
1487 FlagsToEvents(disp->GetRequestedEvents()));
1488 } else {
1489 events.push_back(disp->GetWSAEvent());
1490 event_owners.push_back(disp);
1491 }
1492 }
nisseede5da42017-01-12 05:15:36 -08001493 RTC_DCHECK(iterators_.back() == &i);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001494 iterators_.pop_back();
1495 }
1496
1497 // Which is shorter, the delay wait or the asked wait?
1498
Honghai Zhang82d78622016-05-06 11:29:15 -07001499 int64_t cmsNext;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001500 if (cmsWait == kForever) {
1501 cmsNext = cmsWait;
1502 } else {
Honghai Zhang82d78622016-05-06 11:29:15 -07001503 cmsNext = std::max<int64_t>(0, cmsTotal - cmsElapsed);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001504 }
1505
1506 // Wait for one of the events to signal
1507 DWORD dw = WSAWaitForMultipleEvents(static_cast<DWORD>(events.size()),
1508 &events[0],
1509 false,
Honghai Zhang82d78622016-05-06 11:29:15 -07001510 static_cast<DWORD>(cmsNext),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001511 false);
1512
1513 if (dw == WSA_WAIT_FAILED) {
1514 // Failed?
jbauch095ae152015-12-18 01:39:55 -08001515 // TODO(pthatcher): need a better strategy than this!
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001516 WSAGetLastError();
nissec80e7412017-01-11 05:56:46 -08001517 RTC_NOTREACHED();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001518 return false;
1519 } else if (dw == WSA_WAIT_TIMEOUT) {
1520 // Timeout?
1521 return true;
1522 } else {
1523 // Figure out which one it is and call it
1524 CritScope cr(&crit_);
1525 int index = dw - WSA_WAIT_EVENT_0;
1526 if (index > 0) {
1527 --index; // The first event is the socket event
1528 event_owners[index]->OnPreEvent(0);
1529 event_owners[index]->OnEvent(0, 0);
1530 } else if (process_io) {
1531 size_t i = 0, end = dispatchers_.size();
1532 iterators_.push_back(&i);
1533 iterators_.push_back(&end); // Don't iterate over new dispatchers.
1534 while (i < end) {
1535 Dispatcher* disp = dispatchers_[i++];
1536 SOCKET s = disp->GetSocket();
1537 if (s == INVALID_SOCKET)
1538 continue;
1539
1540 WSANETWORKEVENTS wsaEvents;
1541 int err = WSAEnumNetworkEvents(s, events[0], &wsaEvents);
1542 if (err == 0) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001543 {
1544 if ((wsaEvents.lNetworkEvents & FD_READ) &&
1545 wsaEvents.iErrorCode[FD_READ_BIT] != 0) {
1546 LOG(WARNING) << "PhysicalSocketServer got FD_READ_BIT error "
1547 << wsaEvents.iErrorCode[FD_READ_BIT];
1548 }
1549 if ((wsaEvents.lNetworkEvents & FD_WRITE) &&
1550 wsaEvents.iErrorCode[FD_WRITE_BIT] != 0) {
1551 LOG(WARNING) << "PhysicalSocketServer got FD_WRITE_BIT error "
1552 << wsaEvents.iErrorCode[FD_WRITE_BIT];
1553 }
1554 if ((wsaEvents.lNetworkEvents & FD_CONNECT) &&
1555 wsaEvents.iErrorCode[FD_CONNECT_BIT] != 0) {
1556 LOG(WARNING) << "PhysicalSocketServer got FD_CONNECT_BIT error "
1557 << wsaEvents.iErrorCode[FD_CONNECT_BIT];
1558 }
1559 if ((wsaEvents.lNetworkEvents & FD_ACCEPT) &&
1560 wsaEvents.iErrorCode[FD_ACCEPT_BIT] != 0) {
1561 LOG(WARNING) << "PhysicalSocketServer got FD_ACCEPT_BIT error "
1562 << wsaEvents.iErrorCode[FD_ACCEPT_BIT];
1563 }
1564 if ((wsaEvents.lNetworkEvents & FD_CLOSE) &&
1565 wsaEvents.iErrorCode[FD_CLOSE_BIT] != 0) {
1566 LOG(WARNING) << "PhysicalSocketServer got FD_CLOSE_BIT error "
1567 << wsaEvents.iErrorCode[FD_CLOSE_BIT];
1568 }
1569 }
Peter Boström0c4e06b2015-10-07 12:23:21 +02001570 uint32_t ff = 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001571 int errcode = 0;
1572 if (wsaEvents.lNetworkEvents & FD_READ)
1573 ff |= DE_READ;
1574 if (wsaEvents.lNetworkEvents & FD_WRITE)
1575 ff |= DE_WRITE;
1576 if (wsaEvents.lNetworkEvents & FD_CONNECT) {
1577 if (wsaEvents.iErrorCode[FD_CONNECT_BIT] == 0) {
1578 ff |= DE_CONNECT;
1579 } else {
1580 ff |= DE_CLOSE;
1581 errcode = wsaEvents.iErrorCode[FD_CONNECT_BIT];
1582 }
1583 }
1584 if (wsaEvents.lNetworkEvents & FD_ACCEPT)
1585 ff |= DE_ACCEPT;
1586 if (wsaEvents.lNetworkEvents & FD_CLOSE) {
1587 ff |= DE_CLOSE;
1588 errcode = wsaEvents.iErrorCode[FD_CLOSE_BIT];
1589 }
1590 if (ff != 0) {
1591 disp->OnPreEvent(ff);
1592 disp->OnEvent(ff, errcode);
1593 }
1594 }
1595 }
nisseede5da42017-01-12 05:15:36 -08001596 RTC_DCHECK(iterators_.back() == &end);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001597 iterators_.pop_back();
nisseede5da42017-01-12 05:15:36 -08001598 RTC_DCHECK(iterators_.back() == &i);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001599 iterators_.pop_back();
1600 }
1601
1602 // Reset the network event until new activity occurs
1603 WSAResetEvent(socket_ev_);
1604 }
1605
1606 // Break?
1607 if (!fWait_)
1608 break;
1609 cmsElapsed = TimeSince(msStart);
1610 if ((cmsWait != kForever) && (cmsElapsed >= cmsWait)) {
1611 break;
1612 }
1613 }
1614
1615 // Done
1616 return true;
1617}
honghaizcec0a082016-01-15 14:49:09 -08001618#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001619
1620} // namespace rtc