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
25namespace content {
26
27namespace {
28
29const int kDefaultNonSetOptionValue = -1;
30
31bool 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
40bool 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
65const 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.
70class 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.
185class 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
206IpcPacketSocket::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
222IpcPacketSocket::~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
237void 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
244void 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
253bool 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
297void 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.
313rtc::SocketAddress IpcPacketSocket::GetLocalAddress() const {
314  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
315  return local_address_;
316}
317
318rtc::SocketAddress IpcPacketSocket::GetRemoteAddress() const {
319  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
320  return remote_address_;
321}
322
323int 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
329int 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
395int IpcPacketSocket::Close() {
396  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
397
398  client_->Close();
399  state_ = IS_CLOSED;
400
401  return 0;
402}
403
404rtc::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
431int 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
442int 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
460int 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
468int IpcPacketSocket::GetError() const {
469  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
470  return error_;
471}
472
473void IpcPacketSocket::SetError(int error) {
474  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
475  error_ = error;
476}
477
478void 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
516void 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
532void 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
553void 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
563void 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
581AsyncAddressResolverImpl::AsyncAddressResolverImpl(
582    P2PSocketDispatcher* dispatcher)
583    : resolver_(new P2PAsyncAddressResolver(dispatcher)) {
584}
585
586AsyncAddressResolverImpl::~AsyncAddressResolverImpl() {
587}
588
589void 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
600bool 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
617int AsyncAddressResolverImpl::GetError() const {
618  DCHECK(CalledOnValidThread());
619  return addresses_.empty() ? -1 : 0;
620}
621
622void 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
630void 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
646IpcPacketSocketFactory::IpcPacketSocketFactory(
647    P2PSocketDispatcher* socket_dispatcher)
648    : socket_dispatcher_(socket_dispatcher) {
649}
650
651IpcPacketSocketFactory::~IpcPacketSocketFactory() {
652}
653
654rtc::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
669rtc::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
688rtc::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
712rtc::AsyncResolverInterface*
713IpcPacketSocketFactory::CreateAsyncResolver() {
714  scoped_ptr<AsyncAddressResolverImpl> resolver(
715    new AsyncAddressResolverImpl(socket_dispatcher_));
716  return resolver.release();
717}
718
719}  // namespace content
720