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