• 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/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 
IsTcpClientSocket(P2PSocketType type)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 
JingleSocketOptionToP2PSocketOption(rtc::Socket::Option option,P2PSocketOption * ipc_option)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 
IpcPacketSocket()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 
~IpcPacketSocket()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 
TraceSendThrottlingState() const237 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 
IncrementDiscardCounters(size_t bytes_discarded)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 
Init(P2PSocketType type,P2PSocketClientImpl * client,const rtc::SocketAddress & local_address,const rtc::SocketAddress & remote_address)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 
InitAcceptedTcp(P2PSocketClient * client,const rtc::SocketAddress & local_address,const rtc::SocketAddress & remote_address)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.
GetLocalAddress() const313 rtc::SocketAddress IpcPacketSocket::GetLocalAddress() const {
314   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
315   return local_address_;
316 }
317 
GetRemoteAddress() const318 rtc::SocketAddress IpcPacketSocket::GetRemoteAddress() const {
319   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
320   return remote_address_;
321 }
322 
Send(const void * data,size_t data_size,const rtc::PacketOptions & options)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 
SendTo(const void * data,size_t data_size,const rtc::SocketAddress & address,const rtc::PacketOptions & options)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 
Close()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 
GetState() const404 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 
GetOption(rtc::Socket::Option option,int * value)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 
SetOption(rtc::Socket::Option option,int value)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 
DoSetOption(P2PSocketOption option,int value)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 
GetError() const468 int IpcPacketSocket::GetError() const {
469   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
470   return error_;
471 }
472 
SetError(int error)473 void IpcPacketSocket::SetError(int error) {
474   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
475   error_ = error;
476 }
477 
OnOpen(const net::IPEndPoint & local_address,const net::IPEndPoint & remote_address)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 
OnIncomingTcpConnection(const net::IPEndPoint & address,P2PSocketClient * client)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 
OnSendComplete()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 
OnError()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 
OnDataReceived(const net::IPEndPoint & address,const std::vector<char> & data,const base::TimeTicks & timestamp)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 
AsyncAddressResolverImpl(P2PSocketDispatcher * dispatcher)581 AsyncAddressResolverImpl::AsyncAddressResolverImpl(
582     P2PSocketDispatcher* dispatcher)
583     : resolver_(new P2PAsyncAddressResolver(dispatcher)) {
584 }
585 
~AsyncAddressResolverImpl()586 AsyncAddressResolverImpl::~AsyncAddressResolverImpl() {
587 }
588 
Start(const rtc::SocketAddress & addr)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 
GetResolvedAddress(int family,rtc::SocketAddress * addr) const600 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 
GetError() const617 int AsyncAddressResolverImpl::GetError() const {
618   DCHECK(CalledOnValidThread());
619   return addresses_.empty() ? -1 : 0;
620 }
621 
Destroy(bool wait)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 
OnAddressResolved(const net::IPAddressList & addresses)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 
IpcPacketSocketFactory(P2PSocketDispatcher * socket_dispatcher)646 IpcPacketSocketFactory::IpcPacketSocketFactory(
647     P2PSocketDispatcher* socket_dispatcher)
648     : socket_dispatcher_(socket_dispatcher) {
649 }
650 
~IpcPacketSocketFactory()651 IpcPacketSocketFactory::~IpcPacketSocketFactory() {
652 }
653 
CreateUdpSocket(const rtc::SocketAddress & local_address,int min_port,int max_port)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 
CreateServerTcpSocket(const rtc::SocketAddress & local_address,int min_port,int max_port,int opts)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 
CreateClientTcpSocket(const rtc::SocketAddress & local_address,const rtc::SocketAddress & remote_address,const rtc::ProxyInfo & proxy_info,const std::string & user_agent,int opts)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*
CreateAsyncResolver()713 IpcPacketSocketFactory::CreateAsyncResolver() {
714   scoped_ptr<AsyncAddressResolverImpl> resolver(
715     new AsyncAddressResolverImpl(socket_dispatcher_));
716   return resolver.release();
717 }
718 
719 }  // namespace content
720