147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(_MSC_VER) && _MSC_VER < 1300
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#pragma warning(disable:4786)
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <assert.h>
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX)
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <string.h>
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <errno.h>
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <fcntl.h>
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <sys/time.h>
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <sys/select.h>
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <unistd.h>
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <signal.h>
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define WIN32_LEAN_AND_MEAN
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <windows.h>
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <winsock2.h>
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <ws2tcpip.h>
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#undef SetPort
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <algorithm>
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <map>
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/basictypes.h"
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/byteorder.h"
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/common.h"
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h"
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/nethelpers.h"
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/physicalsocketserver.h"
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/timeutils.h"
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/winping.h"
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/win32socketinit.h"
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// stm: this will tell us if we are on OSX
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef HAVE_CONFIG_H
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "config.h"
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX)
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <netinet/tcp.h>  // for TCP_NODELAY
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define IP_MTU 14 // Until this is integrated from linux/in.h to netinet/in.h
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgtypedef void* SockOptArg;
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // WEBRTC_POSIX
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgtypedef char* SockOptArg;
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Standard MTUs, from RFC 1191
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgconst uint16 PACKET_MAXIMUMS[] = {
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  65535,    // Theoretical maximum, Hyperchannel
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  32000,    // Nothing
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  17914,    // 16Mb IBM Token Ring
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  8166,     // IEEE 802.4
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //4464,   // IEEE 802.5 (4Mb max)
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  4352,     // FDDI
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //2048,   // Wideband Network
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  2002,     // IEEE 802.5 (4Mb recommended)
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //1536,   // Expermental Ethernet Networks
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //1500,   // Ethernet, Point-to-Point (default)
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  1492,     // IEEE 802.3
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  1006,     // SLIP, ARPANET
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //576,    // X.25 Networks
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //544,    // DEC IP Portal
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //512,    // NETBIOS
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  508,      // IEEE 802/Source-Rt Bridge, ARCNET
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  296,      // Point-to-Point (low delay)
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  68,       // Official minimum
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  0,        // End of list marker
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const int IP_HEADER_SIZE = 20u;
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const int IPV6_HEADER_SIZE = 40u;
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const int ICMP_HEADER_SIZE = 8u;
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const int ICMP_PING_TIMEOUT_MILLIS = 10000u;
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  PhysicalSocket(PhysicalSocketServer* ss, SOCKET s = INVALID_SOCKET)
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    : ss_(ss), s_(s), enabled_events_(0), error_(0),
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      state_((s == INVALID_SOCKET) ? CS_CLOSED : CS_CONNECTED),
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      resolver_(NULL) {
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // EnsureWinsockInit() ensures that winsock is initialized. The default
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // version of this function doesn't do anything because winsock is
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // initialized by constructor of a static object. If neccessary libjingle
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // users can link it with a different version of this function by replacing
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // win32socketinit.cc. See win32socketinit.cc for more details.
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    EnsureWinsockInit();
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (s_ != INVALID_SOCKET) {
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ = DE_READ | DE_WRITE;
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      int type = SOCK_STREAM;
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      socklen_t len = sizeof(type);
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      VERIFY(0 == getsockopt(s_, SOL_SOCKET, SO_TYPE, (SockOptArg)&type, &len));
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      udp_ = (SOCK_DGRAM == type);
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual ~PhysicalSocket() {
12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    Close();
12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Creates the underlying OS socket (same as the "socket" function).
12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual bool Create(int family, int type) {
12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    Close();
12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    s_ = ::socket(family, type, 0);
12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    udp_ = (SOCK_DGRAM == type);
12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    UpdateLastError();
12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (udp_)
13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ = DE_READ | DE_WRITE;
13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return s_ != INVALID_SOCKET;
13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SocketAddress GetLocalAddress() const {
13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr_storage addr_storage = {0};
13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    socklen_t addrlen = sizeof(addr_storage);
13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int result = ::getsockname(s_, addr, &addrlen);
13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SocketAddress address;
14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (result >= 0) {
14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SocketAddressFromSockAddrStorage(addr_storage, &address);
14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket="
14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                      << s_;
14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return address;
14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SocketAddress GetRemoteAddress() const {
15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr_storage addr_storage = {0};
15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    socklen_t addrlen = sizeof(addr_storage);
15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int result = ::getpeername(s_, addr, &addrlen);
15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SocketAddress address;
15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (result >= 0) {
15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SocketAddressFromSockAddrStorage(addr_storage, &address);
15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG(LS_WARNING) << "GetRemoteAddress: unable to get remote addr, socket="
15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                      << s_;
16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return address;
16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int Bind(const SocketAddress& bind_addr) {
16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr_storage addr_storage;
16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    size_t len = bind_addr.ToSockAddrStorage(&addr_storage);
16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int err = ::bind(s_, addr, static_cast<int>(len));
16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    UpdateLastError();
17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef _DEBUG
17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (0 == err) {
17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      dbg_addr_ = "Bound @ ";
17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      dbg_addr_.append(GetLocalAddress().ToString());
17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // _DEBUG
17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return err;
17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int Connect(const SocketAddress& addr) {
18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // TODO: Implicit creation is required to reconnect...
18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // ...but should we make it more explicit?
18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (state_ != CS_CLOSED) {
18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SetError(EALREADY);
18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return SOCKET_ERROR;
18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (addr.IsUnresolved()) {
18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG(LS_VERBOSE) << "Resolving addr in PhysicalSocket::Connect";
18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      resolver_ = new AsyncResolver();
18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      resolver_->SignalDone.connect(this, &PhysicalSocket::OnResolveResult);
19047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      resolver_->Start(addr);
19147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      state_ = CS_CONNECTING;
19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return 0;
19347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
19447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
19547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return DoConnect(addr);
19647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
19747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
19847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int DoConnect(const SocketAddress& connect_addr) {
19947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((s_ == INVALID_SOCKET) &&
20047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        !Create(connect_addr.family(), SOCK_STREAM)) {
20147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return SOCKET_ERROR;
20247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
20347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr_storage addr_storage;
20447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    size_t len = connect_addr.ToSockAddrStorage(&addr_storage);
20547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
20647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int err = ::connect(s_, addr, static_cast<int>(len));
20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    UpdateLastError();
20847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (err == 0) {
20947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      state_ = CS_CONNECTED;
21047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (IsBlockingError(GetError())) {
21147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      state_ = CS_CONNECTING;
21247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ |= DE_CONNECT;
21347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
21447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return SOCKET_ERROR;
21547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
21647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
21747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    enabled_events_ |= DE_READ | DE_WRITE;
21847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
21947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
22047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
22147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int GetError() const {
22247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    CritScope cs(&crit_);
22347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return error_;
22447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
22547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
22647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void SetError(int error) {
22747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    CritScope cs(&crit_);
22847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    error_ = error;
22947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
23047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
23147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ConnState GetState() const {
23247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return state_;
23347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
23447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
23547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int GetOption(Option opt, int* value) {
23647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int slevel;
23747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int sopt;
23847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (TranslateOption(opt, &slevel, &sopt) == -1)
23947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return -1;
24047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    socklen_t optlen = sizeof(*value);
24147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int ret = ::getsockopt(s_, slevel, sopt, (SockOptArg)value, &optlen);
24247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ret != -1 && opt == OPT_DONTFRAGMENT) {
24347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
24447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      *value = (*value != IP_PMTUDISC_DONT) ? 1 : 0;
24547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
24647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
24747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return ret;
24847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
24947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
25047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int SetOption(Option opt, int value) {
25147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int slevel;
25247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int sopt;
25347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (TranslateOption(opt, &slevel, &sopt) == -1)
25447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return -1;
25547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (opt == OPT_DONTFRAGMENT) {
25647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
25747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      value = (value) ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
25847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
25947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
26047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return ::setsockopt(s_, slevel, sopt, (SockOptArg)&value, sizeof(value));
26147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
26247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
26347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int Send(const void *pv, size_t cb) {
26447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int sent = ::send(s_, reinterpret_cast<const char *>(pv), (int)cb,
26547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
26647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Suppress SIGPIPE. Without this, attempting to send on a socket whose
26747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // other end is closed will result in a SIGPIPE signal being raised to
26847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // our process, which by default will terminate the process, which we
26947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // don't want. By specifying this flag, we'll just get the error EPIPE
27047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // instead and can handle the error gracefully.
27147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        MSG_NOSIGNAL
27247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else
27347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        0
27447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
27547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        );
27647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    UpdateLastError();
27747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    MaybeRemapSendError();
27847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // We have seen minidumps where this may be false.
27947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(sent <= static_cast<int>(cb));
28047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((sent < 0) && IsBlockingError(GetError())) {
28147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ |= DE_WRITE;
28247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
28347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return sent;
28447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
28547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
28647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int SendTo(const void* buffer, size_t length, const SocketAddress& addr) {
28747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr_storage saddr;
28847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    size_t len = addr.ToSockAddrStorage(&saddr);
28947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int sent = ::sendto(
29047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        s_, static_cast<const char *>(buffer), static_cast<int>(length),
29147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
29247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Suppress SIGPIPE. See above for explanation.
29347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        MSG_NOSIGNAL,
29447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else
29547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        0,
29647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
29747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        reinterpret_cast<sockaddr*>(&saddr), static_cast<int>(len));
29847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    UpdateLastError();
29947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    MaybeRemapSendError();
30047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // We have seen minidumps where this may be false.
30147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(sent <= static_cast<int>(length));
30247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((sent < 0) && IsBlockingError(GetError())) {
30347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ |= DE_WRITE;
30447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
30547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return sent;
30647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
30747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
30847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int Recv(void* buffer, size_t length) {
30947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int received = ::recv(s_, static_cast<char*>(buffer),
31047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                          static_cast<int>(length), 0);
31147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((received == 0) && (length != 0)) {
31247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Note: on graceful shutdown, recv can return 0.  In this case, we
31347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // pretend it is blocking, and then signal close, so that simplifying
31447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // assumptions can be made about Recv.
31547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG(LS_WARNING) << "EOF from socket; deferring close event";
31647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Must turn this back on so that the select() loop will notice the close
31747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // event.
31847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ |= DE_READ;
31947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SetError(EWOULDBLOCK);
32047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return SOCKET_ERROR;
32147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
32247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    UpdateLastError();
32347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int error = GetError();
32447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    bool success = (received >= 0) || IsBlockingError(error);
32547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (udp_ || success) {
32647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ |= DE_READ;
32747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
32847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!success) {
32947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG_F(LS_VERBOSE) << "Error = " << error;
33047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
33147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return received;
33247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
33347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
33447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int RecvFrom(void* buffer, size_t length, SocketAddress *out_addr) {
33547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr_storage addr_storage;
33647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    socklen_t addr_len = sizeof(addr_storage);
33747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
33847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int received = ::recvfrom(s_, static_cast<char*>(buffer),
33947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                              static_cast<int>(length), 0, addr, &addr_len);
34047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    UpdateLastError();
34147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((received >= 0) && (out_addr != NULL))
34247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SocketAddressFromSockAddrStorage(addr_storage, out_addr);
34347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int error = GetError();
34447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    bool success = (received >= 0) || IsBlockingError(error);
34547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (udp_ || success) {
34647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ |= DE_READ;
34747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
34847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!success) {
34947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG_F(LS_VERBOSE) << "Error = " << error;
35047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
35147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return received;
35247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
35347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
35447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int Listen(int backlog) {
35547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int err = ::listen(s_, backlog);
35647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    UpdateLastError();
35747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (err == 0) {
35847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      state_ = CS_CONNECTING;
35947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ |= DE_ACCEPT;
36047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef _DEBUG
36147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      dbg_addr_ = "Listening @ ";
36247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      dbg_addr_.append(GetLocalAddress().ToString());
36347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // _DEBUG
36447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
36547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return err;
36647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
36747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
36847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  AsyncSocket* Accept(SocketAddress *out_addr) {
36947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr_storage addr_storage;
37047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    socklen_t addr_len = sizeof(addr_storage);
37147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
37247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SOCKET s = ::accept(s_, addr, &addr_len);
37347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    UpdateLastError();
37447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (s == INVALID_SOCKET)
37547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return NULL;
37647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    enabled_events_ |= DE_ACCEPT;
37747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (out_addr != NULL)
37847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SocketAddressFromSockAddrStorage(addr_storage, out_addr);
37947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return ss_->WrapSocket(s);
38047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
38147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
38247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int Close() {
38347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (s_ == INVALID_SOCKET)
38447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return 0;
38547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int err = ::closesocket(s_);
38647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    UpdateLastError();
38747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    s_ = INVALID_SOCKET;
38847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    state_ = CS_CLOSED;
38947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    enabled_events_ = 0;
39047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (resolver_) {
39147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      resolver_->Destroy(false);
39247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      resolver_ = NULL;
39347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
39447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return err;
39547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
39647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
39747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int EstimateMTU(uint16* mtu) {
39847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SocketAddress addr = GetRemoteAddress();
39947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (addr.IsAny()) {
40047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SetError(ENOTCONN);
40147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return -1;
40247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
40347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
40447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
40547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Gets the interface MTU (TTL=1) for the interface used to reach |addr|.
40647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    WinPing ping;
40747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!ping.IsValid()) {
40847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SetError(EINVAL);  // can't think of a better error ID
40947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return -1;
41047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
41147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int header_size = ICMP_HEADER_SIZE;
41247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (addr.family() == AF_INET6) {
41347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      header_size += IPV6_HEADER_SIZE;
41447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (addr.family() == AF_INET) {
41547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      header_size += IP_HEADER_SIZE;
41647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
41747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
41847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) {
41947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      int32 size = PACKET_MAXIMUMS[level] - header_size;
42047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      WinPing::PingResult result = ping.Ping(addr.ipaddr(), size,
42147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                             ICMP_PING_TIMEOUT_MILLIS,
42247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                             1, false);
42347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (result == WinPing::PING_FAIL) {
42447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        SetError(EINVAL);  // can't think of a better error ID
42547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        return -1;
42647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else if (result != WinPing::PING_TOO_LARGE) {
42747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *mtu = PACKET_MAXIMUMS[level];
42847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        return 0;
42947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
43047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
43147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
43247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(false);
43347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return -1;
43447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_MAC)
43547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // No simple way to do this on Mac OS X.
43647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // SIOCGIFMTU would work if we knew which interface would be used, but
43747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // figuring that out is pretty complicated. For now we'll return an error
43847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // and let the caller pick a default MTU.
43947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SetError(EINVAL);
44047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return -1;
44147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_LINUX)
44247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Gets the path MTU.
44347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int value;
44447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    socklen_t vlen = sizeof(value);
44547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int err = getsockopt(s_, IPPROTO_IP, IP_MTU, &value, &vlen);
44647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (err < 0) {
44747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      UpdateLastError();
44847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return err;
44947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
45047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
45147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT((0 <= value) && (value <= 65536));
45247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *mtu = value;
45347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
45447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(__native_client__)
45547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Most socket operations, including this, will fail in NaCl's sandbox.
45647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    error_ = EACCES;
45747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return -1;
45847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
45947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
46047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
46147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SocketServer* socketserver() { return ss_; }
46247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
46347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org protected:
46447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void OnResolveResult(AsyncResolverInterface* resolver) {
46547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (resolver != resolver_) {
46647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return;
46747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
46847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
46947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int error = resolver_->GetError();
47047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (error == 0) {
47147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      error = DoConnect(resolver_->address());
47247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
47347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      Close();
47447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
47547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
47647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (error) {
47747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SetError(error);
47847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SignalCloseEvent(this, error);
47947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
48047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
48147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
48247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void UpdateLastError() {
48347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SetError(LAST_SYSTEM_ERROR);
48447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
48547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
48647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void MaybeRemapSendError() {
48747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_MAC)
48847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // https://developer.apple.com/library/mac/documentation/Darwin/
48947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Reference/ManPages/man2/sendto.2.html
49047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // ENOBUFS - The output queue for a network interface is full.
49147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // This generally indicates that the interface has stopped sending,
49247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // but may be caused by transient congestion.
49347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (GetError() == ENOBUFS) {
49447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SetError(EWOULDBLOCK);
49547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
49647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
49747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
49847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
49947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  static int TranslateOption(Option opt, int* slevel, int* sopt) {
50047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    switch (opt) {
50147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      case OPT_DONTFRAGMENT:
50247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
50347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *slevel = IPPROTO_IP;
50447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *sopt = IP_DONTFRAGMENT;
50547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
50647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_MAC) || defined(BSD) || defined(__native_client__)
50747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        LOG(LS_WARNING) << "Socket::OPT_DONTFRAGMENT not supported.";
50847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        return -1;
50947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_POSIX)
51047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *slevel = IPPROTO_IP;
51147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *sopt = IP_MTU_DISCOVER;
51247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
51347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
51447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      case OPT_RCVBUF:
51547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *slevel = SOL_SOCKET;
51647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *sopt = SO_RCVBUF;
51747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
51847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      case OPT_SNDBUF:
51947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *slevel = SOL_SOCKET;
52047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *sopt = SO_SNDBUF;
52147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
52247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      case OPT_NODELAY:
52347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *slevel = IPPROTO_TCP;
52447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *sopt = TCP_NODELAY;
52547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
52647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      case OPT_DSCP:
52747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        LOG(LS_WARNING) << "Socket::OPT_DSCP not supported.";
52847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        return -1;
52947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      case OPT_RTP_SENDTIME_EXTN_ID:
53047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        return -1;  // No logging is necessary as this not a OS socket option.
53147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      default:
53247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        ASSERT(false);
53347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        return -1;
53447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
53547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
53647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
53747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
53847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  PhysicalSocketServer* ss_;
53947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SOCKET s_;
54047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  uint8 enabled_events_;
54147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bool udp_;
54247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int error_;
54347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Protects |error_| that is accessed from different threads.
54447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  mutable CriticalSection crit_;
54547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ConnState state_;
54647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  AsyncResolver* resolver_;
54747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
54847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef _DEBUG
54947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::string dbg_addr_;
55047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // _DEBUG;
55147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
55247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
55347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX)
55447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass EventDispatcher : public Dispatcher {
55547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
55647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  EventDispatcher(PhysicalSocketServer* ss) : ss_(ss), fSignaled_(false) {
55747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (pipe(afd_) < 0)
55847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG(LERROR) << "pipe failed";
55947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ss_->Add(this);
56047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
56147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
56247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual ~EventDispatcher() {
56347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ss_->Remove(this);
56447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    close(afd_[0]);
56547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    close(afd_[1]);
56647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
56747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
56847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void Signal() {
56947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    CritScope cs(&crit_);
57047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!fSignaled_) {
57147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      const uint8 b[1] = { 0 };
57247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (VERIFY(1 == write(afd_[1], b, sizeof(b)))) {
57347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        fSignaled_ = true;
57447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
57547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
57647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
57747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
57847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual uint32 GetRequestedEvents() {
57947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return DE_READ;
58047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
58147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
58247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void OnPreEvent(uint32 ff) {
58347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // It is not possible to perfectly emulate an auto-resetting event with
58447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // pipes.  This simulates it by resetting before the event is handled.
58547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
58647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    CritScope cs(&crit_);
58747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (fSignaled_) {
58847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      uint8 b[4];  // Allow for reading more than 1 byte, but expect 1.
58947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      VERIFY(1 == read(afd_[0], b, sizeof(b)));
59047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      fSignaled_ = false;
59147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
59247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
59347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
59447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void OnEvent(uint32 ff, int err) {
59547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(false);
59647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
59747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
59847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual int GetDescriptor() {
59947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return afd_[0];
60047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
60147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
60247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual bool IsDescriptorClosed() {
60347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
60447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
60547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
60647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private:
60747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  PhysicalSocketServer *ss_;
60847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int afd_[2];
60947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bool fSignaled_;
61047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CriticalSection crit_;
61147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
61247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
61347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// These two classes use the self-pipe trick to deliver POSIX signals to our
61447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// select loop. This is the only safe, reliable, cross-platform way to do
61547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// non-trivial things with a POSIX signal in an event-driven program (until
61647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// proper pselect() implementations become ubiquitous).
61747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
61847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass PosixSignalHandler {
61947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
62047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // POSIX only specifies 32 signals, but in principle the system might have
62147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // more and the programmer might choose to use them, so we size our array
62247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // for 128.
62347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  static const int kNumPosixSignals = 128;
62447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
62547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // There is just a single global instance. (Signal handlers do not get any
62647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // sort of user-defined void * parameter, so they can't access anything that
62747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // isn't global.)
62847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  static PosixSignalHandler* Instance() {
62947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LIBJINGLE_DEFINE_STATIC_LOCAL(PosixSignalHandler, instance, ());
63047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return &instance;
63147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
63247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
63347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Returns true if the given signal number is set.
63447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bool IsSignalSet(int signum) const {
63547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(signum < ARRAY_SIZE(received_signal_));
63647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (signum < ARRAY_SIZE(received_signal_)) {
63747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return received_signal_[signum];
63847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
63947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
64047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
64147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
64247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
64347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Clears the given signal number.
64447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void ClearSignal(int signum) {
64547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(signum < ARRAY_SIZE(received_signal_));
64647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (signum < ARRAY_SIZE(received_signal_)) {
64747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      received_signal_[signum] = false;
64847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
64947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
65047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
65147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Returns the file descriptor to monitor for signal events.
65247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int GetDescriptor() const {
65347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return afd_[0];
65447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
65547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
65647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // This is called directly from our real signal handler, so it must be
65747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // signal-handler-safe. That means it cannot assume anything about the
65847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // user-level state of the process, since the handler could be executed at any
65947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // time on any thread.
66047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void OnPosixSignalReceived(int signum) {
66147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (signum >= ARRAY_SIZE(received_signal_)) {
66247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // We don't have space in our array for this.
66347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return;
66447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
66547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Set a flag saying we've seen this signal.
66647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    received_signal_[signum] = true;
66747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Notify application code that we got a signal.
66847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    const uint8 b[1] = { 0 };
66947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (-1 == write(afd_[1], b, sizeof(b))) {
67047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Nothing we can do here. If there's an error somehow then there's
67147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // nothing we can safely do from a signal handler.
67247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // No, we can't even safely log it.
67347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // But, we still have to check the return value here. Otherwise,
67447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // GCC 4.4.1 complains ignoring return value. Even (void) doesn't help.
67547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return;
67647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
67747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
67847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
67947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private:
68047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  PosixSignalHandler() {
68147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (pipe(afd_) < 0) {
68247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG_ERR(LS_ERROR) << "pipe failed";
68347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return;
68447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
68547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (fcntl(afd_[0], F_SETFL, O_NONBLOCK) < 0) {
68647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG_ERR(LS_WARNING) << "fcntl #1 failed";
68747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
68847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (fcntl(afd_[1], F_SETFL, O_NONBLOCK) < 0) {
68947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG_ERR(LS_WARNING) << "fcntl #2 failed";
69047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
69147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    memset(const_cast<void *>(static_cast<volatile void *>(received_signal_)),
69247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org           0,
69347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org           sizeof(received_signal_));
69447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
69547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
69647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ~PosixSignalHandler() {
69747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int fd1 = afd_[0];
69847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int fd2 = afd_[1];
69947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // We clobber the stored file descriptor numbers here or else in principle
70047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // a signal that happens to be delivered during application termination
70147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // could erroneously write a zero byte to an unrelated file handle in
70247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // OnPosixSignalReceived() if some other file happens to be opened later
70347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // during shutdown and happens to be given the same file descriptor number
70447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // as our pipe had. Unfortunately even with this precaution there is still a
70547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // race where that could occur if said signal happens to be handled
70647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // concurrently with this code and happens to have already read the value of
70747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // afd_[1] from memory before we clobber it, but that's unlikely.
70847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    afd_[0] = -1;
70947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    afd_[1] = -1;
71047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    close(fd1);
71147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    close(fd2);
71247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
71347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
71447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int afd_[2];
71547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // These are boolean flags that will be set in our signal handler and read
71647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // and cleared from Wait(). There is a race involved in this, but it is
71747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // benign. The signal handler sets the flag before signaling the pipe, so
71847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // we'll never end up blocking in select() while a flag is still true.
71947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // However, if two of the same signal arrive close to each other then it's
72047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // possible that the second time the handler may set the flag while it's still
72147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // true, meaning that signal will be missed. But the first occurrence of it
72247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // will still be handled, so this isn't a problem.
72347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Volatile is not necessary here for correctness, but this data _is_ volatile
72447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // so I've marked it as such.
72547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  volatile uint8 received_signal_[kNumPosixSignals];
72647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
72747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
72847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass PosixSignalDispatcher : public Dispatcher {
72947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
73047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  PosixSignalDispatcher(PhysicalSocketServer *owner) : owner_(owner) {
73147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    owner_->Add(this);
73247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
73347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
73447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual ~PosixSignalDispatcher() {
73547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    owner_->Remove(this);
73647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
73747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
73847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual uint32 GetRequestedEvents() {
73947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return DE_READ;
74047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
74147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
74247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void OnPreEvent(uint32 ff) {
74347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Events might get grouped if signals come very fast, so we read out up to
74447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // 16 bytes to make sure we keep the pipe empty.
74547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    uint8 b[16];
74647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ssize_t ret = read(GetDescriptor(), b, sizeof(b));
74747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ret < 0) {
74847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG_ERR(LS_WARNING) << "Error in read()";
74947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (ret == 0) {
75047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG(LS_WARNING) << "Should have read at least one byte";
75147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
75247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
75347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
75447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void OnEvent(uint32 ff, int err) {
75547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    for (int signum = 0; signum < PosixSignalHandler::kNumPosixSignals;
75647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org         ++signum) {
75747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (PosixSignalHandler::Instance()->IsSignalSet(signum)) {
75847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        PosixSignalHandler::Instance()->ClearSignal(signum);
75947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        HandlerMap::iterator i = handlers_.find(signum);
76047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (i == handlers_.end()) {
76147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          // This can happen if a signal is delivered to our process at around
76247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          // the same time as we unset our handler for it. It is not an error
76347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          // condition, but it's unusual enough to be worth logging.
76447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          LOG(LS_INFO) << "Received signal with no handler: " << signum;
76547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        } else {
76647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          // Otherwise, execute our handler.
76747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          (*i->second)(signum);
76847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        }
76947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
77047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
77147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
77247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
77347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual int GetDescriptor() {
77447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return PosixSignalHandler::Instance()->GetDescriptor();
77547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
77647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
77747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual bool IsDescriptorClosed() {
77847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
77947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
78047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
78147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void SetHandler(int signum, void (*handler)(int)) {
78247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    handlers_[signum] = handler;
78347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
78447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
78547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void ClearHandler(int signum) {
78647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    handlers_.erase(signum);
78747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
78847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
78947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bool HasHandlers() {
79047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return !handlers_.empty();
79147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
79247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
79347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private:
79447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  typedef std::map<int, void (*)(int)> HandlerMap;
79547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
79647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  HandlerMap handlers_;
79747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Our owner.
79847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  PhysicalSocketServer *owner_;
79947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
80047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
80147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass SocketDispatcher : public Dispatcher, public PhysicalSocket {
80247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
80347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  explicit SocketDispatcher(PhysicalSocketServer *ss) : PhysicalSocket(ss) {
80447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
80547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SocketDispatcher(SOCKET s, PhysicalSocketServer *ss) : PhysicalSocket(ss, s) {
80647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
80747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
80847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual ~SocketDispatcher() {
80947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    Close();
81047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
81147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
81247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bool Initialize() {
81347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ss_->Add(this);
81447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK);
81547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return true;
81647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
81747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
81847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual bool Create(int type) {
81947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return Create(AF_INET, type);
82047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
82147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
82247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual bool Create(int family, int type) {
82347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Change the socket to be non-blocking.
82447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!PhysicalSocket::Create(family, type))
82547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
82647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
82747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return Initialize();
82847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
82947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
83047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual int GetDescriptor() {
83147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return s_;
83247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
83347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
83447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual bool IsDescriptorClosed() {
83547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // We don't have a reliable way of distinguishing end-of-stream
83647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // from readability.  So test on each readable call.  Is this
83747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // inefficient?  Probably.
83847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    char ch;
83947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ssize_t res = ::recv(s_, &ch, 1, MSG_PEEK);
84047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (res > 0) {
84147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Data available, so not closed.
84247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
84347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (res == 0) {
84447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // EOF, so closed.
84547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return true;
84647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {  // error
84747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      switch (errno) {
84847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Returned if we've already closed s_.
84947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        case EBADF:
85047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Returned during ungraceful peer shutdown.
85147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        case ECONNRESET:
85247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          return true;
85347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        default:
85447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          // Assume that all other errors are just blocking errors, meaning the
85547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          // connection is still good but we just can't read from it right now.
85647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          // This should only happen when connecting (and at most once), because
85747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          // in all other cases this function is only called if the file
85847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          // descriptor is already known to be in the readable state. However,
85947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          // it's not necessary a problem if we spuriously interpret a
86047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          // "connection lost"-type error as a blocking error, because typically
86147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          // the next recv() will get EOF, so we'll still eventually notice that
86247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          // the socket is closed.
86347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          LOG_ERR(LS_WARNING) << "Assuming benign blocking error";
86447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          return false;
86547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
86647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
86747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
86847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
86947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual uint32 GetRequestedEvents() {
87047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return enabled_events_;
87147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
87247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
87347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void OnPreEvent(uint32 ff) {
87447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ff & DE_CONNECT) != 0)
87547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      state_ = CS_CONNECTED;
87647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ff & DE_CLOSE) != 0)
87747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      state_ = CS_CLOSED;
87847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
87947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
88047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void OnEvent(uint32 ff, int err) {
88147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Make sure we deliver connect/accept first. Otherwise, consumers may see
88247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // something like a READ followed by a CONNECT, which would be odd.
88347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ff & DE_CONNECT) != 0) {
88447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ &= ~DE_CONNECT;
88547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SignalConnectEvent(this);
88647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
88747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ff & DE_ACCEPT) != 0) {
88847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ &= ~DE_ACCEPT;
88947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SignalReadEvent(this);
89047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
89147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ff & DE_READ) != 0) {
89247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ &= ~DE_READ;
89347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SignalReadEvent(this);
89447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
89547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ff & DE_WRITE) != 0) {
89647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ &= ~DE_WRITE;
89747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SignalWriteEvent(this);
89847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
89947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ff & DE_CLOSE) != 0) {
90047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // The socket is now dead to us, so stop checking it.
90147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ = 0;
90247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SignalCloseEvent(this, err);
90347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
90447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
90547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
90647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual int Close() {
90747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (s_ == INVALID_SOCKET)
90847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return 0;
90947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
91047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ss_->Remove(this);
91147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return PhysicalSocket::Close();
91247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
91347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
91447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
91547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass FileDispatcher: public Dispatcher, public AsyncFile {
91647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
91747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  FileDispatcher(int fd, PhysicalSocketServer *ss) : ss_(ss), fd_(fd) {
91847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    set_readable(true);
91947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
92047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ss_->Add(this);
92147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
92247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    fcntl(fd_, F_SETFL, fcntl(fd_, F_GETFL, 0) | O_NONBLOCK);
92347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
92447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
92547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual ~FileDispatcher() {
92647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ss_->Remove(this);
92747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
92847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
92947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SocketServer* socketserver() { return ss_; }
93047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
93147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual int GetDescriptor() {
93247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return fd_;
93347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
93447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
93547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual bool IsDescriptorClosed() {
93647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
93747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
93847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
93947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual uint32 GetRequestedEvents() {
94047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return flags_;
94147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
94247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
94347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void OnPreEvent(uint32 ff) {
94447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
94547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
94647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void OnEvent(uint32 ff, int err) {
94747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ff & DE_READ) != 0)
94847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SignalReadEvent(this);
94947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ff & DE_WRITE) != 0)
95047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SignalWriteEvent(this);
95147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ff & DE_CLOSE) != 0)
95247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SignalCloseEvent(this, err);
95347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
95447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
95547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual bool readable() {
95647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return (flags_ & DE_READ) != 0;
95747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
95847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
95947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void set_readable(bool value) {
96047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    flags_ = value ? (flags_ | DE_READ) : (flags_ & ~DE_READ);
96147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
96247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
96347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual bool writable() {
96447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return (flags_ & DE_WRITE) != 0;
96547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
96647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
96747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void set_writable(bool value) {
96847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    flags_ = value ? (flags_ | DE_WRITE) : (flags_ & ~DE_WRITE);
96947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
97047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
97147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private:
97247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  PhysicalSocketServer* ss_;
97347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int fd_;
97447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int flags_;
97547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
97647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
97747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgAsyncFile* PhysicalSocketServer::CreateFile(int fd) {
97847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return new FileDispatcher(fd, this);
97947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
98047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
98147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif // WEBRTC_POSIX
98247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
98347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
98447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic uint32 FlagsToEvents(uint32 events) {
98547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  uint32 ffFD = FD_CLOSE;
98647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (events & DE_READ)
98747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ffFD |= FD_READ;
98847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (events & DE_WRITE)
98947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ffFD |= FD_WRITE;
99047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (events & DE_CONNECT)
99147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ffFD |= FD_CONNECT;
99247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (events & DE_ACCEPT)
99347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ffFD |= FD_ACCEPT;
99447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ffFD;
99547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
99647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
99747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass EventDispatcher : public Dispatcher {
99847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
99947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  EventDispatcher(PhysicalSocketServer *ss) : ss_(ss) {
100047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    hev_ = WSACreateEvent();
100147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (hev_) {
100247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ss_->Add(this);
100347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
100447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
100547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
100647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ~EventDispatcher() {
100747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (hev_ != NULL) {
100847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ss_->Remove(this);
100947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      WSACloseEvent(hev_);
101047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      hev_ = NULL;
101147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
101247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
101347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
101447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void Signal() {
101547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (hev_ != NULL)
101647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      WSASetEvent(hev_);
101747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
101847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
101947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual uint32 GetRequestedEvents() {
102047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
102147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
102247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
102347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void OnPreEvent(uint32 ff) {
102447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    WSAResetEvent(hev_);
102547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
102647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
102747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void OnEvent(uint32 ff, int err) {
102847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
102947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
103047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual WSAEVENT GetWSAEvent() {
103147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return hev_;
103247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
103347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
103447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual SOCKET GetSocket() {
103547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return INVALID_SOCKET;
103647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
103747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
103847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual bool CheckSignalClose() { return false; }
103947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
104047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgprivate:
104147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  PhysicalSocketServer* ss_;
104247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  WSAEVENT hev_;
104347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
104447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
104547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass SocketDispatcher : public Dispatcher, public PhysicalSocket {
104647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
104747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  static int next_id_;
104847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int id_;
104947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bool signal_close_;
105047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int signal_err_;
105147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
105247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SocketDispatcher(PhysicalSocketServer* ss)
105347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      : PhysicalSocket(ss),
105447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        id_(0),
105547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        signal_close_(false) {
105647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
105747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
105847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SocketDispatcher(SOCKET s, PhysicalSocketServer* ss)
105947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      : PhysicalSocket(ss, s),
106047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        id_(0),
106147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        signal_close_(false) {
106247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
106347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
106447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual ~SocketDispatcher() {
106547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    Close();
106647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
106747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
106847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bool Initialize() {
106947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(s_ != INVALID_SOCKET);
107047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Must be a non-blocking
107147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    u_long argp = 1;
107247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ioctlsocket(s_, FIONBIO, &argp);
107347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ss_->Add(this);
107447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return true;
107547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
107647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
107747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual bool Create(int type) {
107847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return Create(AF_INET, type);
107947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
108047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
108147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual bool Create(int family, int type) {
108247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Create socket
108347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!PhysicalSocket::Create(family, type))
108447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
108547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
108647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!Initialize())
108747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
108847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
108947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    do { id_ = ++next_id_; } while (id_ == 0);
109047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return true;
109147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
109247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
109347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual int Close() {
109447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (s_ == INVALID_SOCKET)
109547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return 0;
109647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
109747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    id_ = 0;
109847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    signal_close_ = false;
109947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ss_->Remove(this);
110047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return PhysicalSocket::Close();
110147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
110247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
110347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual uint32 GetRequestedEvents() {
110447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return enabled_events_;
110547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
110647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
110747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void OnPreEvent(uint32 ff) {
110847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ff & DE_CONNECT) != 0)
110947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      state_ = CS_CONNECTED;
111047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // We set CS_CLOSED from CheckSignalClose.
111147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
111247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
111347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void OnEvent(uint32 ff, int err) {
111447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int cache_id = id_;
111547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Make sure we deliver connect/accept first. Otherwise, consumers may see
111647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // something like a READ followed by a CONNECT, which would be odd.
111747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (((ff & DE_CONNECT) != 0) && (id_ == cache_id)) {
111847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (ff != DE_CONNECT)
111947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        LOG(LS_VERBOSE) << "Signalled with DE_CONNECT: " << ff;
112047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ &= ~DE_CONNECT;
112147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef _DEBUG
112247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      dbg_addr_ = "Connected @ ";
112347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      dbg_addr_.append(GetRemoteAddress().ToString());
112447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // _DEBUG
112547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SignalConnectEvent(this);
112647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
112747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (((ff & DE_ACCEPT) != 0) && (id_ == cache_id)) {
112847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ &= ~DE_ACCEPT;
112947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SignalReadEvent(this);
113047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
113147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((ff & DE_READ) != 0) {
113247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ &= ~DE_READ;
113347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SignalReadEvent(this);
113447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
113547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (((ff & DE_WRITE) != 0) && (id_ == cache_id)) {
113647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      enabled_events_ &= ~DE_WRITE;
113747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SignalWriteEvent(this);
113847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
113947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (((ff & DE_CLOSE) != 0) && (id_ == cache_id)) {
114047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      signal_close_ = true;
114147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      signal_err_ = err;
114247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
114347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
114447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
114547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual WSAEVENT GetWSAEvent() {
114647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return WSA_INVALID_EVENT;
114747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
114847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
114947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual SOCKET GetSocket() {
115047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return s_;
115147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
115247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
115347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual bool CheckSignalClose() {
115447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!signal_close_)
115547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
115647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
115747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    char ch;
115847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (recv(s_, &ch, 1, MSG_PEEK) > 0)
115947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
116047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
116147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    state_ = CS_CLOSED;
116247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    signal_close_ = false;
116347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SignalCloseEvent(this, signal_err_);
116447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return true;
116547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
116647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
116747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
116847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint SocketDispatcher::next_id_ = 0;
116947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
117047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // WEBRTC_WIN
117147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
117247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Sets the value of a boolean value to false when signaled.
117347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass Signaler : public EventDispatcher {
117447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
117547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Signaler(PhysicalSocketServer* ss, bool* pf)
117647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      : EventDispatcher(ss), pf_(pf) {
117747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
117847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual ~Signaler() { }
117947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
118047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void OnEvent(uint32 ff, int err) {
118147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (pf_)
118247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      *pf_ = false;
118347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
118447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
118547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private:
118647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bool *pf_;
118747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
118847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
118947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgPhysicalSocketServer::PhysicalSocketServer()
119047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    : fWait_(false) {
119147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  signal_wakeup_ = new Signaler(this, &fWait_);
119247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
119347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  socket_ev_ = WSACreateEvent();
119447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
119547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
119647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
119747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgPhysicalSocketServer::~PhysicalSocketServer() {
119847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
119947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  WSACloseEvent(socket_ev_);
120047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
120147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX)
120247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  signal_dispatcher_.reset();
120347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
120447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  delete signal_wakeup_;
120547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(dispatchers_.empty());
120647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
120747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
120847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid PhysicalSocketServer::WakeUp() {
120947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  signal_wakeup_->Signal();
121047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
121147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
121247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocket* PhysicalSocketServer::CreateSocket(int type) {
121347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return CreateSocket(AF_INET, type);
121447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
121547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
121647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocket* PhysicalSocketServer::CreateSocket(int family, int type) {
121747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  PhysicalSocket* socket = new PhysicalSocket(this);
121847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (socket->Create(family, type)) {
121947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return socket;
122047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
122147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    delete socket;
122247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
122347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
122447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
122547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
122647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgAsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int type) {
122747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return CreateAsyncSocket(AF_INET, type);
122847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
122947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
123047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgAsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int family, int type) {
123147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SocketDispatcher* dispatcher = new SocketDispatcher(this);
123247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (dispatcher->Create(family, type)) {
123347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return dispatcher;
123447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
123547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    delete dispatcher;
123647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
123747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
123847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
123947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
124047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgAsyncSocket* PhysicalSocketServer::WrapSocket(SOCKET s) {
124147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SocketDispatcher* dispatcher = new SocketDispatcher(s, this);
124247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (dispatcher->Initialize()) {
124347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return dispatcher;
124447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
124547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    delete dispatcher;
124647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
124747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
124847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
124947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
125047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid PhysicalSocketServer::Add(Dispatcher *pdispatcher) {
125147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CritScope cs(&crit_);
125247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Prevent duplicates. This can cause dead dispatchers to stick around.
125347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  DispatcherList::iterator pos = std::find(dispatchers_.begin(),
125447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                           dispatchers_.end(),
125547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                           pdispatcher);
125647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (pos != dispatchers_.end())
125747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
125847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  dispatchers_.push_back(pdispatcher);
125947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
126047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
126147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid PhysicalSocketServer::Remove(Dispatcher *pdispatcher) {
126247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CritScope cs(&crit_);
126347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  DispatcherList::iterator pos = std::find(dispatchers_.begin(),
126447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                           dispatchers_.end(),
126547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                           pdispatcher);
126647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // We silently ignore duplicate calls to Add, so we should silently ignore
126747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // the (expected) symmetric calls to Remove. Note that this may still hide
126847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // a real issue, so we at least log a warning about it.
126947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (pos == dispatchers_.end()) {
127047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_WARNING) << "PhysicalSocketServer asked to remove a unknown "
127147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                    << "dispatcher, potentially from a duplicate call to Add.";
127247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
127347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
127447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t index = pos - dispatchers_.begin();
127547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  dispatchers_.erase(pos);
127647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (IteratorList::iterator it = iterators_.begin(); it != iterators_.end();
127747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org       ++it) {
127847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (index < **it) {
127947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      --**it;
128047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
128147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
128247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
128347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
128447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX)
128547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
128647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Calculate timing information
128747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
128847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  struct timeval *ptvWait = NULL;
128947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  struct timeval tvWait;
129047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  struct timeval tvStop;
129147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (cmsWait != kForever) {
129247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Calculate wait timeval
129347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    tvWait.tv_sec = cmsWait / 1000;
129447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    tvWait.tv_usec = (cmsWait % 1000) * 1000;
129547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ptvWait = &tvWait;
129647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
129747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Calculate when to return in a timeval
129847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    gettimeofday(&tvStop, NULL);
129947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    tvStop.tv_sec += tvWait.tv_sec;
130047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    tvStop.tv_usec += tvWait.tv_usec;
130147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (tvStop.tv_usec >= 1000000) {
130247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      tvStop.tv_usec -= 1000000;
130347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      tvStop.tv_sec += 1;
130447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
130547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
130647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
130747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Zero all fd_sets. Don't need to do this inside the loop since
130847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // select() zeros the descriptors not signaled
130947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
131047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  fd_set fdsRead;
131147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  FD_ZERO(&fdsRead);
131247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  fd_set fdsWrite;
131347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  FD_ZERO(&fdsWrite);
131447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
131547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  fWait_ = true;
131647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
131747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while (fWait_) {
131847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int fdmax = -1;
131947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    {
132047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      CritScope cr(&crit_);
132147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      for (size_t i = 0; i < dispatchers_.size(); ++i) {
132247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Query dispatchers for read and write wait state
132347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        Dispatcher *pdispatcher = dispatchers_[i];
132447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        ASSERT(pdispatcher);
132547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (!process_io && (pdispatcher != signal_wakeup_))
132647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          continue;
132747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        int fd = pdispatcher->GetDescriptor();
132847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (fd > fdmax)
132947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          fdmax = fd;
133047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
133147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        uint32 ff = pdispatcher->GetRequestedEvents();
133247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (ff & (DE_READ | DE_ACCEPT))
133347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          FD_SET(fd, &fdsRead);
133447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (ff & (DE_WRITE | DE_CONNECT))
133547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          FD_SET(fd, &fdsWrite);
133647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
133747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
133847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
133947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Wait then call handlers as appropriate
134047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // < 0 means error
134147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // 0 means timeout
134247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // > 0 means count of descriptors ready
134347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int n = select(fdmax + 1, &fdsRead, &fdsWrite, NULL, ptvWait);
134447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
134547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // If error, return error.
134647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (n < 0) {
134747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (errno != EINTR) {
134847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        LOG_E(LS_ERROR, EN, errno) << "select";
134947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        return false;
135047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
135147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Else ignore the error and keep going. If this EINTR was for one of the
135247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // signals managed by this PhysicalSocketServer, the
135347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // PosixSignalDeliveryDispatcher will be in the signaled state in the next
135447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // iteration.
135547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (n == 0) {
135647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // If timeout, return success
135747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return true;
135847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
135947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // We have signaled descriptors
136047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      CritScope cr(&crit_);
136147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      for (size_t i = 0; i < dispatchers_.size(); ++i) {
136247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        Dispatcher *pdispatcher = dispatchers_[i];
136347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        int fd = pdispatcher->GetDescriptor();
136447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        uint32 ff = 0;
136547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        int errcode = 0;
136647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
136747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Reap any error code, which can be signaled through reads or writes.
136847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // TODO: Should we set errcode if getsockopt fails?
136947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (FD_ISSET(fd, &fdsRead) || FD_ISSET(fd, &fdsWrite)) {
137047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          socklen_t len = sizeof(errcode);
137147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          ::getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &len);
137247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        }
137347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
137447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Check readable descriptors. If we're waiting on an accept, signal
137547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // that. Otherwise we're waiting for data, check to see if we're
137647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // readable or really closed.
137747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // TODO: Only peek at TCP descriptors.
137847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (FD_ISSET(fd, &fdsRead)) {
137947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          FD_CLR(fd, &fdsRead);
138047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          if (pdispatcher->GetRequestedEvents() & DE_ACCEPT) {
138147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            ff |= DE_ACCEPT;
138247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          } else if (errcode || pdispatcher->IsDescriptorClosed()) {
138347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            ff |= DE_CLOSE;
138447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          } else {
138547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            ff |= DE_READ;
138647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          }
138747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        }
138847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
138947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Check writable descriptors. If we're waiting on a connect, detect
139047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // success versus failure by the reaped error code.
139147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (FD_ISSET(fd, &fdsWrite)) {
139247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          FD_CLR(fd, &fdsWrite);
139347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          if (pdispatcher->GetRequestedEvents() & DE_CONNECT) {
139447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            if (!errcode) {
139547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              ff |= DE_CONNECT;
139647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            } else {
139747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              ff |= DE_CLOSE;
139847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            }
139947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          } else {
140047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            ff |= DE_WRITE;
140147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          }
140247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        }
140347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
140447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // Tell the descriptor about the event.
140547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (ff != 0) {
140647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          pdispatcher->OnPreEvent(ff);
140747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          pdispatcher->OnEvent(ff, errcode);
140847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        }
140947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
141047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
141147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
141247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Recalc the time remaining to wait. Doing it here means it doesn't get
141347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // calced twice the first time through the loop
141447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ptvWait) {
141547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ptvWait->tv_sec = 0;
141647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ptvWait->tv_usec = 0;
141747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      struct timeval tvT;
141847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      gettimeofday(&tvT, NULL);
141947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if ((tvStop.tv_sec > tvT.tv_sec)
142047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          || ((tvStop.tv_sec == tvT.tv_sec)
142147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              && (tvStop.tv_usec > tvT.tv_usec))) {
142247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        ptvWait->tv_sec = tvStop.tv_sec - tvT.tv_sec;
142347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        ptvWait->tv_usec = tvStop.tv_usec - tvT.tv_usec;
142447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (ptvWait->tv_usec < 0) {
142547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          ASSERT(ptvWait->tv_sec > 0);
142647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          ptvWait->tv_usec += 1000000;
142747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          ptvWait->tv_sec -= 1;
142847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        }
142947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
143047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
143147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
143247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
143347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
143447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
143547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
143647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic void GlobalSignalHandler(int signum) {
143747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  PosixSignalHandler::Instance()->OnPosixSignalReceived(signum);
143847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
143947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
144047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool PhysicalSocketServer::SetPosixSignalHandler(int signum,
144147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                                 void (*handler)(int)) {
144247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // If handler is SIG_IGN or SIG_DFL then clear our user-level handler,
144347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // otherwise set one.
144447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (handler == SIG_IGN || handler == SIG_DFL) {
144547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!InstallSignal(signum, handler)) {
144647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
144747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
144847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (signal_dispatcher_) {
144947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      signal_dispatcher_->ClearHandler(signum);
145047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (!signal_dispatcher_->HasHandlers()) {
145147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        signal_dispatcher_.reset();
145247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
145347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
145447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
145547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!signal_dispatcher_) {
145647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      signal_dispatcher_.reset(new PosixSignalDispatcher(this));
145747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
145847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    signal_dispatcher_->SetHandler(signum, handler);
145947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!InstallSignal(signum, &GlobalSignalHandler)) {
146047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
146147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
146247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
146347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
146447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
146547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
146647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgDispatcher* PhysicalSocketServer::signal_dispatcher() {
146747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return signal_dispatcher_.get();
146847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
146947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
147047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool PhysicalSocketServer::InstallSignal(int signum, void (*handler)(int)) {
147147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  struct sigaction act;
147247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // It doesn't really matter what we set this mask to.
147347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (sigemptyset(&act.sa_mask) != 0) {
147447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_ERR(LS_ERROR) << "Couldn't set mask";
147547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
147647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
147747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  act.sa_handler = handler;
147847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if !defined(__native_client__)
147947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Use SA_RESTART so that our syscalls don't get EINTR, since we don't need it
148047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // and it's a nuisance. Though some syscalls still return EINTR and there's no
148147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // real standard for which ones. :(
148247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  act.sa_flags = SA_RESTART;
148347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else
148447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  act.sa_flags = 0;
148547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
148647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (sigaction(signum, &act, NULL) != 0) {
148747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_ERR(LS_ERROR) << "Couldn't set sigaction";
148847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
148947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
149047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
149147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
149247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // WEBRTC_POSIX
149347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
149447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
149547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
149647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int cmsTotal = cmsWait;
149747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int cmsElapsed = 0;
149847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  uint32 msStart = Time();
149947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
150047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  fWait_ = true;
150147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while (fWait_) {
150247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    std::vector<WSAEVENT> events;
150347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    std::vector<Dispatcher *> event_owners;
150447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
150547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    events.push_back(socket_ev_);
150647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
150747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    {
150847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      CritScope cr(&crit_);
150947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      size_t i = 0;
151047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      iterators_.push_back(&i);
151147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Don't track dispatchers_.size(), because we want to pick up any new
151247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // dispatchers that were added while processing the loop.
151347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      while (i < dispatchers_.size()) {
151447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        Dispatcher* disp = dispatchers_[i++];
151547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (!process_io && (disp != signal_wakeup_))
151647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          continue;
151747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        SOCKET s = disp->GetSocket();
151847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (disp->CheckSignalClose()) {
151947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          // We just signalled close, don't poll this socket
152047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        } else if (s != INVALID_SOCKET) {
152147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          WSAEventSelect(s,
152247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                         events[0],
152347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                         FlagsToEvents(disp->GetRequestedEvents()));
152447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        } else {
152547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          events.push_back(disp->GetWSAEvent());
152647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          event_owners.push_back(disp);
152747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        }
152847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
152947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ASSERT(iterators_.back() == &i);
153047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      iterators_.pop_back();
153147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
153247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
153347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Which is shorter, the delay wait or the asked wait?
153447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
153547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int cmsNext;
153647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (cmsWait == kForever) {
153747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      cmsNext = cmsWait;
153847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
153947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      cmsNext = _max(0, cmsTotal - cmsElapsed);
154047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
154147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
154247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Wait for one of the events to signal
154347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    DWORD dw = WSAWaitForMultipleEvents(static_cast<DWORD>(events.size()),
154447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                        &events[0],
154547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                        false,
154647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                        cmsNext,
154747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                        false);
154847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
154947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (dw == WSA_WAIT_FAILED) {
155047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Failed?
155147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // TODO: need a better strategy than this!
155247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      WSAGetLastError();
155347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ASSERT(false);
155447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
155547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (dw == WSA_WAIT_TIMEOUT) {
155647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Timeout?
155747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return true;
155847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
155947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Figure out which one it is and call it
156047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      CritScope cr(&crit_);
156147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      int index = dw - WSA_WAIT_EVENT_0;
156247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (index > 0) {
156347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        --index; // The first event is the socket event
156447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        event_owners[index]->OnPreEvent(0);
156547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        event_owners[index]->OnEvent(0, 0);
156647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else if (process_io) {
156747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        size_t i = 0, end = dispatchers_.size();
156847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        iterators_.push_back(&i);
156947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        iterators_.push_back(&end);  // Don't iterate over new dispatchers.
157047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        while (i < end) {
157147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          Dispatcher* disp = dispatchers_[i++];
157247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          SOCKET s = disp->GetSocket();
157347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          if (s == INVALID_SOCKET)
157447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            continue;
157547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
157647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          WSANETWORKEVENTS wsaEvents;
157747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          int err = WSAEnumNetworkEvents(s, events[0], &wsaEvents);
157847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          if (err == 0) {
157947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
158047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if LOGGING
158147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            {
158247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              if ((wsaEvents.lNetworkEvents & FD_READ) &&
158347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  wsaEvents.iErrorCode[FD_READ_BIT] != 0) {
158447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                LOG(WARNING) << "PhysicalSocketServer got FD_READ_BIT error "
158547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                             << wsaEvents.iErrorCode[FD_READ_BIT];
158647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              }
158747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              if ((wsaEvents.lNetworkEvents & FD_WRITE) &&
158847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  wsaEvents.iErrorCode[FD_WRITE_BIT] != 0) {
158947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                LOG(WARNING) << "PhysicalSocketServer got FD_WRITE_BIT error "
159047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                             << wsaEvents.iErrorCode[FD_WRITE_BIT];
159147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              }
159247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              if ((wsaEvents.lNetworkEvents & FD_CONNECT) &&
159347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  wsaEvents.iErrorCode[FD_CONNECT_BIT] != 0) {
159447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                LOG(WARNING) << "PhysicalSocketServer got FD_CONNECT_BIT error "
159547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                             << wsaEvents.iErrorCode[FD_CONNECT_BIT];
159647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              }
159747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              if ((wsaEvents.lNetworkEvents & FD_ACCEPT) &&
159847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  wsaEvents.iErrorCode[FD_ACCEPT_BIT] != 0) {
159947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                LOG(WARNING) << "PhysicalSocketServer got FD_ACCEPT_BIT error "
160047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                             << wsaEvents.iErrorCode[FD_ACCEPT_BIT];
160147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              }
160247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              if ((wsaEvents.lNetworkEvents & FD_CLOSE) &&
160347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  wsaEvents.iErrorCode[FD_CLOSE_BIT] != 0) {
160447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                LOG(WARNING) << "PhysicalSocketServer got FD_CLOSE_BIT error "
160547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                             << wsaEvents.iErrorCode[FD_CLOSE_BIT];
160647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              }
160747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            }
160847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
160947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            uint32 ff = 0;
161047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            int errcode = 0;
161147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            if (wsaEvents.lNetworkEvents & FD_READ)
161247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              ff |= DE_READ;
161347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            if (wsaEvents.lNetworkEvents & FD_WRITE)
161447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              ff |= DE_WRITE;
161547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            if (wsaEvents.lNetworkEvents & FD_CONNECT) {
161647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              if (wsaEvents.iErrorCode[FD_CONNECT_BIT] == 0) {
161747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                ff |= DE_CONNECT;
161847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              } else {
161947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                ff |= DE_CLOSE;
162047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                errcode = wsaEvents.iErrorCode[FD_CONNECT_BIT];
162147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              }
162247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            }
162347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            if (wsaEvents.lNetworkEvents & FD_ACCEPT)
162447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              ff |= DE_ACCEPT;
162547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            if (wsaEvents.lNetworkEvents & FD_CLOSE) {
162647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              ff |= DE_CLOSE;
162747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              errcode = wsaEvents.iErrorCode[FD_CLOSE_BIT];
162847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            }
162947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            if (ff != 0) {
163047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              disp->OnPreEvent(ff);
163147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              disp->OnEvent(ff, errcode);
163247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org            }
163347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          }
163447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        }
163547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        ASSERT(iterators_.back() == &end);
163647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        iterators_.pop_back();
163747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        ASSERT(iterators_.back() == &i);
163847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        iterators_.pop_back();
163947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
164047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
164147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Reset the network event until new activity occurs
164247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      WSAResetEvent(socket_ev_);
164347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
164447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
164547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Break?
164647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!fWait_)
164747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      break;
164847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    cmsElapsed = TimeSince(msStart);
164947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if ((cmsWait != kForever) && (cmsElapsed >= cmsWait)) {
165047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org       break;
165147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
165247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
165347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
165447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Done
165547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
165647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
165747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // WEBRTC_WIN
165847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
165947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}  // namespace rtc
1660