Home | History | Annotate | Download | only in p2p
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/renderer/p2p/ipc_socket_factory.h"
      6 
      7 #include <algorithm>
      8 #include <deque>
      9 
     10 #include "base/compiler_specific.h"
     11 #include "base/debug/trace_event.h"
     12 #include "base/message_loop/message_loop.h"
     13 #include "base/message_loop/message_loop_proxy.h"
     14 #include "base/metrics/histogram.h"
     15 #include "base/strings/stringprintf.h"
     16 #include "base/threading/non_thread_safe.h"
     17 #include "content/renderer/media/webrtc_logging.h"
     18 #include "content/renderer/p2p/host_address_request.h"
     19 #include "content/renderer/p2p/socket_client_delegate.h"
     20 #include "content/renderer/p2p/socket_client_impl.h"
     21 #include "content/renderer/p2p/socket_dispatcher.h"
     22 #include "jingle/glue/utils.h"
     23 #include "third_party/webrtc/base/asyncpacketsocket.h"
     24 
     25 namespace content {
     26 
     27 namespace {
     28 
     29 const int kDefaultNonSetOptionValue = -1;
     30 
     31 bool IsTcpClientSocket(P2PSocketType type) {
     32   return (type == P2P_SOCKET_STUN_TCP_CLIENT) ||
     33          (type == P2P_SOCKET_TCP_CLIENT) ||
     34          (type == P2P_SOCKET_STUN_SSLTCP_CLIENT) ||
     35          (type == P2P_SOCKET_SSLTCP_CLIENT) ||
     36          (type == P2P_SOCKET_TLS_CLIENT) ||
     37          (type == P2P_SOCKET_STUN_TLS_CLIENT);
     38 }
     39 
     40 bool JingleSocketOptionToP2PSocketOption(rtc::Socket::Option option,
     41                                          P2PSocketOption* ipc_option) {
     42   switch (option) {
     43     case rtc::Socket::OPT_RCVBUF:
     44       *ipc_option = P2P_SOCKET_OPT_RCVBUF;
     45       break;
     46     case rtc::Socket::OPT_SNDBUF:
     47       *ipc_option = P2P_SOCKET_OPT_SNDBUF;
     48       break;
     49     case rtc::Socket::OPT_DSCP:
     50       *ipc_option = P2P_SOCKET_OPT_DSCP;
     51       break;
     52     case rtc::Socket::OPT_DONTFRAGMENT:
     53     case rtc::Socket::OPT_NODELAY:
     54     case rtc::Socket::OPT_IPV6_V6ONLY:
     55     case rtc::Socket::OPT_RTP_SENDTIME_EXTN_ID:
     56       return false;  // Not supported by the chrome sockets.
     57     default:
     58       NOTREACHED();
     59       return false;
     60   }
     61   return true;
     62 }
     63 
     64 // TODO(miu): This needs tuning.  http://crbug.com/237960
     65 const size_t kMaximumInFlightBytes = 64 * 1024;  // 64 KB
     66 
     67 // IpcPacketSocket implements rtc::AsyncPacketSocket interface
     68 // using P2PSocketClient that works over IPC-channel. It must be used
     69 // on the thread it was created.
     70 class IpcPacketSocket : public rtc::AsyncPacketSocket,
     71                         public P2PSocketClientDelegate {
     72  public:
     73   IpcPacketSocket();
     74   virtual ~IpcPacketSocket();
     75 
     76   // Always takes ownership of client even if initialization fails.
     77   bool Init(P2PSocketType type, P2PSocketClientImpl* client,
     78             const rtc::SocketAddress& local_address,
     79             const rtc::SocketAddress& remote_address);
     80 
     81   // rtc::AsyncPacketSocket interface.
     82   virtual rtc::SocketAddress GetLocalAddress() const OVERRIDE;
     83   virtual rtc::SocketAddress GetRemoteAddress() const OVERRIDE;
     84   virtual int Send(const void *pv, size_t cb,
     85                    const rtc::PacketOptions& options) OVERRIDE;
     86   virtual int SendTo(const void *pv, size_t cb,
     87                      const rtc::SocketAddress& addr,
     88                      const rtc::PacketOptions& options) OVERRIDE;
     89   virtual int Close() OVERRIDE;
     90   virtual State GetState() const OVERRIDE;
     91   virtual int GetOption(rtc::Socket::Option option, int* value) OVERRIDE;
     92   virtual int SetOption(rtc::Socket::Option option, int value) OVERRIDE;
     93   virtual int GetError() const OVERRIDE;
     94   virtual void SetError(int error) OVERRIDE;
     95 
     96   // P2PSocketClientDelegate implementation.
     97   virtual void OnOpen(const net::IPEndPoint& local_address,
     98                       const net::IPEndPoint& remote_address) OVERRIDE;
     99   virtual void OnIncomingTcpConnection(
    100       const net::IPEndPoint& address,
    101       P2PSocketClient* client) OVERRIDE;
    102   virtual void OnSendComplete() OVERRIDE;
    103   virtual void OnError() OVERRIDE;
    104   virtual void OnDataReceived(const net::IPEndPoint& address,
    105                               const std::vector<char>& data,
    106                               const base::TimeTicks& timestamp) OVERRIDE;
    107 
    108  private:
    109   enum InternalState {
    110     IS_UNINITIALIZED,
    111     IS_OPENING,
    112     IS_OPEN,
    113     IS_CLOSED,
    114     IS_ERROR,
    115   };
    116 
    117   // Increment the counter for consecutive bytes discarded as socket is running
    118   // out of buffer.
    119   void IncrementDiscardCounters(size_t bytes_discarded);
    120 
    121   // Update trace of send throttling internal state. This should be called
    122   // immediately after any changes to |send_bytes_available_| and/or
    123   // |in_flight_packet_sizes_|.
    124   void TraceSendThrottlingState() const;
    125 
    126   void InitAcceptedTcp(P2PSocketClient* client,
    127                        const rtc::SocketAddress& local_address,
    128                        const rtc::SocketAddress& remote_address);
    129 
    130   int DoSetOption(P2PSocketOption option, int value);
    131 
    132   P2PSocketType type_;
    133 
    134   // Message loop on which this socket was created and being used.
    135   base::MessageLoop* message_loop_;
    136 
    137   // Corresponding P2P socket client.
    138   scoped_refptr<P2PSocketClient> client_;
    139 
    140   // Local address is allocated by the browser process, and the
    141   // renderer side doesn't know the address until it receives OnOpen()
    142   // event from the browser.
    143   rtc::SocketAddress local_address_;
    144 
    145   // Remote address for client TCP connections.
    146   rtc::SocketAddress remote_address_;
    147 
    148   // Current state of the object.
    149   InternalState state_;
    150 
    151   // Track the number of bytes allowed to be sent non-blocking. This is used to
    152   // throttle the sending of packets to the browser process. For each packet
    153   // sent, the value is decreased. As callbacks to OnSendComplete() (as IPCs
    154   // from the browser process) are made, the value is increased back. This
    155   // allows short bursts of high-rate sending without dropping packets, but
    156   // quickly restricts the client to a sustainable steady-state rate.
    157   size_t send_bytes_available_;
    158   std::deque<size_t> in_flight_packet_sizes_;
    159 
    160   // Set to true once EWOULDBLOCK was returned from Send(). Indicates that the
    161   // caller expects SignalWritable notification.
    162   bool writable_signal_expected_;
    163 
    164   // Current error code. Valid when state_ == IS_ERROR.
    165   int error_;
    166   int options_[P2P_SOCKET_OPT_MAX];
    167 
    168   // Track the maximum and current consecutive bytes discarded due to not enough
    169   // send_bytes_available_.
    170   size_t max_discard_bytes_sequence_;
    171   size_t current_discard_bytes_sequence_;
    172 
    173   // Track the total number of packets and the number of packets discarded.
    174   size_t packets_discarded_;
    175   size_t total_packets_;
    176 
    177   DISALLOW_COPY_AND_ASSIGN(IpcPacketSocket);
    178 };
    179 
    180 // Simple wrapper around P2PAsyncAddressResolver. The main purpose of this
    181 // class is to send SignalDone, after OnDone callback from
    182 // P2PAsyncAddressResolver. Libjingle sig slots are not thread safe. In case
    183 // of MT sig slots clients must call disconnect. This class is to make sure
    184 // we destruct from the same thread on which is created.
    185 class AsyncAddressResolverImpl :  public base::NonThreadSafe,
    186                                   public rtc::AsyncResolverInterface {
    187  public:
    188   AsyncAddressResolverImpl(P2PSocketDispatcher* dispatcher);
    189   virtual ~AsyncAddressResolverImpl();
    190 
    191   // rtc::AsyncResolverInterface interface.
    192   virtual void Start(const rtc::SocketAddress& addr) OVERRIDE;
    193   virtual bool GetResolvedAddress(
    194       int family, rtc::SocketAddress* addr) const OVERRIDE;
    195   virtual int GetError() const OVERRIDE;
    196   virtual void Destroy(bool wait) OVERRIDE;
    197 
    198  private:
    199   virtual void OnAddressResolved(const net::IPAddressList& addresses);
    200 
    201   scoped_refptr<P2PAsyncAddressResolver> resolver_;
    202   int port_;   // Port number in |addr| from Start() method.
    203   std::vector<rtc::IPAddress> addresses_;  // Resolved addresses.
    204 };
    205 
    206 IpcPacketSocket::IpcPacketSocket()
    207     : type_(P2P_SOCKET_UDP),
    208       message_loop_(base::MessageLoop::current()),
    209       state_(IS_UNINITIALIZED),
    210       send_bytes_available_(kMaximumInFlightBytes),
    211       writable_signal_expected_(false),
    212       error_(0),
    213       max_discard_bytes_sequence_(0),
    214       current_discard_bytes_sequence_(0),
    215       packets_discarded_(0),
    216       total_packets_(0) {
    217   COMPILE_ASSERT(kMaximumInFlightBytes > 0, would_send_at_zero_rate);
    218   std::fill_n(options_, static_cast<int> (P2P_SOCKET_OPT_MAX),
    219               kDefaultNonSetOptionValue);
    220 }
    221 
    222 IpcPacketSocket::~IpcPacketSocket() {
    223   if (state_ == IS_OPENING || state_ == IS_OPEN ||
    224       state_ == IS_ERROR) {
    225     Close();
    226   }
    227 
    228   UMA_HISTOGRAM_COUNTS_10000("WebRTC.ApplicationMaxConsecutiveBytesDiscard",
    229                              max_discard_bytes_sequence_);
    230 
    231   if (total_packets_ > 0) {
    232     UMA_HISTOGRAM_PERCENTAGE("WebRTC.ApplicationPercentPacketsDiscarded",
    233                              (packets_discarded_ * 100) / total_packets_);
    234   }
    235 }
    236 
    237 void IpcPacketSocket::TraceSendThrottlingState() const {
    238   TRACE_COUNTER_ID1("p2p", "P2PSendBytesAvailable", local_address_.port(),
    239                     send_bytes_available_);
    240   TRACE_COUNTER_ID1("p2p", "P2PSendPacketsInFlight", local_address_.port(),
    241                     in_flight_packet_sizes_.size());
    242 }
    243 
    244 void IpcPacketSocket::IncrementDiscardCounters(size_t bytes_discarded) {
    245   current_discard_bytes_sequence_ += bytes_discarded;
    246   packets_discarded_++;
    247 
    248   if (current_discard_bytes_sequence_ > max_discard_bytes_sequence_) {
    249     max_discard_bytes_sequence_ = current_discard_bytes_sequence_;
    250   }
    251 }
    252 
    253 bool IpcPacketSocket::Init(P2PSocketType type,
    254                            P2PSocketClientImpl* client,
    255                            const rtc::SocketAddress& local_address,
    256                            const rtc::SocketAddress& remote_address) {
    257   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    258   DCHECK_EQ(state_, IS_UNINITIALIZED);
    259 
    260   type_ = type;
    261   client_ = client;
    262   local_address_ = local_address;
    263   remote_address_ = remote_address;
    264   state_ = IS_OPENING;
    265 
    266   net::IPEndPoint local_endpoint;
    267   if (!jingle_glue::SocketAddressToIPEndPoint(
    268           local_address, &local_endpoint)) {
    269     return false;
    270   }
    271 
    272   net::IPEndPoint remote_endpoint;
    273   if (!remote_address.IsNil()) {
    274     DCHECK(IsTcpClientSocket(type_));
    275 
    276     if (remote_address.IsUnresolvedIP()) {
    277       remote_endpoint =
    278           net::IPEndPoint(net::IPAddressNumber(), remote_address.port());
    279     } else {
    280       if (!jingle_glue::SocketAddressToIPEndPoint(remote_address,
    281                                                   &remote_endpoint)) {
    282         return false;
    283       }
    284     }
    285   }
    286 
    287   // We need to send both resolved and unresolved address in Init. Unresolved
    288   // address will be used in case of TLS for certificate hostname matching.
    289   // Certificate will be tied to domain name not to IP address.
    290   P2PHostAndIPEndPoint remote_info(remote_address.hostname(), remote_endpoint);
    291 
    292   client->Init(type, local_endpoint, remote_info, this);
    293 
    294   return true;
    295 }
    296 
    297 void IpcPacketSocket::InitAcceptedTcp(
    298     P2PSocketClient* client,
    299     const rtc::SocketAddress& local_address,
    300     const rtc::SocketAddress& remote_address) {
    301   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    302   DCHECK_EQ(state_, IS_UNINITIALIZED);
    303 
    304   client_ = client;
    305   local_address_ = local_address;
    306   remote_address_ = remote_address;
    307   state_ = IS_OPEN;
    308   TraceSendThrottlingState();
    309   client_->SetDelegate(this);
    310 }
    311 
    312 // rtc::AsyncPacketSocket interface.
    313 rtc::SocketAddress IpcPacketSocket::GetLocalAddress() const {
    314   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    315   return local_address_;
    316 }
    317 
    318 rtc::SocketAddress IpcPacketSocket::GetRemoteAddress() const {
    319   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    320   return remote_address_;
    321 }
    322 
    323 int IpcPacketSocket::Send(const void *data, size_t data_size,
    324                           const rtc::PacketOptions& options) {
    325   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    326   return SendTo(data, data_size, remote_address_, options);
    327 }
    328 
    329 int IpcPacketSocket::SendTo(const void *data, size_t data_size,
    330                             const rtc::SocketAddress& address,
    331                             const rtc::PacketOptions& options) {
    332   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    333 
    334   switch (state_) {
    335     case IS_UNINITIALIZED:
    336       NOTREACHED();
    337       return EWOULDBLOCK;
    338     case IS_OPENING:
    339       return EWOULDBLOCK;
    340     case IS_CLOSED:
    341       return ENOTCONN;
    342     case IS_ERROR:
    343       return error_;
    344     case IS_OPEN:
    345       // Continue sending the packet.
    346       break;
    347   }
    348 
    349   if (data_size == 0) {
    350     NOTREACHED();
    351     return 0;
    352   }
    353 
    354   total_packets_++;
    355 
    356   if (data_size > send_bytes_available_) {
    357     TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock",
    358                          TRACE_EVENT_SCOPE_THREAD,
    359                          "id",
    360                          client_->GetSocketID());
    361     if (!writable_signal_expected_) {
    362       WebRtcLogMessage(base::StringPrintf(
    363           "IpcPacketSocket: sending is blocked. %d packets_in_flight.",
    364           static_cast<int>(in_flight_packet_sizes_.size())));
    365 
    366       writable_signal_expected_ = true;
    367     }
    368 
    369     error_ = EWOULDBLOCK;
    370     IncrementDiscardCounters(data_size);
    371     return -1;
    372   } else {
    373     current_discard_bytes_sequence_ = 0;
    374   }
    375 
    376   net::IPEndPoint address_chrome;
    377   if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) {
    378     NOTREACHED();
    379     error_ = EINVAL;
    380     return -1;
    381   }
    382 
    383   send_bytes_available_ -= data_size;
    384   in_flight_packet_sizes_.push_back(data_size);
    385   TraceSendThrottlingState();
    386 
    387   const char* data_char = reinterpret_cast<const char*>(data);
    388   std::vector<char> data_vector(data_char, data_char + data_size);
    389   client_->SendWithDscp(address_chrome, data_vector, options);
    390 
    391   // Fake successful send. The caller ignores result anyway.
    392   return data_size;
    393 }
    394 
    395 int IpcPacketSocket::Close() {
    396   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    397 
    398   client_->Close();
    399   state_ = IS_CLOSED;
    400 
    401   return 0;
    402 }
    403 
    404 rtc::AsyncPacketSocket::State IpcPacketSocket::GetState() const {
    405   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    406 
    407   switch (state_) {
    408     case IS_UNINITIALIZED:
    409       NOTREACHED();
    410       return STATE_CLOSED;
    411 
    412     case IS_OPENING:
    413       return STATE_BINDING;
    414 
    415     case IS_OPEN:
    416       if (IsTcpClientSocket(type_)) {
    417         return STATE_CONNECTED;
    418       } else {
    419         return STATE_BOUND;
    420       }
    421 
    422     case IS_CLOSED:
    423     case IS_ERROR:
    424       return STATE_CLOSED;
    425   }
    426 
    427   NOTREACHED();
    428   return STATE_CLOSED;
    429 }
    430 
    431 int IpcPacketSocket::GetOption(rtc::Socket::Option option, int* value) {
    432   P2PSocketOption p2p_socket_option = P2P_SOCKET_OPT_MAX;
    433   if (!JingleSocketOptionToP2PSocketOption(option, &p2p_socket_option)) {
    434     // unsupported option.
    435     return -1;
    436   }
    437 
    438   *value = options_[p2p_socket_option];
    439   return 0;
    440 }
    441 
    442 int IpcPacketSocket::SetOption(rtc::Socket::Option option, int value) {
    443   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    444 
    445   P2PSocketOption p2p_socket_option = P2P_SOCKET_OPT_MAX;
    446   if (!JingleSocketOptionToP2PSocketOption(option, &p2p_socket_option)) {
    447     // Option is not supported.
    448     return -1;
    449   }
    450 
    451   options_[p2p_socket_option] = value;
    452 
    453   if (state_ == IS_OPEN) {
    454     // Options will be applied when state becomes IS_OPEN in OnOpen.
    455     return DoSetOption(p2p_socket_option, value);
    456   }
    457   return 0;
    458 }
    459 
    460 int IpcPacketSocket::DoSetOption(P2PSocketOption option, int value) {
    461   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    462   DCHECK_EQ(state_, IS_OPEN);
    463 
    464   client_->SetOption(option, value);
    465   return 0;
    466 }
    467 
    468 int IpcPacketSocket::GetError() const {
    469   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    470   return error_;
    471 }
    472 
    473 void IpcPacketSocket::SetError(int error) {
    474   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    475   error_ = error;
    476 }
    477 
    478 void IpcPacketSocket::OnOpen(const net::IPEndPoint& local_address,
    479                              const net::IPEndPoint& remote_address) {
    480   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    481 
    482   if (!jingle_glue::IPEndPointToSocketAddress(local_address, &local_address_)) {
    483     // Always expect correct IPv4 address to be allocated.
    484     NOTREACHED();
    485     OnError();
    486     return;
    487   }
    488 
    489   state_ = IS_OPEN;
    490   TraceSendThrottlingState();
    491 
    492   // Set all pending options if any.
    493   for (int i = 0; i < P2P_SOCKET_OPT_MAX; ++i) {
    494     if (options_[i] != kDefaultNonSetOptionValue)
    495       DoSetOption(static_cast<P2PSocketOption> (i), options_[i]);
    496   }
    497 
    498   SignalAddressReady(this, local_address_);
    499   if (IsTcpClientSocket(type_)) {
    500     SignalConnect(this);
    501     // If remote address is unresolved, set resolved remote IP address received
    502     // in the callback. This address will be used while sending the packets
    503     // over the network.
    504     if (remote_address_.IsUnresolvedIP()) {
    505       rtc::SocketAddress jingle_socket_address;
    506       if (!jingle_glue::IPEndPointToSocketAddress(
    507             remote_address, &jingle_socket_address)) {
    508         NOTREACHED();
    509       }
    510       // Set only the IP address.
    511       remote_address_.SetResolvedIP(jingle_socket_address.ipaddr());
    512     }
    513   }
    514 }
    515 
    516 void IpcPacketSocket::OnIncomingTcpConnection(
    517     const net::IPEndPoint& address,
    518     P2PSocketClient* client) {
    519   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    520 
    521   scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
    522 
    523   rtc::SocketAddress remote_address;
    524   if (!jingle_glue::IPEndPointToSocketAddress(address, &remote_address)) {
    525     // Always expect correct IPv4 address to be allocated.
    526     NOTREACHED();
    527   }
    528   socket->InitAcceptedTcp(client, local_address_, remote_address);
    529   SignalNewConnection(this, socket.release());
    530 }
    531 
    532 void IpcPacketSocket::OnSendComplete() {
    533   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    534 
    535   CHECK(!in_flight_packet_sizes_.empty());
    536   send_bytes_available_ += in_flight_packet_sizes_.front();
    537 
    538   DCHECK_LE(send_bytes_available_, kMaximumInFlightBytes);
    539 
    540   in_flight_packet_sizes_.pop_front();
    541   TraceSendThrottlingState();
    542 
    543   if (writable_signal_expected_ && send_bytes_available_ > 0) {
    544     WebRtcLogMessage(base::StringPrintf(
    545         "IpcPacketSocket: sending is unblocked. %d packets in flight.",
    546         static_cast<int>(in_flight_packet_sizes_.size())));
    547 
    548     SignalReadyToSend(this);
    549     writable_signal_expected_ = false;
    550   }
    551 }
    552 
    553 void IpcPacketSocket::OnError() {
    554   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    555   bool was_closed = (state_ == IS_ERROR || state_ == IS_CLOSED);
    556   state_ = IS_ERROR;
    557   error_ = ECONNABORTED;
    558   if (!was_closed) {
    559     SignalClose(this, 0);
    560   }
    561 }
    562 
    563 void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address,
    564                                      const std::vector<char>& data,
    565                                      const base::TimeTicks& timestamp) {
    566   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    567 
    568   rtc::SocketAddress address_lj;
    569   if (!jingle_glue::IPEndPointToSocketAddress(address, &address_lj)) {
    570     // We should always be able to convert address here because we
    571     // don't expect IPv6 address on IPv4 connections.
    572     NOTREACHED();
    573     return;
    574   }
    575 
    576   rtc::PacketTime packet_time(timestamp.ToInternalValue(), 0);
    577   SignalReadPacket(this, &data[0], data.size(), address_lj,
    578                    packet_time);
    579 }
    580 
    581 AsyncAddressResolverImpl::AsyncAddressResolverImpl(
    582     P2PSocketDispatcher* dispatcher)
    583     : resolver_(new P2PAsyncAddressResolver(dispatcher)) {
    584 }
    585 
    586 AsyncAddressResolverImpl::~AsyncAddressResolverImpl() {
    587 }
    588 
    589 void AsyncAddressResolverImpl::Start(const rtc::SocketAddress& addr) {
    590   DCHECK(CalledOnValidThread());
    591   // Copy port number from |addr|. |port_| must be copied
    592   // when resolved address is returned in GetResolvedAddress.
    593   port_ = addr.port();
    594 
    595   resolver_->Start(addr, base::Bind(
    596       &AsyncAddressResolverImpl::OnAddressResolved,
    597       base::Unretained(this)));
    598 }
    599 
    600 bool AsyncAddressResolverImpl::GetResolvedAddress(
    601     int family, rtc::SocketAddress* addr) const {
    602   DCHECK(CalledOnValidThread());
    603 
    604   if (addresses_.empty())
    605    return false;
    606 
    607   for (size_t i = 0; i < addresses_.size(); ++i) {
    608     if (family == addresses_[i].family()) {
    609       addr->SetResolvedIP(addresses_[i]);
    610       addr->SetPort(port_);
    611       return true;
    612     }
    613   }
    614   return false;
    615 }
    616 
    617 int AsyncAddressResolverImpl::GetError() const {
    618   DCHECK(CalledOnValidThread());
    619   return addresses_.empty() ? -1 : 0;
    620 }
    621 
    622 void AsyncAddressResolverImpl::Destroy(bool wait) {
    623   DCHECK(CalledOnValidThread());
    624   resolver_->Cancel();
    625   // Libjingle doesn't need this object any more and it's not going to delete
    626   // it explicitly.
    627   delete this;
    628 }
    629 
    630 void AsyncAddressResolverImpl::OnAddressResolved(
    631     const net::IPAddressList& addresses) {
    632   DCHECK(CalledOnValidThread());
    633   for (size_t i = 0; i < addresses.size(); ++i) {
    634     rtc::SocketAddress socket_address;
    635     if (!jingle_glue::IPEndPointToSocketAddress(
    636             net::IPEndPoint(addresses[i], 0), &socket_address)) {
    637       NOTREACHED();
    638     }
    639     addresses_.push_back(socket_address.ipaddr());
    640   }
    641   SignalDone(this);
    642 }
    643 
    644 }  // namespace
    645 
    646 IpcPacketSocketFactory::IpcPacketSocketFactory(
    647     P2PSocketDispatcher* socket_dispatcher)
    648     : socket_dispatcher_(socket_dispatcher) {
    649 }
    650 
    651 IpcPacketSocketFactory::~IpcPacketSocketFactory() {
    652 }
    653 
    654 rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateUdpSocket(
    655     const rtc::SocketAddress& local_address, int min_port, int max_port) {
    656   rtc::SocketAddress crome_address;
    657   P2PSocketClientImpl* socket_client =
    658       new P2PSocketClientImpl(socket_dispatcher_);
    659   scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
    660   // TODO(sergeyu): Respect local_address and port limits here (need
    661   // to pass them over IPC channel to the browser).
    662   if (!socket->Init(P2P_SOCKET_UDP, socket_client,
    663                     local_address, rtc::SocketAddress())) {
    664     return NULL;
    665   }
    666   return socket.release();
    667 }
    668 
    669 rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateServerTcpSocket(
    670     const rtc::SocketAddress& local_address, int min_port, int max_port,
    671     int opts) {
    672   // TODO(sergeyu): Implement SSL support.
    673   if (opts & rtc::PacketSocketFactory::OPT_SSLTCP)
    674     return NULL;
    675 
    676   P2PSocketType type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
    677       P2P_SOCKET_STUN_TCP_SERVER : P2P_SOCKET_TCP_SERVER;
    678   P2PSocketClientImpl* socket_client =
    679       new P2PSocketClientImpl(socket_dispatcher_);
    680   scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
    681   if (!socket->Init(type, socket_client, local_address,
    682                     rtc::SocketAddress())) {
    683     return NULL;
    684   }
    685   return socket.release();
    686 }
    687 
    688 rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateClientTcpSocket(
    689     const rtc::SocketAddress& local_address,
    690     const rtc::SocketAddress& remote_address,
    691     const rtc::ProxyInfo& proxy_info,
    692     const std::string& user_agent, int opts) {
    693   P2PSocketType type;
    694   if (opts & rtc::PacketSocketFactory::OPT_SSLTCP) {
    695     type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
    696         P2P_SOCKET_STUN_SSLTCP_CLIENT : P2P_SOCKET_SSLTCP_CLIENT;
    697   } else if (opts & rtc::PacketSocketFactory::OPT_TLS) {
    698     type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
    699         P2P_SOCKET_STUN_TLS_CLIENT : P2P_SOCKET_TLS_CLIENT;
    700   } else {
    701     type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
    702         P2P_SOCKET_STUN_TCP_CLIENT : P2P_SOCKET_TCP_CLIENT;
    703   }
    704   P2PSocketClientImpl* socket_client =
    705       new P2PSocketClientImpl(socket_dispatcher_);
    706   scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
    707   if (!socket->Init(type, socket_client, local_address, remote_address))
    708     return NULL;
    709   return socket.release();
    710 }
    711 
    712 rtc::AsyncResolverInterface*
    713 IpcPacketSocketFactory::CreateAsyncResolver() {
    714   scoped_ptr<AsyncAddressResolverImpl> resolver(
    715     new AsyncAddressResolverImpl(socket_dispatcher_));
    716   return resolver.release();
    717 }
    718 
    719 }  // namespace content
    720