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