15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/* 25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle 35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2004--2005, Google Inc. 45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without 65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met: 75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * this list of conditions and the following disclaimer. 105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * this list of conditions and the following disclaimer in the documentation 125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * and/or other materials provided with the distribution. 135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 3. The name of the author may not be used to endorse or promote products 145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * derived from this software without specific prior written permission. 155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */ 275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/virtualsocketserver.h" 295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <errno.h> 315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <algorithm> 335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <cmath> 345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <map> 355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <vector> 365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/common.h" 385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/logging.h" 395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/physicalsocketserver.h" 405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/socketaddresspair.h" 415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/thread.h" 425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/timeutils.h" 435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace talk_base { 455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef WIN32 465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst in_addr kInitialNextIPv4 = { {0x01, 0, 0, 0} }; 475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#else 485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// This value is entirely arbitrary, hence the lack of concern about endianness. 495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst in_addr kInitialNextIPv4 = { 0x01000000 }; 505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Starts at ::2 so as to not cause confusion with ::1. 525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst in6_addr kInitialNextIPv6 = { { { 535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } } }; 555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst uint16 kFirstEphemeralPort = 49152; 575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst uint16 kLastEphemeralPort = 65535; 585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst uint16 kEphemeralPortCount = kLastEphemeralPort - kFirstEphemeralPort + 1; 595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst uint32 kDefaultNetworkCapacity = 64 * 1024; 605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst uint32 kDefaultTcpBufferSize = 32 * 1024; 615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst uint32 UDP_HEADER_SIZE = 28; // IP + UDP headers 635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst uint32 TCP_HEADER_SIZE = 40; // IP + TCP headers 645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst uint32 TCP_MSS = 1400; // Maximum segment size 655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Note: The current algorithm doesn't work for sample sizes smaller than this. 675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst int NUM_SAMPLES = 1000; 685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgenum { 705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org MSG_ID_PACKET, 715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org MSG_ID_CONNECT, 725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org MSG_ID_DISCONNECT, 735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Packets are passed between sockets as messages. We copy the data just like 765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// the kernel does. 775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass Packet : public MessageData { 785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Packet(const char* data, size_t size, const SocketAddress& from) 805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : size_(size), consumed_(0), from_(from) { 815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(NULL != data); 825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org data_ = new char[size_]; 835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::memcpy(data_, data, size_); 845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual ~Packet() { 875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete[] data_; 885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const char* data() const { return data_ + consumed_; } 915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t size() const { return size_ - consumed_; } 925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const SocketAddress& from() const { return from_; } 935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Remove the first size bytes from the data. 955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void Consume(size_t size) { 965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(size + consumed_ < size_); 975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org consumed_ += size; 985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org private: 1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org char* data_; 1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t size_, consumed_; 1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress from_; 1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstruct MessageAddress : public MessageData { 1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org explicit MessageAddress(const SocketAddress& a) : addr(a) { } 1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress addr; 1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Implements the socket interface using the virtual network. Packets are 1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// passed as messages using the message queue of the socket server. 1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass VirtualSocket : public AsyncSocket, public MessageHandler { 1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocket(VirtualSocketServer* server, int family, int type, bool async) 1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : server_(server), family_(family), type_(type), async_(async), 117c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org state_(CS_CLOSED), error_(0), listen_queue_(NULL), 118c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org write_enabled_(false), 1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org network_size_(0), recv_buffer_size_(0), bound_(false), was_any_(false) { 1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT((type_ == SOCK_DGRAM) || (type_ == SOCK_STREAM)); 1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(async_ || (type_ != SOCK_STREAM)); // We only support async streams 1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual ~VirtualSocket() { 1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Close(); 1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (RecvBuffer::iterator it = recv_buffer_.begin(); 1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org it != recv_buffer_.end(); ++it) { 1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete *it; 1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual SocketAddress GetLocalAddress() const { 1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return local_addr_; 1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual SocketAddress GetRemoteAddress() const { 1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return remote_addr_; 1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Used by server sockets to set the local address without binding. 1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void SetLocalAddress(const SocketAddress& addr) { 1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org local_addr_ = addr; 1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int Bind(const SocketAddress& addr) { 1475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!local_addr_.IsNil()) { 1485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = EINVAL; 1495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 1505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org local_addr_ = addr; 1525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int result = server_->Bind(this, &local_addr_); 1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (result != 0) { 1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org local_addr_.Clear(); 1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = EADDRINUSE; 1565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 1575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bound_ = true; 1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org was_any_ = addr.IsAnyIP(); 1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return result; 1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int Connect(const SocketAddress& addr) { 1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return InitiateConnect(addr, true); 1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int Close() { 1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!local_addr_.IsNil() && bound_) { 1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Remove from the binding table. 1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->Unbind(local_addr_, this); 1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bound_ = false; 1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (SOCK_STREAM == type_) { 1755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Cancel pending sockets 1765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (listen_queue_) { 1775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org while (!listen_queue_->empty()) { 1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress addr = listen_queue_->front(); 1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Disconnect listening socket. 1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->Disconnect(server_->LookupBinding(addr)); 1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org listen_queue_->pop_front(); 1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete listen_queue_; 1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org listen_queue_ = NULL; 1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Disconnect stream sockets 1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (CS_CONNECTED == state_) { 1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Disconnect remote socket, check if it is a child of a server socket. 1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocket* socket = 1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->LookupConnection(local_addr_, remote_addr_); 1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!socket) { 1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Not a server socket child, then see if it is bound. 1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO: If this is indeed a server socket that has no 1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // children this will cause the server socket to be 1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // closed. This might lead to unexpected results, how to fix this? 1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket = server_->LookupBinding(remote_addr_); 1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->Disconnect(socket); 2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Remove mapping for both directions. 2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->RemoveConnection(remote_addr_, local_addr_); 2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->RemoveConnection(local_addr_, remote_addr_); 2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Cancel potential connects 2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org MessageList msgs; 2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (server_->msg_queue_) { 2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->msg_queue_->Clear(this, MSG_ID_CONNECT, &msgs); 2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (MessageList::iterator it = msgs.begin(); it != msgs.end(); ++it) { 2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(NULL != it->pdata); 2125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org MessageAddress* data = static_cast<MessageAddress*>(it->pdata); 2135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Lookup remote side. 2155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocket* socket = server_->LookupConnection(local_addr_, 2165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org data->addr); 2175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (socket) { 2185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Server socket, remote side is a socket retreived by 2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // accept. Accepted sockets are not bound so we will not 2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // find it by looking in the bindings table. 2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->Disconnect(socket); 2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->RemoveConnection(local_addr_, data->addr); 2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 2245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->Disconnect(server_->LookupBinding(data->addr)); 2255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete data; 2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Clear incoming packets and disconnect messages 2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (server_->msg_queue_) { 2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->msg_queue_->Clear(this); 2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CLOSED; 2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org local_addr_.Clear(); 2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org remote_addr_.Clear(); 2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int Send(const void *pv, size_t cb) { 2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (CS_CONNECTED != state_) { 2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = ENOTCONN; 2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (SOCK_DGRAM == type_) { 2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SendUdp(pv, cb, remote_addr_); 2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SendTcp(pv, cb); 2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int SendTo(const void *pv, size_t cb, const SocketAddress& addr) { 2535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (SOCK_DGRAM == type_) { 2545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SendUdp(pv, cb, addr); 2555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 2565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (CS_CONNECTED != state_) { 2575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = ENOTCONN; 2585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 2595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SendTcp(pv, cb); 2615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int Recv(void *pv, size_t cb) { 2655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress addr; 2665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return RecvFrom(pv, cb, &addr); 2675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int RecvFrom(void *pv, size_t cb, SocketAddress *paddr) { 2705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // If we don't have a packet, then either error or wait for one to arrive. 2715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (recv_buffer_.empty()) { 2725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (async_) { 2735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = EAGAIN; 2745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 2755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org while (recv_buffer_.empty()) { 2775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Message msg; 2785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->msg_queue_->Get(&msg); 2795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->msg_queue_->Dispatch(&msg); 2805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Return the packet at the front of the queue. 2845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Packet* packet = recv_buffer_.front(); 2855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t data_read = _min(cb, packet->size()); 2865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::memcpy(pv, packet->data(), data_read); 2875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *paddr = packet->from(); 2885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (data_read < packet->size()) { 2905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org packet->Consume(data_read); 2915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 2925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org recv_buffer_.pop_front(); 2935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete packet; 2945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (SOCK_STREAM == type_) { 2975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool was_full = (recv_buffer_size_ == server_->recv_buffer_capacity_); 2985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org recv_buffer_size_ -= data_read; 2995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (was_full) { 3005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocket* sender = server_->LookupBinding(remote_addr_); 3015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(NULL != sender); 3025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->SendTcp(sender); 3035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return static_cast<int>(data_read); 3075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int Listen(int backlog) { 3105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(SOCK_STREAM == type_); 3115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(CS_CLOSED == state_); 3125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (local_addr_.IsNil()) { 3135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = EINVAL; 3145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 3155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(NULL == listen_queue_); 3175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org listen_queue_ = new ListenQueue; 3185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CONNECTING; 3195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 3205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual VirtualSocket* Accept(SocketAddress *paddr) { 3235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (NULL == listen_queue_) { 3245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = EINVAL; 3255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return NULL; 3265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org while (!listen_queue_->empty()) { 3285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocket* socket = new VirtualSocket(server_, AF_INET, type_, 3295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org async_); 3305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Set the new local address to the same as this server socket. 3325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket->SetLocalAddress(local_addr_); 3335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Sockets made from a socket that 'was Any' need to inherit that. 3345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket->set_was_any(was_any_); 3355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress remote_addr(listen_queue_->front()); 3365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int result = socket->InitiateConnect(remote_addr, false); 3375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org listen_queue_->pop_front(); 3385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (result != 0) { 3395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete socket; 3405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org continue; 3415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket->CompleteConnect(remote_addr, false); 3435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (paddr) { 3445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *paddr = remote_addr; 3455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return socket; 3475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = EWOULDBLOCK; 3495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return NULL; 3505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int GetError() const { 3535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return error_; 3545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void SetError(int error) { 3575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = error; 3585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual ConnState GetState() const { 3615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return state_; 3625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int GetOption(Option opt, int* value) { 3655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org OptionsMap::const_iterator it = options_map_.find(opt); 3665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (it == options_map_.end()) { 3675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 3685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *value = it->second; 3705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; // 0 is success to emulate getsockopt() 3715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int SetOption(Option opt, int value) { 3745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org options_map_[opt] = value; 3755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; // 0 is success to emulate setsockopt() 3765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual int EstimateMTU(uint16* mtu) { 3795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (CS_CONNECTED != state_) 3805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return ENOTCONN; 3815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org else 3825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 65536; 3835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void OnMessage(Message *pmsg) { 3865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (pmsg->message_id == MSG_ID_PACKET) { 3875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org //ASSERT(!local_addr_.IsAny()); 3885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(NULL != pmsg->pdata); 3895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Packet* packet = static_cast<Packet*>(pmsg->pdata); 3905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org recv_buffer_.push_back(packet); 3925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (async_) { 3945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalReadEvent(this); 3955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (pmsg->message_id == MSG_ID_CONNECT) { 3975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(NULL != pmsg->pdata); 3985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org MessageAddress* data = static_cast<MessageAddress*>(pmsg->pdata); 3995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (listen_queue_ != NULL) { 4005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org listen_queue_->push_back(data->addr); 4015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (async_) { 4025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalReadEvent(this); 4035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if ((SOCK_STREAM == type_) && (CS_CONNECTING == state_)) { 4055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CompleteConnect(data->addr, true); 4065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 4075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_VERBOSE) << "Socket at " << local_addr_ << " is not listening"; 4085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->Disconnect(server_->LookupBinding(data->addr)); 4095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete data; 4115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (pmsg->message_id == MSG_ID_DISCONNECT) { 4125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(SOCK_STREAM == type_); 4135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (CS_CLOSED != state_) { 4145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int error = (CS_CONNECTING == state_) ? ECONNREFUSED : 0; 4155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CLOSED; 4165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org remote_addr_.Clear(); 4175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (async_) { 4185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalCloseEvent(this, error); 4195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 4225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(false); 4235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool was_any() { return was_any_; } 4275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void set_was_any(bool was_any) { was_any_ = was_any; } 4285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org private: 4305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org struct NetworkEntry { 4315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t size; 4325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 done_time; 4335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org }; 4345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org typedef std::deque<SocketAddress> ListenQueue; 4365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org typedef std::deque<NetworkEntry> NetworkQueue; 4375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org typedef std::vector<char> SendBuffer; 4385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org typedef std::list<Packet*> RecvBuffer; 4395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org typedef std::map<Option, int> OptionsMap; 4405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int InitiateConnect(const SocketAddress& addr, bool use_delay) { 4425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!remote_addr_.IsNil()) { 4435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = (CS_CONNECTED == state_) ? EISCONN : EINPROGRESS; 4445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 4455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (local_addr_.IsNil()) { 4475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // If there's no local address set, grab a random one in the correct AF. 4485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int result = 0; 4495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (addr.ipaddr().family() == AF_INET) { 4505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org result = Bind(SocketAddress("0.0.0.0", 0)); 4515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (addr.ipaddr().family() == AF_INET6) { 4525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org result = Bind(SocketAddress("::", 0)); 4535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (result != 0) { 4555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return result; 4565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (type_ == SOCK_DGRAM) { 4595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org remote_addr_ = addr; 4605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CONNECTED; 4615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 4625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int result = server_->Connect(this, addr, use_delay); 4635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (result != 0) { 4645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = EHOSTUNREACH; 4655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 4665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CONNECTING; 4685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 4705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void CompleteConnect(const SocketAddress& addr, bool notify) { 4735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(CS_CONNECTING == state_); 4745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org remote_addr_ = addr; 4755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = CS_CONNECTED; 4765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->AddConnection(remote_addr_, local_addr_, this); 4775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (async_ && notify) { 4785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalConnectEvent(this); 4795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int SendUdp(const void* pv, size_t cb, const SocketAddress& addr) { 4835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // If we have not been assigned a local port, then get one. 4845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (local_addr_.IsNil()) { 4855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org local_addr_ = EmptySocketAddressWithFamily(addr.ipaddr().family()); 4865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int result = server_->Bind(this, &local_addr_); 4875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (result != 0) { 4885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org local_addr_.Clear(); 4895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = EADDRINUSE; 4905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return result; 4915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Send the data in a message to the appropriate socket. 4955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return server_->SendUdp(this, static_cast<const char*>(pv), cb, addr); 4965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int SendTcp(const void* pv, size_t cb) { 4995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t capacity = server_->send_buffer_capacity_ - send_buffer_.size(); 5005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (0 == capacity) { 5015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org write_enabled_ = true; 5025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error_ = EWOULDBLOCK; 5035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 5045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t consumed = _min(cb, capacity); 5065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const char* cpv = static_cast<const char*>(pv); 5075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org send_buffer_.insert(send_buffer_.end(), cpv, cpv + consumed); 5085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_->SendTcp(this); 5095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return static_cast<int>(consumed); 5105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocketServer* server_; 5135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int family_; 5145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int type_; 5155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool async_; 5165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ConnState state_; 5175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int error_; 5185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress local_addr_; 5195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress remote_addr_; 5205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Pending sockets which can be Accepted 5225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ListenQueue* listen_queue_; 5235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Data which tcp has buffered for sending 5255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SendBuffer send_buffer_; 5265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool write_enabled_; 5275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Critical section to protect the recv_buffer and queue_ 5295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CriticalSection crit_; 5305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Network model that enforces bandwidth and capacity constraints 5325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NetworkQueue network_; 5335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t network_size_; 5345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Data which has been received from the network 5365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org RecvBuffer recv_buffer_; 5375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // The amount of data which is in flight or in recv_buffer_ 5385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t recv_buffer_size_; 5395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Is this socket bound? 5415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool bound_; 5425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // When we bind a socket to Any, VSS's Bind gives it another address. For 5445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // dual-stack sockets, we want to distinguish between sockets that were 5455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // explicitly given a particular address and sockets that had one picked 5465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // for them by VSS. 5475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool was_any_; 5485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Store the options that are set 5505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org OptionsMap options_map_; 5515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org friend class VirtualSocketServer; 5535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 5545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgVirtualSocketServer::VirtualSocketServer(SocketServer* ss) 5565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : server_(ss), server_owned_(false), msg_queue_(NULL), stop_on_idle_(false), 5575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org network_delay_(Time()), next_ipv4_(kInitialNextIPv4), 5585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org next_ipv6_(kInitialNextIPv6), next_port_(kFirstEphemeralPort), 5595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bindings_(new AddressMap()), connections_(new ConnectionMap()), 5605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bandwidth_(0), network_capacity_(kDefaultNetworkCapacity), 5615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org send_buffer_capacity_(kDefaultTcpBufferSize), 5625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org recv_buffer_capacity_(kDefaultTcpBufferSize), 5635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delay_mean_(0), delay_stddev_(0), delay_samples_(NUM_SAMPLES), 5645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delay_dist_(NULL), drop_prob_(0.0) { 5655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!server_) { 5665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_ = new PhysicalSocketServer(); 5675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org server_owned_ = true; 5685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UpdateDelayDistribution(); 5705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgVirtualSocketServer::~VirtualSocketServer() { 5735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete bindings_; 5745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete connections_; 5755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete delay_dist_; 5765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (server_owned_) { 5775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete server_; 5785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgIPAddress VirtualSocketServer::GetNextIP(int family) { 5825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (family == AF_INET) { 5835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org IPAddress next_ip(next_ipv4_); 5845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org next_ipv4_.s_addr = 5855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org HostToNetwork32(NetworkToHost32(next_ipv4_.s_addr) + 1); 5865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return next_ip; 5875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (family == AF_INET6) { 5885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org IPAddress next_ip(next_ipv6_); 5895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32* as_ints = reinterpret_cast<uint32*>(&next_ipv6_.s6_addr); 5905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org as_ints[3] += 1; 5915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return next_ip; 5925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return IPAddress(); 5945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orguint16 VirtualSocketServer::GetNextPort() { 5975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint16 port = next_port_; 5985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (next_port_ < kLastEphemeralPort) { 5995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ++next_port_; 6005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 6015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org next_port_ = kFirstEphemeralPort; 6025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return port; 6045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSocket* VirtualSocketServer::CreateSocket(int type) { 6075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return CreateSocket(AF_INET, type); 6085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSocket* VirtualSocketServer::CreateSocket(int family, int type) { 6115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return CreateSocketInternal(family, type); 6125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgAsyncSocket* VirtualSocketServer::CreateAsyncSocket(int type) { 6155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return CreateAsyncSocket(AF_INET, type); 6165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgAsyncSocket* VirtualSocketServer::CreateAsyncSocket(int family, int type) { 6195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return CreateSocketInternal(family, type); 6205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgVirtualSocket* VirtualSocketServer::CreateSocketInternal(int family, int type) { 6235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return new VirtualSocket(this, family, type, true); 6245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid VirtualSocketServer::SetMessageQueue(MessageQueue* msg_queue) { 6275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org msg_queue_ = msg_queue; 6285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (msg_queue_) { 6295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org msg_queue_->SignalQueueDestroyed.connect(this, 6305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org &VirtualSocketServer::OnMessageQueueDestroyed); 6315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool VirtualSocketServer::Wait(int cmsWait, bool process_io) { 6355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(msg_queue_ == Thread::Current()); 6365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (stop_on_idle_ && Thread::Current()->empty()) { 6375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 6385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return socketserver()->Wait(cmsWait, process_io); 6405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid VirtualSocketServer::WakeUp() { 6435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socketserver()->WakeUp(); 6445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool VirtualSocketServer::ProcessMessagesUntilIdle() { 6475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(msg_queue_ == Thread::Current()); 6485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org stop_on_idle_ = true; 6495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org while (!msg_queue_->empty()) { 6505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Message msg; 6515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (msg_queue_->Get(&msg, kForever)) { 6525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org msg_queue_->Dispatch(&msg); 6535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org stop_on_idle_ = false; 6565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return !msg_queue_->IsQuitting(); 6575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint VirtualSocketServer::Bind(VirtualSocket* socket, 6605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const SocketAddress& addr) { 6615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(NULL != socket); 6625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Address must be completely specified at this point 6635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(!IPIsUnspec(addr.ipaddr())); 6645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(addr.port() != 0); 6655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Normalize the address (turns v6-mapped addresses into v4-addresses). 6675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress normalized(addr.ipaddr().Normalized(), addr.port()); 6685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org AddressMap::value_type entry(normalized, socket); 6705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return bindings_->insert(entry).second ? 0 : -1; 6715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint VirtualSocketServer::Bind(VirtualSocket* socket, SocketAddress* addr) { 6745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(NULL != socket); 6755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (IPIsAny(addr->ipaddr())) { 6775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org addr->SetIP(GetNextIP(addr->ipaddr().family())); 6785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (!IPIsUnspec(addr->ipaddr())) { 6795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org addr->SetIP(addr->ipaddr().Normalized()); 6805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 6815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(false); 6825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (addr->port() == 0) { 6855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (int i = 0; i < kEphemeralPortCount; ++i) { 6865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org addr->SetPort(GetNextPort()); 6875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (bindings_->find(*addr) == bindings_->end()) { 6885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 6895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return Bind(socket, *addr); 6945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgVirtualSocket* VirtualSocketServer::LookupBinding(const SocketAddress& addr) { 6975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress normalized(addr.ipaddr().Normalized(), 6985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org addr.port()); 6995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org AddressMap::iterator it = bindings_->find(normalized); 7005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return (bindings_->end() != it) ? it->second : NULL; 7015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 7025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint VirtualSocketServer::Unbind(const SocketAddress& addr, 7045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocket* socket) { 7055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress normalized(addr.ipaddr().Normalized(), 7065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org addr.port()); 7075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT((*bindings_)[normalized] == socket); 7085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bindings_->erase(bindings_->find(normalized)); 7095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 7105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 7115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid VirtualSocketServer::AddConnection(const SocketAddress& local, 7135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const SocketAddress& remote, 7145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocket* remote_socket) { 7155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Add this socket pair to our routing table. This will allow 7165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // multiple clients to connect to the same server address. 7175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress local_normalized(local.ipaddr().Normalized(), 7185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org local.port()); 7195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress remote_normalized(remote.ipaddr().Normalized(), 7205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org remote.port()); 7215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddressPair address_pair(local_normalized, remote_normalized); 7225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org connections_->insert(std::pair<SocketAddressPair, 7235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocket*>(address_pair, remote_socket)); 7245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 7255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgVirtualSocket* VirtualSocketServer::LookupConnection( 7275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const SocketAddress& local, 7285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const SocketAddress& remote) { 7295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress local_normalized(local.ipaddr().Normalized(), 7305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org local.port()); 7315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress remote_normalized(remote.ipaddr().Normalized(), 7325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org remote.port()); 7335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddressPair address_pair(local_normalized, remote_normalized); 7345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ConnectionMap::iterator it = connections_->find(address_pair); 7355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return (connections_->end() != it) ? it->second : NULL; 7365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 7375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid VirtualSocketServer::RemoveConnection(const SocketAddress& local, 7395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const SocketAddress& remote) { 7405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress local_normalized(local.ipaddr().Normalized(), 7415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org local.port()); 7425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress remote_normalized(remote.ipaddr().Normalized(), 7435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org remote.port()); 7445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddressPair address_pair(local_normalized, remote_normalized); 7455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org connections_->erase(address_pair); 7465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 7475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic double Random() { 7495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return static_cast<double>(rand()) / RAND_MAX; 7505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 7515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint VirtualSocketServer::Connect(VirtualSocket* socket, 7535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const SocketAddress& remote_addr, 7545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool use_delay) { 7555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 delay = use_delay ? GetRandomTransitDelay() : 0; 7565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocket* remote = LookupBinding(remote_addr); 7575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!CanInteractWith(socket, remote)) { 7585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Address family mismatch between " 7595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << socket->GetLocalAddress() << " and " << remote_addr; 7605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 7615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (remote != NULL) { 7635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SocketAddress addr = socket->GetLocalAddress(); 7645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org msg_queue_->PostDelayed(delay, remote, MSG_ID_CONNECT, 7655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org new MessageAddress(addr)); 7665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 7675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "No one listening at " << remote_addr; 7685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org msg_queue_->PostDelayed(delay, socket, MSG_ID_DISCONNECT); 7695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 7715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 7725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool VirtualSocketServer::Disconnect(VirtualSocket* socket) { 7745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (socket) { 7755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Remove the mapping. 7765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org msg_queue_->Post(socket, MSG_ID_DISCONNECT); 7775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 7785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 7805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 7815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint VirtualSocketServer::SendUdp(VirtualSocket* socket, 7835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const char* data, size_t data_size, 7845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const SocketAddress& remote_addr) { 7855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // See if we want to drop this packet. 7865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (Random() < drop_prob_) { 7875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_VERBOSE) << "Dropping packet: bad luck"; 7885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return static_cast<int>(data_size); 7895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocket* recipient = LookupBinding(remote_addr); 7925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!recipient) { 7935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Make a fake recipient for address family checking. 7945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org scoped_ptr<VirtualSocket> dummy_socket( 7955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CreateSocketInternal(AF_INET, SOCK_DGRAM)); 7965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dummy_socket->SetLocalAddress(remote_addr); 7975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!CanInteractWith(socket, dummy_socket.get())) { 7985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_VERBOSE) << "Incompatible address families: " 7995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << socket->GetLocalAddress() << " and " << remote_addr; 8005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 8015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_VERBOSE) << "No one listening at " << remote_addr; 8035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return static_cast<int>(data_size); 8045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!CanInteractWith(socket, recipient)) { 8075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_VERBOSE) << "Incompatible address families: " 8085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << socket->GetLocalAddress() << " and " << remote_addr; 8095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 8105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CritScope cs(&socket->crit_); 8135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 cur_time = Time(); 8155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PurgeNetworkPackets(socket, cur_time); 8165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Determine whether we have enough bandwidth to accept this packet. To do 8185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // this, we need to update the send queue. Once we know it's current size, 8195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // we know whether we can fit this packet. 8205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // 8215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // NOTE: There are better algorithms for maintaining such a queue (such as 8225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // "Derivative Random Drop"); however, this algorithm is a more accurate 8235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // simulation of what a normal network would do. 8245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t packet_size = data_size + UDP_HEADER_SIZE; 8265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (socket->network_size_ + packet_size > network_capacity_) { 8275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_VERBOSE) << "Dropping packet: network capacity exceeded"; 8285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return static_cast<int>(data_size); 8295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org AddPacketToNetwork(socket, recipient, cur_time, data, data_size, 8325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UDP_HEADER_SIZE, false); 8335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return static_cast<int>(data_size); 8355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 8365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid VirtualSocketServer::SendTcp(VirtualSocket* socket) { 8385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TCP can't send more data than will fill up the receiver's buffer. 8395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // We track the data that is in the buffer plus data in flight using the 8405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // recipient's recv_buffer_size_. Anything beyond that must be stored in the 8415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // sender's buffer. We will trigger the buffered data to be sent when data 8425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // is read from the recv_buffer. 8435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Lookup the local/remote pair in the connections table. 8455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocket* recipient = LookupConnection(socket->local_addr_, 8465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket->remote_addr_); 8475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!recipient) { 8485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_VERBOSE) << "Sending data to no one."; 8495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return; 8505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CritScope cs(&socket->crit_); 8535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 cur_time = Time(); 8555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PurgeNetworkPackets(socket, cur_time); 8565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org while (true) { 8585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t available = recv_buffer_capacity_ - recipient->recv_buffer_size_; 8595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t max_data_size = _min<size_t>(available, TCP_MSS - TCP_HEADER_SIZE); 8605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t data_size = _min(socket->send_buffer_.size(), max_data_size); 8615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (0 == data_size) 8625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 8635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org AddPacketToNetwork(socket, recipient, cur_time, &socket->send_buffer_[0], 8655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org data_size, TCP_HEADER_SIZE, true); 8665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org recipient->recv_buffer_size_ += data_size; 8675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t new_buffer_size = socket->send_buffer_.size() - data_size; 8695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Avoid undefined access beyond the last element of the vector. 8705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // This only happens when new_buffer_size is 0. 8715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (data_size < socket->send_buffer_.size()) { 8725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // memmove is required for potentially overlapping source/destination. 8735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org memmove(&socket->send_buffer_[0], &socket->send_buffer_[data_size], 8745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org new_buffer_size); 8755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket->send_buffer_.resize(new_buffer_size); 8775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (socket->write_enabled_ 8805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org && (socket->send_buffer_.size() < send_buffer_capacity_)) { 8815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket->write_enabled_ = false; 8825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket->SignalWriteEvent(socket); 8835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 8855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid VirtualSocketServer::AddPacketToNetwork(VirtualSocket* sender, 8875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocket* recipient, 8885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 cur_time, 8895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const char* data, 8905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t data_size, 8915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t header_size, 8925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool ordered) { 8935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocket::NetworkEntry entry; 8945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org entry.size = data_size + header_size; 8955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sender->network_size_ += entry.size; 8975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 send_delay = SendDelay(static_cast<uint32>(sender->network_size_)); 8985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org entry.done_time = cur_time + send_delay; 8995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sender->network_.push_back(entry); 9005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Find the delay for crossing the many virtual hops of the network. 9025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 transit_delay = GetRandomTransitDelay(); 9035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Post the packet as a message to be delivered (on our own thread) 9055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Packet* p = new Packet(data, data_size, sender->local_addr_); 9065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 ts = TimeAfter(send_delay + transit_delay); 9075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ordered) { 9085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Ensure that new packets arrive after previous ones 9095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO: consider ordering on a per-socket basis, since this 9105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // introduces artifical delay. 9115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ts = TimeMax(ts, network_delay_); 9125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org msg_queue_->PostAt(ts, recipient, MSG_ID_PACKET, p); 9145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org network_delay_ = TimeMax(ts, network_delay_); 9155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid VirtualSocketServer::PurgeNetworkPackets(VirtualSocket* socket, 9185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 cur_time) { 9195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org while (!socket->network_.empty() && 9205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org (socket->network_.front().done_time <= cur_time)) { 9215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(socket->network_size_ >= socket->network_.front().size); 9225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket->network_size_ -= socket->network_.front().size; 9235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org socket->network_.pop_front(); 9245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orguint32 VirtualSocketServer::SendDelay(uint32 size) { 9285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (bandwidth_ == 0) 9295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 9305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org else 9315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 1000 * size / bandwidth_; 9325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#if 0 9355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PrintFunction(std::vector<std::pair<double, double> >* f) { 9365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return; 9375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double sum = 0; 9385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (uint32 i = 0; i < f->size(); ++i) { 9395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::cout << (*f)[i].first << '\t' << (*f)[i].second << std::endl; 9405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sum += (*f)[i].second; 9415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!f->empty()) { 9435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const double mean = sum / f->size(); 9445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double sum_sq_dev = 0; 9455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (uint32 i = 0; i < f->size(); ++i) { 9465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double dev = (*f)[i].second - mean; 9475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sum_sq_dev += dev * dev; 9485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::cout << "Mean = " << mean << " StdDev = " 9505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << sqrt(sum_sq_dev / f->size()) << std::endl; 9515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif // <unused> 9545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid VirtualSocketServer::UpdateDelayDistribution() { 9565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Function* dist = CreateDistribution(delay_mean_, delay_stddev_, 9575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delay_samples_); 9585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // We take a lock just to make sure we don't leak memory. 9595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org { 9605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CritScope cs(&delay_crit_); 9615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete delay_dist_; 9625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delay_dist_ = dist; 9635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic double PI = 4 * std::atan(1.0); 9675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic double Normal(double x, double mean, double stddev) { 9695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double a = (x - mean) * (x - mean) / (2 * stddev * stddev); 9705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return std::exp(-a) / (stddev * sqrt(2 * PI)); 9715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#if 0 // static unused gives a warning 9745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic double Pareto(double x, double min, double k) { 9755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (x < min) 9765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 9775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org else 9785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return k * std::pow(min, k) / std::pow(x, k+1); 9795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 9815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgVirtualSocketServer::Function* VirtualSocketServer::CreateDistribution( 9835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32 mean, uint32 stddev, uint32 samples) { 9845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Function* f = new Function(); 9855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (0 == stddev) { 9875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org f->push_back(Point(mean, 1.0)); 9885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 9895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double start = 0; 9905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (mean >= 4 * static_cast<double>(stddev)) 9915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org start = mean - 4 * static_cast<double>(stddev); 9925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double end = mean + 4 * static_cast<double>(stddev); 9935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (uint32 i = 0; i < samples; i++) { 9955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double x = start + (end - start) * i / (samples - 1); 9965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double y = Normal(x, mean, stddev); 9975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org f->push_back(Point(x, y)); 9985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return Resample(Invert(Accumulate(f)), 0, 1, samples); 10015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 10025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orguint32 VirtualSocketServer::GetRandomTransitDelay() { 10045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t index = rand() % delay_dist_->size(); 10055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double delay = (*delay_dist_)[index].second; 10065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org //LOG_F(LS_INFO) << "random[" << index << "] = " << delay; 10075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return static_cast<uint32>(delay); 10085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 10095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstruct FunctionDomainCmp { 10115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool operator()(const VirtualSocketServer::Point& p1, 10125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const VirtualSocketServer::Point& p2) { 10135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return p1.first < p2.first; 10145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool operator()(double v1, const VirtualSocketServer::Point& p2) { 10165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return v1 < p2.first; 10175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool operator()(const VirtualSocketServer::Point& p1, double v2) { 10195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return p1.first < v2; 10205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 10225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgVirtualSocketServer::Function* VirtualSocketServer::Accumulate(Function* f) { 10245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(f->size() >= 1); 10255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double v = 0; 10265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (Function::size_type i = 0; i < f->size() - 1; ++i) { 10275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double dx = (*f)[i + 1].first - (*f)[i].first; 10285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double avgy = ((*f)[i + 1].second + (*f)[i].second) / 2; 10295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org (*f)[i].second = v; 10305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org v = v + dx * avgy; 10315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org (*f)[f->size()-1].second = v; 10335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return f; 10345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 10355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgVirtualSocketServer::Function* VirtualSocketServer::Invert(Function* f) { 10375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (Function::size_type i = 0; i < f->size(); ++i) 10385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::swap((*f)[i].first, (*f)[i].second); 10395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::sort(f->begin(), f->end(), FunctionDomainCmp()); 10415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return f; 10425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 10435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgVirtualSocketServer::Function* VirtualSocketServer::Resample( 10455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Function* f, double x1, double x2, uint32 samples) { 10465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Function* g = new Function(); 10475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (size_t i = 0; i < samples; i++) { 10495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double x = x1 + (x2 - x1) * i / (samples - 1); 10505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double y = Evaluate(f, x); 10515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org g->push_back(Point(x, y)); 10525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete f; 10555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return g; 10565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 10575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgdouble VirtualSocketServer::Evaluate(Function* f, double x) { 10595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Function::iterator iter = 10605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::lower_bound(f->begin(), f->end(), x, FunctionDomainCmp()); 10615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (iter == f->begin()) { 10625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return (*f)[0].second; 10635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (iter == f->end()) { 10645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(f->size() >= 1); 10655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return (*f)[f->size() - 1].second; 10665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (iter->first == x) { 10675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return iter->second; 10685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 10695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double x1 = (iter - 1)->first; 10705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double y1 = (iter - 1)->second; 10715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double x2 = iter->first; 10725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org double y2 = iter->second; 10735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return y1 + (y2 - y1) * (x - x1) / (x2 - x1); 10745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 10765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool VirtualSocketServer::CanInteractWith(VirtualSocket* local, 10785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org VirtualSocket* remote) { 10795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!local || !remote) { 10805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 10815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org IPAddress local_ip = local->GetLocalAddress().ipaddr(); 10835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org IPAddress remote_ip = remote->GetLocalAddress().ipaddr(); 10845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org IPAddress local_normalized = local_ip.Normalized(); 10855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org IPAddress remote_normalized = remote_ip.Normalized(); 10865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Check if the addresses are the same family after Normalization (turns 10875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // mapped IPv6 address into IPv4 addresses). 10885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // This will stop unmapped V6 addresses from talking to mapped V6 addresses. 10895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (local_normalized.family() == remote_normalized.family()) { 10905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 10915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // If ip1 is IPv4 and ip2 is :: and ip2 is not IPV6_V6ONLY. 10945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int remote_v6_only = 0; 10955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org remote->GetOption(Socket::OPT_IPV6_V6ONLY, &remote_v6_only); 10965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (local_ip.family() == AF_INET && !remote_v6_only && IPIsAny(remote_ip)) { 10975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 10985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 10995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Same check, backwards. 11005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int local_v6_only = 0; 11015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org local->GetOption(Socket::OPT_IPV6_V6ONLY, &local_v6_only); 11025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (remote_ip.family() == AF_INET && !local_v6_only && IPIsAny(local_ip)) { 11035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 11045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Check to see if either socket was explicitly bound to IPv6-any. 11075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // These sockets can talk with anyone. 11085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (local_ip.family() == AF_INET6 && local->was_any()) { 11095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 11105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (remote_ip.family() == AF_INET6 && remote->was_any()) { 11125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 11135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 11145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 11165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 11175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 11185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} // namespace talk_base 1119