15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/* 25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle 35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2004--2005, Google Inc. 45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without 65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met: 75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * this list of conditions and the following disclaimer. 105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * this list of conditions and the following disclaimer in the documentation 125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * and/or other materials provided with the distribution. 135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 3. The name of the author may not be used to endorse or promote products 145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * derived from this software without specific prior written permission. 155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */ 275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#if defined(_MSC_VER) && _MSC_VER < 1300 295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#pragma warning(disable:4786) 305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <cassert> 335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef POSIX 355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <string.h> 365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <errno.h> 375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <fcntl.h> 385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <sys/time.h> 395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <unistd.h> 405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <signal.h> 415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef WIN32 445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#define WIN32_LEAN_AND_MEAN 455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <windows.h> 465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <winsock2.h> 475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <ws2tcpip.h> 485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#undef SetPort 495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <algorithm> 525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <map> 535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/basictypes.h" 555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/byteorder.h" 565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/common.h" 575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/logging.h" 585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/nethelpers.h" 595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/physicalsocketserver.h" 605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/timeutils.h" 615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/winping.h" 625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/win32socketinit.h" 635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// stm: this will tell us if we are on OSX 655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef HAVE_CONFIG_H 665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "config.h" 675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef POSIX 705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <netinet/tcp.h> // for TCP_NODELAY 715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#define IP_MTU 14 // Until this is integrated from linux/in.h to netinet/in.h 725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtypedef void* SockOptArg; 735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif // POSIX 745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef WIN32 765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtypedef char* SockOptArg; 775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace talk_base { 805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Standard MTUs, from RFC 1191 825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst uint16 PACKET_MAXIMUMS[] = { 835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 65535, // Theoretical maximum, Hyperchannel 845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 32000, // Nothing 855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 17914, // 16Mb IBM Token Ring 865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8166, // IEEE 802.4 875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org //4464, // IEEE 802.5 (4Mb max) 885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4352, // FDDI 895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org //2048, // Wideband Network 905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2002, // IEEE 802.5 (4Mb recommended) 915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org //1536, // Expermental Ethernet Networks 925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org //1500, // Ethernet, Point-to-Point (default) 935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1492, // IEEE 802.3 945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1006, // SLIP, ARPANET 955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org //576, // X.25 Networks 965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org //544, // DEC IP Portal 975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org //512, // NETBIOS 985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 508, // IEEE 802/Source-Rt Bridge, ARCNET 995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 296, // Point-to-Point (low delay) 1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 68, // Official minimum 1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 0, // End of list marker 1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const int IP_HEADER_SIZE = 20u; 1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const int IPV6_HEADER_SIZE = 40u; 1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const int ICMP_HEADER_SIZE = 8u; 1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const int ICMP_PING_TIMEOUT_MILLIS = 10000u; 1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> { 1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PhysicalSocket(PhysicalSocketServer* ss, SOCKET s = INVALID_SOCKET) 1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : ss_(ss), s_(s), enabled_events_(0), error_(0), 1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_((s == INVALID_SOCKET) ? CS_CLOSED : CS_CONNECTED), 1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org resolver_(NULL) { 1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef WIN32 1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // EnsureWinsockInit() ensures that winsock is initialized. The default 1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // version of this function doesn't do anything because winsock is 1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // initialized by constructor of a static object. If neccessary libjingle 1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // users can link it with a different version of this function by replacing 1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // win32socketinit.cc. See win32socketinit.cc for more details. 1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org EnsureWinsockInit(); 1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (s_ != INVALID_SOCKET) { 1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ = DE_READ | DE_WRITE; 1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int type = SOCK_STREAM; 1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socklen_t len = sizeof(type); 1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VERIFY(0 == getsockopt(s_, SOL_SOCKET, SO_TYPE, (SockOptArg)&type, &len)); 1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org udp_ = (SOCK_DGRAM == type); 1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual ~PhysicalSocket() { 1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Close(); 1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Creates the underlying OS socket (same as the "socket" function). 1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool Create(int family, int type) { 1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Close(); 1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org s_ = ::socket(family, type, 0); 1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org udp_ = (SOCK_DGRAM == type); 1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UpdateLastError(); 1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (udp_) 1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ = DE_READ | DE_WRITE; 1455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return s_ != INVALID_SOCKET; 1465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress GetLocalAddress() const { 1495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sockaddr_storage addr_storage = {0}; 1505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socklen_t addrlen = sizeof(addr_storage); 1515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); 1525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int result = ::getsockname(s_, addr, &addrlen); 1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress address; 1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (result >= 0) { 1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddressFromSockAddrStorage(addr_storage, &address); 1565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 1575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket=" 1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << s_; 1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return address; 1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress GetRemoteAddress() const { 1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sockaddr_storage addr_storage = {0}; 1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socklen_t addrlen = sizeof(addr_storage); 1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); 1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int result = ::getpeername(s_, addr, &addrlen); 1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress address; 1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (result >= 0) { 1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddressFromSockAddrStorage(addr_storage, &address); 1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_WARNING) << "GetRemoteAddress: unable to get remote addr, socket=" 1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << s_; 1745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return address; 1765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int Bind(const SocketAddress& bind_addr) { 1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sockaddr_storage addr_storage; 1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t len = bind_addr.ToSockAddrStorage(&addr_storage); 1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); 1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int err = ::bind(s_, addr, static_cast<int>(len)); 1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UpdateLastError(); 1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef _DEBUG 1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (0 == err) { 1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dbg_addr_ = "Bound @ "; 1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dbg_addr_.append(GetLocalAddress().ToString()); 1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif // _DEBUG 1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return err; 1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int Connect(const SocketAddress& addr) { 1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO: Implicit creation is required to reconnect... 1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // ...but should we make it more explicit? 1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (state_ != CS_CLOSED) { 1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SetError(EALREADY); 1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SOCKET_ERROR; 1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (addr.IsUnresolved()) { 2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_VERBOSE) << "Resolving addr in PhysicalSocket::Connect"; 2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org resolver_ = new AsyncResolver(); 203edac505d92ae2ab28b41f26f1a5b889d3e2a99f3sergeyu@chromium.org resolver_->SignalDone.connect(this, &PhysicalSocket::OnResolveResult); 204edac505d92ae2ab28b41f26f1a5b889d3e2a99f3sergeyu@chromium.org resolver_->Start(addr); 2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CONNECTING; 2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return DoConnect(addr); 2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int DoConnect(const SocketAddress& connect_addr) { 2135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((s_ == INVALID_SOCKET) && 2145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org !Create(connect_addr.family(), SOCK_STREAM)) { 2155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SOCKET_ERROR; 2165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sockaddr_storage addr_storage; 2185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t len = connect_addr.ToSockAddrStorage(&addr_storage); 2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); 2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int err = ::connect(s_, addr, static_cast<int>(len)); 2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UpdateLastError(); 2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (err == 0) { 2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CONNECTED; 224582fe818e571fa2571267f5e369715188472f352wu@webrtc.org } else if (IsBlockingError(GetError())) { 2255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CONNECTING; 2265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ |= DE_CONNECT; 2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SOCKET_ERROR; 2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ |= DE_READ | DE_WRITE; 2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int GetError() const { 236582fe818e571fa2571267f5e369715188472f352wu@webrtc.org CritScope cs(&crit_); 2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return error_; 2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void SetError(int error) { 241582fe818e571fa2571267f5e369715188472f352wu@webrtc.org CritScope cs(&crit_); 2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = error; 2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ConnState GetState() const { 2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return state_; 2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int GetOption(Option opt, int* value) { 2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int slevel; 2515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int sopt; 2525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (TranslateOption(opt, &slevel, &sopt) == -1) 2535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 2545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socklen_t optlen = sizeof(*value); 2555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int ret = ::getsockopt(s_, slevel, sopt, (SockOptArg)value, &optlen); 2565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ret != -1 && opt == OPT_DONTFRAGMENT) { 2575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef LINUX 2585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *value = (*value != IP_PMTUDISC_DONT) ? 1 : 0; 2595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 2605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return ret; 2625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int SetOption(Option opt, int value) { 2655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int slevel; 2665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int sopt; 2675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (TranslateOption(opt, &slevel, &sopt) == -1) 2685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 2695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (opt == OPT_DONTFRAGMENT) { 2705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef LINUX 2715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org value = (value) ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT; 2725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 2735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return ::setsockopt(s_, slevel, sopt, (SockOptArg)&value, sizeof(value)); 2755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int Send(const void *pv, size_t cb) { 2785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int sent = ::send(s_, reinterpret_cast<const char *>(pv), (int)cb, 2795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef LINUX 2805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Suppress SIGPIPE. Without this, attempting to send on a socket whose 2815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // other end is closed will result in a SIGPIPE signal being raised to 2825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // our process, which by default will terminate the process, which we 2835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // don't want. By specifying this flag, we'll just get the error EPIPE 2845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // instead and can handle the error gracefully. 2855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org MSG_NOSIGNAL 2865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#else 2875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 0 2885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 2895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ); 2905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UpdateLastError(); 2915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org MaybeRemapSendError(); 2925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // We have seen minidumps where this may be false. 2935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(sent <= static_cast<int>(cb)); 294582fe818e571fa2571267f5e369715188472f352wu@webrtc.org if ((sent < 0) && IsBlockingError(GetError())) { 2955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ |= DE_WRITE; 2965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return sent; 2985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int SendTo(const void* buffer, size_t length, const SocketAddress& addr) { 3015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sockaddr_storage saddr; 3025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t len = addr.ToSockAddrStorage(&saddr); 3035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int sent = ::sendto( 3045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org s_, static_cast<const char *>(buffer), static_cast<int>(length), 3055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef LINUX 3065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Suppress SIGPIPE. See above for explanation. 3075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org MSG_NOSIGNAL, 3085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#else 3095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 0, 3105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 3115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org reinterpret_cast<sockaddr*>(&saddr), static_cast<int>(len)); 3125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UpdateLastError(); 3135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org MaybeRemapSendError(); 3145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // We have seen minidumps where this may be false. 3155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(sent <= static_cast<int>(length)); 316582fe818e571fa2571267f5e369715188472f352wu@webrtc.org if ((sent < 0) && IsBlockingError(GetError())) { 3175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ |= DE_WRITE; 3185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return sent; 3205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int Recv(void* buffer, size_t length) { 3235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int received = ::recv(s_, static_cast<char*>(buffer), 3245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org static_cast<int>(length), 0); 3255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((received == 0) && (length != 0)) { 3265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Note: on graceful shutdown, recv can return 0. In this case, we 3275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // pretend it is blocking, and then signal close, so that simplifying 3285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // assumptions can be made about Recv. 3295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_WARNING) << "EOF from socket; deferring close event"; 3305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Must turn this back on so that the select() loop will notice the close 3315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // event. 3325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ |= DE_READ; 333582fe818e571fa2571267f5e369715188472f352wu@webrtc.org SetError(EWOULDBLOCK); 3345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SOCKET_ERROR; 3355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UpdateLastError(); 337582fe818e571fa2571267f5e369715188472f352wu@webrtc.org int error = GetError(); 338582fe818e571fa2571267f5e369715188472f352wu@webrtc.org bool success = (received >= 0) || IsBlockingError(error); 3395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (udp_ || success) { 3405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ |= DE_READ; 3415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!success) { 343582fe818e571fa2571267f5e369715188472f352wu@webrtc.org LOG_F(LS_VERBOSE) << "Error = " << error; 3445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return received; 3465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int RecvFrom(void* buffer, size_t length, SocketAddress *out_addr) { 3495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sockaddr_storage addr_storage; 3505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socklen_t addr_len = sizeof(addr_storage); 3515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); 3525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int received = ::recvfrom(s_, static_cast<char*>(buffer), 3535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org static_cast<int>(length), 0, addr, &addr_len); 3545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UpdateLastError(); 3555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((received >= 0) && (out_addr != NULL)) 3565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddressFromSockAddrStorage(addr_storage, out_addr); 357582fe818e571fa2571267f5e369715188472f352wu@webrtc.org int error = GetError(); 358582fe818e571fa2571267f5e369715188472f352wu@webrtc.org bool success = (received >= 0) || IsBlockingError(error); 3595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (udp_ || success) { 3605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ |= DE_READ; 3615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!success) { 363582fe818e571fa2571267f5e369715188472f352wu@webrtc.org LOG_F(LS_VERBOSE) << "Error = " << error; 3645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return received; 3665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int Listen(int backlog) { 3695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int err = ::listen(s_, backlog); 3705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UpdateLastError(); 3715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (err == 0) { 3725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CONNECTING; 3735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ |= DE_ACCEPT; 3745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef _DEBUG 3755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dbg_addr_ = "Listening @ "; 3765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dbg_addr_.append(GetLocalAddress().ToString()); 3775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif // _DEBUG 3785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return err; 3805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org AsyncSocket* Accept(SocketAddress *out_addr) { 3835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sockaddr_storage addr_storage; 3845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socklen_t addr_len = sizeof(addr_storage); 3855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); 3865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SOCKET s = ::accept(s_, addr, &addr_len); 3875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UpdateLastError(); 3885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (s == INVALID_SOCKET) 3895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return NULL; 3905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ |= DE_ACCEPT; 3915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (out_addr != NULL) 3925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddressFromSockAddrStorage(addr_storage, out_addr); 3935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return ss_->WrapSocket(s); 3945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int Close() { 3975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (s_ == INVALID_SOCKET) 3985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 3995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int err = ::closesocket(s_); 4005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UpdateLastError(); 4015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org s_ = INVALID_SOCKET; 4025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CLOSED; 4035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ = 0; 4045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (resolver_) { 4055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org resolver_->Destroy(false); 4065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org resolver_ = NULL; 4075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return err; 4095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int EstimateMTU(uint16* mtu) { 4125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress addr = GetRemoteAddress(); 4135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (addr.IsAny()) { 414582fe818e571fa2571267f5e369715188472f352wu@webrtc.org SetError(ENOTCONN); 4155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 4165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#if defined(WIN32) 4195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Gets the interface MTU (TTL=1) for the interface used to reach |addr|. 4205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org WinPing ping; 4215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!ping.IsValid()) { 422582fe818e571fa2571267f5e369715188472f352wu@webrtc.org SetError(EINVAL); // can't think of a better error ID 4235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 4245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int header_size = ICMP_HEADER_SIZE; 4265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (addr.family() == AF_INET6) { 4275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org header_size += IPV6_HEADER_SIZE; 4285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (addr.family() == AF_INET) { 4295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org header_size += IP_HEADER_SIZE; 4305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) { 4335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int32 size = PACKET_MAXIMUMS[level] - header_size; 4345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org WinPing::PingResult result = ping.Ping(addr.ipaddr(), size, 4355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ICMP_PING_TIMEOUT_MILLIS, 4365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1, false); 4375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (result == WinPing::PING_FAIL) { 438582fe818e571fa2571267f5e369715188472f352wu@webrtc.org SetError(EINVAL); // can't think of a better error ID 4395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 4405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (result != WinPing::PING_TOO_LARGE) { 4415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *mtu = PACKET_MAXIMUMS[level]; 4425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 4435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(false); 4475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 4485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#elif defined(IOS) || defined(OSX) 4495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // No simple way to do this on Mac OS X. 4505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // SIOCGIFMTU would work if we knew which interface would be used, but 4515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // figuring that out is pretty complicated. For now we'll return an error 4525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // and let the caller pick a default MTU. 453582fe818e571fa2571267f5e369715188472f352wu@webrtc.org SetError(EINVAL); 4545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 4555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#elif defined(LINUX) || defined(ANDROID) 4565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Gets the path MTU. 4575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int value; 4585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socklen_t vlen = sizeof(value); 4595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int err = getsockopt(s_, IPPROTO_IP, IP_MTU, &value, &vlen); 4605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (err < 0) { 4615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UpdateLastError(); 4625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return err; 4635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT((0 <= value) && (value <= 65536)); 4665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *mtu = value; 4675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 468582fe818e571fa2571267f5e369715188472f352wu@webrtc.org#elif defined(__native_client__) 469582fe818e571fa2571267f5e369715188472f352wu@webrtc.org // Most socket operations, including this, will fail in NaCl's sandbox. 470582fe818e571fa2571267f5e369715188472f352wu@webrtc.org error_ = EACCES; 471582fe818e571fa2571267f5e369715188472f352wu@webrtc.org return -1; 4725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 4735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketServer* socketserver() { return ss_; } 4765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org protected: 478edac505d92ae2ab28b41f26f1a5b889d3e2a99f3sergeyu@chromium.org void OnResolveResult(AsyncResolverInterface* resolver) { 479edac505d92ae2ab28b41f26f1a5b889d3e2a99f3sergeyu@chromium.org if (resolver != resolver_) { 4805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return; 4815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 483edac505d92ae2ab28b41f26f1a5b889d3e2a99f3sergeyu@chromium.org int error = resolver_->GetError(); 4845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (error == 0) { 4855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error = DoConnect(resolver_->address()); 4865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 4875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Close(); 4885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (error) { 491582fe818e571fa2571267f5e369715188472f352wu@webrtc.org SetError(error); 492582fe818e571fa2571267f5e369715188472f352wu@webrtc.org SignalCloseEvent(this, error); 4935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void UpdateLastError() { 497582fe818e571fa2571267f5e369715188472f352wu@webrtc.org SetError(LAST_SYSTEM_ERROR); 4985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void MaybeRemapSendError() { 5015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#if defined(OSX) 5025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // https://developer.apple.com/library/mac/documentation/Darwin/ 5035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Reference/ManPages/man2/sendto.2.html 5045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // ENOBUFS - The output queue for a network interface is full. 5055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // This generally indicates that the interface has stopped sending, 5065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // but may be caused by transient congestion. 507582fe818e571fa2571267f5e369715188472f352wu@webrtc.org if (GetError() == ENOBUFS) { 508582fe818e571fa2571267f5e369715188472f352wu@webrtc.org SetError(EWOULDBLOCK); 5095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 5115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org static int TranslateOption(Option opt, int* slevel, int* sopt) { 5145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org switch (opt) { 5155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case OPT_DONTFRAGMENT: 5165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef WIN32 5175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *slevel = IPPROTO_IP; 5185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *sopt = IP_DONTFRAGMENT; 5195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 5205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#elif defined(IOS) || defined(OSX) || defined(BSD) 5215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_WARNING) << "Socket::OPT_DONTFRAGMENT not supported."; 5225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 5235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#elif defined(POSIX) 5245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *slevel = IPPROTO_IP; 5255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *sopt = IP_MTU_DISCOVER; 5265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 5275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 5285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case OPT_RCVBUF: 5295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *slevel = SOL_SOCKET; 5305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *sopt = SO_RCVBUF; 5315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 5325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case OPT_SNDBUF: 5335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *slevel = SOL_SOCKET; 5345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *sopt = SO_SNDBUF; 5355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 5365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case OPT_NODELAY: 5375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *slevel = IPPROTO_TCP; 5385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *sopt = TCP_NODELAY; 5395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 540582fe818e571fa2571267f5e369715188472f352wu@webrtc.org case OPT_DSCP: 541582fe818e571fa2571267f5e369715188472f352wu@webrtc.org LOG(LS_WARNING) << "Socket::OPT_DSCP not supported."; 542582fe818e571fa2571267f5e369715188472f352wu@webrtc.org return -1; 5435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org default: 5445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(false); 5455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 5465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 5485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PhysicalSocketServer* ss_; 5515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SOCKET s_; 5525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint8 enabled_events_; 5535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool udp_; 5545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int error_; 555582fe818e571fa2571267f5e369715188472f352wu@webrtc.org // Protects |error_| that is accessed from different threads. 556582fe818e571fa2571267f5e369715188472f352wu@webrtc.org mutable CriticalSection crit_; 5575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ConnState state_; 5585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org AsyncResolver* resolver_; 5595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef _DEBUG 5615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string dbg_addr_; 5625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif // _DEBUG; 5635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 5645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef POSIX 5665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass EventDispatcher : public Dispatcher { 5675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 5685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org EventDispatcher(PhysicalSocketServer* ss) : ss_(ss), fSignaled_(false) { 5695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (pipe(afd_) < 0) 5705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LERROR) << "pipe failed"; 5715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ss_->Add(this); 5725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual ~EventDispatcher() { 5755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ss_->Remove(this); 5765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org close(afd_[0]); 5775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org close(afd_[1]); 5785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void Signal() { 5815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CritScope cs(&crit_); 5825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!fSignaled_) { 5835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const uint8 b[1] = { 0 }; 5845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (VERIFY(1 == write(afd_[1], b, sizeof(b)))) { 5855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org fSignaled_ = true; 5865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual uint32 GetRequestedEvents() { 5915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return DE_READ; 5925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void OnPreEvent(uint32 ff) { 5955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // It is not possible to perfectly emulate an auto-resetting event with 5965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // pipes. This simulates it by resetting before the event is handled. 5975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CritScope cs(&crit_); 5995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (fSignaled_) { 6005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint8 b[4]; // Allow for reading more than 1 byte, but expect 1. 6015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VERIFY(1 == read(afd_[0], b, sizeof(b))); 6025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org fSignaled_ = false; 6035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void OnEvent(uint32 ff, int err) { 6075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(false); 6085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int GetDescriptor() { 6115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return afd_[0]; 6125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool IsDescriptorClosed() { 6155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 6165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org private: 6195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PhysicalSocketServer *ss_; 6205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int afd_[2]; 6215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool fSignaled_; 6225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CriticalSection crit_; 6235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 6245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// These two classes use the self-pipe trick to deliver POSIX signals to our 6265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// select loop. This is the only safe, reliable, cross-platform way to do 6275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// non-trivial things with a POSIX signal in an event-driven program (until 6285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// proper pselect() implementations become ubiquitous). 6295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass PosixSignalHandler { 6315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 6325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // POSIX only specifies 32 signals, but in principle the system might have 6335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // more and the programmer might choose to use them, so we size our array 6345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // for 128. 6355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org static const int kNumPosixSignals = 128; 6365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // There is just a single global instance. (Signal handlers do not get any 6385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // sort of user-defined void * parameter, so they can't access anything that 6395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // isn't global.) 6405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org static PosixSignalHandler* Instance() { 6415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LIBJINGLE_DEFINE_STATIC_LOCAL(PosixSignalHandler, instance, ()); 6425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return &instance; 6435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Returns true if the given signal number is set. 6465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool IsSignalSet(int signum) const { 6475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(signum < ARRAY_SIZE(received_signal_)); 6485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (signum < ARRAY_SIZE(received_signal_)) { 6495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return received_signal_[signum]; 6505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 6515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 6525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Clears the given signal number. 6565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void ClearSignal(int signum) { 6575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(signum < ARRAY_SIZE(received_signal_)); 6585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (signum < ARRAY_SIZE(received_signal_)) { 6595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org received_signal_[signum] = false; 6605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Returns the file descriptor to monitor for signal events. 6645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int GetDescriptor() const { 6655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return afd_[0]; 6665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // This is called directly from our real signal handler, so it must be 6695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // signal-handler-safe. That means it cannot assume anything about the 6705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // user-level state of the process, since the handler could be executed at any 6715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // time on any thread. 6725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void OnPosixSignalReceived(int signum) { 6735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (signum >= ARRAY_SIZE(received_signal_)) { 6745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // We don't have space in our array for this. 6755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return; 6765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Set a flag saying we've seen this signal. 6785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org received_signal_[signum] = true; 6795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Notify application code that we got a signal. 6805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const uint8 b[1] = { 0 }; 6815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (-1 == write(afd_[1], b, sizeof(b))) { 6825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Nothing we can do here. If there's an error somehow then there's 6835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // nothing we can safely do from a signal handler. 6845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // No, we can't even safely log it. 6855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // But, we still have to check the return value here. Otherwise, 6865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // GCC 4.4.1 complains ignoring return value. Even (void) doesn't help. 6875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return; 6885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org private: 6925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PosixSignalHandler() { 6935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (pipe(afd_) < 0) { 6945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_ERR(LS_ERROR) << "pipe failed"; 6955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return; 6965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (fcntl(afd_[0], F_SETFL, O_NONBLOCK) < 0) { 6985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_ERR(LS_WARNING) << "fcntl #1 failed"; 6995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (fcntl(afd_[1], F_SETFL, O_NONBLOCK) < 0) { 7015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_ERR(LS_WARNING) << "fcntl #2 failed"; 7025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org memset(const_cast<void *>(static_cast<volatile void *>(received_signal_)), 7045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 0, 7055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sizeof(received_signal_)); 7065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ~PosixSignalHandler() { 7095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int fd1 = afd_[0]; 7105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int fd2 = afd_[1]; 7115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // We clobber the stored file descriptor numbers here or else in principle 7125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // a signal that happens to be delivered during application termination 7135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // could erroneously write a zero byte to an unrelated file handle in 7145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // OnPosixSignalReceived() if some other file happens to be opened later 7155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // during shutdown and happens to be given the same file descriptor number 7165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // as our pipe had. Unfortunately even with this precaution there is still a 7175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // race where that could occur if said signal happens to be handled 7185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // concurrently with this code and happens to have already read the value of 7195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // afd_[1] from memory before we clobber it, but that's unlikely. 7205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org afd_[0] = -1; 7215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org afd_[1] = -1; 7225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org close(fd1); 7235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org close(fd2); 7245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int afd_[2]; 7275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // These are boolean flags that will be set in our signal handler and read 7285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // and cleared from Wait(). There is a race involved in this, but it is 7295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // benign. The signal handler sets the flag before signaling the pipe, so 7305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // we'll never end up blocking in select() while a flag is still true. 7315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // However, if two of the same signal arrive close to each other then it's 7325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // possible that the second time the handler may set the flag while it's still 7335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // true, meaning that signal will be missed. But the first occurrence of it 7345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // will still be handled, so this isn't a problem. 7355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Volatile is not necessary here for correctness, but this data _is_ volatile 7365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // so I've marked it as such. 7375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org volatile uint8 received_signal_[kNumPosixSignals]; 7385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 7395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass PosixSignalDispatcher : public Dispatcher { 7415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 7425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PosixSignalDispatcher(PhysicalSocketServer *owner) : owner_(owner) { 7435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org owner_->Add(this); 7445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual ~PosixSignalDispatcher() { 7475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org owner_->Remove(this); 7485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual uint32 GetRequestedEvents() { 7515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return DE_READ; 7525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void OnPreEvent(uint32 ff) { 7555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Events might get grouped if signals come very fast, so we read out up to 7565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // 16 bytes to make sure we keep the pipe empty. 7575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint8 b[16]; 7585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ssize_t ret = read(GetDescriptor(), b, sizeof(b)); 7595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ret < 0) { 7605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_ERR(LS_WARNING) << "Error in read()"; 7615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (ret == 0) { 7625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_WARNING) << "Should have read at least one byte"; 7635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void OnEvent(uint32 ff, int err) { 7675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (int signum = 0; signum < PosixSignalHandler::kNumPosixSignals; 7685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ++signum) { 7695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (PosixSignalHandler::Instance()->IsSignalSet(signum)) { 7705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PosixSignalHandler::Instance()->ClearSignal(signum); 7715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org HandlerMap::iterator i = handlers_.find(signum); 7725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (i == handlers_.end()) { 7735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // This can happen if a signal is delivered to our process at around 7745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // the same time as we unset our handler for it. It is not an error 7755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // condition, but it's unusual enough to be worth logging. 7765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Received signal with no handler: " << signum; 7775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 7785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Otherwise, execute our handler. 7795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org (*i->second)(signum); 7805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int GetDescriptor() { 7865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PosixSignalHandler::Instance()->GetDescriptor(); 7875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool IsDescriptorClosed() { 7905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 7915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void SetHandler(int signum, void (*handler)(int)) { 7945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org handlers_[signum] = handler; 7955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void ClearHandler(int signum) { 7985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org handlers_.erase(signum); 7995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool HasHandlers() { 8025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return !handlers_.empty(); 8035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org private: 8065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org typedef std::map<int, void (*)(int)> HandlerMap; 8075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org HandlerMap handlers_; 8095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Our owner. 8105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PhysicalSocketServer *owner_; 8115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 8125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass SocketDispatcher : public Dispatcher, public PhysicalSocket { 8145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 8155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org explicit SocketDispatcher(PhysicalSocketServer *ss) : PhysicalSocket(ss) { 8165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketDispatcher(SOCKET s, PhysicalSocketServer *ss) : PhysicalSocket(ss, s) { 8185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual ~SocketDispatcher() { 8215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Close(); 8225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool Initialize() { 8255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ss_->Add(this); 8265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK); 8275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 8285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool Create(int type) { 8315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return Create(AF_INET, type); 8325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool Create(int family, int type) { 8355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Change the socket to be non-blocking. 8365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!PhysicalSocket::Create(family, type)) 8375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 8385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return Initialize(); 8405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int GetDescriptor() { 8435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return s_; 8445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool IsDescriptorClosed() { 8475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // We don't have a reliable way of distinguishing end-of-stream 8485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // from readability. So test on each readable call. Is this 8495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // inefficient? Probably. 8505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org char ch; 8515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ssize_t res = ::recv(s_, &ch, 1, MSG_PEEK); 8525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (res > 0) { 8535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Data available, so not closed. 8545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 8555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (res == 0) { 8565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // EOF, so closed. 8575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 8585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { // error 8595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org switch (errno) { 8605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Returned if we've already closed s_. 8615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case EBADF: 8625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Returned during ungraceful peer shutdown. 8635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case ECONNRESET: 8645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 8655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org default: 8665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Assume that all other errors are just blocking errors, meaning the 8675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // connection is still good but we just can't read from it right now. 8685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // This should only happen when connecting (and at most once), because 8695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // in all other cases this function is only called if the file 8705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // descriptor is already known to be in the readable state. However, 8715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // it's not necessary a problem if we spuriously interpret a 8725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // "connection lost"-type error as a blocking error, because typically 8735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // the next recv() will get EOF, so we'll still eventually notice that 8745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // the socket is closed. 8755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_ERR(LS_WARNING) << "Assuming benign blocking error"; 8765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 8775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual uint32 GetRequestedEvents() { 8825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return enabled_events_; 8835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void OnPreEvent(uint32 ff) { 8865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((ff & DE_CONNECT) != 0) 8875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CONNECTED; 8885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((ff & DE_CLOSE) != 0) 8895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CLOSED; 8905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void OnEvent(uint32 ff, int err) { 8935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Make sure we deliver connect/accept first. Otherwise, consumers may see 8945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // something like a READ followed by a CONNECT, which would be odd. 8955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((ff & DE_CONNECT) != 0) { 8965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ &= ~DE_CONNECT; 8975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalConnectEvent(this); 8985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((ff & DE_ACCEPT) != 0) { 9005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ &= ~DE_ACCEPT; 9015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalReadEvent(this); 9025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((ff & DE_READ) != 0) { 9045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ &= ~DE_READ; 9055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalReadEvent(this); 9065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((ff & DE_WRITE) != 0) { 9085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ &= ~DE_WRITE; 9095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalWriteEvent(this); 9105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((ff & DE_CLOSE) != 0) { 9125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // The socket is now dead to us, so stop checking it. 9135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ = 0; 9145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalCloseEvent(this, err); 9155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int Close() { 9195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (s_ == INVALID_SOCKET) 9205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 9215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ss_->Remove(this); 9235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PhysicalSocket::Close(); 9245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 9265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass FileDispatcher: public Dispatcher, public AsyncFile { 9285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 9295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org FileDispatcher(int fd, PhysicalSocketServer *ss) : ss_(ss), fd_(fd) { 9305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org set_readable(true); 9315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ss_->Add(this); 9335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org fcntl(fd_, F_SETFL, fcntl(fd_, F_GETFL, 0) | O_NONBLOCK); 9355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual ~FileDispatcher() { 9385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ss_->Remove(this); 9395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketServer* socketserver() { return ss_; } 9425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int GetDescriptor() { 9445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return fd_; 9455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool IsDescriptorClosed() { 9485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 9495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual uint32 GetRequestedEvents() { 9525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return flags_; 9535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void OnPreEvent(uint32 ff) { 9565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void OnEvent(uint32 ff, int err) { 9595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((ff & DE_READ) != 0) 9605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalReadEvent(this); 9615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((ff & DE_WRITE) != 0) 9625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalWriteEvent(this); 9635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((ff & DE_CLOSE) != 0) 9645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalCloseEvent(this, err); 9655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool readable() { 9685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return (flags_ & DE_READ) != 0; 9695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void set_readable(bool value) { 9725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org flags_ = value ? (flags_ | DE_READ) : (flags_ & ~DE_READ); 9735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool writable() { 9765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return (flags_ & DE_WRITE) != 0; 9775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void set_writable(bool value) { 9805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org flags_ = value ? (flags_ | DE_WRITE) : (flags_ & ~DE_WRITE); 9815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org private: 9845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PhysicalSocketServer* ss_; 9855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int fd_; 9865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int flags_; 9875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 9885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgAsyncFile* PhysicalSocketServer::CreateFile(int fd) { 9905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return new FileDispatcher(fd, this); 9915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif // POSIX 9945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef WIN32 9965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic uint32 FlagsToEvents(uint32 events) { 9975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 ffFD = FD_CLOSE; 9985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (events & DE_READ) 9995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ffFD |= FD_READ; 10005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (events & DE_WRITE) 10015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ffFD |= FD_WRITE; 10025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (events & DE_CONNECT) 10035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ffFD |= FD_CONNECT; 10045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (events & DE_ACCEPT) 10055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ffFD |= FD_ACCEPT; 10065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return ffFD; 10075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 10085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass EventDispatcher : public Dispatcher { 10105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 10115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org EventDispatcher(PhysicalSocketServer *ss) : ss_(ss) { 10125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org hev_ = WSACreateEvent(); 10135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (hev_) { 10145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ss_->Add(this); 10155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ~EventDispatcher() { 10195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (hev_ != NULL) { 10205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ss_->Remove(this); 10215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org WSACloseEvent(hev_); 10225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org hev_ = NULL; 10235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void Signal() { 10275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (hev_ != NULL) 10285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org WSASetEvent(hev_); 10295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual uint32 GetRequestedEvents() { 10325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 10335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void OnPreEvent(uint32 ff) { 10365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org WSAResetEvent(hev_); 10375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void OnEvent(uint32 ff, int err) { 10405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual WSAEVENT GetWSAEvent() { 10435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return hev_; 10445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual SOCKET GetSocket() { 10475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return INVALID_SOCKET; 10485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool CheckSignalClose() { return false; } 10515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgprivate: 10535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PhysicalSocketServer* ss_; 10545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org WSAEVENT hev_; 10555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 10565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass SocketDispatcher : public Dispatcher, public PhysicalSocket { 10585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 10595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org static int next_id_; 10605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int id_; 10615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool signal_close_; 10625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int signal_err_; 10635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketDispatcher(PhysicalSocketServer* ss) 10655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : PhysicalSocket(ss), 10665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org id_(0), 10675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org signal_close_(false) { 10685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketDispatcher(SOCKET s, PhysicalSocketServer* ss) 10715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : PhysicalSocket(ss, s), 10725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org id_(0), 10735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org signal_close_(false) { 10745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual ~SocketDispatcher() { 10775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Close(); 10785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool Initialize() { 10815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(s_ != INVALID_SOCKET); 10825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Must be a non-blocking 10835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org u_long argp = 1; 10845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ioctlsocket(s_, FIONBIO, &argp); 10855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ss_->Add(this); 10865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 10875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool Create(int type) { 10905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return Create(AF_INET, type); 10915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool Create(int family, int type) { 10945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Create socket 10955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!PhysicalSocket::Create(family, type)) 10965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 10975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!Initialize()) 10995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 11005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org do { id_ = ++next_id_; } while (id_ == 0); 11025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 11035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int Close() { 11065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (s_ == INVALID_SOCKET) 11075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 11085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org id_ = 0; 11105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org signal_close_ = false; 11115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ss_->Remove(this); 11125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PhysicalSocket::Close(); 11135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual uint32 GetRequestedEvents() { 11165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return enabled_events_; 11175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void OnPreEvent(uint32 ff) { 11205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((ff & DE_CONNECT) != 0) 11215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CONNECTED; 11225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // We set CS_CLOSED from CheckSignalClose. 11235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void OnEvent(uint32 ff, int err) { 11265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int cache_id = id_; 11275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Make sure we deliver connect/accept first. Otherwise, consumers may see 11285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // something like a READ followed by a CONNECT, which would be odd. 11295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (((ff & DE_CONNECT) != 0) && (id_ == cache_id)) { 11305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ff != DE_CONNECT) 11315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_VERBOSE) << "Signalled with DE_CONNECT: " << ff; 11325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ &= ~DE_CONNECT; 11335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef _DEBUG 11345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dbg_addr_ = "Connected @ "; 11355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dbg_addr_.append(GetRemoteAddress().ToString()); 11365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif // _DEBUG 11375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalConnectEvent(this); 11385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (((ff & DE_ACCEPT) != 0) && (id_ == cache_id)) { 11405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ &= ~DE_ACCEPT; 11415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalReadEvent(this); 11425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((ff & DE_READ) != 0) { 11445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ &= ~DE_READ; 11455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalReadEvent(this); 11465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (((ff & DE_WRITE) != 0) && (id_ == cache_id)) { 11485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org enabled_events_ &= ~DE_WRITE; 11495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalWriteEvent(this); 11505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (((ff & DE_CLOSE) != 0) && (id_ == cache_id)) { 11525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org signal_close_ = true; 11535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org signal_err_ = err; 11545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual WSAEVENT GetWSAEvent() { 11585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return WSA_INVALID_EVENT; 11595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual SOCKET GetSocket() { 11625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return s_; 11635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool CheckSignalClose() { 11665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!signal_close_) 11675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 11685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org char ch; 11705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (recv(s_, &ch, 1, MSG_PEEK) > 0) 11715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 11725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CLOSED; 11745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org signal_close_ = false; 11755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalCloseEvent(this, signal_err_); 11765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 11775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 11795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint SocketDispatcher::next_id_ = 0; 11815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif // WIN32 11835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Sets the value of a boolean value to false when signaled. 11855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass Signaler : public EventDispatcher { 11865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 11875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Signaler(PhysicalSocketServer* ss, bool* pf) 11885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : EventDispatcher(ss), pf_(pf) { 11895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual ~Signaler() { } 11915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void OnEvent(uint32 ff, int err) { 11935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (pf_) 11945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *pf_ = false; 11955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org private: 11985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool *pf_; 11995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 12005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 12015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPhysicalSocketServer::PhysicalSocketServer() 12025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : fWait_(false), 12035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org last_tick_tracked_(0), 12045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org last_tick_dispatch_count_(0) { 12055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org signal_wakeup_ = new Signaler(this, &fWait_); 12065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef WIN32 12075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket_ev_ = WSACreateEvent(); 12085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 12095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 12105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 12115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPhysicalSocketServer::~PhysicalSocketServer() { 12125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef WIN32 12135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org WSACloseEvent(socket_ev_); 12145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 12155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef POSIX 12165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org signal_dispatcher_.reset(); 12175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 12185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete signal_wakeup_; 12195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(dispatchers_.empty()); 12205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 12215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 12225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PhysicalSocketServer::WakeUp() { 12235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org signal_wakeup_->Signal(); 12245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 12255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 12265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSocket* PhysicalSocketServer::CreateSocket(int type) { 12275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return CreateSocket(AF_INET, type); 12285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 12295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 12305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSocket* PhysicalSocketServer::CreateSocket(int family, int type) { 12315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PhysicalSocket* socket = new PhysicalSocket(this); 12325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (socket->Create(family, type)) { 12335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return socket; 12345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 12355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete socket; 12365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 12375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 12385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 12395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 12405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgAsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int type) { 12415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return CreateAsyncSocket(AF_INET, type); 12425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 12435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 12445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgAsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int family, int type) { 12455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketDispatcher* dispatcher = new SocketDispatcher(this); 12465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (dispatcher->Create(family, type)) { 12475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return dispatcher; 12485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 12495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete dispatcher; 12505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 12515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 12525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 12535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 12545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgAsyncSocket* PhysicalSocketServer::WrapSocket(SOCKET s) { 12555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketDispatcher* dispatcher = new SocketDispatcher(s, this); 12565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (dispatcher->Initialize()) { 12575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return dispatcher; 12585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 12595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete dispatcher; 12605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 12615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 12625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 12635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 12645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PhysicalSocketServer::Add(Dispatcher *pdispatcher) { 12655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CritScope cs(&crit_); 12665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Prevent duplicates. This can cause dead dispatchers to stick around. 12675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org DispatcherList::iterator pos = std::find(dispatchers_.begin(), 12685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dispatchers_.end(), 12695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org pdispatcher); 12705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (pos != dispatchers_.end()) 12715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return; 12725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dispatchers_.push_back(pdispatcher); 12735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 12745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 12755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PhysicalSocketServer::Remove(Dispatcher *pdispatcher) { 12765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CritScope cs(&crit_); 12775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org DispatcherList::iterator pos = std::find(dispatchers_.begin(), 12785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dispatchers_.end(), 12795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org pdispatcher); 1280204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org // We silently ignore duplicate calls to Add, so we should silently ignore 1281204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org // the (expected) symmetric calls to Remove. Note that this may still hide 1282204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org // a real issue, so we at least log a warning about it. 1283204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org if (pos == dispatchers_.end()) { 1284204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org LOG(LS_WARNING) << "PhysicalSocketServer asked to remove a unknown " 1285204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org << "dispatcher, potentially from a duplicate call to Add."; 1286204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org return; 1287204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org } 12885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t index = pos - dispatchers_.begin(); 12895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dispatchers_.erase(pos); 12905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (IteratorList::iterator it = iterators_.begin(); it != iterators_.end(); 12915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ++it) { 12925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (index < **it) { 12935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org --**it; 12945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 12955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 12965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 12975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 12985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef POSIX 12995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool PhysicalSocketServer::Wait(int cmsWait, bool process_io) { 13005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Calculate timing information 13015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 13025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org struct timeval *ptvWait = NULL; 13035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org struct timeval tvWait; 13045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org struct timeval tvStop; 13055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (cmsWait != kForever) { 13065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Calculate wait timeval 13075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org tvWait.tv_sec = cmsWait / 1000; 13085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org tvWait.tv_usec = (cmsWait % 1000) * 1000; 13095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ptvWait = &tvWait; 13105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 13115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Calculate when to return in a timeval 13125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org gettimeofday(&tvStop, NULL); 13135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org tvStop.tv_sec += tvWait.tv_sec; 13145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org tvStop.tv_usec += tvWait.tv_usec; 13155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (tvStop.tv_usec >= 1000000) { 13165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org tvStop.tv_usec -= 1000000; 13175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org tvStop.tv_sec += 1; 13185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 13195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 13205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 13215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Zero all fd_sets. Don't need to do this inside the loop since 13225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // select() zeros the descriptors not signaled 13235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 13245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org fd_set fdsRead; 13255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org FD_ZERO(&fdsRead); 13265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org fd_set fdsWrite; 13275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org FD_ZERO(&fdsWrite); 13285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 13295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org fWait_ = true; 13305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 13315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org while (fWait_) { 13325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int fdmax = -1; 13335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org { 13345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CritScope cr(&crit_); 13355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (size_t i = 0; i < dispatchers_.size(); ++i) { 13365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Query dispatchers for read and write wait state 13375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Dispatcher *pdispatcher = dispatchers_[i]; 13385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(pdispatcher); 13395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!process_io && (pdispatcher != signal_wakeup_)) 13405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org continue; 13415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int fd = pdispatcher->GetDescriptor(); 13425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (fd > fdmax) 13435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org fdmax = fd; 13445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 13455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 ff = pdispatcher->GetRequestedEvents(); 13465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ff & (DE_READ | DE_ACCEPT)) 13475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org FD_SET(fd, &fdsRead); 13485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ff & (DE_WRITE | DE_CONNECT)) 13495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org FD_SET(fd, &fdsWrite); 13505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 13515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 13525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 13535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Wait then call handlers as appropriate 13545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // < 0 means error 13555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // 0 means timeout 13565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // > 0 means count of descriptors ready 13575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int n = select(fdmax + 1, &fdsRead, &fdsWrite, NULL, ptvWait); 13585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 13595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // If error, return error. 13605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (n < 0) { 13615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (errno != EINTR) { 13625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_E(LS_ERROR, EN, errno) << "select"; 13635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 13645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 13655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Else ignore the error and keep going. If this EINTR was for one of the 13665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // signals managed by this PhysicalSocketServer, the 13675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // PosixSignalDeliveryDispatcher will be in the signaled state in the next 13685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // iteration. 13695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (n == 0) { 13705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // If timeout, return success 13715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 13725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 13735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // We have signaled descriptors 13745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CritScope cr(&crit_); 13755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (size_t i = 0; i < dispatchers_.size(); ++i) { 13765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Dispatcher *pdispatcher = dispatchers_[i]; 13775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int fd = pdispatcher->GetDescriptor(); 13785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 ff = 0; 13795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int errcode = 0; 13805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 13815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Reap any error code, which can be signaled through reads or writes. 13825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO: Should we set errcode if getsockopt fails? 13835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (FD_ISSET(fd, &fdsRead) || FD_ISSET(fd, &fdsWrite)) { 13845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socklen_t len = sizeof(errcode); 13855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ::getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &len); 13865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 13875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 13885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Check readable descriptors. If we're waiting on an accept, signal 13895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // that. Otherwise we're waiting for data, check to see if we're 13905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // readable or really closed. 13915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO: Only peek at TCP descriptors. 13925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (FD_ISSET(fd, &fdsRead)) { 13935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org FD_CLR(fd, &fdsRead); 13945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (pdispatcher->GetRequestedEvents() & DE_ACCEPT) { 13955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ff |= DE_ACCEPT; 13965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (errcode || pdispatcher->IsDescriptorClosed()) { 13975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ff |= DE_CLOSE; 13985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 13995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ff |= DE_READ; 14005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 14035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Check writable descriptors. If we're waiting on a connect, detect 14045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // success versus failure by the reaped error code. 14055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (FD_ISSET(fd, &fdsWrite)) { 14065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org FD_CLR(fd, &fdsWrite); 14075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (pdispatcher->GetRequestedEvents() & DE_CONNECT) { 14085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!errcode) { 14095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ff |= DE_CONNECT; 14105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 14115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ff |= DE_CLOSE; 14125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 14145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ff |= DE_WRITE; 14155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 14185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Tell the descriptor about the event. 14195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ff != 0) { 14205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org pdispatcher->OnPreEvent(ff); 14215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org pdispatcher->OnEvent(ff, errcode); 14225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 14265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Recalc the time remaining to wait. Doing it here means it doesn't get 14275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // calced twice the first time through the loop 14285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ptvWait) { 14295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ptvWait->tv_sec = 0; 14305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ptvWait->tv_usec = 0; 14315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org struct timeval tvT; 14325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org gettimeofday(&tvT, NULL); 14335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((tvStop.tv_sec > tvT.tv_sec) 14345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org || ((tvStop.tv_sec == tvT.tv_sec) 14355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org && (tvStop.tv_usec > tvT.tv_usec))) { 14365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ptvWait->tv_sec = tvStop.tv_sec - tvT.tv_sec; 14375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ptvWait->tv_usec = tvStop.tv_usec - tvT.tv_usec; 14385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ptvWait->tv_usec < 0) { 14395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(ptvWait->tv_sec > 0); 14405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ptvWait->tv_usec += 1000000; 14415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ptvWait->tv_sec -= 1; 14425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 14475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 14485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 14495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 14505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic void GlobalSignalHandler(int signum) { 14515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PosixSignalHandler::Instance()->OnPosixSignalReceived(signum); 14525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 14535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 14545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool PhysicalSocketServer::SetPosixSignalHandler(int signum, 14555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void (*handler)(int)) { 14565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // If handler is SIG_IGN or SIG_DFL then clear our user-level handler, 14575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // otherwise set one. 14585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (handler == SIG_IGN || handler == SIG_DFL) { 14595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!InstallSignal(signum, handler)) { 14605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 14615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (signal_dispatcher_) { 14635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org signal_dispatcher_->ClearHandler(signum); 14645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!signal_dispatcher_->HasHandlers()) { 14655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org signal_dispatcher_.reset(); 14665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 14695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!signal_dispatcher_) { 14705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org signal_dispatcher_.reset(new PosixSignalDispatcher(this)); 14715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org signal_dispatcher_->SetHandler(signum, handler); 14735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!InstallSignal(signum, &GlobalSignalHandler)) { 14745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 14755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 14785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 14795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 14805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgDispatcher* PhysicalSocketServer::signal_dispatcher() { 14815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return signal_dispatcher_.get(); 14825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 14835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 14845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool PhysicalSocketServer::InstallSignal(int signum, void (*handler)(int)) { 14855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org struct sigaction act; 14865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // It doesn't really matter what we set this mask to. 14875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (sigemptyset(&act.sa_mask) != 0) { 14885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_ERR(LS_ERROR) << "Couldn't set mask"; 14895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 14905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 14915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org act.sa_handler = handler; 14925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Use SA_RESTART so that our syscalls don't get EINTR, since we don't need it 14935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // and it's a nuisance. Though some syscalls still return EINTR and there's no 14945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // real standard for which ones. :( 14955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org act.sa_flags = SA_RESTART; 14965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (sigaction(signum, &act, NULL) != 0) { 14975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_ERR(LS_ERROR) << "Couldn't set sigaction"; 14985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 14995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 15005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 15015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 15025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif // POSIX 15035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 15045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef WIN32 15055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool PhysicalSocketServer::Wait(int cmsWait, bool process_io) { 15065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int cmsTotal = cmsWait; 15075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int cmsElapsed = 0; 15085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 msStart = Time(); 15095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 15105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#if LOGGING 15115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (last_tick_dispatch_count_ == 0) { 15125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org last_tick_tracked_ = msStart; 15135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 15145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 15155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 15165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org fWait_ = true; 15175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org while (fWait_) { 15185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::vector<WSAEVENT> events; 15195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::vector<Dispatcher *> event_owners; 15205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 15215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org events.push_back(socket_ev_); 15225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 15235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org { 15245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CritScope cr(&crit_); 15255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t i = 0; 15265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org iterators_.push_back(&i); 15275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Don't track dispatchers_.size(), because we want to pick up any new 15285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // dispatchers that were added while processing the loop. 15295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org while (i < dispatchers_.size()) { 15305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Dispatcher* disp = dispatchers_[i++]; 15315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!process_io && (disp != signal_wakeup_)) 15325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org continue; 15335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SOCKET s = disp->GetSocket(); 15345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (disp->CheckSignalClose()) { 15355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // We just signalled close, don't poll this socket 15365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (s != INVALID_SOCKET) { 15375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org WSAEventSelect(s, 15385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org events[0], 15395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org FlagsToEvents(disp->GetRequestedEvents())); 15405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 15415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org events.push_back(disp->GetWSAEvent()); 15425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org event_owners.push_back(disp); 15435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 15445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 15455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(iterators_.back() == &i); 15465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org iterators_.pop_back(); 15475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 15485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 15495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Which is shorter, the delay wait or the asked wait? 15505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 15515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int cmsNext; 15525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (cmsWait == kForever) { 15535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org cmsNext = cmsWait; 15545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 15555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org cmsNext = _max(0, cmsTotal - cmsElapsed); 15565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 15575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 15585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Wait for one of the events to signal 15595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org DWORD dw = WSAWaitForMultipleEvents(static_cast<DWORD>(events.size()), 15605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org &events[0], 15615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org false, 15625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org cmsNext, 15635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org false); 15645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 15655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#if 0 // LOGGING 15665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // we track this information purely for logging purposes. 15675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org last_tick_dispatch_count_++; 15685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (last_tick_dispatch_count_ >= 1000) { 15695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int32 elapsed = TimeSince(last_tick_tracked_); 15705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(INFO) << "PhysicalSocketServer took " << elapsed 15715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << "ms for 1000 events"; 15725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 15735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // If we get more than 1000 events in a second, we are spinning badly 15745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // (normally it should take about 8-20 seconds). 15755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(elapsed > 1000); 15765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 15775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org last_tick_tracked_ = Time(); 15785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org last_tick_dispatch_count_ = 0; 15795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 15805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 15815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 15825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (dw == WSA_WAIT_FAILED) { 15835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Failed? 15845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO: need a better strategy than this! 15855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int error = WSAGetLastError(); 15865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(false); 15875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 15885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (dw == WSA_WAIT_TIMEOUT) { 15895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Timeout? 15905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 15915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 15925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Figure out which one it is and call it 15935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CritScope cr(&crit_); 15945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int index = dw - WSA_WAIT_EVENT_0; 15955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (index > 0) { 15965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org --index; // The first event is the socket event 15975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org event_owners[index]->OnPreEvent(0); 15985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org event_owners[index]->OnEvent(0, 0); 15995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (process_io) { 16005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t i = 0, end = dispatchers_.size(); 16015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org iterators_.push_back(&i); 16025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org iterators_.push_back(&end); // Don't iterate over new dispatchers. 16035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org while (i < end) { 16045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Dispatcher* disp = dispatchers_[i++]; 16055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SOCKET s = disp->GetSocket(); 16065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (s == INVALID_SOCKET) 16075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org continue; 16085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 16095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org WSANETWORKEVENTS wsaEvents; 16105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int err = WSAEnumNetworkEvents(s, events[0], &wsaEvents); 16115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (err == 0) { 16125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 16135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#if LOGGING 16145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org { 16155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((wsaEvents.lNetworkEvents & FD_READ) && 16165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org wsaEvents.iErrorCode[FD_READ_BIT] != 0) { 16175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(WARNING) << "PhysicalSocketServer got FD_READ_BIT error " 16185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << wsaEvents.iErrorCode[FD_READ_BIT]; 16195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((wsaEvents.lNetworkEvents & FD_WRITE) && 16215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org wsaEvents.iErrorCode[FD_WRITE_BIT] != 0) { 16225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(WARNING) << "PhysicalSocketServer got FD_WRITE_BIT error " 16235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << wsaEvents.iErrorCode[FD_WRITE_BIT]; 16245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((wsaEvents.lNetworkEvents & FD_CONNECT) && 16265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org wsaEvents.iErrorCode[FD_CONNECT_BIT] != 0) { 16275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(WARNING) << "PhysicalSocketServer got FD_CONNECT_BIT error " 16285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << wsaEvents.iErrorCode[FD_CONNECT_BIT]; 16295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((wsaEvents.lNetworkEvents & FD_ACCEPT) && 16315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org wsaEvents.iErrorCode[FD_ACCEPT_BIT] != 0) { 16325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(WARNING) << "PhysicalSocketServer got FD_ACCEPT_BIT error " 16335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << wsaEvents.iErrorCode[FD_ACCEPT_BIT]; 16345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((wsaEvents.lNetworkEvents & FD_CLOSE) && 16365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org wsaEvents.iErrorCode[FD_CLOSE_BIT] != 0) { 16375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(WARNING) << "PhysicalSocketServer got FD_CLOSE_BIT error " 16385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << wsaEvents.iErrorCode[FD_CLOSE_BIT]; 16395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 16425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 ff = 0; 16435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int errcode = 0; 16445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (wsaEvents.lNetworkEvents & FD_READ) 16455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ff |= DE_READ; 16465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (wsaEvents.lNetworkEvents & FD_WRITE) 16475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ff |= DE_WRITE; 16485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (wsaEvents.lNetworkEvents & FD_CONNECT) { 16495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (wsaEvents.iErrorCode[FD_CONNECT_BIT] == 0) { 16505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ff |= DE_CONNECT; 16515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 16525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ff |= DE_CLOSE; 16535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org errcode = wsaEvents.iErrorCode[FD_CONNECT_BIT]; 16545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (wsaEvents.lNetworkEvents & FD_ACCEPT) 16575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ff |= DE_ACCEPT; 16585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (wsaEvents.lNetworkEvents & FD_CLOSE) { 16595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ff |= DE_CLOSE; 16605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org errcode = wsaEvents.iErrorCode[FD_CLOSE_BIT]; 16615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ff != 0) { 16635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org disp->OnPreEvent(ff); 16645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org disp->OnEvent(ff, errcode); 16655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(iterators_.back() == &end); 16695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org iterators_.pop_back(); 16705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(iterators_.back() == &i); 16715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org iterators_.pop_back(); 16725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 16745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Reset the network event until new activity occurs 16755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org WSAResetEvent(socket_ev_); 16765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 16785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Break? 16795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!fWait_) 16805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 16815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org cmsElapsed = TimeSince(msStart); 16825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((cmsWait != kForever) && (cmsElapsed >= cmsWait)) { 16835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 16845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 16865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 16875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Done 16885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 16895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 16905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif // WIN32 16915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 16925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} // namespace talk_base 1693