OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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), | 103 #if defined(WEBRTC_WIN) |
105 resolver_(NULL) { | 104 // EnsureWinsockInit() ensures that winsock is initialized. The default |
106 #if defined(WEBRTC_WIN) | 105 // version of this function doesn't do anything because winsock is |
107 // EnsureWinsockInit() ensures that winsock is initialized. The default | 106 // initialized by constructor of a static object. If neccessary libjingle |
108 // version of this function doesn't do anything because winsock is | 107 // users can link it with a different version of this function by replacing |
109 // initialized by constructor of a static object. If neccessary libjingle | 108 // win32socketinit.cc. See win32socketinit.cc for more details. |
110 // users can link it with a different version of this function by replacing | 109 EnsureWinsockInit(); |
111 // win32socketinit.cc. See win32socketinit.cc for more details. | 110 #endif |
112 EnsureWinsockInit(); | 111 if (s_ != INVALID_SOCKET) { |
113 #endif | 112 enabled_events_ = DE_READ | DE_WRITE; |
114 if (s_ != INVALID_SOCKET) { | 113 |
115 enabled_events_ = DE_READ | DE_WRITE; | 114 int type = SOCK_STREAM; |
116 | 115 socklen_t len = sizeof(type); |
117 int type = SOCK_STREAM; | 116 VERIFY(0 == getsockopt(s_, SOL_SOCKET, SO_TYPE, (SockOptArg)&type, &len)); |
118 socklen_t len = sizeof(type); | |
119 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 AsyncSocket::ConnState PhysicalSocket::GetState() const { | |
233 return state_; | |
234 } | |
235 | |
236 int PhysicalSocket::GetOption(Option opt, int* value) { | |
237 int slevel; | |
238 int sopt; | |
239 if (TranslateOption(opt, &slevel, &sopt) == -1) | |
240 return -1; | |
241 socklen_t optlen = sizeof(*value); | |
242 int ret = ::getsockopt(s_, slevel, sopt, (SockOptArg)value, &optlen); | |
243 if (ret != -1 && opt == OPT_DONTFRAGMENT) { | |
244 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) | |
245 *value = (*value != IP_PMTUDISC_DONT) ? 1 : 0; | |
246 #endif | |
247 } | |
248 return ret; | |
249 } | |
250 | |
251 int PhysicalSocket::SetOption(Option opt, int value) { | |
252 int slevel; | |
253 int sopt; | |
254 if (TranslateOption(opt, &slevel, &sopt) == -1) | |
255 return -1; | |
256 if (opt == OPT_DONTFRAGMENT) { | |
257 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) | |
258 value = (value) ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT; | |
259 #endif | |
260 } | |
261 return ::setsockopt(s_, slevel, sopt, (SockOptArg)&value, sizeof(value)); | |
262 } | |
263 | |
264 int PhysicalSocket::Send(const void* pv, size_t cb) { | |
265 int sent = ::send(s_, reinterpret_cast<const char *>(pv), (int)cb, | |
266 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) | |
267 // Suppress SIGPIPE. Without this, attempting to send on a socket whose | |
268 // other end is closed will result in a SIGPIPE signal being raised to | |
269 // our process, which by default will terminate the process, which we | |
270 // don't want. By specifying this flag, we'll just get the error EPIPE | |
271 // instead and can handle the error gracefully. | |
272 MSG_NOSIGNAL | |
273 #else | |
274 0 | |
275 #endif | |
276 ); | |
277 UpdateLastError(); | |
278 MaybeRemapSendError(); | |
279 // We have seen minidumps where this may be false. | |
280 ASSERT(sent <= static_cast<int>(cb)); | |
281 if ((sent < 0) && IsBlockingError(GetError())) { | |
282 enabled_events_ |= DE_WRITE; | |
283 } | |
284 return sent; | |
285 } | |
286 | |
287 int PhysicalSocket::SendTo(const void* buffer, | |
288 size_t length, | |
289 const SocketAddress& addr) { | |
290 sockaddr_storage saddr; | |
291 size_t len = addr.ToSockAddrStorage(&saddr); | |
292 int sent = ::sendto( | |
293 s_, static_cast<const char *>(buffer), static_cast<int>(length), | |
294 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) | |
295 // Suppress SIGPIPE. See above for explanation. | |
296 MSG_NOSIGNAL, | |
297 #else | |
298 0, | |
299 #endif | |
300 reinterpret_cast<sockaddr*>(&saddr), static_cast<int>(len)); | |
301 UpdateLastError(); | |
302 MaybeRemapSendError(); | |
303 // We have seen minidumps where this may be false. | |
304 ASSERT(sent <= static_cast<int>(length)); | |
305 if ((sent < 0) && IsBlockingError(GetError())) { | |
306 enabled_events_ |= DE_WRITE; | |
307 } | |
308 return sent; | |
309 } | |
310 | |
311 int PhysicalSocket::Recv(void* buffer, size_t length) { | |
312 int received = ::recv(s_, static_cast<char*>(buffer), | |
313 static_cast<int>(length), 0); | |
314 if ((received == 0) && (length != 0)) { | |
315 // Note: on graceful shutdown, recv can return 0. In this case, we | |
316 // pretend it is blocking, and then signal close, so that simplifying | |
317 // assumptions can be made about Recv. | |
318 LOG(LS_WARNING) << "EOF from socket; deferring close event"; | |
319 // Must turn this back on so that the select() loop will notice the close | |
320 // event. | |
321 enabled_events_ |= DE_READ; | |
322 SetError(EWOULDBLOCK); | |
323 return SOCKET_ERROR; | |
324 } | |
325 UpdateLastError(); | |
326 int error = GetError(); | |
327 bool success = (received >= 0) || IsBlockingError(error); | |
328 if (udp_ || success) { | |
329 enabled_events_ |= DE_READ; | |
330 } | |
331 if (!success) { | |
332 LOG_F(LS_VERBOSE) << "Error = " << error; | |
333 } | |
334 return received; | |
335 } | |
336 | |
337 int PhysicalSocket::RecvFrom(void* buffer, | |
338 size_t length, | |
339 SocketAddress* out_addr) { | |
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 != nullptr)) | |
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 PhysicalSocket::Listen(int backlog) { | |
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* PhysicalSocket::Accept(SocketAddress* out_addr) { | |
374 // Always re-subscribe DE_ACCEPT to make sure new incoming connections will | |
375 // trigger an event even if DoAccept returns an error here. | |
376 enabled_events_ |= DE_ACCEPT; | |
377 sockaddr_storage addr_storage; | |
378 socklen_t addr_len = sizeof(addr_storage); | |
379 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); | |
380 SOCKET s = DoAccept(s_, addr, &addr_len); | |
381 UpdateLastError(); | |
382 if (s == INVALID_SOCKET) | |
383 return nullptr; | |
384 if (out_addr != nullptr) | |
385 SocketAddressFromSockAddrStorage(addr_storage, out_addr); | |
386 return ss_->WrapSocket(s); | |
387 } | |
388 | |
389 int PhysicalSocket::Close() { | |
390 if (s_ == INVALID_SOCKET) | |
391 return 0; | |
392 int err = ::closesocket(s_); | |
393 UpdateLastError(); | |
394 s_ = INVALID_SOCKET; | |
395 state_ = CS_CLOSED; | |
396 enabled_events_ = 0; | |
397 if (resolver_) { | |
398 resolver_->Destroy(false); | |
399 resolver_ = nullptr; | |
400 } | |
401 return err; | |
402 } | |
403 | |
404 int PhysicalSocket::EstimateMTU(uint16_t* mtu) { | |
405 SocketAddress addr = GetRemoteAddress(); | |
406 if (addr.IsAnyIP()) { | |
407 SetError(ENOTCONN); | |
408 return -1; | |
409 } | |
410 | |
411 #if defined(WEBRTC_WIN) | |
412 // Gets the interface MTU (TTL=1) for the interface used to reach |addr|. | |
413 WinPing ping; | |
414 if (!ping.IsValid()) { | |
415 SetError(EINVAL); // can't think of a better error ID | |
416 return -1; | |
417 } | |
418 int header_size = ICMP_HEADER_SIZE; | |
419 if (addr.family() == AF_INET6) { | |
420 header_size += IPV6_HEADER_SIZE; | |
421 } else if (addr.family() == AF_INET) { | |
422 header_size += IP_HEADER_SIZE; | |
423 } | |
424 | |
425 for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) { | |
426 int32_t size = PACKET_MAXIMUMS[level] - header_size; | |
427 WinPing::PingResult result = ping.Ping(addr.ipaddr(), size, | |
428 ICMP_PING_TIMEOUT_MILLIS, | |
429 1, false); | |
430 if (result == WinPing::PING_FAIL) { | |
431 SetError(EINVAL); // can't think of a better error ID | |
432 return -1; | |
433 } else if (result != WinPing::PING_TOO_LARGE) { | |
434 *mtu = PACKET_MAXIMUMS[level]; | |
197 return 0; | 435 return 0; |
198 } | 436 } |
199 | 437 } |
200 return DoConnect(addr); | 438 |
201 } | 439 ASSERT(false); |
202 | 440 return -1; |
203 int DoConnect(const SocketAddress& connect_addr) { | 441 #elif defined(WEBRTC_MAC) |
204 if ((s_ == INVALID_SOCKET) && | 442 // No simple way to do this on Mac OS X. |
205 !Create(connect_addr.family(), SOCK_STREAM)) { | 443 // SIOCGIFMTU would work if we knew which interface would be used, but |
206 return SOCKET_ERROR; | 444 // figuring that out is pretty complicated. For now we'll return an error |
445 // and let the caller pick a default MTU. | |
446 SetError(EINVAL); | |
447 return -1; | |
448 #elif defined(WEBRTC_LINUX) | |
449 // Gets the path MTU. | |
450 int value; | |
451 socklen_t vlen = sizeof(value); | |
452 int err = getsockopt(s_, IPPROTO_IP, IP_MTU, &value, &vlen); | |
453 if (err < 0) { | |
454 UpdateLastError(); | |
455 return err; | |
456 } | |
457 | |
458 ASSERT((0 <= value) && (value <= 65536)); | |
459 *mtu = value; | |
460 return 0; | |
461 #elif defined(__native_client__) | |
462 // Most socket operations, including this, will fail in NaCl's sandbox. | |
463 error_ = EACCES; | |
464 return -1; | |
465 #endif | |
466 } | |
467 | |
468 | |
469 SOCKET PhysicalSocket::DoAccept(SOCKET socket, | |
470 sockaddr* addr, | |
471 socklen_t* addrlen) { | |
472 return ::accept(socket, addr, addrlen); | |
473 } | |
474 | |
475 void PhysicalSocket::OnResolveResult(AsyncResolverInterface* resolver) { | |
476 if (resolver != resolver_) { | |
477 return; | |
478 } | |
479 | |
480 int error = resolver_->GetError(); | |
481 if (error == 0) { | |
482 error = DoConnect(resolver_->address()); | |
483 } else { | |
484 Close(); | |
485 } | |
486 | |
487 if (error) { | |
488 SetError(error); | |
489 SignalCloseEvent(this, error); | |
490 } | |
491 } | |
492 | |
493 void PhysicalSocket::UpdateLastError() { | |
494 SetError(LAST_SYSTEM_ERROR); | |
495 } | |
496 | |
497 void PhysicalSocket::MaybeRemapSendError() { | |
498 #if defined(WEBRTC_MAC) | |
499 // https://developer.apple.com/library/mac/documentation/Darwin/ | |
500 // Reference/ManPages/man2/sendto.2.html | |
501 // ENOBUFS - The output queue for a network interface is full. | |
502 // This generally indicates that the interface has stopped sending, | |
503 // but may be caused by transient congestion. | |
504 if (GetError() == ENOBUFS) { | |
505 SetError(EWOULDBLOCK); | |
506 } | |
507 #endif | |
508 } | |
509 | |
510 int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) { | |
511 switch (opt) { | |
512 case OPT_DONTFRAGMENT: | |
513 #if defined(WEBRTC_WIN) | |
514 *slevel = IPPROTO_IP; | |
515 *sopt = IP_DONTFRAGMENT; | |
516 break; | |
517 #elif defined(WEBRTC_MAC) || defined(BSD) || defined(__native_client__) | |
518 LOG(LS_WARNING) << "Socket::OPT_DONTFRAGMENT not supported."; | |
519 return -1; | |
520 #elif defined(WEBRTC_POSIX) | |
521 *slevel = IPPROTO_IP; | |
522 *sopt = IP_MTU_DISCOVER; | |
523 break; | |
524 #endif | |
525 case OPT_RCVBUF: | |
526 *slevel = SOL_SOCKET; | |
527 *sopt = SO_RCVBUF; | |
528 break; | |
529 case OPT_SNDBUF: | |
530 *slevel = SOL_SOCKET; | |
531 *sopt = SO_SNDBUF; | |
532 break; | |
533 case OPT_NODELAY: | |
534 *slevel = IPPROTO_TCP; | |
535 *sopt = TCP_NODELAY; | |
536 break; | |
537 case OPT_DSCP: | |
538 LOG(LS_WARNING) << "Socket::OPT_DSCP not supported."; | |
539 return -1; | |
540 case OPT_RTP_SENDTIME_EXTN_ID: | |
541 return -1; // No logging is necessary as this not a OS socket option. | |
542 default: | |
543 ASSERT(false); | |
544 return -1; | |
545 } | |
546 return 0; | |
547 } | |
548 | |
549 SocketDispatcher::SocketDispatcher(PhysicalSocketServer *ss) | |
550 : PhysicalSocket(ss) | |
551 #if defined(WEBRTC_WIN) | |
552 , id_(0), signal_close_(false) | |
joachim
2015/12/07 21:15:30
I didn't know how to properly format this accordin
pthatcher1
2015/12/08 20:20:43
Maybe this?
#if defined(WEBRTC_WIN)
: PhysicalS
| |
553 #endif | |
554 { | |
555 } | |
556 | |
557 SocketDispatcher::SocketDispatcher(SOCKET s, PhysicalSocketServer *ss) | |
558 : PhysicalSocket(ss, s) | |
559 #if defined(WEBRTC_WIN) | |
560 , id_(0), signal_close_(false) | |
joachim
2015/12/07 21:15:30
I didn't know how to properly format this accordin
| |
561 #endif | |
562 { | |
563 } | |
564 | |
565 SocketDispatcher::~SocketDispatcher() { | |
566 Close(); | |
567 } | |
568 | |
569 bool SocketDispatcher::Initialize() { | |
570 ASSERT(s_ != INVALID_SOCKET); | |
571 #if defined(WEBRTC_WIN) | |
572 // Must be a non-blocking | |
573 u_long argp = 1; | |
574 ioctlsocket(s_, FIONBIO, &argp); | |
575 #endif | |
576 ss_->Add(this); | |
577 #if defined(WEBRTC_POSIX) | |
578 fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK); | |
579 #endif | |
580 return true; | |
581 } | |
582 | |
583 bool SocketDispatcher::Create(int type) { | |
584 return Create(AF_INET, type); | |
585 } | |
586 | |
587 bool SocketDispatcher::Create(int family, int type) { | |
588 // Change the socket to be non-blocking. | |
589 if (!PhysicalSocket::Create(family, type)) | |
590 return false; | |
591 | |
592 if (!Initialize()) | |
593 return false; | |
594 | |
595 #if defined(WEBRTC_WIN) | |
596 do { id_ = ++next_id_; } while (id_ == 0); | |
597 #endif | |
598 return true; | |
599 } | |
600 | |
601 #if defined(WEBRTC_WIN) | |
602 | |
603 WSAEVENT SocketDispatcher::GetWSAEvent() { | |
604 return WSA_INVALID_EVENT; | |
605 } | |
606 | |
607 SOCKET SocketDispatcher::GetSocket() { | |
608 return s_; | |
609 } | |
610 | |
611 bool SocketDispatcher::CheckSignalClose() { | |
612 if (!signal_close_) | |
613 return false; | |
614 | |
615 char ch; | |
616 if (recv(s_, &ch, 1, MSG_PEEK) > 0) | |
617 return false; | |
618 | |
619 state_ = CS_CLOSED; | |
620 signal_close_ = false; | |
621 SignalCloseEvent(this, signal_err_); | |
622 return true; | |
623 } | |
624 | |
625 int SocketDispatcher::next_id_ = 0; | |
626 | |
627 #elif defined(WEBRTC_POSIX) | |
628 | |
629 int SocketDispatcher::GetDescriptor() { | |
630 return s_; | |
631 } | |
632 | |
633 bool SocketDispatcher::IsDescriptorClosed() { | |
634 // We don't have a reliable way of distinguishing end-of-stream | |
635 // from readability. So test on each readable call. Is this | |
636 // inefficient? Probably. | |
637 char ch; | |
638 ssize_t res = ::recv(s_, &ch, 1, MSG_PEEK); | |
639 if (res > 0) { | |
640 // Data available, so not closed. | |
641 return false; | |
642 } else if (res == 0) { | |
643 // EOF, so closed. | |
644 return true; | |
645 } else { // error | |
646 switch (errno) { | |
647 // Returned if we've already closed s_. | |
648 case EBADF: | |
649 // Returned during ungraceful peer shutdown. | |
650 case ECONNRESET: | |
651 return true; | |
652 default: | |
653 // Assume that all other errors are just blocking errors, meaning the | |
654 // connection is still good but we just can't read from it right now. | |
655 // This should only happen when connecting (and at most once), because | |
656 // in all other cases this function is only called if the file | |
657 // descriptor is already known to be in the readable state. However, | |
658 // it's not necessary a problem if we spuriously interpret a | |
659 // "connection lost"-type error as a blocking error, because typically | |
660 // the next recv() will get EOF, so we'll still eventually notice that | |
661 // the socket is closed. | |
662 LOG_ERR(LS_WARNING) << "Assuming benign blocking error"; | |
663 return false; | |
207 } | 664 } |
208 sockaddr_storage addr_storage; | 665 } |
209 size_t len = connect_addr.ToSockAddrStorage(&addr_storage); | 666 } |
210 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); | 667 |
211 int err = ::connect(s_, addr, static_cast<int>(len)); | 668 #endif // WEBRTC_POSIX |
212 UpdateLastError(); | 669 |
213 if (err == 0) { | 670 uint32_t SocketDispatcher::GetRequestedEvents() { |
214 state_ = CS_CONNECTED; | 671 return enabled_events_; |
215 } else if (IsBlockingError(GetError())) { | 672 } |
216 state_ = CS_CONNECTING; | 673 |
217 enabled_events_ |= DE_CONNECT; | 674 void SocketDispatcher::OnPreEvent(uint32_t ff) { |
218 } else { | 675 if ((ff & DE_CONNECT) != 0) |
219 return SOCKET_ERROR; | 676 state_ = CS_CONNECTED; |
220 } | 677 |
221 | 678 #if defined(WEBRTC_WIN) |
222 enabled_events_ |= DE_READ | DE_WRITE; | 679 // We set CS_CLOSED from CheckSignalClose. |
680 #elif defined(WEBRTC_POSIX) | |
681 if ((ff & DE_CLOSE) != 0) | |
682 state_ = CS_CLOSED; | |
683 #endif | |
684 } | |
685 | |
686 #if defined(WEBRTC_WIN) | |
687 void SocketDispatcher::OnEvent(uint32_t ff, int err) { | |
688 int cache_id = id_; | |
689 // Make sure we deliver connect/accept first. Otherwise, consumers may see | |
690 // something like a READ followed by a CONNECT, which would be odd. | |
691 if (((ff & DE_CONNECT) != 0) && (id_ == cache_id)) { | |
692 if (ff != DE_CONNECT) | |
693 LOG(LS_VERBOSE) << "Signalled with DE_CONNECT: " << ff; | |
694 enabled_events_ &= ~DE_CONNECT; | |
695 #if !defined(NDEBUG) | |
696 dbg_addr_ = "Connected @ "; | |
697 dbg_addr_.append(GetRemoteAddress().ToString()); | |
698 #endif | |
699 SignalConnectEvent(this); | |
700 } | |
701 if (((ff & DE_ACCEPT) != 0) && (id_ == cache_id)) { | |
702 enabled_events_ &= ~DE_ACCEPT; | |
703 SignalReadEvent(this); | |
704 } | |
705 if ((ff & DE_READ) != 0) { | |
706 enabled_events_ &= ~DE_READ; | |
707 SignalReadEvent(this); | |
708 } | |
709 if (((ff & DE_WRITE) != 0) && (id_ == cache_id)) { | |
710 enabled_events_ &= ~DE_WRITE; | |
711 SignalWriteEvent(this); | |
712 } | |
713 if (((ff & DE_CLOSE) != 0) && (id_ == cache_id)) { | |
714 signal_close_ = true; | |
715 signal_err_ = err; | |
716 } | |
717 } | |
718 #elif defined(WEBRTC_POSIX) | |
719 void SocketDispatcher::OnEvent(uint32_t ff, int err) { | |
720 // Make sure we deliver connect/accept first. Otherwise, consumers may see | |
721 // something like a READ followed by a CONNECT, which would be odd. | |
722 if ((ff & DE_CONNECT) != 0) { | |
723 enabled_events_ &= ~DE_CONNECT; | |
724 SignalConnectEvent(this); | |
725 } | |
726 if ((ff & DE_ACCEPT) != 0) { | |
727 enabled_events_ &= ~DE_ACCEPT; | |
728 SignalReadEvent(this); | |
729 } | |
730 if ((ff & DE_READ) != 0) { | |
731 enabled_events_ &= ~DE_READ; | |
732 SignalReadEvent(this); | |
733 } | |
734 if ((ff & DE_WRITE) != 0) { | |
735 enabled_events_ &= ~DE_WRITE; | |
736 SignalWriteEvent(this); | |
737 } | |
738 if ((ff & DE_CLOSE) != 0) { | |
739 // The socket is now dead to us, so stop checking it. | |
740 enabled_events_ = 0; | |
741 SignalCloseEvent(this, err); | |
742 } | |
743 } | |
744 #endif // WEBRTC_POSIX | |
745 | |
746 int SocketDispatcher::Close() { | |
747 if (s_ == INVALID_SOCKET) | |
223 return 0; | 748 return 0; |
224 } | 749 |
225 | 750 #if defined(WEBRTC_WIN) |
226 int GetError() const override { | 751 id_ = 0; |
227 CritScope cs(&crit_); | 752 signal_close_ = false; |
228 return error_; | 753 #endif |
229 } | 754 ss_->Remove(this); |
230 | 755 return PhysicalSocket::Close(); |
231 void SetError(int error) override { | 756 } |
232 CritScope cs(&crit_); | |
233 error_ = error; | |
234 } | |
235 | |
236 ConnState GetState() const override { return state_; } | |
237 | |
238 int GetOption(Option opt, int* value) override { | |
239 int slevel; | |
240 int sopt; | |
241 if (TranslateOption(opt, &slevel, &sopt) == -1) | |
242 return -1; | |
243 socklen_t optlen = sizeof(*value); | |
244 int ret = ::getsockopt(s_, slevel, sopt, (SockOptArg)value, &optlen); | |
245 if (ret != -1 && opt == OPT_DONTFRAGMENT) { | |
246 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) | |
247 *value = (*value != IP_PMTUDISC_DONT) ? 1 : 0; | |
248 #endif | |
249 } | |
250 return ret; | |
251 } | |
252 | |
253 int SetOption(Option opt, int value) override { | |
254 int slevel; | |
255 int sopt; | |
256 if (TranslateOption(opt, &slevel, &sopt) == -1) | |
257 return -1; | |
258 if (opt == OPT_DONTFRAGMENT) { | |
259 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) | |
260 value = (value) ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT; | |
261 #endif | |
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; | |
407 } | |
408 | |
409 #if defined(WEBRTC_WIN) | |
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 | 757 |
558 #if defined(WEBRTC_POSIX) | 758 #if defined(WEBRTC_POSIX) |
559 class EventDispatcher : public Dispatcher { | 759 class EventDispatcher : public Dispatcher { |
560 public: | 760 public: |
561 EventDispatcher(PhysicalSocketServer* ss) : ss_(ss), fSignaled_(false) { | 761 EventDispatcher(PhysicalSocketServer* ss) : ss_(ss), fSignaled_(false) { |
562 if (pipe(afd_) < 0) | 762 if (pipe(afd_) < 0) |
563 LOG(LERROR) << "pipe failed"; | 763 LOG(LERROR) << "pipe failed"; |
564 ss_->Add(this); | 764 ss_->Add(this); |
565 } | 765 } |
566 | 766 |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
784 } | 984 } |
785 | 985 |
786 private: | 986 private: |
787 typedef std::map<int, void (*)(int)> HandlerMap; | 987 typedef std::map<int, void (*)(int)> HandlerMap; |
788 | 988 |
789 HandlerMap handlers_; | 989 HandlerMap handlers_; |
790 // Our owner. | 990 // Our owner. |
791 PhysicalSocketServer *owner_; | 991 PhysicalSocketServer *owner_; |
792 }; | 992 }; |
793 | 993 |
794 class SocketDispatcher : public Dispatcher, public PhysicalSocket { | |
795 public: | |
796 explicit SocketDispatcher(PhysicalSocketServer *ss) : PhysicalSocket(ss) { | |
797 } | |
798 SocketDispatcher(SOCKET s, PhysicalSocketServer *ss) : PhysicalSocket(ss, s) { | |
799 } | |
800 | |
801 ~SocketDispatcher() override { | |
802 Close(); | |
803 } | |
804 | |
805 bool Initialize() { | |
806 ss_->Add(this); | |
807 fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK); | |
808 return true; | |
809 } | |
810 | |
811 virtual bool Create(int type) { | |
812 return Create(AF_INET, type); | |
813 } | |
814 | |
815 bool Create(int family, int type) override { | |
816 // Change the socket to be non-blocking. | |
817 if (!PhysicalSocket::Create(family, type)) | |
818 return false; | |
819 | |
820 return Initialize(); | |
821 } | |
822 | |
823 int GetDescriptor() override { return s_; } | |
824 | |
825 bool IsDescriptorClosed() override { | |
826 // We don't have a reliable way of distinguishing end-of-stream | |
827 // from readability. So test on each readable call. Is this | |
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 } | |
858 } | |
859 | |
860 uint32_t GetRequestedEvents() override { return enabled_events_; } | |
861 | |
862 void OnPreEvent(uint32_t ff) override { | |
863 if ((ff & DE_CONNECT) != 0) | |
864 state_ = CS_CONNECTED; | |
865 if ((ff & DE_CLOSE) != 0) | |
866 state_ = CS_CLOSED; | |
867 } | |
868 | |
869 void OnEvent(uint32_t ff, int err) override { | |
870 // Make sure we deliver connect/accept first. Otherwise, consumers may see | |
871 // something like a READ followed by a CONNECT, which would be odd. | |
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 | |
895 int Close() override { | |
896 if (s_ == INVALID_SOCKET) | |
897 return 0; | |
898 | |
899 ss_->Remove(this); | |
900 return PhysicalSocket::Close(); | |
901 } | |
902 }; | |
903 | |
904 class FileDispatcher: public Dispatcher, public AsyncFile { | 994 class FileDispatcher: public Dispatcher, public AsyncFile { |
905 public: | 995 public: |
906 FileDispatcher(int fd, PhysicalSocketServer *ss) : ss_(ss), fd_(fd) { | 996 FileDispatcher(int fd, PhysicalSocketServer *ss) : ss_(ss), fd_(fd) { |
907 set_readable(true); | 997 set_readable(true); |
908 | 998 |
909 ss_->Add(this); | 999 ss_->Add(this); |
910 | 1000 |
911 fcntl(fd_, F_SETFL, fcntl(fd_, F_GETFL, 0) | O_NONBLOCK); | 1001 fcntl(fd_, F_SETFL, fcntl(fd_, F_GETFL, 0) | O_NONBLOCK); |
912 } | 1002 } |
913 | 1003 |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1007 virtual SOCKET GetSocket() { | 1097 virtual SOCKET GetSocket() { |
1008 return INVALID_SOCKET; | 1098 return INVALID_SOCKET; |
1009 } | 1099 } |
1010 | 1100 |
1011 virtual bool CheckSignalClose() { return false; } | 1101 virtual bool CheckSignalClose() { return false; } |
1012 | 1102 |
1013 private: | 1103 private: |
1014 PhysicalSocketServer* ss_; | 1104 PhysicalSocketServer* ss_; |
1015 WSAEVENT hev_; | 1105 WSAEVENT hev_; |
1016 }; | 1106 }; |
1017 | |
1018 class SocketDispatcher : public Dispatcher, public PhysicalSocket { | |
1019 public: | |
1020 static int next_id_; | |
1021 int id_; | |
1022 bool signal_close_; | |
1023 int signal_err_; | |
1024 | |
1025 SocketDispatcher(PhysicalSocketServer* ss) | |
1026 : PhysicalSocket(ss), | |
1027 id_(0), | |
1028 signal_close_(false) { | |
1029 } | |
1030 | |
1031 SocketDispatcher(SOCKET s, PhysicalSocketServer* ss) | |
1032 : PhysicalSocket(ss, s), | |
1033 id_(0), | |
1034 signal_close_(false) { | |
1035 } | |
1036 | |
1037 virtual ~SocketDispatcher() { | |
1038 Close(); | |
1039 } | |
1040 | |
1041 bool Initialize() { | |
1042 ASSERT(s_ != INVALID_SOCKET); | |
1043 // Must be a non-blocking | |
1044 u_long argp = 1; | |
1045 ioctlsocket(s_, FIONBIO, &argp); | |
1046 ss_->Add(this); | |
1047 return true; | |
1048 } | |
1049 | |
1050 virtual bool Create(int type) { | |
1051 return Create(AF_INET, type); | |
1052 } | |
1053 | |
1054 virtual bool Create(int family, int type) { | |
1055 // Create socket | |
1056 if (!PhysicalSocket::Create(family, type)) | |
1057 return false; | |
1058 | |
1059 if (!Initialize()) | |
1060 return false; | |
1061 | |
1062 do { id_ = ++next_id_; } while (id_ == 0); | |
1063 return true; | |
1064 } | |
1065 | |
1066 virtual int Close() { | |
1067 if (s_ == INVALID_SOCKET) | |
1068 return 0; | |
1069 | |
1070 id_ = 0; | |
1071 signal_close_ = false; | |
1072 ss_->Remove(this); | |
1073 return PhysicalSocket::Close(); | |
1074 } | |
1075 | |
1076 virtual uint32_t GetRequestedEvents() { return enabled_events_; } | |
1077 | |
1078 virtual void OnPreEvent(uint32_t ff) { | |
1079 if ((ff & DE_CONNECT) != 0) | |
1080 state_ = CS_CONNECTED; | |
1081 // We set CS_CLOSED from CheckSignalClose. | |
1082 } | |
1083 | |
1084 virtual void OnEvent(uint32_t ff, int err) { | |
1085 int cache_id = id_; | |
1086 // Make sure we deliver connect/accept first. Otherwise, consumers may see | |
1087 // something like a READ followed by a CONNECT, which would be odd. | |
1088 if (((ff & DE_CONNECT) != 0) && (id_ == cache_id)) { | |
1089 if (ff != DE_CONNECT) | |
1090 LOG(LS_VERBOSE) << "Signalled with DE_CONNECT: " << ff; | |
1091 enabled_events_ &= ~DE_CONNECT; | |
1092 #if !defined(NDEBUG) | |
1093 dbg_addr_ = "Connected @ "; | |
1094 dbg_addr_.append(GetRemoteAddress().ToString()); | |
1095 #endif | |
1096 SignalConnectEvent(this); | |
1097 } | |
1098 if (((ff & DE_ACCEPT) != 0) && (id_ == cache_id)) { | |
1099 enabled_events_ &= ~DE_ACCEPT; | |
1100 SignalReadEvent(this); | |
1101 } | |
1102 if ((ff & DE_READ) != 0) { | |
1103 enabled_events_ &= ~DE_READ; | |
1104 SignalReadEvent(this); | |
1105 } | |
1106 if (((ff & DE_WRITE) != 0) && (id_ == cache_id)) { | |
1107 enabled_events_ &= ~DE_WRITE; | |
1108 SignalWriteEvent(this); | |
1109 } | |
1110 if (((ff & DE_CLOSE) != 0) && (id_ == cache_id)) { | |
1111 signal_close_ = true; | |
1112 signal_err_ = err; | |
1113 } | |
1114 } | |
1115 | |
1116 virtual WSAEVENT GetWSAEvent() { | |
1117 return WSA_INVALID_EVENT; | |
1118 } | |
1119 | |
1120 virtual SOCKET GetSocket() { | |
1121 return s_; | |
1122 } | |
1123 | |
1124 virtual bool CheckSignalClose() { | |
1125 if (!signal_close_) | |
1126 return false; | |
1127 | |
1128 char ch; | |
1129 if (recv(s_, &ch, 1, MSG_PEEK) > 0) | |
1130 return false; | |
1131 | |
1132 state_ = CS_CLOSED; | |
1133 signal_close_ = false; | |
1134 SignalCloseEvent(this, signal_err_); | |
1135 return true; | |
1136 } | |
1137 }; | |
1138 | |
1139 int SocketDispatcher::next_id_ = 0; | |
1140 | |
1141 #endif // WEBRTC_WIN | 1107 #endif // WEBRTC_WIN |
1142 | 1108 |
1143 // Sets the value of a boolean value to false when signaled. | 1109 // Sets the value of a boolean value to false when signaled. |
1144 class Signaler : public EventDispatcher { | 1110 class Signaler : public EventDispatcher { |
1145 public: | 1111 public: |
1146 Signaler(PhysicalSocketServer* ss, bool* pf) | 1112 Signaler(PhysicalSocketServer* ss, bool* pf) |
1147 : EventDispatcher(ss), pf_(pf) { | 1113 : EventDispatcher(ss), pf_(pf) { |
1148 } | 1114 } |
1149 ~Signaler() override { } | 1115 ~Signaler() override { } |
1150 | 1116 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1183 Socket* PhysicalSocketServer::CreateSocket(int type) { | 1149 Socket* PhysicalSocketServer::CreateSocket(int type) { |
1184 return CreateSocket(AF_INET, type); | 1150 return CreateSocket(AF_INET, type); |
1185 } | 1151 } |
1186 | 1152 |
1187 Socket* PhysicalSocketServer::CreateSocket(int family, int type) { | 1153 Socket* PhysicalSocketServer::CreateSocket(int family, int type) { |
1188 PhysicalSocket* socket = new PhysicalSocket(this); | 1154 PhysicalSocket* socket = new PhysicalSocket(this); |
1189 if (socket->Create(family, type)) { | 1155 if (socket->Create(family, type)) { |
1190 return socket; | 1156 return socket; |
1191 } else { | 1157 } else { |
1192 delete socket; | 1158 delete socket; |
1193 return 0; | 1159 return nullptr; |
1194 } | 1160 } |
1195 } | 1161 } |
1196 | 1162 |
1197 AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int type) { | 1163 AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int type) { |
1198 return CreateAsyncSocket(AF_INET, type); | 1164 return CreateAsyncSocket(AF_INET, type); |
1199 } | 1165 } |
1200 | 1166 |
1201 AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int family, int type) { | 1167 AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int family, int type) { |
1202 SocketDispatcher* dispatcher = new SocketDispatcher(this); | 1168 SocketDispatcher* dispatcher = new SocketDispatcher(this); |
1203 if (dispatcher->Create(family, type)) { | 1169 if (dispatcher->Create(family, type)) { |
1204 return dispatcher; | 1170 return dispatcher; |
1205 } else { | 1171 } else { |
1206 delete dispatcher; | 1172 delete dispatcher; |
1207 return 0; | 1173 return nullptr; |
1208 } | 1174 } |
1209 } | 1175 } |
1210 | 1176 |
1211 AsyncSocket* PhysicalSocketServer::WrapSocket(SOCKET s) { | 1177 AsyncSocket* PhysicalSocketServer::WrapSocket(SOCKET s) { |
1212 SocketDispatcher* dispatcher = new SocketDispatcher(s, this); | 1178 SocketDispatcher* dispatcher = new SocketDispatcher(s, this); |
1213 if (dispatcher->Initialize()) { | 1179 if (dispatcher->Initialize()) { |
1214 return dispatcher; | 1180 return dispatcher; |
1215 } else { | 1181 } else { |
1216 delete dispatcher; | 1182 delete dispatcher; |
1217 return 0; | 1183 return nullptr; |
1218 } | 1184 } |
1219 } | 1185 } |
1220 | 1186 |
1221 void PhysicalSocketServer::Add(Dispatcher *pdispatcher) { | 1187 void PhysicalSocketServer::Add(Dispatcher *pdispatcher) { |
1222 CritScope cs(&crit_); | 1188 CritScope cs(&crit_); |
1223 // Prevent duplicates. This can cause dead dispatchers to stick around. | 1189 // Prevent duplicates. This can cause dead dispatchers to stick around. |
1224 DispatcherList::iterator pos = std::find(dispatchers_.begin(), | 1190 DispatcherList::iterator pos = std::find(dispatchers_.begin(), |
1225 dispatchers_.end(), | 1191 dispatchers_.end(), |
1226 pdispatcher); | 1192 pdispatcher); |
1227 if (pos != dispatchers_.end()) | 1193 if (pos != dispatchers_.end()) |
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1628 break; | 1594 break; |
1629 } | 1595 } |
1630 } | 1596 } |
1631 | 1597 |
1632 // Done | 1598 // Done |
1633 return true; | 1599 return true; |
1634 } | 1600 } |
1635 #endif // WEBRTC_WIN | 1601 #endif // WEBRTC_WIN |
1636 | 1602 |
1637 } // namespace rtc | 1603 } // namespace rtc |
OLD | NEW |