• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
IsTcpClientSocket(P2PSocketType type)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 
JingleSocketOptionToP2PSocketOption(talk_base::Socket::Option option,P2PSocketOption * ipc_option)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 
IpcPacketSocket()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 
~IpcPacketSocket()203 IpcPacketSocket::~IpcPacketSocket() {
204   if (state_ == IS_OPENING || state_ == IS_OPEN ||
205       state_ == IS_ERROR) {
206     Close();
207   }
208 }
209 
TraceSendThrottlingState() const210 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 
Init(P2PSocketType type,P2PSocketClientImpl * client,const talk_base::SocketAddress & local_address,const talk_base::SocketAddress & remote_address)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 
InitAcceptedTcp(P2PSocketClient * client,const talk_base::SocketAddress & local_address,const talk_base::SocketAddress & remote_address)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.
GetLocalAddress() const269 talk_base::SocketAddress IpcPacketSocket::GetLocalAddress() const {
270   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
271   return local_address_;
272 }
273 
GetRemoteAddress() const274 talk_base::SocketAddress IpcPacketSocket::GetRemoteAddress() const {
275   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
276   return remote_address_;
277 }
278 
Send(const void * data,size_t data_size,const talk_base::PacketOptions & options)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 
SendTo(const void * data,size_t data_size,const talk_base::SocketAddress & address,const talk_base::PacketOptions & options)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 
Close()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 
GetState() const355 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 
GetOption(talk_base::Socket::Option option,int * value)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 
SetOption(talk_base::Socket::Option option,int value)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 
DoSetOption(P2PSocketOption option,int value)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 
GetError() const419 int IpcPacketSocket::GetError() const {
420   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
421   return error_;
422 }
423 
SetError(int error)424 void IpcPacketSocket::SetError(int error) {
425   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
426   error_ = error;
427 }
428 
OnOpen(const net::IPEndPoint & address)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 
OnIncomingTcpConnection(const net::IPEndPoint & address,P2PSocketClient * client)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 
OnSendComplete()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 
OnError()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 
OnDataReceived(const net::IPEndPoint & address,const std::vector<char> & data,const base::TimeTicks & timestamp)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 
AsyncAddressResolverImpl(P2PSocketDispatcher * dispatcher)518 AsyncAddressResolverImpl::AsyncAddressResolverImpl(
519     P2PSocketDispatcher* dispatcher)
520     : resolver_(new P2PAsyncAddressResolver(dispatcher)) {
521 }
522 
~AsyncAddressResolverImpl()523 AsyncAddressResolverImpl::~AsyncAddressResolverImpl() {
524 }
525 
Start(const talk_base::SocketAddress & addr)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 
GetResolvedAddress(int family,talk_base::SocketAddress * addr) const537 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 
GetError() const554 int AsyncAddressResolverImpl::GetError() const {
555   DCHECK(CalledOnValidThread());
556   return addresses_.empty() ? -1 : 0;
557 }
558 
Destroy(bool wait)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 
OnAddressResolved(const net::IPAddressList & addresses)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 
IpcPacketSocketFactory(P2PSocketDispatcher * socket_dispatcher)583 IpcPacketSocketFactory::IpcPacketSocketFactory(
584     P2PSocketDispatcher* socket_dispatcher)
585     : socket_dispatcher_(socket_dispatcher) {
586 }
587 
~IpcPacketSocketFactory()588 IpcPacketSocketFactory::~IpcPacketSocketFactory() {
589 }
590 
CreateUdpSocket(const talk_base::SocketAddress & local_address,int min_port,int max_port)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 
CreateServerTcpSocket(const talk_base::SocketAddress & local_address,int min_port,int max_port,int opts)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 
CreateClientTcpSocket(const talk_base::SocketAddress & local_address,const talk_base::SocketAddress & remote_address,const talk_base::ProxyInfo & proxy_info,const std::string & user_agent,int opts)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*
CreateAsyncResolver()650 IpcPacketSocketFactory::CreateAsyncResolver() {
651   scoped_ptr<AsyncAddressResolverImpl> resolver(
652     new AsyncAddressResolverImpl(socket_dispatcher_));
653   return resolver.release();
654 }
655 
656 }  // namespace content
657