1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/*
2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle
3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2005, Google Inc.
4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without
6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met:
7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  1. Redistributions of source code must retain the above copyright notice,
9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer.
10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  2. Redistributions in binary form must reproduce the above copyright notice,
11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer in the documentation
12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     and/or other materials provided with the distribution.
13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  3. The name of the author may not be used to endorse or promote products
14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     derived from this software without specific prior written permission.
15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */
27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if defined(_MSC_VER) && _MSC_VER < 1300
29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#pragma warning(disable:4786)
30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <cassert>
33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef POSIX
35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <string.h>
36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <errno.h>
37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <fcntl.h>
38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <sys/time.h>
39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <unistd.h>
40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <signal.h>
41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define WIN32_LEAN_AND_MEAN
45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <windows.h>
46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <winsock2.h>
47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <ws2tcpip.h>
48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#undef SetPort
49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <algorithm>
52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <map>
53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/basictypes.h"
55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/byteorder.h"
56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/common.h"
57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h"
58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/nethelpers.h"
59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/physicalsocketserver.h"
60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/time.h"
61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/winping.h"
62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/win32socketinit.h"
63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// stm: this will tell us if we are on OSX
65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef HAVE_CONFIG_H
66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "config.h"
67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef POSIX
70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <netinet/tcp.h>  // for TCP_NODELAY
71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_MTU 14 // Until this is integrated from linux/in.h to netinet/in.h
72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochtypedef void* SockOptArg;
73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // POSIX
74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochtypedef char* SockOptArg;
77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace talk_base {
80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Standard MTUs, from RFC 1191
82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst uint16 PACKET_MAXIMUMS[] = {
83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  65535,    // Theoretical maximum, Hyperchannel
84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  32000,    // Nothing
85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  17914,    // 16Mb IBM Token Ring
86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  8166,     // IEEE 802.4
87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //4464,   // IEEE 802.5 (4Mb max)
88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  4352,     // FDDI
89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //2048,   // Wideband Network
90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  2002,     // IEEE 802.5 (4Mb recommended)
91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //1536,   // Expermental Ethernet Networks
92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //1500,   // Ethernet, Point-to-Point (default)
93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  1492,     // IEEE 802.3
94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  1006,     // SLIP, ARPANET
95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //576,    // X.25 Networks
96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //544,    // DEC IP Portal
97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //512,    // NETBIOS
98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  508,      // IEEE 802/Source-Rt Bridge, ARCNET
99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  296,      // Point-to-Point (low delay)
100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  68,       // Official minimum
101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  0,        // End of list marker
102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst uint32 IP_HEADER_SIZE = 20;
105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst uint32 ICMP_HEADER_SIZE = 8;
106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public:
109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  PhysicalSocket(PhysicalSocketServer* ss, SOCKET s = INVALID_SOCKET)
110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    : ss_(ss), s_(s), enabled_events_(0), error_(0),
111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      state_((s == INVALID_SOCKET) ? CS_CLOSED : CS_CONNECTED),
112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      resolver_(NULL) {
113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // EnsureWinsockInit() ensures that winsock is initialized. The default
115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // version of this function doesn't do anything because winsock is
116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // initialized by constructor of a static object. If neccessary libjingle
117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // users can link it with a different version of this function by replacing
118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // win32socketinit.cc. See win32socketinit.cc for more details.
119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    EnsureWinsockInit();
120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (s_ != INVALID_SOCKET) {
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ = DE_READ | DE_WRITE;
123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      int type = SOCK_STREAM;
125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      socklen_t len = sizeof(type);
126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      VERIFY(0 == getsockopt(s_, SOL_SOCKET, SO_TYPE, (SockOptArg)&type, &len));
127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      udp_ = (SOCK_DGRAM == type);
128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual ~PhysicalSocket() {
132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    Close();
133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Creates the underlying OS socket (same as the "socket" function).
136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual bool Create(int type) {
137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    Close();
138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    s_ = ::socket(AF_INET, type, 0);
139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    udp_ = (SOCK_DGRAM == type);
140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    UpdateLastError();
141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (udp_)
142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ = DE_READ | DE_WRITE;
143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return s_ != INVALID_SOCKET;
144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SocketAddress GetLocalAddress() const {
147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    sockaddr_in addr;
148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    socklen_t addrlen = sizeof(addr);
149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int result = ::getsockname(s_, (sockaddr*)&addr, &addrlen);
150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SocketAddress address;
151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (result >= 0) {
152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ASSERT(addrlen == sizeof(addr));
153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      address.FromSockAddr(addr);
154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket="
156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                      << s_;
157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return address;
159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SocketAddress GetRemoteAddress() const {
162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    sockaddr_in addr;
163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    socklen_t addrlen = sizeof(addr);
164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int result = ::getpeername(s_, (sockaddr*)&addr, &addrlen);
165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SocketAddress address;
166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (result >= 0) {
167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ASSERT(addrlen == sizeof(addr));
168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      address.FromSockAddr(addr);
169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_WARNING) << "GetRemoteAddress: unable to get remote addr, socket="
171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                      << s_;
172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return address;
174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int Bind(const SocketAddress& addr) {
177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    sockaddr_in saddr;
178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    addr.ToSockAddr(&saddr);
179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int err = ::bind(s_, (sockaddr*)&saddr, sizeof(saddr));
180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    UpdateLastError();
181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG
182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (0 == err) {
183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      dbg_addr_ = "Bound @ ";
184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      dbg_addr_.append(GetLocalAddress().ToString());
185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // _DEBUG
187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return err;
188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int Connect(const SocketAddress& addr) {
191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // TODO: Implicit creation is required to reconnect...
192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // ...but should we make it more explicit?
193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if ((s_ == INVALID_SOCKET) && !Create(SOCK_STREAM))
194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return SOCKET_ERROR;
195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (addr.IsUnresolved()) {
196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (state_ != CS_CLOSED) {
197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        SetError(EALREADY);
198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        return SOCKET_ERROR;
199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_VERBOSE) << "Resolving addr in PhysicalSocket::Connect";
202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      resolver_ = new AsyncResolver();
203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      resolver_->set_address(addr);
204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      resolver_->SignalWorkDone.connect(this, &PhysicalSocket::OnResolveResult);
205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      resolver_->Start();
206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      state_ = CS_CONNECTING;
207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return 0;
208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return DoConnect(addr);
211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int DoConnect(const SocketAddress& addr) {
214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    sockaddr_in saddr;
215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    addr.ToSockAddr(&saddr);
216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int err = ::connect(s_, (sockaddr*)&saddr, sizeof(saddr));
217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    UpdateLastError();
218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (err == 0) {
219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      state_ = CS_CONNECTED;
220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else if (IsBlockingError(error_)) {
221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      state_ = CS_CONNECTING;
222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ |= DE_CONNECT;
223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return SOCKET_ERROR;
225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    enabled_events_ |= DE_READ | DE_WRITE;
228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int GetError() const {
232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return error_;
233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  void SetError(int error) {
236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    error_ = error;
237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ConnState GetState() const {
240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return state_;
241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int GetOption(Option opt, int* value) {
244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int slevel;
245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int sopt;
246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (TranslateOption(opt, &slevel, &sopt) == -1)
247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return -1;
248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    socklen_t optlen = sizeof(*value);
249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int ret = ::getsockopt(s_, slevel, sopt, (SockOptArg)value, &optlen);
250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (ret != -1 && opt == OPT_DONTFRAGMENT) {
251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef LINUX
252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      *value = (*value != IP_PMTUDISC_DONT) ? 1 : 0;
253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return ret;
256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int SetOption(Option opt, int value) {
259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int slevel;
260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int sopt;
261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (TranslateOption(opt, &slevel, &sopt) == -1)
262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return -1;
263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (opt == OPT_DONTFRAGMENT) {
264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef LINUX
265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      value = (value) ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return ::setsockopt(s_, slevel, sopt, (SockOptArg)&value, sizeof(value));
269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int Send(const void *pv, size_t cb) {
272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int sent = ::send(s_, reinterpret_cast<const char *>(pv), (int)cb,
273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef LINUX
274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // Suppress SIGPIPE. Without this, attempting to send on a socket whose
275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // other end is closed will result in a SIGPIPE signal being raised to
276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // our process, which by default will terminate the process, which we
277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // don't want. By specifying this flag, we'll just get the error EPIPE
278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // instead and can handle the error gracefully.
279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        MSG_NOSIGNAL
280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else
281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        0
282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        );
284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    UpdateLastError();
285dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // We have seen minidumps where this may be false.
286dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ASSERT(sent <= static_cast<int>(cb));
287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if ((sent < 0) && IsBlockingError(error_)) {
288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ |= DE_WRITE;
289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return sent;
291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int SendTo(const void *pv, size_t cb, const SocketAddress& addr) {
294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    sockaddr_in saddr;
295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    addr.ToSockAddr(&saddr);
296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int sent = ::sendto(
297f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        s_, (const char *)pv, (int)cb,
298f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef LINUX
299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // Suppress SIGPIPE. See above for explanation.
300f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        MSG_NOSIGNAL,
301f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else
302f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        0,
303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
304f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        (sockaddr*)&saddr, sizeof(saddr));
305f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    UpdateLastError();
306dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // We have seen minidumps where this may be false.
307dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ASSERT(sent <= static_cast<int>(cb));
308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if ((sent < 0) && IsBlockingError(error_)) {
309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ |= DE_WRITE;
310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
311f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return sent;
312f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
313f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
314f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int Recv(void *pv, size_t cb) {
315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int received = ::recv(s_, (char *)pv, (int)cb, 0);
316f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if ((received == 0) && (cb != 0)) {
317f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // Note: on graceful shutdown, recv can return 0.  In this case, we
318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // pretend it is blocking, and then signal close, so that simplifying
319f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // assumptions can be made about Recv.
320f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_WARNING) << "EOF from socket; deferring close event";
321f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // Must turn this back on so that the select() loop will notice the close
322f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // event.
323dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ |= DE_READ;
324f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      error_ = EWOULDBLOCK;
325f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return SOCKET_ERROR;
326f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
327f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    UpdateLastError();
328f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    bool success = (received >= 0) || IsBlockingError(error_);
329f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (udp_ || success) {
330dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ |= DE_READ;
331f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
332f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!success) {
333f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG_F(LS_VERBOSE) << "Error = " << error_;
334f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
335f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return received;
336f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
337f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
338f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int RecvFrom(void *pv, size_t cb, SocketAddress *paddr) {
339f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    sockaddr_in saddr;
340f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    socklen_t cbAddr = sizeof(saddr);
341f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int received = ::recvfrom(s_, (char *)pv, (int)cb, 0, (sockaddr*)&saddr,
342f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                              &cbAddr);
343f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    UpdateLastError();
344f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if ((received >= 0) && (paddr != NULL))
345f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      paddr->FromSockAddr(saddr);
346f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    bool success = (received >= 0) || IsBlockingError(error_);
347f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (udp_ || success) {
348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ |= DE_READ;
349f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
350f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!success) {
351f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG_F(LS_VERBOSE) << "Error = " << error_;
352f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
353f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return received;
354f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
355f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
356f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int Listen(int backlog) {
357f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int err = ::listen(s_, backlog);
358f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    UpdateLastError();
359f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (err == 0) {
360f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      state_ = CS_CONNECTING;
361dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ |= DE_ACCEPT;
362f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG
363f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      dbg_addr_ = "Listening @ ";
364f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      dbg_addr_.append(GetLocalAddress().ToString());
365f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // _DEBUG
366f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
367f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return err;
368f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
369f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
370f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  AsyncSocket* Accept(SocketAddress *paddr) {
371f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    sockaddr_in saddr;
372f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    socklen_t cbAddr = sizeof(saddr);
373f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SOCKET s = ::accept(s_, (sockaddr*)&saddr, &cbAddr);
374f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    UpdateLastError();
375f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (s == INVALID_SOCKET)
376f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return NULL;
377dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    enabled_events_ |= DE_ACCEPT;
378f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (paddr != NULL)
379f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      paddr->FromSockAddr(saddr);
380f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return ss_->WrapSocket(s);
381f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
382f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
383f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int Close() {
384f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (s_ == INVALID_SOCKET)
385f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return 0;
386f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int err = ::closesocket(s_);
387f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    UpdateLastError();
388f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    s_ = INVALID_SOCKET;
389f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    state_ = CS_CLOSED;
390f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    enabled_events_ = 0;
391f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (resolver_) {
392f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      resolver_->Destroy(false);
393f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      resolver_ = NULL;
394f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
395f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return err;
396f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
397f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
398f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int EstimateMTU(uint16* mtu) {
399f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SocketAddress addr = GetRemoteAddress();
400f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (addr.IsAny()) {
401f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      error_ = ENOTCONN;
402f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return -1;
403f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
404f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
405f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if defined(WIN32)
406f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Gets the interface MTU (TTL=1) for the interface used to reach |addr|.
407f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    WinPing ping;
408f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!ping.IsValid()) {
409f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      error_ = EINVAL; // can't think of a better error ID
410f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return -1;
411f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
412f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
413f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) {
414f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      int32 size = PACKET_MAXIMUMS[level] - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
415f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      WinPing::PingResult result = ping.Ping(addr.ip(), size, 0, 1, false);
416f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (result == WinPing::PING_FAIL) {
417f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        error_ = EINVAL; // can't think of a better error ID
418f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        return -1;
419f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else if (result != WinPing::PING_TOO_LARGE) {
420f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        *mtu = PACKET_MAXIMUMS[level];
421f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        return 0;
422f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
423f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
424f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
425f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ASSERT(false);
426f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return -1;
427dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#elif defined(IOS) || defined(OSX)
428f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // No simple way to do this on Mac OS X.
429f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // SIOCGIFMTU would work if we knew which interface would be used, but
430f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // figuring that out is pretty complicated. For now we'll return an error
431f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // and let the caller pick a default MTU.
432f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    error_ = EINVAL;
433f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return -1;
434dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#elif defined(LINUX) || defined(ANDROID)
435f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Gets the path MTU.
436f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int value;
437f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    socklen_t vlen = sizeof(value);
438f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int err = getsockopt(s_, IPPROTO_IP, IP_MTU, &value, &vlen);
439f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (err < 0) {
440f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      UpdateLastError();
441f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return err;
442f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
443f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
444f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ASSERT((0 <= value) && (value <= 65536));
445f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    *mtu = value;
446f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
447f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
448f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
449f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
450f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SocketServer* socketserver() { return ss_; }
451f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
452f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch protected:
453f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  void OnResolveResult(SignalThread* thread) {
454f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (thread != resolver_) {
455f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return;
456f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
457f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
458f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int error = resolver_->error();
459f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (error == 0) {
460f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      error = DoConnect(resolver_->address());
461f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
462f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      Close();
463f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
464f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
465f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (error) {
466f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      error_ = error;
467f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SignalCloseEvent(this, error_);
468f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
469f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
470f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
471f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  void UpdateLastError() {
472f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    error_ = LAST_SYSTEM_ERROR;
473f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
474f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
475f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static int TranslateOption(Option opt, int* slevel, int* sopt) {
476f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    switch (opt) {
477f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      case OPT_DONTFRAGMENT:
478f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
479f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        *slevel = IPPROTO_IP;
480f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        *sopt = IP_DONTFRAGMENT;
481f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        break;
482dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#elif defined(IOS) || defined(OSX) || defined(BSD)
483f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        LOG(LS_WARNING) << "Socket::OPT_DONTFRAGMENT not supported.";
484f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        return -1;
485f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#elif defined(POSIX)
486f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        *slevel = IPPROTO_IP;
487f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        *sopt = IP_MTU_DISCOVER;
488f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        break;
489f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
490f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      case OPT_RCVBUF:
491f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        *slevel = SOL_SOCKET;
492f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        *sopt = SO_RCVBUF;
493f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        break;
494f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      case OPT_SNDBUF:
495f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        *slevel = SOL_SOCKET;
496f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        *sopt = SO_SNDBUF;
497f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        break;
498f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      case OPT_NODELAY:
499f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        *slevel = IPPROTO_TCP;
500f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        *sopt = TCP_NODELAY;
501f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        break;
502f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      default:
503f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        ASSERT(false);
504f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        return -1;
505f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
506f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
507f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
508f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
509f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  PhysicalSocketServer* ss_;
510f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SOCKET s_;
511f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  uint8 enabled_events_;
512f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool udp_;
513f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int error_;
514f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ConnState state_;
515f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  AsyncResolver* resolver_;
516f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
517f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG
518f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string dbg_addr_;
519f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // _DEBUG;
520f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
521f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
522f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef POSIX
523f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass EventDispatcher : public Dispatcher {
524f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public:
525f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  EventDispatcher(PhysicalSocketServer* ss) : ss_(ss), fSignaled_(false) {
526f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (pipe(afd_) < 0)
527f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LERROR) << "pipe failed";
528f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ss_->Add(this);
529f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
530f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
531f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual ~EventDispatcher() {
532f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ss_->Remove(this);
533f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    close(afd_[0]);
534f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    close(afd_[1]);
535f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
536f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
537f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void Signal() {
538f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    CritScope cs(&crit_);
539f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!fSignaled_) {
540f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      const uint8 b[1] = { 0 };
541f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (VERIFY(1 == write(afd_[1], b, sizeof(b)))) {
542f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        fSignaled_ = true;
543f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
544f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
545f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
546f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
547f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual uint32 GetRequestedEvents() {
548dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return DE_READ;
549f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
550f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
551f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void OnPreEvent(uint32 ff) {
552f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // It is not possible to perfectly emulate an auto-resetting event with
553f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // pipes.  This simulates it by resetting before the event is handled.
554f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
555f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    CritScope cs(&crit_);
556f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (fSignaled_) {
557f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      uint8 b[4];  // Allow for reading more than 1 byte, but expect 1.
558f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      VERIFY(1 == read(afd_[0], b, sizeof(b)));
559f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      fSignaled_ = false;
560f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
561f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
562f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
563f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void OnEvent(uint32 ff, int err) {
564f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ASSERT(false);
565f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
566f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
567f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual int GetDescriptor() {
568f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return afd_[0];
569f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
570f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
571f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual bool IsDescriptorClosed() {
572f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
573f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
574f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
575f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch private:
576f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  PhysicalSocketServer *ss_;
577f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int afd_[2];
578f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool fSignaled_;
579f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CriticalSection crit_;
580f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
581f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
582dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// These two classes use the self-pipe trick to deliver POSIX signals to our
583dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// select loop. This is the only safe, reliable, cross-platform way to do
584dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// non-trivial things with a POSIX signal in an event-driven program (until
585dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// proper pselect() implementations become ubiquitous).
586dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
587dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass PosixSignalHandler {
588f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public:
589dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // POSIX only specifies 32 signals, but in principle the system might have
590dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // more and the programmer might choose to use them, so we size our array
591dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // for 128.
592dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static const int kNumPosixSignals = 128;
593f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
594dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static PosixSignalHandler *Instance() { return &instance_; }
595f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
596dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Returns true if the given signal number is set.
597dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool IsSignalSet(int signum) const {
598dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ASSERT(signum < ARRAY_SIZE(received_signal_));
599dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (signum < ARRAY_SIZE(received_signal_)) {
600dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return received_signal_[signum];
601dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else {
602dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return false;
603f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
604f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
605f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
606dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Clears the given signal number.
607dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void ClearSignal(int signum) {
608dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ASSERT(signum < ARRAY_SIZE(received_signal_));
609dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (signum < ARRAY_SIZE(received_signal_)) {
610dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      received_signal_[signum] = false;
611f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
612f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
613f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
614dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Returns the file descriptor to monitor for signal events.
615dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int GetDescriptor() const {
616f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return afd_[0];
617f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
618f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
619f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // This is called directly from our real signal handler, so it must be
620f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // signal-handler-safe. That means it cannot assume anything about the
621f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // user-level state of the process, since the handler could be executed at any
622f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // time on any thread.
623f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  void OnPosixSignalReceived(int signum) {
624f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (signum >= ARRAY_SIZE(received_signal_)) {
625f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // We don't have space in our array for this.
626f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return;
627f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
628f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Set a flag saying we've seen this signal.
629f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    received_signal_[signum] = true;
630dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Notify application code that we got a signal.
631f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    const uint8 b[1] = { 0 };
632f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (-1 == write(afd_[1], b, sizeof(b))) {
633f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // Nothing we can do here. If there's an error somehow then there's
634f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // nothing we can safely do from a signal handler.
635f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // No, we can't even safely log it.
636f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // But, we still have to check the return value here. Otherwise,
637f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // GCC 4.4.1 complains ignoring return value. Even (void) doesn't help.
638f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return;
639f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
640f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
641f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
642f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch private:
643dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  PosixSignalHandler() {
644f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (pipe(afd_) < 0) {
645f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG_ERR(LS_ERROR) << "pipe failed";
646f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return;
647f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
648f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (fcntl(afd_[0], F_SETFL, O_NONBLOCK) < 0) {
649f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG_ERR(LS_WARNING) << "fcntl #1 failed";
650f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
651f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (fcntl(afd_[1], F_SETFL, O_NONBLOCK) < 0) {
652f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG_ERR(LS_WARNING) << "fcntl #2 failed";
653f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
654f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    memset(const_cast<void *>(static_cast<volatile void *>(received_signal_)),
655f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch           0,
656f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch           sizeof(received_signal_));
657f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
658f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
659dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ~PosixSignalHandler() {
660dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int fd1 = afd_[0];
661dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int fd2 = afd_[1];
662dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // We clobber the stored file descriptor numbers here or else in principle
663dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // a signal that happens to be delivered during application termination
664dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // could erroneously write a zero byte to an unrelated file handle in
665dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // OnPosixSignalReceived() if some other file happens to be opened later
666dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // during shutdown and happens to be given the same file descriptor number
667dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // as our pipe had. Unfortunately even with this precaution there is still a
668dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // race where that could occur if said signal happens to be handled
669dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // concurrently with this code and happens to have already read the value of
670dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // afd_[1] from memory before we clobber it, but that's unlikely.
671dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    afd_[0] = -1;
672dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    afd_[1] = -1;
673dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    close(fd1);
674dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    close(fd2);
675dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
676dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
677dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // There is just a single global instance. (Signal handlers do not get any
678dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // sort of user-defined void * parameter, so they can't access anything that
679dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // isn't global.)
680dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static PosixSignalHandler instance_;
681dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
682f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int afd_[2];
683f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // These are boolean flags that will be set in our signal handler and read
684f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // and cleared from Wait(). There is a race involved in this, but it is
685f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // benign. The signal handler sets the flag before signaling the pipe, so
686f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // we'll never end up blocking in select() while a flag is still true.
687f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // However, if two of the same signal arrive close to each other then it's
688f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // possible that the second time the handler may set the flag while it's still
689f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // true, meaning that signal will be missed. But the first occurrence of it
690f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // will still be handled, so this isn't a problem.
691f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Volatile is not necessary here for correctness, but this data _is_ volatile
692f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // so I've marked it as such.
693f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  volatile uint8 received_signal_[kNumPosixSignals];
694dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
695dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
696dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenPosixSignalHandler PosixSignalHandler::instance_;
697dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
698dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass PosixSignalDispatcher : public Dispatcher {
699dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen public:
700dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  PosixSignalDispatcher(PhysicalSocketServer *owner) : owner_(owner) {
701dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    owner_->Add(this);
702dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
703dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
704dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual ~PosixSignalDispatcher() {
705dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    owner_->Remove(this);
706dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
707dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
708dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual uint32 GetRequestedEvents() {
709dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return DE_READ;
710dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
711dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
712dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual void OnPreEvent(uint32 ff) {
713dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Events might get grouped if signals come very fast, so we read out up to
714dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // 16 bytes to make sure we keep the pipe empty.
715dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    uint8 b[16];
716dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ssize_t ret = read(GetDescriptor(), b, sizeof(b));
717dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (ret < 0) {
718dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      LOG_ERR(LS_WARNING) << "Error in read()";
719dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else if (ret == 0) {
720dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      LOG(LS_WARNING) << "Should have read at least one byte";
721dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
722dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
723dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
724dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual void OnEvent(uint32 ff, int err) {
725dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    for (int signum = 0; signum < PosixSignalHandler::kNumPosixSignals;
726dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen         ++signum) {
727dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (PosixSignalHandler::Instance()->IsSignalSet(signum)) {
728dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        PosixSignalHandler::Instance()->ClearSignal(signum);
729dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        HandlerMap::iterator i = handlers_.find(signum);
730dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        if (i == handlers_.end()) {
731dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          // This can happen if a signal is delivered to our process at around
732dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          // the same time as we unset our handler for it. It is not an error
733dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          // condition, but it's unusual enough to be worth logging.
734dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          LOG(LS_INFO) << "Received signal with no handler: " << signum;
735dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        } else {
736dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          // Otherwise, execute our handler.
737dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          (*i->second)(signum);
738dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        }
739dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
740dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
741dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
742dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
743dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual int GetDescriptor() {
744dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return PosixSignalHandler::Instance()->GetDescriptor();
745dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
746dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
747dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual bool IsDescriptorClosed() {
748dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return false;
749dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
750dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
751dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void SetHandler(int signum, void (*handler)(int)) {
752dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    handlers_[signum] = handler;
753dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
754dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
755dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void ClearHandler(int signum) {
756dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    handlers_.erase(signum);
757dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
758dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
759dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool HasHandlers() {
760dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return !handlers_.empty();
761dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
762dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
763dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen private:
764dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  typedef std::map<int, void (*)(int)> HandlerMap;
765dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
766dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HandlerMap handlers_;
767f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Our owner.
768f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  PhysicalSocketServer *owner_;
769f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
770f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
771f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass SocketDispatcher : public Dispatcher, public PhysicalSocket {
772f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public:
773f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  explicit SocketDispatcher(PhysicalSocketServer *ss) : PhysicalSocket(ss) {
774f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
775f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SocketDispatcher(SOCKET s, PhysicalSocketServer *ss) : PhysicalSocket(ss, s) {
776f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
777f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
778f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual ~SocketDispatcher() {
779f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    Close();
780f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
781f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
782f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool Initialize() {
783f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ss_->Add(this);
784f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK);
785f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return true;
786f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
787f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
788f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual bool Create(int type) {
789f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Change the socket to be non-blocking.
790f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!PhysicalSocket::Create(type))
791f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
792f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
793f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return Initialize();
794f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
795f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
796f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual int GetDescriptor() {
797f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return s_;
798f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
799f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
800f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual bool IsDescriptorClosed() {
801f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // We don't have a reliable way of distinguishing end-of-stream
802f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // from readability.  So test on each readable call.  Is this
803f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // inefficient?  Probably.
804f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    char ch;
805f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ssize_t res = ::recv(s_, &ch, 1, MSG_PEEK);
806f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (res > 0) {
807f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // Data available, so not closed.
808f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
809f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else if (res == 0) {
810f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // EOF, so closed.
811f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return true;
812f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {  // error
813f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      switch (errno) {
814f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // Returned if we've already closed s_.
815f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        case EBADF:
816f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // Returned during ungraceful peer shutdown.
817f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        case ECONNRESET:
818f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          return true;
819f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        default:
820f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // Assume that all other errors are just blocking errors, meaning the
821f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // connection is still good but we just can't read from it right now.
822f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // This should only happen when connecting (and at most once), because
823f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // in all other cases this function is only called if the file
824f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // descriptor is already known to be in the readable state. However,
825f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // it's not necessary a problem if we spuriously interpret a
826f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // "connection lost"-type error as a blocking error, because typically
827f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // the next recv() will get EOF, so we'll still eventually notice that
828f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // the socket is closed.
829f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          LOG_ERR(LS_WARNING) << "Assuming benign blocking error";
830f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          return false;
831f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
832f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
833f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
834f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
835f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual uint32 GetRequestedEvents() {
836f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return enabled_events_;
837f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
838f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
839f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void OnPreEvent(uint32 ff) {
840dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if ((ff & DE_CONNECT) != 0)
841f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      state_ = CS_CONNECTED;
842dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if ((ff & DE_CLOSE) != 0)
843f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      state_ = CS_CLOSED;
844f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
845f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
846f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void OnEvent(uint32 ff, int err) {
847dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if ((ff & DE_READ) != 0) {
848dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ &= ~DE_READ;
849f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SignalReadEvent(this);
850f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
851dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if ((ff & DE_WRITE) != 0) {
852dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ &= ~DE_WRITE;
853f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SignalWriteEvent(this);
854f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
855dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if ((ff & DE_CONNECT) != 0) {
856dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ &= ~DE_CONNECT;
857f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SignalConnectEvent(this);
858f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
859dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if ((ff & DE_ACCEPT) != 0) {
860dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ &= ~DE_ACCEPT;
861f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SignalReadEvent(this);
862f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
863dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if ((ff & DE_CLOSE) != 0) {
864f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // The socket is now dead to us, so stop checking it.
865f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      enabled_events_ = 0;
866f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SignalCloseEvent(this, err);
867f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
868f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
869f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
870f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual int Close() {
871f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (s_ == INVALID_SOCKET)
872f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return 0;
873f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
874f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ss_->Remove(this);
875f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return PhysicalSocket::Close();
876f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
877f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
878f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
879f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass FileDispatcher: public Dispatcher, public AsyncFile {
880f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public:
881f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  FileDispatcher(int fd, PhysicalSocketServer *ss) : ss_(ss), fd_(fd) {
882f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    set_readable(true);
883f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
884f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ss_->Add(this);
885f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
886f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    fcntl(fd_, F_SETFL, fcntl(fd_, F_GETFL, 0) | O_NONBLOCK);
887f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
888f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
889f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual ~FileDispatcher() {
890f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ss_->Remove(this);
891f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
892f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
893f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SocketServer* socketserver() { return ss_; }
894f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
895f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual int GetDescriptor() {
896f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return fd_;
897f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
898f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
899f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual bool IsDescriptorClosed() {
900f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
901f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
902f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
903f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual uint32 GetRequestedEvents() {
904f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return flags_;
905f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
906f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
907f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void OnPreEvent(uint32 ff) {
908f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
909f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
910f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void OnEvent(uint32 ff, int err) {
911dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if ((ff & DE_READ) != 0)
912f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SignalReadEvent(this);
913dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if ((ff & DE_WRITE) != 0)
914f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SignalWriteEvent(this);
915dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if ((ff & DE_CLOSE) != 0)
916f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SignalCloseEvent(this, err);
917f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
918f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
919f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual bool readable() {
920dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return (flags_ & DE_READ) != 0;
921f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
922f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
923f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void set_readable(bool value) {
924dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    flags_ = value ? (flags_ | DE_READ) : (flags_ & ~DE_READ);
925f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
926f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
927f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual bool writable() {
928dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return (flags_ & DE_WRITE) != 0;
929f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
930f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
931f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void set_writable(bool value) {
932dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    flags_ = value ? (flags_ | DE_WRITE) : (flags_ & ~DE_WRITE);
933f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
934f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
935f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch private:
936f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  PhysicalSocketServer* ss_;
937f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int fd_;
938f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int flags_;
939f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
940f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
941f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochAsyncFile* PhysicalSocketServer::CreateFile(int fd) {
942f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return new FileDispatcher(fd, this);
943f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
944f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
945f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif // POSIX
946f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
947f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
948f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic uint32 FlagsToEvents(uint32 events) {
949f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  uint32 ffFD = FD_CLOSE;
950dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (events & DE_READ)
951f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ffFD |= FD_READ;
952dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (events & DE_WRITE)
953f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ffFD |= FD_WRITE;
954dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (events & DE_CONNECT)
955f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ffFD |= FD_CONNECT;
956dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (events & DE_ACCEPT)
957f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ffFD |= FD_ACCEPT;
958f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ffFD;
959f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
960f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
961f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass EventDispatcher : public Dispatcher {
962f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public:
963f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  EventDispatcher(PhysicalSocketServer *ss) : ss_(ss) {
964f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    hev_ = WSACreateEvent();
965f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (hev_) {
966f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ss_->Add(this);
967f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
968f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
969f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
970f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ~EventDispatcher() {
971f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (hev_ != NULL) {
972f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ss_->Remove(this);
973f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      WSACloseEvent(hev_);
974f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      hev_ = NULL;
975f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
976f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
977f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
978f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void Signal() {
979f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (hev_ != NULL)
980f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      WSASetEvent(hev_);
981f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
982f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
983f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual uint32 GetRequestedEvents() {
984f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
985f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
986f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
987f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void OnPreEvent(uint32 ff) {
988f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    WSAResetEvent(hev_);
989f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
990f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
991f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void OnEvent(uint32 ff, int err) {
992f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
993f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
994f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual WSAEVENT GetWSAEvent() {
995f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return hev_;
996f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
997f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
998f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual SOCKET GetSocket() {
999f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return INVALID_SOCKET;
1000f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1001f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1002f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual bool CheckSignalClose() { return false; }
1003f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1004f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochprivate:
1005f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  PhysicalSocketServer* ss_;
1006f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  WSAEVENT hev_;
1007f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
1008f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1009f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass SocketDispatcher : public Dispatcher, public PhysicalSocket {
1010f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public:
1011f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static int next_id_;
1012f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int id_;
1013f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool signal_close_;
1014f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int signal_err_;
1015f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1016dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SocketDispatcher(PhysicalSocketServer* ss)
1017dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      : PhysicalSocket(ss),
1018dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        id_(0),
1019dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        signal_close_(false) {
1020f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1021dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1022dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SocketDispatcher(SOCKET s, PhysicalSocketServer* ss)
1023dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      : PhysicalSocket(ss, s),
1024dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        id_(0),
1025dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        signal_close_(false) {
1026f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1027f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1028f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual ~SocketDispatcher() {
1029f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    Close();
1030f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1031f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1032f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool Initialize() {
1033f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ASSERT(s_ != INVALID_SOCKET);
1034f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Must be a non-blocking
1035f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    u_long argp = 1;
1036f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ioctlsocket(s_, FIONBIO, &argp);
1037f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ss_->Add(this);
1038f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return true;
1039f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1040f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1041f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual bool Create(int type) {
1042f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Create socket
1043f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!PhysicalSocket::Create(type))
1044f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
1045f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1046f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!Initialize())
1047f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
1048f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1049f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    do { id_ = ++next_id_; } while (id_ == 0);
1050f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return true;
1051f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1052f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1053f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual int Close() {
1054f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (s_ == INVALID_SOCKET)
1055f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return 0;
1056f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1057f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    id_ = 0;
1058f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    signal_close_ = false;
1059f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ss_->Remove(this);
1060f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return PhysicalSocket::Close();
1061f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1062f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1063f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual uint32 GetRequestedEvents() {
1064f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return enabled_events_;
1065f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1066f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1067f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void OnPreEvent(uint32 ff) {
1068dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if ((ff & DE_CONNECT) != 0)
1069f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      state_ = CS_CONNECTED;
1070f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // We set CS_CLOSED from CheckSignalClose.
1071f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1072f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1073f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void OnEvent(uint32 ff, int err) {
1074f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int cache_id = id_;
1075dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if ((ff & DE_READ) != 0) {
1076dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ &= ~DE_READ;
1077f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SignalReadEvent(this);
1078f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1079dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (((ff & DE_WRITE) != 0) && (id_ == cache_id)) {
1080dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ &= ~DE_WRITE;
1081f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SignalWriteEvent(this);
1082f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1083dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (((ff & DE_CONNECT) != 0) && (id_ == cache_id)) {
1084dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (ff != DE_CONNECT)
1085dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        LOG(LS_VERBOSE) << "Signalled with DE_CONNECT: " << ff;
1086dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ &= ~DE_CONNECT;
1087f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG
1088f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      dbg_addr_ = "Connected @ ";
1089f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      dbg_addr_.append(GetRemoteAddress().ToString());
1090f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // _DEBUG
1091f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SignalConnectEvent(this);
1092f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1093dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (((ff & DE_ACCEPT) != 0) && (id_ == cache_id)) {
1094dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      enabled_events_ &= ~DE_ACCEPT;
1095f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SignalReadEvent(this);
1096f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1097dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (((ff & DE_CLOSE) != 0) && (id_ == cache_id)) {
1098f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      signal_close_ = true;
1099f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      signal_err_ = err;
1100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual WSAEVENT GetWSAEvent() {
1104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return WSA_INVALID_EVENT;
1105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual SOCKET GetSocket() {
1108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return s_;
1109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual bool CheckSignalClose() {
1112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!signal_close_)
1113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
1114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    char ch;
1116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (recv(s_, &ch, 1, MSG_PEEK) > 0)
1117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
1118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    state_ = CS_CLOSED;
1120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    signal_close_ = false;
1121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SignalCloseEvent(this, signal_err_);
1122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return true;
1123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
1125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint SocketDispatcher::next_id_ = 0;
1127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // WIN32
1129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Sets the value of a boolean value to false when signaled.
1131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass Signaler : public EventDispatcher {
1132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public:
1133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Signaler(PhysicalSocketServer* ss, bool* pf)
1134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      : EventDispatcher(ss), pf_(pf) {
1135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual ~Signaler() { }
1137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  void OnEvent(uint32 ff, int err) {
1139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (pf_)
1140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      *pf_ = false;
1141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch private:
1144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool *pf_;
1145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
1146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochPhysicalSocketServer::PhysicalSocketServer()
1148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    : fWait_(false),
1149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      last_tick_tracked_(0),
1150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      last_tick_dispatch_count_(0) {
1151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  signal_wakeup_ = new Signaler(this, &fWait_);
1152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
1153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  socket_ev_ = WSACreateEvent();
1154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
1155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochPhysicalSocketServer::~PhysicalSocketServer() {
1158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
1159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  WSACloseEvent(socket_ev_);
1160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
1161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef POSIX
1162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  signal_dispatcher_.reset();
1163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
1164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  delete signal_wakeup_;
1165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(dispatchers_.empty());
1166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid PhysicalSocketServer::WakeUp() {
1169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  signal_wakeup_->Signal();
1170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSocket* PhysicalSocketServer::CreateSocket(int type) {
1173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  PhysicalSocket* socket = new PhysicalSocket(this);
1174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (socket->Create(type)) {
1175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return socket;
1176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
1177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    delete socket;
1178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
1179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochAsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int type) {
1183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SocketDispatcher* dispatcher = new SocketDispatcher(this);
1184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (dispatcher->Create(type)) {
1185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return dispatcher;
1186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
1187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    delete dispatcher;
1188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
1189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochAsyncSocket* PhysicalSocketServer::WrapSocket(SOCKET s) {
1193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SocketDispatcher* dispatcher = new SocketDispatcher(s, this);
1194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (dispatcher->Initialize()) {
1195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return dispatcher;
1196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
1197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    delete dispatcher;
1198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
1199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid PhysicalSocketServer::Add(Dispatcher *pdispatcher) {
1203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CritScope cs(&crit_);
1204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Prevent duplicates. This can cause dead dispatchers to stick around.
1205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DispatcherList::iterator pos = std::find(dispatchers_.begin(),
1206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                           dispatchers_.end(),
1207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                           pdispatcher);
1208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (pos != dispatchers_.end())
1209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
1210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  dispatchers_.push_back(pdispatcher);
1211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid PhysicalSocketServer::Remove(Dispatcher *pdispatcher) {
1214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CritScope cs(&crit_);
1215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DispatcherList::iterator pos = std::find(dispatchers_.begin(),
1216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                           dispatchers_.end(),
1217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                           pdispatcher);
1218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(pos != dispatchers_.end());
1219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  size_t index = pos - dispatchers_.begin();
1220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  dispatchers_.erase(pos);
1221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (IteratorList::iterator it = iterators_.begin(); it != iterators_.end();
1222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch       ++it) {
1223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (index < **it) {
1224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      --**it;
1225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef POSIX
1230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
1231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Calculate timing information
1232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  struct timeval *ptvWait = NULL;
1234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  struct timeval tvWait;
1235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  struct timeval tvStop;
1236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (cmsWait != kForever) {
1237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Calculate wait timeval
1238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    tvWait.tv_sec = cmsWait / 1000;
1239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    tvWait.tv_usec = (cmsWait % 1000) * 1000;
1240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ptvWait = &tvWait;
1241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Calculate when to return in a timeval
1243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    gettimeofday(&tvStop, NULL);
1244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    tvStop.tv_sec += tvWait.tv_sec;
1245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    tvStop.tv_usec += tvWait.tv_usec;
1246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (tvStop.tv_usec >= 1000000) {
1247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      tvStop.tv_usec -= 1000000;
1248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      tvStop.tv_sec += 1;
1249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Zero all fd_sets. Don't need to do this inside the loop since
1253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // select() zeros the descriptors not signaled
1254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  fd_set fdsRead;
1256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  FD_ZERO(&fdsRead);
1257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  fd_set fdsWrite;
1258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  FD_ZERO(&fdsWrite);
1259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  fWait_ = true;
1261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  while (fWait_) {
1263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int fdmax = -1;
1264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    {
1265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      CritScope cr(&crit_);
1266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      for (size_t i = 0; i < dispatchers_.size(); ++i) {
1267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // Query dispatchers for read and write wait state
1268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        Dispatcher *pdispatcher = dispatchers_[i];
1269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        ASSERT(pdispatcher);
1270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (!process_io && (pdispatcher != signal_wakeup_))
1271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          continue;
1272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        int fd = pdispatcher->GetDescriptor();
1273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (fd > fdmax)
1274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          fdmax = fd;
1275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        uint32 ff = pdispatcher->GetRequestedEvents();
1277dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        if (ff & (DE_READ | DE_ACCEPT))
1278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          FD_SET(fd, &fdsRead);
1279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        if (ff & (DE_WRITE | DE_CONNECT))
1280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          FD_SET(fd, &fdsWrite);
1281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
1282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Wait then call handlers as appropriate
1285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // < 0 means error
1286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // 0 means timeout
1287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // > 0 means count of descriptors ready
1288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int n = select(fdmax + 1, &fdsRead, &fdsWrite, NULL, ptvWait);
1289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // If error, return error.
1291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (n < 0) {
1292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (errno != EINTR) {
1293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        LOG_E(LS_ERROR, EN, errno) << "select";
1294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        return false;
1295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
1296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // Else ignore the error and keep going. If this EINTR was for one of the
1297f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // signals managed by this PhysicalSocketServer, the
1298f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // PosixSignalDeliveryDispatcher will be in the signaled state in the next
1299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // iteration.
1300f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else if (n == 0) {
1301f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // If timeout, return success
1302f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return true;
1303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
1304f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // We have signaled descriptors
1305f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      CritScope cr(&crit_);
1306f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      for (size_t i = 0; i < dispatchers_.size(); ++i) {
1307f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        Dispatcher *pdispatcher = dispatchers_[i];
1308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        int fd = pdispatcher->GetDescriptor();
1309f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        uint32 ff = 0;
1310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        int errcode = 0;
1311f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1312f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // Reap any error code, which can be signaled through reads or writes.
1313731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        // TODO: Should we set errcode if getsockopt fails?
1314f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (FD_ISSET(fd, &fdsRead) || FD_ISSET(fd, &fdsWrite)) {
1315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          socklen_t len = sizeof(errcode);
1316f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          ::getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &len);
1317f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        }
1318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1319f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // Check readable descriptors. If we're waiting on an accept, signal
1320f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // that. Otherwise we're waiting for data, check to see if we're
1321f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // readable or really closed.
1322731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        // TODO: Only peek at TCP descriptors.
1323f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (FD_ISSET(fd, &fdsRead)) {
1324f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          FD_CLR(fd, &fdsRead);
1325dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          if (pdispatcher->GetRequestedEvents() & DE_ACCEPT) {
1326dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            ff |= DE_ACCEPT;
1327f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          } else if (errcode || pdispatcher->IsDescriptorClosed()) {
1328dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            ff |= DE_CLOSE;
1329f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          } else {
1330dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            ff |= DE_READ;
1331f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          }
1332f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        }
1333f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1334f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // Check writable descriptors. If we're waiting on a connect, detect
1335f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // success versus failure by the reaped error code.
1336f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (FD_ISSET(fd, &fdsWrite)) {
1337f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          FD_CLR(fd, &fdsWrite);
1338dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          if (pdispatcher->GetRequestedEvents() & DE_CONNECT) {
1339f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            if (!errcode) {
1340dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              ff |= DE_CONNECT;
1341f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            } else {
1342dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              ff |= DE_CLOSE;
1343f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            }
1344f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          } else {
1345dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            ff |= DE_WRITE;
1346f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          }
1347f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        }
1348f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1349f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // Tell the descriptor about the event.
1350f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (ff != 0) {
1351f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          pdispatcher->OnPreEvent(ff);
1352f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          pdispatcher->OnEvent(ff, errcode);
1353f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        }
1354f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
1355f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1356f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1357f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Recalc the time remaining to wait. Doing it here means it doesn't get
1358f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // calced twice the first time through the loop
1359f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1360f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (cmsWait != kForever) {
1361f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ptvWait->tv_sec = 0;
1362f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ptvWait->tv_usec = 0;
1363f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      struct timeval tvT;
1364f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      gettimeofday(&tvT, NULL);
1365f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if ((tvStop.tv_sec > tvT.tv_sec)
1366f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          || ((tvStop.tv_sec == tvT.tv_sec)
1367f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              && (tvStop.tv_usec > tvT.tv_usec))) {
1368f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        ptvWait->tv_sec = tvStop.tv_sec - tvT.tv_sec;
1369f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        ptvWait->tv_usec = tvStop.tv_usec - tvT.tv_usec;
1370f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (ptvWait->tv_usec < 0) {
1371f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          ASSERT(ptvWait->tv_sec > 0);
1372f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          ptvWait->tv_usec += 1000000;
1373f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          ptvWait->tv_sec -= 1;
1374f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        }
1375f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
1376f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1377f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1378f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1379f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
1380f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1381f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1382f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic void GlobalSignalHandler(int signum) {
1383dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  PosixSignalHandler::Instance()->OnPosixSignalReceived(signum);
1384f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1385f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1386f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool PhysicalSocketServer::SetPosixSignalHandler(int signum,
1387f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                                 void (*handler)(int)) {
1388f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // If handler is SIG_IGN or SIG_DFL then clear our user-level handler,
1389f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // otherwise set one.
1390f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (handler == SIG_IGN || handler == SIG_DFL) {
1391f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!InstallSignal(signum, handler)) {
1392f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
1393f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1394dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (signal_dispatcher_.get()) {
1395dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      signal_dispatcher_->ClearHandler(signum);
1396dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (!signal_dispatcher_->HasHandlers()) {
1397dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        signal_dispatcher_.reset();
1398f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
1399f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1400f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
1401dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!signal_dispatcher_.get()) {
1402dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      signal_dispatcher_.reset(new PosixSignalDispatcher(this));
1403f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1404dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    signal_dispatcher_->SetHandler(signum, handler);
1405f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!InstallSignal(signum, &GlobalSignalHandler)) {
1406f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
1407f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1408f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1409f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
1410f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1411f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1412f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool PhysicalSocketServer::InstallSignal(int signum, void (*handler)(int)) {
1413f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  struct sigaction act;
1414f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // It doesn't really matter what we set this mask to.
1415f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (sigemptyset(&act.sa_mask) != 0) {
1416f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG_ERR(LS_ERROR) << "Couldn't set mask";
1417f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
1418f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1419f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  act.sa_handler = handler;
1420f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Use SA_RESTART so that our syscalls don't get EINTR, since we don't need it
1421f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // and it's a nuisance. Though some syscalls still return EINTR and there's no
1422f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // real standard for which ones. :(
1423f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  act.sa_flags = SA_RESTART;
1424f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (sigaction(signum, &act, NULL) != 0) {
1425f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG_ERR(LS_ERROR) << "Couldn't set sigaction";
1426f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
1427f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1428f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
1429f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1430f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // POSIX
1431f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1432f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
1433f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
1434f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int cmsTotal = cmsWait;
1435f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int cmsElapsed = 0;
1436f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  uint32 msStart = Time();
1437f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1438f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if LOGGING
1439f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (last_tick_dispatch_count_ == 0) {
1440f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    last_tick_tracked_ = msStart;
1441f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1442f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
1443f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1444f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  fWait_ = true;
1445f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  while (fWait_) {
1446f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    std::vector<WSAEVENT> events;
1447f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    std::vector<Dispatcher *> event_owners;
1448f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1449f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    events.push_back(socket_ev_);
1450f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1451f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    {
1452f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      CritScope cr(&crit_);
1453f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      size_t i = 0;
1454f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      iterators_.push_back(&i);
1455f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // Don't track dispatchers_.size(), because we want to pick up any new
1456f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // dispatchers that were added while processing the loop.
1457f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      while (i < dispatchers_.size()) {
1458f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        Dispatcher* disp = dispatchers_[i++];
1459f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (!process_io && (disp != signal_wakeup_))
1460f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          continue;
1461f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        SOCKET s = disp->GetSocket();
1462f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (disp->CheckSignalClose()) {
1463f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // We just signalled close, don't poll this socket
1464f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        } else if (s != INVALID_SOCKET) {
1465dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          WSAEventSelect(s,
1466dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                         events[0],
1467dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                         FlagsToEvents(disp->GetRequestedEvents()));
1468f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        } else {
1469f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          events.push_back(disp->GetWSAEvent());
1470f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          event_owners.push_back(disp);
1471f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        }
1472f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
1473f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ASSERT(iterators_.back() == &i);
1474f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      iterators_.pop_back();
1475f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1476f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1477f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Which is shorter, the delay wait or the asked wait?
1478f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1479f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int cmsNext;
1480f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (cmsWait == kForever) {
1481f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      cmsNext = cmsWait;
1482f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
1483f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      cmsNext = _max(0, cmsTotal - cmsElapsed);
1484f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1485f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1486f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Wait for one of the events to signal
1487dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DWORD dw = WSAWaitForMultipleEvents(static_cast<DWORD>(events.size()),
1488dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                        &events[0],
1489dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                        false,
1490dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                        cmsNext,
1491dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                        false);
1492f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1493f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if 0  // LOGGING
1494f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // we track this information purely for logging purposes.
1495f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    last_tick_dispatch_count_++;
1496f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (last_tick_dispatch_count_ >= 1000) {
1497f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      int32 elapsed = TimeSince(last_tick_tracked_);
1498dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      LOG(INFO) << "PhysicalSocketServer took " << elapsed
1499dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                << "ms for 1000 events";
1500f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1501f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // If we get more than 1000 events in a second, we are spinning badly
1502f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // (normally it should take about 8-20 seconds).
1503f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ASSERT(elapsed > 1000);
1504f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1505f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      last_tick_tracked_ = Time();
1506f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      last_tick_dispatch_count_ = 0;
1507f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1508f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
1509f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1510f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (dw == WSA_WAIT_FAILED) {
1511f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // Failed?
1512731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      // TODO: need a better strategy than this!
1513f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      int error = WSAGetLastError();
1514f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ASSERT(false);
1515f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
1516f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else if (dw == WSA_WAIT_TIMEOUT) {
1517f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // Timeout?
1518f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return true;
1519f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
1520f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // Figure out which one it is and call it
1521f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      CritScope cr(&crit_);
1522f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      int index = dw - WSA_WAIT_EVENT_0;
1523f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (index > 0) {
1524f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        --index; // The first event is the socket event
1525f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        event_owners[index]->OnPreEvent(0);
1526f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        event_owners[index]->OnEvent(0, 0);
1527f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else if (process_io) {
1528f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        size_t i = 0, end = dispatchers_.size();
1529f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        iterators_.push_back(&i);
1530f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        iterators_.push_back(&end);  // Don't iterate over new dispatchers.
1531f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        while (i < end) {
1532f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          Dispatcher* disp = dispatchers_[i++];
1533f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          SOCKET s = disp->GetSocket();
1534f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          if (s == INVALID_SOCKET)
1535f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            continue;
1536f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1537f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          WSANETWORKEVENTS wsaEvents;
1538f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          int err = WSAEnumNetworkEvents(s, events[0], &wsaEvents);
1539f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          if (err == 0) {
1540f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1541f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if LOGGING
1542f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            {
1543dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              if ((wsaEvents.lNetworkEvents & FD_READ) &&
1544dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  wsaEvents.iErrorCode[FD_READ_BIT] != 0) {
1545dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                LOG(WARNING) << "PhysicalSocketServer got FD_READ_BIT error "
1546dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                             << wsaEvents.iErrorCode[FD_READ_BIT];
1547f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              }
1548dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              if ((wsaEvents.lNetworkEvents & FD_WRITE) &&
1549dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  wsaEvents.iErrorCode[FD_WRITE_BIT] != 0) {
1550dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                LOG(WARNING) << "PhysicalSocketServer got FD_WRITE_BIT error "
1551dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                             << wsaEvents.iErrorCode[FD_WRITE_BIT];
1552f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              }
1553dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              if ((wsaEvents.lNetworkEvents & FD_CONNECT) &&
1554dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  wsaEvents.iErrorCode[FD_CONNECT_BIT] != 0) {
1555dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                LOG(WARNING) << "PhysicalSocketServer got FD_CONNECT_BIT error "
1556dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                             << wsaEvents.iErrorCode[FD_CONNECT_BIT];
1557f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              }
1558dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              if ((wsaEvents.lNetworkEvents & FD_ACCEPT) &&
1559dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  wsaEvents.iErrorCode[FD_ACCEPT_BIT] != 0) {
1560dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                LOG(WARNING) << "PhysicalSocketServer got FD_ACCEPT_BIT error "
1561dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                             << wsaEvents.iErrorCode[FD_ACCEPT_BIT];
1562f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              }
1563dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              if ((wsaEvents.lNetworkEvents & FD_CLOSE) &&
1564dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  wsaEvents.iErrorCode[FD_CLOSE_BIT] != 0) {
1565dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                LOG(WARNING) << "PhysicalSocketServer got FD_CLOSE_BIT error "
1566dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                             << wsaEvents.iErrorCode[FD_CLOSE_BIT];
1567f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              }
1568f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            }
1569f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
1570f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            uint32 ff = 0;
1571f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            int errcode = 0;
1572f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            if (wsaEvents.lNetworkEvents & FD_READ)
1573dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              ff |= DE_READ;
1574f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            if (wsaEvents.lNetworkEvents & FD_WRITE)
1575dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              ff |= DE_WRITE;
1576f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            if (wsaEvents.lNetworkEvents & FD_CONNECT) {
1577f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              if (wsaEvents.iErrorCode[FD_CONNECT_BIT] == 0) {
1578dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                ff |= DE_CONNECT;
1579f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              } else {
1580dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                ff |= DE_CLOSE;
1581f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                errcode = wsaEvents.iErrorCode[FD_CONNECT_BIT];
1582f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              }
1583f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            }
1584f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            if (wsaEvents.lNetworkEvents & FD_ACCEPT)
1585dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              ff |= DE_ACCEPT;
1586f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            if (wsaEvents.lNetworkEvents & FD_CLOSE) {
1587dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              ff |= DE_CLOSE;
1588f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              errcode = wsaEvents.iErrorCode[FD_CLOSE_BIT];
1589f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            }
1590f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            if (ff != 0) {
1591f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              disp->OnPreEvent(ff);
1592f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              disp->OnEvent(ff, errcode);
1593f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            }
1594f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          }
1595f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        }
1596f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        ASSERT(iterators_.back() == &end);
1597f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        iterators_.pop_back();
1598f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        ASSERT(iterators_.back() == &i);
1599f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        iterators_.pop_back();
1600f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
1601f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1602f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // Reset the network event until new activity occurs
1603f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      WSAResetEvent(socket_ev_);
1604f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1605f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1606f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Break?
1607f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!fWait_)
1608f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
1609f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    cmsElapsed = TimeSince(msStart);
1610f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if ((cmsWait != kForever) && (cmsElapsed >= cmsWait)) {
1611f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch       break;
1612f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1613f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1614f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1615f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Done
1616f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
1617f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1618f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // WIN32
1619f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1620f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}  // namespace talk_base
1621