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