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