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