Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(396)

Side by Side Diff: webrtc/base/physicalsocketserver.cc

Issue 1452903006: Keep listening if "accept" returns an invalid socket. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Added unittest Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 26 matching lines...) Expand all
37 #endif 37 #endif
38 38
39 #include <algorithm> 39 #include <algorithm>
40 #include <map> 40 #include <map>
41 41
42 #include "webrtc/base/arraysize.h" 42 #include "webrtc/base/arraysize.h"
43 #include "webrtc/base/basictypes.h" 43 #include "webrtc/base/basictypes.h"
44 #include "webrtc/base/byteorder.h" 44 #include "webrtc/base/byteorder.h"
45 #include "webrtc/base/common.h" 45 #include "webrtc/base/common.h"
46 #include "webrtc/base/logging.h" 46 #include "webrtc/base/logging.h"
47 #include "webrtc/base/nethelpers.h"
48 #include "webrtc/base/physicalsocketserver.h" 47 #include "webrtc/base/physicalsocketserver.h"
49 #include "webrtc/base/timeutils.h" 48 #include "webrtc/base/timeutils.h"
50 #include "webrtc/base/winping.h" 49 #include "webrtc/base/winping.h"
51 #include "webrtc/base/win32socketinit.h" 50 #include "webrtc/base/win32socketinit.h"
52 51
53 // stm: this will tell us if we are on OSX 52 // stm: this will tell us if we are on OSX
54 #ifdef HAVE_CONFIG_H 53 #ifdef HAVE_CONFIG_H
55 #include "config.h" 54 #include "config.h"
56 #endif 55 #endif
57 56
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 68, // Official minimum 89 68, // Official minimum
91 0, // End of list marker 90 0, // End of list marker
92 }; 91 };
93 92
94 static const int IP_HEADER_SIZE = 20u; 93 static const int IP_HEADER_SIZE = 20u;
95 static const int IPV6_HEADER_SIZE = 40u; 94 static const int IPV6_HEADER_SIZE = 40u;
96 static const int ICMP_HEADER_SIZE = 8u; 95 static const int ICMP_HEADER_SIZE = 8u;
97 static const int ICMP_PING_TIMEOUT_MILLIS = 10000u; 96 static const int ICMP_PING_TIMEOUT_MILLIS = 10000u;
98 #endif 97 #endif
99 98
100 class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> { 99 PhysicalSocket::PhysicalSocket(PhysicalSocketServer* ss, SOCKET s)
101 public: 100 : ss_(ss), s_(s), enabled_events_(0), error_(0),
102 PhysicalSocket(PhysicalSocketServer* ss, SOCKET s = INVALID_SOCKET) 101 state_((s == INVALID_SOCKET) ? CS_CLOSED : CS_CONNECTED),
103 : ss_(ss), s_(s), enabled_events_(0), error_(0), 102 resolver_(nullptr) {
104 state_((s == INVALID_SOCKET) ? CS_CLOSED : CS_CONNECTED),
105 resolver_(NULL) {
106 #if defined(WEBRTC_WIN) 103 #if defined(WEBRTC_WIN)
107 // EnsureWinsockInit() ensures that winsock is initialized. The default 104 // EnsureWinsockInit() ensures that winsock is initialized. The default
108 // version of this function doesn't do anything because winsock is 105 // version of this function doesn't do anything because winsock is
109 // initialized by constructor of a static object. If neccessary libjingle 106 // initialized by constructor of a static object. If neccessary libjingle
110 // users can link it with a different version of this function by replacing 107 // users can link it with a different version of this function by replacing
111 // win32socketinit.cc. See win32socketinit.cc for more details. 108 // win32socketinit.cc. See win32socketinit.cc for more details.
112 EnsureWinsockInit(); 109 EnsureWinsockInit();
113 #endif 110 #endif
114 if (s_ != INVALID_SOCKET) { 111 if (s_ != INVALID_SOCKET) {
115 enabled_events_ = DE_READ | DE_WRITE; 112 enabled_events_ = DE_READ | DE_WRITE;
116 113
117 int type = SOCK_STREAM; 114 int type = SOCK_STREAM;
118 socklen_t len = sizeof(type); 115 socklen_t len = sizeof(type);
119 VERIFY(0 == getsockopt(s_, SOL_SOCKET, SO_TYPE, (SockOptArg)&type, &len)); 116 VERIFY(0 == getsockopt(s_, SOL_SOCKET, SO_TYPE, (SockOptArg)&type, &len));
120 udp_ = (SOCK_DGRAM == type);
121 }
122 }
123
124 ~PhysicalSocket() override {
125 Close();
126 }
127
128 // Creates the underlying OS socket (same as the "socket" function).
129 virtual bool Create(int family, int type) {
130 Close();
131 s_ = ::socket(family, type, 0);
132 udp_ = (SOCK_DGRAM == type); 117 udp_ = (SOCK_DGRAM == type);
133 UpdateLastError(); 118 }
134 if (udp_) 119 }
135 enabled_events_ = DE_READ | DE_WRITE; 120
136 return s_ != INVALID_SOCKET; 121 PhysicalSocket::~PhysicalSocket() {
137 } 122 Close();
138 123 }
139 SocketAddress GetLocalAddress() const override { 124
140 sockaddr_storage addr_storage = {0}; 125 bool PhysicalSocket::Create(int family, int type) {
141 socklen_t addrlen = sizeof(addr_storage); 126 Close();
142 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); 127 s_ = ::socket(family, type, 0);
143 int result = ::getsockname(s_, addr, &addrlen); 128 udp_ = (SOCK_DGRAM == type);
144 SocketAddress address; 129 UpdateLastError();
145 if (result >= 0) { 130 if (udp_)
146 SocketAddressFromSockAddrStorage(addr_storage, &address); 131 enabled_events_ = DE_READ | DE_WRITE;
147 } else { 132 return s_ != INVALID_SOCKET;
148 LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket=" 133 }
149 << s_; 134
150 } 135 SocketAddress PhysicalSocket::GetLocalAddress() const {
151 return address; 136 sockaddr_storage addr_storage = {0};
152 } 137 socklen_t addrlen = sizeof(addr_storage);
153 138 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
154 SocketAddress GetRemoteAddress() const override { 139 int result = ::getsockname(s_, addr, &addrlen);
155 sockaddr_storage addr_storage = {0}; 140 SocketAddress address;
156 socklen_t addrlen = sizeof(addr_storage); 141 if (result >= 0) {
157 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); 142 SocketAddressFromSockAddrStorage(addr_storage, &address);
158 int result = ::getpeername(s_, addr, &addrlen); 143 } else {
159 SocketAddress address; 144 LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket="
160 if (result >= 0) { 145 << s_;
161 SocketAddressFromSockAddrStorage(addr_storage, &address); 146 }
162 } else { 147 return address;
163 LOG(LS_WARNING) << "GetRemoteAddress: unable to get remote addr, socket=" 148 }
164 << s_; 149
165 } 150 SocketAddress PhysicalSocket::GetRemoteAddress() const {
166 return address; 151 sockaddr_storage addr_storage = {0};
167 } 152 socklen_t addrlen = sizeof(addr_storage);
168 153 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
169 int Bind(const SocketAddress& bind_addr) override { 154 int result = ::getpeername(s_, addr, &addrlen);
170 sockaddr_storage addr_storage; 155 SocketAddress address;
171 size_t len = bind_addr.ToSockAddrStorage(&addr_storage); 156 if (result >= 0) {
172 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); 157 SocketAddressFromSockAddrStorage(addr_storage, &address);
173 int err = ::bind(s_, addr, static_cast<int>(len)); 158 } else {
174 UpdateLastError(); 159 LOG(LS_WARNING) << "GetRemoteAddress: unable to get remote addr, socket="
160 << s_;
161 }
162 return address;
163 }
164
165 int PhysicalSocket::Bind(const SocketAddress& bind_addr) {
166 sockaddr_storage addr_storage;
167 size_t len = bind_addr.ToSockAddrStorage(&addr_storage);
168 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
169 int err = ::bind(s_, addr, static_cast<int>(len));
170 UpdateLastError();
175 #if !defined(NDEBUG) 171 #if !defined(NDEBUG)
176 if (0 == err) { 172 if (0 == err) {
177 dbg_addr_ = "Bound @ "; 173 dbg_addr_ = "Bound @ ";
178 dbg_addr_.append(GetLocalAddress().ToString()); 174 dbg_addr_.append(GetLocalAddress().ToString());
179 } 175 }
180 #endif 176 #endif
181 return err; 177 return err;
182 } 178 }
183 179
184 int Connect(const SocketAddress& addr) override { 180 int PhysicalSocket::Connect(const SocketAddress& addr) {
185 // TODO: Implicit creation is required to reconnect... 181 // TODO: Implicit creation is required to reconnect...
186 // ...but should we make it more explicit? 182 // ...but should we make it more explicit?
187 if (state_ != CS_CLOSED) { 183 if (state_ != CS_CLOSED) {
188 SetError(EALREADY); 184 SetError(EALREADY);
189 return SOCKET_ERROR; 185 return SOCKET_ERROR;
190 } 186 }
191 if (addr.IsUnresolvedIP()) { 187 if (addr.IsUnresolvedIP()) {
192 LOG(LS_VERBOSE) << "Resolving addr in PhysicalSocket::Connect"; 188 LOG(LS_VERBOSE) << "Resolving addr in PhysicalSocket::Connect";
193 resolver_ = new AsyncResolver(); 189 resolver_ = new AsyncResolver();
194 resolver_->SignalDone.connect(this, &PhysicalSocket::OnResolveResult); 190 resolver_->SignalDone.connect(this, &PhysicalSocket::OnResolveResult);
195 resolver_->Start(addr); 191 resolver_->Start(addr);
196 state_ = CS_CONNECTING; 192 state_ = CS_CONNECTING;
193 return 0;
194 }
195
196 return DoConnect(addr);
197 }
198
199 int PhysicalSocket::DoConnect(const SocketAddress& connect_addr) {
200 if ((s_ == INVALID_SOCKET) &&
201 !Create(connect_addr.family(), SOCK_STREAM)) {
202 return SOCKET_ERROR;
203 }
204 sockaddr_storage addr_storage;
205 size_t len = connect_addr.ToSockAddrStorage(&addr_storage);
206 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
207 int err = ::connect(s_, addr, static_cast<int>(len));
208 UpdateLastError();
209 if (err == 0) {
210 state_ = CS_CONNECTED;
211 } else if (IsBlockingError(GetError())) {
212 state_ = CS_CONNECTING;
213 enabled_events_ |= DE_CONNECT;
214 } else {
215 return SOCKET_ERROR;
216 }
217
218 enabled_events_ |= DE_READ | DE_WRITE;
219 return 0;
220 }
221
222 int PhysicalSocket::GetError() const {
223 CritScope cs(&crit_);
224 return error_;
225 }
226
227 void PhysicalSocket::SetError(int error) {
228 CritScope cs(&crit_);
229 error_ = error;
230 }
231
232 int PhysicalSocket::GetOption(Option opt, int* value) {
233 int slevel;
234 int sopt;
235 if (TranslateOption(opt, &slevel, &sopt) == -1)
236 return -1;
237 socklen_t optlen = sizeof(*value);
238 int ret = ::getsockopt(s_, slevel, sopt, (SockOptArg)value, &optlen);
239 if (ret != -1 && opt == OPT_DONTFRAGMENT) {
240 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
241 *value = (*value != IP_PMTUDISC_DONT) ? 1 : 0;
242 #endif
243 }
244 return ret;
245 }
246
247 int PhysicalSocket::SetOption(Option opt, int value) {
248 int slevel;
249 int sopt;
250 if (TranslateOption(opt, &slevel, &sopt) == -1)
251 return -1;
252 if (opt == OPT_DONTFRAGMENT) {
253 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
254 value = (value) ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
255 #endif
256 }
257 return ::setsockopt(s_, slevel, sopt, (SockOptArg)&value, sizeof(value));
258 }
259
260 int PhysicalSocket::Send(const void* pv, size_t cb) {
261 int sent = ::send(s_, reinterpret_cast<const char *>(pv), (int)cb,
262 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
263 // Suppress SIGPIPE. Without this, attempting to send on a socket whose
264 // other end is closed will result in a SIGPIPE signal being raised to
265 // our process, which by default will terminate the process, which we
266 // don't want. By specifying this flag, we'll just get the error EPIPE
267 // instead and can handle the error gracefully.
268 MSG_NOSIGNAL
269 #else
270 0
271 #endif
272 );
273 UpdateLastError();
274 MaybeRemapSendError();
275 // We have seen minidumps where this may be false.
276 ASSERT(sent <= static_cast<int>(cb));
277 if ((sent < 0) && IsBlockingError(GetError())) {
278 enabled_events_ |= DE_WRITE;
279 }
280 return sent;
281 }
282
283 int PhysicalSocket::SendTo(const void* buffer,
284 size_t length,
285 const SocketAddress& addr) {
286 sockaddr_storage saddr;
287 size_t len = addr.ToSockAddrStorage(&saddr);
288 int sent = ::sendto(
289 s_, static_cast<const char *>(buffer), static_cast<int>(length),
290 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
291 // Suppress SIGPIPE. See above for explanation.
292 MSG_NOSIGNAL,
293 #else
294 0,
295 #endif
296 reinterpret_cast<sockaddr*>(&saddr), static_cast<int>(len));
297 UpdateLastError();
298 MaybeRemapSendError();
299 // We have seen minidumps where this may be false.
300 ASSERT(sent <= static_cast<int>(length));
301 if ((sent < 0) && IsBlockingError(GetError())) {
302 enabled_events_ |= DE_WRITE;
303 }
304 return sent;
305 }
306
307 int PhysicalSocket::Recv(void* buffer, size_t length) {
308 int received = ::recv(s_, static_cast<char*>(buffer),
309 static_cast<int>(length), 0);
310 if ((received == 0) && (length != 0)) {
311 // Note: on graceful shutdown, recv can return 0. In this case, we
312 // pretend it is blocking, and then signal close, so that simplifying
313 // assumptions can be made about Recv.
314 LOG(LS_WARNING) << "EOF from socket; deferring close event";
315 // Must turn this back on so that the select() loop will notice the close
316 // event.
317 enabled_events_ |= DE_READ;
318 SetError(EWOULDBLOCK);
319 return SOCKET_ERROR;
320 }
321 UpdateLastError();
322 int error = GetError();
323 bool success = (received >= 0) || IsBlockingError(error);
324 if (udp_ || success) {
325 enabled_events_ |= DE_READ;
326 }
327 if (!success) {
328 LOG_F(LS_VERBOSE) << "Error = " << error;
329 }
330 return received;
331 }
332
333 int PhysicalSocket::RecvFrom(void* buffer,
334 size_t length,
335 SocketAddress* out_addr) {
336 sockaddr_storage addr_storage;
337 socklen_t addr_len = sizeof(addr_storage);
338 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
339 int received = ::recvfrom(s_, static_cast<char*>(buffer),
340 static_cast<int>(length), 0, addr, &addr_len);
341 UpdateLastError();
342 if ((received >= 0) && (out_addr != nullptr))
343 SocketAddressFromSockAddrStorage(addr_storage, out_addr);
344 int error = GetError();
345 bool success = (received >= 0) || IsBlockingError(error);
346 if (udp_ || success) {
347 enabled_events_ |= DE_READ;
348 }
349 if (!success) {
350 LOG_F(LS_VERBOSE) << "Error = " << error;
351 }
352 return received;
353 }
354
355 int PhysicalSocket::Listen(int backlog) {
356 int err = ::listen(s_, backlog);
357 UpdateLastError();
358 if (err == 0) {
359 state_ = CS_CONNECTING;
360 enabled_events_ |= DE_ACCEPT;
361 #if !defined(NDEBUG)
362 dbg_addr_ = "Listening @ ";
363 dbg_addr_.append(GetLocalAddress().ToString());
364 #endif
365 }
366 return err;
367 }
368
369 AsyncSocket* PhysicalSocket::Accept(SocketAddress* out_addr) {
370 // Always re-subscribe DE_ACCEPT to make sure new incoming connections will
371 // trigger an event even if DoAccept returns an error here.
372 enabled_events_ |= DE_ACCEPT;
373 sockaddr_storage addr_storage;
374 socklen_t addr_len = sizeof(addr_storage);
375 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
376 SOCKET s = DoAccept(s_, addr, &addr_len);
377 UpdateLastError();
378 if (s == INVALID_SOCKET)
379 return nullptr;
380 if (out_addr != nullptr)
381 SocketAddressFromSockAddrStorage(addr_storage, out_addr);
382 return ss_->WrapSocket(s);
383 }
384
385 int PhysicalSocket::Close() {
386 if (s_ == INVALID_SOCKET)
387 return 0;
388 int err = ::closesocket(s_);
389 UpdateLastError();
390 s_ = INVALID_SOCKET;
391 state_ = CS_CLOSED;
392 enabled_events_ = 0;
393 if (resolver_) {
394 resolver_->Destroy(false);
395 resolver_ = nullptr;
396 }
397 return err;
398 }
399
400 int PhysicalSocket::EstimateMTU(uint16_t* mtu) {
401 SocketAddress addr = GetRemoteAddress();
402 if (addr.IsAnyIP()) {
403 SetError(ENOTCONN);
404 return -1;
405 }
406
407 #if defined(WEBRTC_WIN)
408 // Gets the interface MTU (TTL=1) for the interface used to reach |addr|.
409 WinPing ping;
410 if (!ping.IsValid()) {
411 SetError(EINVAL); // can't think of a better error ID
412 return -1;
413 }
414 int header_size = ICMP_HEADER_SIZE;
415 if (addr.family() == AF_INET6) {
416 header_size += IPV6_HEADER_SIZE;
417 } else if (addr.family() == AF_INET) {
418 header_size += IP_HEADER_SIZE;
419 }
420
421 for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) {
422 int32_t size = PACKET_MAXIMUMS[level] - header_size;
423 WinPing::PingResult result = ping.Ping(addr.ipaddr(), size,
424 ICMP_PING_TIMEOUT_MILLIS,
425 1, false);
426 if (result == WinPing::PING_FAIL) {
427 SetError(EINVAL); // can't think of a better error ID
428 return -1;
429 } else if (result != WinPing::PING_TOO_LARGE) {
430 *mtu = PACKET_MAXIMUMS[level];
197 return 0; 431 return 0;
198 } 432 }
199 433 }
200 return DoConnect(addr); 434
201 } 435 ASSERT(false);
202 436 return -1;
203 int DoConnect(const SocketAddress& connect_addr) { 437 #elif defined(WEBRTC_MAC)
204 if ((s_ == INVALID_SOCKET) && 438 // No simple way to do this on Mac OS X.
205 !Create(connect_addr.family(), SOCK_STREAM)) { 439 // SIOCGIFMTU would work if we knew which interface would be used, but
206 return SOCKET_ERROR; 440 // figuring that out is pretty complicated. For now we'll return an error
207 } 441 // and let the caller pick a default MTU.
208 sockaddr_storage addr_storage; 442 SetError(EINVAL);
209 size_t len = connect_addr.ToSockAddrStorage(&addr_storage); 443 return -1;
210 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); 444 #elif defined(WEBRTC_LINUX)
211 int err = ::connect(s_, addr, static_cast<int>(len)); 445 // Gets the path MTU.
446 int value;
447 socklen_t vlen = sizeof(value);
448 int err = getsockopt(s_, IPPROTO_IP, IP_MTU, &value, &vlen);
449 if (err < 0) {
212 UpdateLastError(); 450 UpdateLastError();
213 if (err == 0) { 451 return err;
214 state_ = CS_CONNECTED; 452 }
215 } else if (IsBlockingError(GetError())) { 453
216 state_ = CS_CONNECTING; 454 ASSERT((0 <= value) && (value <= 65536));
217 enabled_events_ |= DE_CONNECT; 455 *mtu = value;
218 } else { 456 return 0;
219 return SOCKET_ERROR; 457 #elif defined(__native_client__)
220 } 458 // Most socket operations, including this, will fail in NaCl's sandbox.
221 459 error_ = EACCES;
222 enabled_events_ |= DE_READ | DE_WRITE; 460 return -1;
223 return 0; 461 #endif
224 } 462 }
225 463
226 int GetError() const override { 464
227 CritScope cs(&crit_); 465 SOCKET PhysicalSocket::DoAccept(SOCKET socket,
228 return error_; 466 sockaddr* addr,
229 } 467 socklen_t* addrlen) {
230 468 return ::accept(socket, addr, addrlen);
231 void SetError(int error) override { 469 }
232 CritScope cs(&crit_); 470
233 error_ = error; 471 void PhysicalSocket::OnResolveResult(AsyncResolverInterface* resolver) {
234 } 472 if (resolver != resolver_) {
235 473 return;
236 ConnState GetState() const override { return state_; } 474 }
237 475
238 int GetOption(Option opt, int* value) override { 476 int error = resolver_->GetError();
239 int slevel; 477 if (error == 0) {
240 int sopt; 478 error = DoConnect(resolver_->address());
241 if (TranslateOption(opt, &slevel, &sopt) == -1) 479 } else {
480 Close();
481 }
482
483 if (error) {
484 SetError(error);
485 SignalCloseEvent(this, error);
486 }
487 }
488
489 void PhysicalSocket::UpdateLastError() {
490 SetError(LAST_SYSTEM_ERROR);
491 }
492
493 void PhysicalSocket::MaybeRemapSendError() {
494 #if defined(WEBRTC_MAC)
495 // https://developer.apple.com/library/mac/documentation/Darwin/
496 // Reference/ManPages/man2/sendto.2.html
497 // ENOBUFS - The output queue for a network interface is full.
498 // This generally indicates that the interface has stopped sending,
499 // but may be caused by transient congestion.
500 if (GetError() == ENOBUFS) {
501 SetError(EWOULDBLOCK);
502 }
503 #endif
504 }
505
506 int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
507 switch (opt) {
508 case OPT_DONTFRAGMENT:
509 #if defined(WEBRTC_WIN)
510 *slevel = IPPROTO_IP;
511 *sopt = IP_DONTFRAGMENT;
512 break;
513 #elif defined(WEBRTC_MAC) || defined(BSD) || defined(__native_client__)
514 LOG(LS_WARNING) << "Socket::OPT_DONTFRAGMENT not supported.";
242 return -1; 515 return -1;
243 socklen_t optlen = sizeof(*value); 516 #elif defined(WEBRTC_POSIX)
244 int ret = ::getsockopt(s_, slevel, sopt, (SockOptArg)value, &optlen); 517 *slevel = IPPROTO_IP;
245 if (ret != -1 && opt == OPT_DONTFRAGMENT) { 518 *sopt = IP_MTU_DISCOVER;
246 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) 519 break;
247 *value = (*value != IP_PMTUDISC_DONT) ? 1 : 0; 520 #endif
248 #endif 521 case OPT_RCVBUF:
249 } 522 *slevel = SOL_SOCKET;
250 return ret; 523 *sopt = SO_RCVBUF;
251 } 524 break;
252 525 case OPT_SNDBUF:
253 int SetOption(Option opt, int value) override { 526 *slevel = SOL_SOCKET;
254 int slevel; 527 *sopt = SO_SNDBUF;
255 int sopt; 528 break;
256 if (TranslateOption(opt, &slevel, &sopt) == -1) 529 case OPT_NODELAY:
530 *slevel = IPPROTO_TCP;
531 *sopt = TCP_NODELAY;
532 break;
533 case OPT_DSCP:
534 LOG(LS_WARNING) << "Socket::OPT_DSCP not supported.";
257 return -1; 535 return -1;
258 if (opt == OPT_DONTFRAGMENT) { 536 case OPT_RTP_SENDTIME_EXTN_ID:
259 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) 537 return -1; // No logging is necessary as this not a OS socket option.
260 value = (value) ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT; 538 default:
261 #endif 539 ASSERT(false);
262 }
263 return ::setsockopt(s_, slevel, sopt, (SockOptArg)&value, sizeof(value));
264 }
265
266 int Send(const void* pv, size_t cb) override {
267 int sent = ::send(s_, reinterpret_cast<const char *>(pv), (int)cb,
268 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
269 // Suppress SIGPIPE. Without this, attempting to send on a socket whose
270 // other end is closed will result in a SIGPIPE signal being raised to
271 // our process, which by default will terminate the process, which we
272 // don't want. By specifying this flag, we'll just get the error EPIPE
273 // instead and can handle the error gracefully.
274 MSG_NOSIGNAL
275 #else
276 0
277 #endif
278 );
279 UpdateLastError();
280 MaybeRemapSendError();
281 // We have seen minidumps where this may be false.
282 ASSERT(sent <= static_cast<int>(cb));
283 if ((sent < 0) && IsBlockingError(GetError())) {
284 enabled_events_ |= DE_WRITE;
285 }
286 return sent;
287 }
288
289 int SendTo(const void* buffer,
290 size_t length,
291 const SocketAddress& addr) override {
292 sockaddr_storage saddr;
293 size_t len = addr.ToSockAddrStorage(&saddr);
294 int sent = ::sendto(
295 s_, static_cast<const char *>(buffer), static_cast<int>(length),
296 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
297 // Suppress SIGPIPE. See above for explanation.
298 MSG_NOSIGNAL,
299 #else
300 0,
301 #endif
302 reinterpret_cast<sockaddr*>(&saddr), static_cast<int>(len));
303 UpdateLastError();
304 MaybeRemapSendError();
305 // We have seen minidumps where this may be false.
306 ASSERT(sent <= static_cast<int>(length));
307 if ((sent < 0) && IsBlockingError(GetError())) {
308 enabled_events_ |= DE_WRITE;
309 }
310 return sent;
311 }
312
313 int Recv(void* buffer, size_t length) override {
314 int received = ::recv(s_, static_cast<char*>(buffer),
315 static_cast<int>(length), 0);
316 if ((received == 0) && (length != 0)) {
317 // Note: on graceful shutdown, recv can return 0. In this case, we
318 // pretend it is blocking, and then signal close, so that simplifying
319 // assumptions can be made about Recv.
320 LOG(LS_WARNING) << "EOF from socket; deferring close event";
321 // Must turn this back on so that the select() loop will notice the close
322 // event.
323 enabled_events_ |= DE_READ;
324 SetError(EWOULDBLOCK);
325 return SOCKET_ERROR;
326 }
327 UpdateLastError();
328 int error = GetError();
329 bool success = (received >= 0) || IsBlockingError(error);
330 if (udp_ || success) {
331 enabled_events_ |= DE_READ;
332 }
333 if (!success) {
334 LOG_F(LS_VERBOSE) << "Error = " << error;
335 }
336 return received;
337 }
338
339 int RecvFrom(void* buffer, size_t length, SocketAddress* out_addr) override {
340 sockaddr_storage addr_storage;
341 socklen_t addr_len = sizeof(addr_storage);
342 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
343 int received = ::recvfrom(s_, static_cast<char*>(buffer),
344 static_cast<int>(length), 0, addr, &addr_len);
345 UpdateLastError();
346 if ((received >= 0) && (out_addr != NULL))
347 SocketAddressFromSockAddrStorage(addr_storage, out_addr);
348 int error = GetError();
349 bool success = (received >= 0) || IsBlockingError(error);
350 if (udp_ || success) {
351 enabled_events_ |= DE_READ;
352 }
353 if (!success) {
354 LOG_F(LS_VERBOSE) << "Error = " << error;
355 }
356 return received;
357 }
358
359 int Listen(int backlog) override {
360 int err = ::listen(s_, backlog);
361 UpdateLastError();
362 if (err == 0) {
363 state_ = CS_CONNECTING;
364 enabled_events_ |= DE_ACCEPT;
365 #if !defined(NDEBUG)
366 dbg_addr_ = "Listening @ ";
367 dbg_addr_.append(GetLocalAddress().ToString());
368 #endif
369 }
370 return err;
371 }
372
373 AsyncSocket* Accept(SocketAddress* out_addr) override {
374 sockaddr_storage addr_storage;
375 socklen_t addr_len = sizeof(addr_storage);
376 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
377 SOCKET s = ::accept(s_, addr, &addr_len);
378 UpdateLastError();
379 if (s == INVALID_SOCKET)
380 return NULL;
381 enabled_events_ |= DE_ACCEPT;
382 if (out_addr != NULL)
383 SocketAddressFromSockAddrStorage(addr_storage, out_addr);
384 return ss_->WrapSocket(s);
385 }
386
387 int Close() override {
388 if (s_ == INVALID_SOCKET)
389 return 0;
390 int err = ::closesocket(s_);
391 UpdateLastError();
392 s_ = INVALID_SOCKET;
393 state_ = CS_CLOSED;
394 enabled_events_ = 0;
395 if (resolver_) {
396 resolver_->Destroy(false);
397 resolver_ = NULL;
398 }
399 return err;
400 }
401
402 int EstimateMTU(uint16_t* mtu) override {
403 SocketAddress addr = GetRemoteAddress();
404 if (addr.IsAnyIP()) {
405 SetError(ENOTCONN);
406 return -1; 540 return -1;
407 } 541 }
408 542 return 0;
409 #if defined(WEBRTC_WIN) 543 }
410 // Gets the interface MTU (TTL=1) for the interface used to reach |addr|.
411 WinPing ping;
412 if (!ping.IsValid()) {
413 SetError(EINVAL); // can't think of a better error ID
414 return -1;
415 }
416 int header_size = ICMP_HEADER_SIZE;
417 if (addr.family() == AF_INET6) {
418 header_size += IPV6_HEADER_SIZE;
419 } else if (addr.family() == AF_INET) {
420 header_size += IP_HEADER_SIZE;
421 }
422
423 for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) {
424 int32_t size = PACKET_MAXIMUMS[level] - header_size;
425 WinPing::PingResult result = ping.Ping(addr.ipaddr(), size,
426 ICMP_PING_TIMEOUT_MILLIS,
427 1, false);
428 if (result == WinPing::PING_FAIL) {
429 SetError(EINVAL); // can't think of a better error ID
430 return -1;
431 } else if (result != WinPing::PING_TOO_LARGE) {
432 *mtu = PACKET_MAXIMUMS[level];
433 return 0;
434 }
435 }
436
437 ASSERT(false);
438 return -1;
439 #elif defined(WEBRTC_MAC)
440 // No simple way to do this on Mac OS X.
441 // SIOCGIFMTU would work if we knew which interface would be used, but
442 // figuring that out is pretty complicated. For now we'll return an error
443 // and let the caller pick a default MTU.
444 SetError(EINVAL);
445 return -1;
446 #elif defined(WEBRTC_LINUX)
447 // Gets the path MTU.
448 int value;
449 socklen_t vlen = sizeof(value);
450 int err = getsockopt(s_, IPPROTO_IP, IP_MTU, &value, &vlen);
451 if (err < 0) {
452 UpdateLastError();
453 return err;
454 }
455
456 ASSERT((0 <= value) && (value <= 65536));
457 *mtu = value;
458 return 0;
459 #elif defined(__native_client__)
460 // Most socket operations, including this, will fail in NaCl's sandbox.
461 error_ = EACCES;
462 return -1;
463 #endif
464 }
465
466 SocketServer* socketserver() { return ss_; }
467
468 protected:
469 void OnResolveResult(AsyncResolverInterface* resolver) {
470 if (resolver != resolver_) {
471 return;
472 }
473
474 int error = resolver_->GetError();
475 if (error == 0) {
476 error = DoConnect(resolver_->address());
477 } else {
478 Close();
479 }
480
481 if (error) {
482 SetError(error);
483 SignalCloseEvent(this, error);
484 }
485 }
486
487 void UpdateLastError() {
488 SetError(LAST_SYSTEM_ERROR);
489 }
490
491 void MaybeRemapSendError() {
492 #if defined(WEBRTC_MAC)
493 // https://developer.apple.com/library/mac/documentation/Darwin/
494 // Reference/ManPages/man2/sendto.2.html
495 // ENOBUFS - The output queue for a network interface is full.
496 // This generally indicates that the interface has stopped sending,
497 // but may be caused by transient congestion.
498 if (GetError() == ENOBUFS) {
499 SetError(EWOULDBLOCK);
500 }
501 #endif
502 }
503
504 static int TranslateOption(Option opt, int* slevel, int* sopt) {
505 switch (opt) {
506 case OPT_DONTFRAGMENT:
507 #if defined(WEBRTC_WIN)
508 *slevel = IPPROTO_IP;
509 *sopt = IP_DONTFRAGMENT;
510 break;
511 #elif defined(WEBRTC_MAC) || defined(BSD) || defined(__native_client__)
512 LOG(LS_WARNING) << "Socket::OPT_DONTFRAGMENT not supported.";
513 return -1;
514 #elif defined(WEBRTC_POSIX)
515 *slevel = IPPROTO_IP;
516 *sopt = IP_MTU_DISCOVER;
517 break;
518 #endif
519 case OPT_RCVBUF:
520 *slevel = SOL_SOCKET;
521 *sopt = SO_RCVBUF;
522 break;
523 case OPT_SNDBUF:
524 *slevel = SOL_SOCKET;
525 *sopt = SO_SNDBUF;
526 break;
527 case OPT_NODELAY:
528 *slevel = IPPROTO_TCP;
529 *sopt = TCP_NODELAY;
530 break;
531 case OPT_DSCP:
532 LOG(LS_WARNING) << "Socket::OPT_DSCP not supported.";
533 return -1;
534 case OPT_RTP_SENDTIME_EXTN_ID:
535 return -1; // No logging is necessary as this not a OS socket option.
536 default:
537 ASSERT(false);
538 return -1;
539 }
540 return 0;
541 }
542
543 PhysicalSocketServer* ss_;
544 SOCKET s_;
545 uint8_t enabled_events_;
546 bool udp_;
547 int error_;
548 // Protects |error_| that is accessed from different threads.
549 mutable CriticalSection crit_;
550 ConnState state_;
551 AsyncResolver* resolver_;
552
553 #if !defined(NDEBUG)
554 std::string dbg_addr_;
555 #endif
556 };
557 544
558 #if defined(WEBRTC_POSIX) 545 #if defined(WEBRTC_POSIX)
559 class EventDispatcher : public Dispatcher { 546 class EventDispatcher : public Dispatcher {
560 public: 547 public:
561 EventDispatcher(PhysicalSocketServer* ss) : ss_(ss), fSignaled_(false) { 548 EventDispatcher(PhysicalSocketServer* ss) : ss_(ss), fSignaled_(false) {
562 if (pipe(afd_) < 0) 549 if (pipe(afd_) < 0)
563 LOG(LERROR) << "pipe failed"; 550 LOG(LERROR) << "pipe failed";
564 ss_->Add(this); 551 ss_->Add(this);
565 } 552 }
566 553
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 } 771 }
785 772
786 private: 773 private:
787 typedef std::map<int, void (*)(int)> HandlerMap; 774 typedef std::map<int, void (*)(int)> HandlerMap;
788 775
789 HandlerMap handlers_; 776 HandlerMap handlers_;
790 // Our owner. 777 // Our owner.
791 PhysicalSocketServer *owner_; 778 PhysicalSocketServer *owner_;
792 }; 779 };
793 780
794 class SocketDispatcher : public Dispatcher, public PhysicalSocket { 781 SocketDispatcher::SocketDispatcher(PhysicalSocketServer *ss)
795 public: 782 : PhysicalSocket(ss) {
796 explicit SocketDispatcher(PhysicalSocketServer *ss) : PhysicalSocket(ss) { 783 }
797 }
798 SocketDispatcher(SOCKET s, PhysicalSocketServer *ss) : PhysicalSocket(ss, s) {
799 }
800 784
801 ~SocketDispatcher() override { 785 SocketDispatcher::SocketDispatcher(SOCKET s, PhysicalSocketServer *ss)
802 Close(); 786 : PhysicalSocket(ss, s) {
803 } 787 }
804 788
805 bool Initialize() { 789 SocketDispatcher::~SocketDispatcher() {
806 ss_->Add(this); 790 Close();
807 fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK); 791 }
792
793 bool SocketDispatcher::Initialize() {
794 ss_->Add(this);
795 fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK);
796 return true;
797 }
798
799 bool SocketDispatcher::Create(int type) {
800 return Create(AF_INET, type);
801 }
802
803 bool SocketDispatcher::Create(int family, int type) {
804 // Change the socket to be non-blocking.
805 if (!PhysicalSocket::Create(family, type))
806 return false;
807
808 return Initialize();
809 }
810
811 bool SocketDispatcher::IsDescriptorClosed() {
812 // We don't have a reliable way of distinguishing end-of-stream
813 // from readability. So test on each readable call. Is this
814 // inefficient? Probably.
815 char ch;
816 ssize_t res = ::recv(s_, &ch, 1, MSG_PEEK);
817 if (res > 0) {
818 // Data available, so not closed.
819 return false;
820 } else if (res == 0) {
821 // EOF, so closed.
808 return true; 822 return true;
809 } 823 } else { // error
810 824 switch (errno) {
811 virtual bool Create(int type) { 825 // Returned if we've already closed s_.
812 return Create(AF_INET, type); 826 case EBADF:
813 } 827 // Returned during ungraceful peer shutdown.
814 828 case ECONNRESET:
815 bool Create(int family, int type) override { 829 return true;
816 // Change the socket to be non-blocking. 830 default:
817 if (!PhysicalSocket::Create(family, type)) 831 // Assume that all other errors are just blocking errors, meaning the
818 return false; 832 // connection is still good but we just can't read from it right now.
819 833 // This should only happen when connecting (and at most once), because
820 return Initialize(); 834 // in all other cases this function is only called if the file
821 } 835 // descriptor is already known to be in the readable state. However,
822 836 // it's not necessary a problem if we spuriously interpret a
823 int GetDescriptor() override { return s_; } 837 // "connection lost"-type error as a blocking error, because typically
824 838 // the next recv() will get EOF, so we'll still eventually notice that
825 bool IsDescriptorClosed() override { 839 // the socket is closed.
826 // We don't have a reliable way of distinguishing end-of-stream 840 LOG_ERR(LS_WARNING) << "Assuming benign blocking error";
827 // from readability. So test on each readable call. Is this 841 return false;
828 // inefficient? Probably.
829 char ch;
830 ssize_t res = ::recv(s_, &ch, 1, MSG_PEEK);
831 if (res > 0) {
832 // Data available, so not closed.
833 return false;
834 } else if (res == 0) {
835 // EOF, so closed.
836 return true;
837 } else { // error
838 switch (errno) {
839 // Returned if we've already closed s_.
840 case EBADF:
841 // Returned during ungraceful peer shutdown.
842 case ECONNRESET:
843 return true;
844 default:
845 // Assume that all other errors are just blocking errors, meaning the
846 // connection is still good but we just can't read from it right now.
847 // This should only happen when connecting (and at most once), because
848 // in all other cases this function is only called if the file
849 // descriptor is already known to be in the readable state. However,
850 // it's not necessary a problem if we spuriously interpret a
851 // "connection lost"-type error as a blocking error, because typically
852 // the next recv() will get EOF, so we'll still eventually notice that
853 // the socket is closed.
854 LOG_ERR(LS_WARNING) << "Assuming benign blocking error";
855 return false;
856 }
857 } 842 }
858 } 843 }
844 }
859 845
860 uint32_t GetRequestedEvents() override { return enabled_events_; } 846 void SocketDispatcher::OnPreEvent(uint32_t ff) {
847 if ((ff & DE_CONNECT) != 0)
848 state_ = CS_CONNECTED;
849 if ((ff & DE_CLOSE) != 0)
850 state_ = CS_CLOSED;
851 }
861 852
862 void OnPreEvent(uint32_t ff) override { 853 void SocketDispatcher::OnEvent(uint32_t ff, int err) {
863 if ((ff & DE_CONNECT) != 0) 854 // Make sure we deliver connect/accept first. Otherwise, consumers may see
864 state_ = CS_CONNECTED; 855 // something like a READ followed by a CONNECT, which would be odd.
865 if ((ff & DE_CLOSE) != 0) 856 if ((ff & DE_CONNECT) != 0) {
866 state_ = CS_CLOSED; 857 enabled_events_ &= ~DE_CONNECT;
858 SignalConnectEvent(this);
867 } 859 }
860 if ((ff & DE_ACCEPT) != 0) {
861 enabled_events_ &= ~DE_ACCEPT;
862 SignalReadEvent(this);
863 }
864 if ((ff & DE_READ) != 0) {
865 enabled_events_ &= ~DE_READ;
866 SignalReadEvent(this);
867 }
868 if ((ff & DE_WRITE) != 0) {
869 enabled_events_ &= ~DE_WRITE;
870 SignalWriteEvent(this);
871 }
872 if ((ff & DE_CLOSE) != 0) {
873 // The socket is now dead to us, so stop checking it.
874 enabled_events_ = 0;
875 SignalCloseEvent(this, err);
876 }
877 }
868 878
869 void OnEvent(uint32_t ff, int err) override { 879 int SocketDispatcher::Close() {
870 // Make sure we deliver connect/accept first. Otherwise, consumers may see 880 if (s_ == INVALID_SOCKET)
871 // something like a READ followed by a CONNECT, which would be odd. 881 return 0;
872 if ((ff & DE_CONNECT) != 0) {
873 enabled_events_ &= ~DE_CONNECT;
874 SignalConnectEvent(this);
875 }
876 if ((ff & DE_ACCEPT) != 0) {
877 enabled_events_ &= ~DE_ACCEPT;
878 SignalReadEvent(this);
879 }
880 if ((ff & DE_READ) != 0) {
881 enabled_events_ &= ~DE_READ;
882 SignalReadEvent(this);
883 }
884 if ((ff & DE_WRITE) != 0) {
885 enabled_events_ &= ~DE_WRITE;
886 SignalWriteEvent(this);
887 }
888 if ((ff & DE_CLOSE) != 0) {
889 // The socket is now dead to us, so stop checking it.
890 enabled_events_ = 0;
891 SignalCloseEvent(this, err);
892 }
893 }
894 882
895 int Close() override { 883 ss_->Remove(this);
896 if (s_ == INVALID_SOCKET) 884 return PhysicalSocket::Close();
897 return 0; 885 }
898
899 ss_->Remove(this);
900 return PhysicalSocket::Close();
901 }
902 };
903 886
904 class FileDispatcher: public Dispatcher, public AsyncFile { 887 class FileDispatcher: public Dispatcher, public AsyncFile {
905 public: 888 public:
906 FileDispatcher(int fd, PhysicalSocketServer *ss) : ss_(ss), fd_(fd) { 889 FileDispatcher(int fd, PhysicalSocketServer *ss) : ss_(ss), fd_(fd) {
907 set_readable(true); 890 set_readable(true);
908 891
909 ss_->Add(this); 892 ss_->Add(this);
910 893
911 fcntl(fd_, F_SETFL, fcntl(fd_, F_GETFL, 0) | O_NONBLOCK); 894 fcntl(fd_, F_SETFL, fcntl(fd_, F_GETFL, 0) | O_NONBLOCK);
912 } 895 }
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
1183 Socket* PhysicalSocketServer::CreateSocket(int type) { 1166 Socket* PhysicalSocketServer::CreateSocket(int type) {
1184 return CreateSocket(AF_INET, type); 1167 return CreateSocket(AF_INET, type);
1185 } 1168 }
1186 1169
1187 Socket* PhysicalSocketServer::CreateSocket(int family, int type) { 1170 Socket* PhysicalSocketServer::CreateSocket(int family, int type) {
1188 PhysicalSocket* socket = new PhysicalSocket(this); 1171 PhysicalSocket* socket = new PhysicalSocket(this);
1189 if (socket->Create(family, type)) { 1172 if (socket->Create(family, type)) {
1190 return socket; 1173 return socket;
1191 } else { 1174 } else {
1192 delete socket; 1175 delete socket;
1193 return 0; 1176 return nullptr;
1194 } 1177 }
1195 } 1178 }
1196 1179
1197 AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int type) { 1180 AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int type) {
1198 return CreateAsyncSocket(AF_INET, type); 1181 return CreateAsyncSocket(AF_INET, type);
1199 } 1182 }
1200 1183
1201 AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int family, int type) { 1184 AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int family, int type) {
1202 SocketDispatcher* dispatcher = new SocketDispatcher(this); 1185 SocketDispatcher* dispatcher = new SocketDispatcher(this);
1203 if (dispatcher->Create(family, type)) { 1186 if (dispatcher->Create(family, type)) {
1204 return dispatcher; 1187 return dispatcher;
1205 } else { 1188 } else {
1206 delete dispatcher; 1189 delete dispatcher;
1207 return 0; 1190 return nullptr;
1208 } 1191 }
1209 } 1192 }
1210 1193
1211 AsyncSocket* PhysicalSocketServer::WrapSocket(SOCKET s) { 1194 AsyncSocket* PhysicalSocketServer::WrapSocket(SOCKET s) {
1212 SocketDispatcher* dispatcher = new SocketDispatcher(s, this); 1195 SocketDispatcher* dispatcher = new SocketDispatcher(s, this);
1213 if (dispatcher->Initialize()) { 1196 if (dispatcher->Initialize()) {
1214 return dispatcher; 1197 return dispatcher;
1215 } else { 1198 } else {
1216 delete dispatcher; 1199 delete dispatcher;
1217 return 0; 1200 return nullptr;
1218 } 1201 }
1219 } 1202 }
1220 1203
1221 void PhysicalSocketServer::Add(Dispatcher *pdispatcher) { 1204 void PhysicalSocketServer::Add(Dispatcher *pdispatcher) {
1222 CritScope cs(&crit_); 1205 CritScope cs(&crit_);
1223 // Prevent duplicates. This can cause dead dispatchers to stick around. 1206 // Prevent duplicates. This can cause dead dispatchers to stick around.
1224 DispatcherList::iterator pos = std::find(dispatchers_.begin(), 1207 DispatcherList::iterator pos = std::find(dispatchers_.begin(),
1225 dispatchers_.end(), 1208 dispatchers_.end(),
1226 pdispatcher); 1209 pdispatcher);
1227 if (pos != dispatchers_.end()) 1210 if (pos != dispatchers_.end())
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
1628 break; 1611 break;
1629 } 1612 }
1630 } 1613 }
1631 1614
1632 // Done 1615 // Done
1633 return true; 1616 return true;
1634 } 1617 }
1635 #endif // WEBRTC_WIN 1618 #endif // WEBRTC_WIN
1636 1619
1637 } // namespace rtc 1620 } // namespace rtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698