Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / content / renderer / p2p / ipc_socket_factory.cc
blobd61f3143ec70bed11b8c1d23c7e37ab886beda11
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.
5 #include "content/renderer/p2p/ipc_socket_factory.h"
7 #include <algorithm>
8 #include <list>
10 #include "base/compiler_specific.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/metrics/histogram.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/threading/non_thread_safe.h"
17 #include "base/trace_event/trace_event.h"
18 #include "content/renderer/media/webrtc_logging.h"
19 #include "content/renderer/p2p/host_address_request.h"
20 #include "content/renderer/p2p/socket_client_delegate.h"
21 #include "content/renderer/p2p/socket_client_impl.h"
22 #include "content/renderer/p2p/socket_dispatcher.h"
23 #include "jingle/glue/utils.h"
24 #include "third_party/webrtc/base/asyncpacketsocket.h"
26 namespace content {
28 namespace {
30 const int kDefaultNonSetOptionValue = -1;
32 bool IsTcpClientSocket(P2PSocketType type) {
33 return (type == P2P_SOCKET_STUN_TCP_CLIENT) ||
34 (type == P2P_SOCKET_TCP_CLIENT) ||
35 (type == P2P_SOCKET_STUN_SSLTCP_CLIENT) ||
36 (type == P2P_SOCKET_SSLTCP_CLIENT) ||
37 (type == P2P_SOCKET_TLS_CLIENT) ||
38 (type == P2P_SOCKET_STUN_TLS_CLIENT);
41 bool JingleSocketOptionToP2PSocketOption(rtc::Socket::Option option,
42 P2PSocketOption* ipc_option) {
43 switch (option) {
44 case rtc::Socket::OPT_RCVBUF:
45 *ipc_option = P2P_SOCKET_OPT_RCVBUF;
46 break;
47 case rtc::Socket::OPT_SNDBUF:
48 *ipc_option = P2P_SOCKET_OPT_SNDBUF;
49 break;
50 case rtc::Socket::OPT_DSCP:
51 *ipc_option = P2P_SOCKET_OPT_DSCP;
52 break;
53 case rtc::Socket::OPT_DONTFRAGMENT:
54 case rtc::Socket::OPT_NODELAY:
55 case rtc::Socket::OPT_IPV6_V6ONLY:
56 case rtc::Socket::OPT_RTP_SENDTIME_EXTN_ID:
57 return false; // Not supported by the chrome sockets.
58 default:
59 NOTREACHED();
60 return false;
62 return true;
65 // TODO(miu): This needs tuning. http://crbug.com/237960
66 // http://crbug.com/427555
67 const size_t kMaximumInFlightBytes = 64 * 1024; // 64 KB
69 // IpcPacketSocket implements rtc::AsyncPacketSocket interface
70 // using P2PSocketClient that works over IPC-channel. It must be used
71 // on the thread it was created.
72 class IpcPacketSocket : public rtc::AsyncPacketSocket,
73 public P2PSocketClientDelegate {
74 public:
75 IpcPacketSocket();
76 ~IpcPacketSocket() override;
78 // Struct to track information when a packet is received by this socket for
79 // send. The information tracked here will be used to match with the
80 // P2PSendPacketMetrics from the underneath system socket.
81 struct InFlightPacketRecord {
82 InFlightPacketRecord(uint64_t packet_id, size_t packet_size)
83 : packet_id(packet_id), packet_size(packet_size) {}
85 uint64_t packet_id;
86 size_t packet_size;
89 typedef std::list<InFlightPacketRecord> InFlightPacketList;
91 // Always takes ownership of client even if initialization fails.
92 bool Init(P2PSocketType type, P2PSocketClientImpl* client,
93 const rtc::SocketAddress& local_address,
94 const rtc::SocketAddress& remote_address);
96 // rtc::AsyncPacketSocket interface.
97 rtc::SocketAddress GetLocalAddress() const override;
98 rtc::SocketAddress GetRemoteAddress() const override;
99 int Send(const void* pv,
100 size_t cb,
101 const rtc::PacketOptions& options) override;
102 int SendTo(const void* pv,
103 size_t cb,
104 const rtc::SocketAddress& addr,
105 const rtc::PacketOptions& options) override;
106 int Close() override;
107 State GetState() const override;
108 int GetOption(rtc::Socket::Option option, int* value) override;
109 int SetOption(rtc::Socket::Option option, int value) override;
110 int GetError() const override;
111 void SetError(int error) override;
113 // P2PSocketClientDelegate implementation.
114 void OnOpen(const net::IPEndPoint& local_address,
115 const net::IPEndPoint& remote_address) override;
116 void OnIncomingTcpConnection(const net::IPEndPoint& address,
117 P2PSocketClient* client) override;
118 void OnSendComplete(const P2PSendPacketMetrics& send_metrics) override;
119 void OnError() override;
120 void OnDataReceived(const net::IPEndPoint& address,
121 const std::vector<char>& data,
122 const base::TimeTicks& timestamp) override;
124 private:
125 enum InternalState {
126 IS_UNINITIALIZED,
127 IS_OPENING,
128 IS_OPEN,
129 IS_CLOSED,
130 IS_ERROR,
133 // Increment the counter for consecutive bytes discarded as socket is running
134 // out of buffer.
135 void IncrementDiscardCounters(size_t bytes_discarded);
137 // Update trace of send throttling internal state. This should be called
138 // immediately after any changes to |send_bytes_available_| and/or
139 // |in_flight_packet_records_|.
140 void TraceSendThrottlingState() const;
142 void InitAcceptedTcp(P2PSocketClient* client,
143 const rtc::SocketAddress& local_address,
144 const rtc::SocketAddress& remote_address);
146 int DoSetOption(P2PSocketOption option, int value);
148 // Allow a finch experiment to control the initial value of
149 // send_bytes_available_;
150 void AdjustUdpSendBufferSize();
152 P2PSocketType type_;
154 // Message loop on which this socket was created and being used.
155 base::MessageLoop* message_loop_;
157 // Corresponding P2P socket client.
158 scoped_refptr<P2PSocketClient> client_;
160 // Local address is allocated by the browser process, and the
161 // renderer side doesn't know the address until it receives OnOpen()
162 // event from the browser.
163 rtc::SocketAddress local_address_;
165 // Remote address for client TCP connections.
166 rtc::SocketAddress remote_address_;
168 // Current state of the object.
169 InternalState state_;
171 // Track the number of bytes allowed to be sent non-blocking. This is used to
172 // throttle the sending of packets to the browser process. For each packet
173 // sent, the value is decreased. As callbacks to OnSendComplete() (as IPCs
174 // from the browser process) are made, the value is increased back. This
175 // allows short bursts of high-rate sending without dropping packets, but
176 // quickly restricts the client to a sustainable steady-state rate.
177 size_t send_bytes_available_;
179 // Used to detect when browser doesn't send SendComplete message for some
180 // packets. In normal case, the first packet should be the one that we're
181 // going to receive the next completion signal.
182 InFlightPacketList in_flight_packet_records_;
184 // Set to true once EWOULDBLOCK was returned from Send(). Indicates that the
185 // caller expects SignalWritable notification.
186 bool writable_signal_expected_;
188 // Current error code. Valid when state_ == IS_ERROR.
189 int error_;
190 int options_[P2P_SOCKET_OPT_MAX];
192 // Track the maximum and current consecutive bytes discarded due to not enough
193 // send_bytes_available_.
194 size_t max_discard_bytes_sequence_;
195 size_t current_discard_bytes_sequence_;
197 // Track the total number of packets and the number of packets discarded.
198 size_t packets_discarded_;
199 size_t total_packets_;
201 DISALLOW_COPY_AND_ASSIGN(IpcPacketSocket);
204 // Simple wrapper around P2PAsyncAddressResolver. The main purpose of this
205 // class is to send SignalDone, after OnDone callback from
206 // P2PAsyncAddressResolver. Libjingle sig slots are not thread safe. In case
207 // of MT sig slots clients must call disconnect. This class is to make sure
208 // we destruct from the same thread on which is created.
209 class AsyncAddressResolverImpl : public base::NonThreadSafe,
210 public rtc::AsyncResolverInterface {
211 public:
212 AsyncAddressResolverImpl(P2PSocketDispatcher* dispatcher);
213 ~AsyncAddressResolverImpl() override;
215 // rtc::AsyncResolverInterface interface.
216 void Start(const rtc::SocketAddress& addr) override;
217 bool GetResolvedAddress(int family, rtc::SocketAddress* addr) const override;
218 int GetError() const override;
219 void Destroy(bool wait) override;
221 private:
222 virtual void OnAddressResolved(const net::IPAddressList& addresses);
224 scoped_refptr<P2PAsyncAddressResolver> resolver_;
225 int port_; // Port number in |addr| from Start() method.
226 std::vector<rtc::IPAddress> addresses_; // Resolved addresses.
229 IpcPacketSocket::IpcPacketSocket()
230 : type_(P2P_SOCKET_UDP),
231 message_loop_(base::MessageLoop::current()),
232 state_(IS_UNINITIALIZED),
233 send_bytes_available_(kMaximumInFlightBytes),
234 writable_signal_expected_(false),
235 error_(0),
236 max_discard_bytes_sequence_(0),
237 current_discard_bytes_sequence_(0),
238 packets_discarded_(0),
239 total_packets_(0) {
240 static_assert(kMaximumInFlightBytes > 0, "would send at zero rate");
241 std::fill_n(options_, static_cast<int> (P2P_SOCKET_OPT_MAX),
242 kDefaultNonSetOptionValue);
245 IpcPacketSocket::~IpcPacketSocket() {
246 if (state_ == IS_OPENING || state_ == IS_OPEN ||
247 state_ == IS_ERROR) {
248 Close();
251 UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.ApplicationMaxConsecutiveBytesDiscard.v2",
252 max_discard_bytes_sequence_, 1, 1000000, 200);
253 if (total_packets_ > 0) {
254 UMA_HISTOGRAM_PERCENTAGE("WebRTC.ApplicationPercentPacketsDiscarded",
255 (packets_discarded_ * 100) / total_packets_);
259 void IpcPacketSocket::TraceSendThrottlingState() const {
260 TRACE_COUNTER_ID1("p2p", "P2PSendBytesAvailable", local_address_.port(),
261 send_bytes_available_);
262 TRACE_COUNTER_ID1("p2p", "P2PSendPacketsInFlight", local_address_.port(),
263 in_flight_packet_records_.size());
266 void IpcPacketSocket::IncrementDiscardCounters(size_t bytes_discarded) {
267 current_discard_bytes_sequence_ += bytes_discarded;
268 packets_discarded_++;
270 if (current_discard_bytes_sequence_ > max_discard_bytes_sequence_) {
271 max_discard_bytes_sequence_ = current_discard_bytes_sequence_;
275 void IpcPacketSocket::AdjustUdpSendBufferSize() {
276 DCHECK_EQ(type_, P2P_SOCKET_UDP);
277 unsigned int send_buffer_size = 0;
279 base::StringToUint(
280 base::FieldTrialList::FindFullName("WebRTC-ApplicationUDPSendSocketSize"),
281 &send_buffer_size);
283 if (send_buffer_size > 0) {
284 send_bytes_available_ = send_buffer_size;
288 bool IpcPacketSocket::Init(P2PSocketType type,
289 P2PSocketClientImpl* client,
290 const rtc::SocketAddress& local_address,
291 const rtc::SocketAddress& remote_address) {
292 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
293 DCHECK_EQ(state_, IS_UNINITIALIZED);
295 type_ = type;
296 client_ = client;
297 local_address_ = local_address;
298 remote_address_ = remote_address;
299 state_ = IS_OPENING;
301 net::IPEndPoint local_endpoint;
302 if (!jingle_glue::SocketAddressToIPEndPoint(
303 local_address, &local_endpoint)) {
304 return false;
307 if (type_ == P2P_SOCKET_UDP) {
308 AdjustUdpSendBufferSize();
311 net::IPEndPoint remote_endpoint;
312 if (!remote_address.IsNil()) {
313 DCHECK(IsTcpClientSocket(type_));
315 if (remote_address.IsUnresolvedIP()) {
316 remote_endpoint =
317 net::IPEndPoint(net::IPAddressNumber(), remote_address.port());
318 } else {
319 if (!jingle_glue::SocketAddressToIPEndPoint(remote_address,
320 &remote_endpoint)) {
321 return false;
326 // We need to send both resolved and unresolved address in Init. Unresolved
327 // address will be used in case of TLS for certificate hostname matching.
328 // Certificate will be tied to domain name not to IP address.
329 P2PHostAndIPEndPoint remote_info(remote_address.hostname(), remote_endpoint);
331 client->Init(type, local_endpoint, remote_info, this);
333 return true;
336 void IpcPacketSocket::InitAcceptedTcp(
337 P2PSocketClient* client,
338 const rtc::SocketAddress& local_address,
339 const rtc::SocketAddress& remote_address) {
340 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
341 DCHECK_EQ(state_, IS_UNINITIALIZED);
343 client_ = client;
344 local_address_ = local_address;
345 remote_address_ = remote_address;
346 state_ = IS_OPEN;
347 TraceSendThrottlingState();
348 client_->SetDelegate(this);
351 // rtc::AsyncPacketSocket interface.
352 rtc::SocketAddress IpcPacketSocket::GetLocalAddress() const {
353 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
354 return local_address_;
357 rtc::SocketAddress IpcPacketSocket::GetRemoteAddress() const {
358 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
359 return remote_address_;
362 int IpcPacketSocket::Send(const void *data, size_t data_size,
363 const rtc::PacketOptions& options) {
364 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
365 return SendTo(data, data_size, remote_address_, options);
368 int IpcPacketSocket::SendTo(const void *data, size_t data_size,
369 const rtc::SocketAddress& address,
370 const rtc::PacketOptions& options) {
371 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
373 switch (state_) {
374 case IS_UNINITIALIZED:
375 NOTREACHED();
376 error_ = EWOULDBLOCK;
377 return -1;
378 case IS_OPENING:
379 error_ = EWOULDBLOCK;
380 return -1;
381 case IS_CLOSED:
382 error_ = ENOTCONN;
383 return -1;
384 case IS_ERROR:
385 return -1;
386 case IS_OPEN:
387 // Continue sending the packet.
388 break;
391 if (data_size == 0) {
392 NOTREACHED();
393 return 0;
396 total_packets_++;
398 if (data_size > send_bytes_available_) {
399 TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock",
400 TRACE_EVENT_SCOPE_THREAD,
401 "id",
402 client_->GetSocketID());
403 if (!writable_signal_expected_) {
404 WebRtcLogMessage(base::StringPrintf(
405 "IpcPacketSocket: sending is blocked. %d packets_in_flight.",
406 static_cast<int>(in_flight_packet_records_.size())));
408 writable_signal_expected_ = true;
411 error_ = EWOULDBLOCK;
412 IncrementDiscardCounters(data_size);
413 return -1;
414 } else {
415 current_discard_bytes_sequence_ = 0;
418 net::IPEndPoint address_chrome;
419 if (address.IsUnresolvedIP()) {
420 address_chrome = net::IPEndPoint(net::IPAddressNumber(), address.port());
421 } else {
422 if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) {
423 LOG(WARNING) << "Failed to convert remote address to IPEndPoint: address="
424 << address.ipaddr().ToSensitiveString()
425 << ", remote_address_="
426 << remote_address_.ipaddr().ToSensitiveString();
427 NOTREACHED();
428 error_ = EINVAL;
429 return -1;
433 send_bytes_available_ -= data_size;
435 const char* data_char = reinterpret_cast<const char*>(data);
436 std::vector<char> data_vector(data_char, data_char + data_size);
437 uint64_t packet_id = client_->Send(address_chrome, data_vector, options);
439 // Ensure packet_id is not 0. It can't be the case according to
440 // P2PSocketClientImpl::Send().
441 DCHECK_NE(packet_id, 0uL);
443 in_flight_packet_records_.push_back(
444 InFlightPacketRecord(packet_id, data_size));
445 TraceSendThrottlingState();
447 // Fake successful send. The caller ignores result anyway.
448 return data_size;
451 int IpcPacketSocket::Close() {
452 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
454 client_->Close();
455 state_ = IS_CLOSED;
457 return 0;
460 rtc::AsyncPacketSocket::State IpcPacketSocket::GetState() const {
461 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
463 switch (state_) {
464 case IS_UNINITIALIZED:
465 NOTREACHED();
466 return STATE_CLOSED;
468 case IS_OPENING:
469 return STATE_BINDING;
471 case IS_OPEN:
472 if (IsTcpClientSocket(type_)) {
473 return STATE_CONNECTED;
474 } else {
475 return STATE_BOUND;
478 case IS_CLOSED:
479 case IS_ERROR:
480 return STATE_CLOSED;
483 NOTREACHED();
484 return STATE_CLOSED;
487 int IpcPacketSocket::GetOption(rtc::Socket::Option option, int* value) {
488 P2PSocketOption p2p_socket_option = P2P_SOCKET_OPT_MAX;
489 if (!JingleSocketOptionToP2PSocketOption(option, &p2p_socket_option)) {
490 // unsupported option.
491 return -1;
494 *value = options_[p2p_socket_option];
495 return 0;
498 int IpcPacketSocket::SetOption(rtc::Socket::Option option, int value) {
499 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
501 P2PSocketOption p2p_socket_option = P2P_SOCKET_OPT_MAX;
502 if (!JingleSocketOptionToP2PSocketOption(option, &p2p_socket_option)) {
503 // Option is not supported.
504 return -1;
507 options_[p2p_socket_option] = value;
509 if (state_ == IS_OPEN) {
510 // Options will be applied when state becomes IS_OPEN in OnOpen.
511 return DoSetOption(p2p_socket_option, value);
513 return 0;
516 int IpcPacketSocket::DoSetOption(P2PSocketOption option, int value) {
517 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
518 DCHECK_EQ(state_, IS_OPEN);
520 client_->SetOption(option, value);
521 return 0;
524 int IpcPacketSocket::GetError() const {
525 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
526 return error_;
529 void IpcPacketSocket::SetError(int error) {
530 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
531 error_ = error;
534 void IpcPacketSocket::OnOpen(const net::IPEndPoint& local_address,
535 const net::IPEndPoint& remote_address) {
536 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
538 if (!jingle_glue::IPEndPointToSocketAddress(local_address, &local_address_)) {
539 // Always expect correct IPv4 address to be allocated.
540 NOTREACHED();
541 OnError();
542 return;
545 state_ = IS_OPEN;
546 TraceSendThrottlingState();
548 // Set all pending options if any.
549 for (int i = 0; i < P2P_SOCKET_OPT_MAX; ++i) {
550 if (options_[i] != kDefaultNonSetOptionValue)
551 DoSetOption(static_cast<P2PSocketOption> (i), options_[i]);
554 SignalAddressReady(this, local_address_);
555 if (IsTcpClientSocket(type_)) {
556 // If remote address is unresolved, set resolved remote IP address received
557 // in the callback. This address will be used while sending the packets
558 // over the network.
559 if (remote_address_.IsUnresolvedIP()) {
560 rtc::SocketAddress jingle_socket_address;
561 // |remote_address| could be unresolved if the connection is behind a
562 // proxy.
563 if (!remote_address.address().empty() &&
564 jingle_glue::IPEndPointToSocketAddress(
565 remote_address, &jingle_socket_address)) {
566 // Set only the IP address.
567 remote_address_.SetResolvedIP(jingle_socket_address.ipaddr());
571 // SignalConnect after updating the |remote_address_| so that the listener
572 // can get the resolved remote address.
573 SignalConnect(this);
577 void IpcPacketSocket::OnIncomingTcpConnection(
578 const net::IPEndPoint& address,
579 P2PSocketClient* client) {
580 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
582 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
584 rtc::SocketAddress remote_address;
585 if (!jingle_glue::IPEndPointToSocketAddress(address, &remote_address)) {
586 // Always expect correct IPv4 address to be allocated.
587 NOTREACHED();
589 socket->InitAcceptedTcp(client, local_address_, remote_address);
590 SignalNewConnection(this, socket.release());
593 void IpcPacketSocket::OnSendComplete(const P2PSendPacketMetrics& send_metrics) {
594 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
596 CHECK(!in_flight_packet_records_.empty());
598 const InFlightPacketRecord& record = in_flight_packet_records_.front();
600 // Tracking is not turned on for TCP so it's always 0. For UDP, this will
601 // cause a crash when the packet ids don't match.
602 CHECK(send_metrics.packet_id == 0 ||
603 record.packet_id == send_metrics.packet_id);
605 send_bytes_available_ += record.packet_size;
607 DCHECK_LE(send_bytes_available_, kMaximumInFlightBytes);
609 in_flight_packet_records_.pop_front();
610 TraceSendThrottlingState();
612 if (writable_signal_expected_ && send_bytes_available_ > 0) {
613 WebRtcLogMessage(base::StringPrintf(
614 "IpcPacketSocket: sending is unblocked. %d packets in flight.",
615 static_cast<int>(in_flight_packet_records_.size())));
617 SignalReadyToSend(this);
618 writable_signal_expected_ = false;
622 void IpcPacketSocket::OnError() {
623 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
624 bool was_closed = (state_ == IS_ERROR || state_ == IS_CLOSED);
625 state_ = IS_ERROR;
626 error_ = ECONNABORTED;
627 if (!was_closed) {
628 SignalClose(this, 0);
632 void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address,
633 const std::vector<char>& data,
634 const base::TimeTicks& timestamp) {
635 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
637 rtc::SocketAddress address_lj;
639 if (address.address().empty()) {
640 DCHECK(IsTcpClientSocket(type_));
641 // |address| could be empty for TCP connections behind a proxy.
642 address_lj = remote_address_;
643 } else {
644 if (!jingle_glue::IPEndPointToSocketAddress(address, &address_lj)) {
645 // We should always be able to convert address here because we
646 // don't expect IPv6 address on IPv4 connections.
647 NOTREACHED();
648 return;
652 rtc::PacketTime packet_time(timestamp.ToInternalValue(), 0);
653 SignalReadPacket(this, &data[0], data.size(), address_lj,
654 packet_time);
657 AsyncAddressResolverImpl::AsyncAddressResolverImpl(
658 P2PSocketDispatcher* dispatcher)
659 : resolver_(new P2PAsyncAddressResolver(dispatcher)) {
662 AsyncAddressResolverImpl::~AsyncAddressResolverImpl() {
665 void AsyncAddressResolverImpl::Start(const rtc::SocketAddress& addr) {
666 DCHECK(CalledOnValidThread());
667 // Copy port number from |addr|. |port_| must be copied
668 // when resolved address is returned in GetResolvedAddress.
669 port_ = addr.port();
671 resolver_->Start(addr, base::Bind(
672 &AsyncAddressResolverImpl::OnAddressResolved,
673 base::Unretained(this)));
676 bool AsyncAddressResolverImpl::GetResolvedAddress(
677 int family, rtc::SocketAddress* addr) const {
678 DCHECK(CalledOnValidThread());
680 if (addresses_.empty())
681 return false;
683 for (size_t i = 0; i < addresses_.size(); ++i) {
684 if (family == addresses_[i].family()) {
685 addr->SetResolvedIP(addresses_[i]);
686 addr->SetPort(port_);
687 return true;
690 return false;
693 int AsyncAddressResolverImpl::GetError() const {
694 DCHECK(CalledOnValidThread());
695 return addresses_.empty() ? -1 : 0;
698 void AsyncAddressResolverImpl::Destroy(bool wait) {
699 DCHECK(CalledOnValidThread());
700 resolver_->Cancel();
701 // Libjingle doesn't need this object any more and it's not going to delete
702 // it explicitly.
703 delete this;
706 void AsyncAddressResolverImpl::OnAddressResolved(
707 const net::IPAddressList& addresses) {
708 DCHECK(CalledOnValidThread());
709 for (size_t i = 0; i < addresses.size(); ++i) {
710 rtc::SocketAddress socket_address;
711 if (!jingle_glue::IPEndPointToSocketAddress(
712 net::IPEndPoint(addresses[i], 0), &socket_address)) {
713 NOTREACHED();
715 addresses_.push_back(socket_address.ipaddr());
717 SignalDone(this);
720 } // namespace
722 IpcPacketSocketFactory::IpcPacketSocketFactory(
723 P2PSocketDispatcher* socket_dispatcher)
724 : socket_dispatcher_(socket_dispatcher) {
727 IpcPacketSocketFactory::~IpcPacketSocketFactory() {
730 rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateUdpSocket(
731 const rtc::SocketAddress& local_address, uint16 min_port, uint16 max_port) {
732 rtc::SocketAddress crome_address;
733 P2PSocketClientImpl* socket_client =
734 new P2PSocketClientImpl(socket_dispatcher_);
735 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
736 // TODO(sergeyu): Respect local_address and port limits here (need
737 // to pass them over IPC channel to the browser).
738 if (!socket->Init(P2P_SOCKET_UDP, socket_client,
739 local_address, rtc::SocketAddress())) {
740 return NULL;
742 return socket.release();
745 rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateServerTcpSocket(
746 const rtc::SocketAddress& local_address, uint16 min_port, uint16 max_port,
747 int opts) {
748 // TODO(sergeyu): Implement SSL support.
749 if (opts & rtc::PacketSocketFactory::OPT_SSLTCP)
750 return NULL;
752 P2PSocketType type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
753 P2P_SOCKET_STUN_TCP_SERVER : P2P_SOCKET_TCP_SERVER;
754 P2PSocketClientImpl* socket_client =
755 new P2PSocketClientImpl(socket_dispatcher_);
756 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
757 if (!socket->Init(type, socket_client, local_address,
758 rtc::SocketAddress())) {
759 return NULL;
761 return socket.release();
764 rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateClientTcpSocket(
765 const rtc::SocketAddress& local_address,
766 const rtc::SocketAddress& remote_address,
767 const rtc::ProxyInfo& proxy_info,
768 const std::string& user_agent, int opts) {
769 P2PSocketType type;
770 if (opts & rtc::PacketSocketFactory::OPT_SSLTCP) {
771 type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
772 P2P_SOCKET_STUN_SSLTCP_CLIENT : P2P_SOCKET_SSLTCP_CLIENT;
773 } else if (opts & rtc::PacketSocketFactory::OPT_TLS) {
774 type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
775 P2P_SOCKET_STUN_TLS_CLIENT : P2P_SOCKET_TLS_CLIENT;
776 } else {
777 type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
778 P2P_SOCKET_STUN_TCP_CLIENT : P2P_SOCKET_TCP_CLIENT;
780 P2PSocketClientImpl* socket_client =
781 new P2PSocketClientImpl(socket_dispatcher_);
782 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
783 if (!socket->Init(type, socket_client, local_address, remote_address))
784 return NULL;
785 return socket.release();
788 rtc::AsyncResolverInterface*
789 IpcPacketSocketFactory::CreateAsyncResolver() {
790 scoped_ptr<AsyncAddressResolverImpl> resolver(
791 new AsyncAddressResolverImpl(socket_dispatcher_));
792 return resolver.release();
795 } // namespace content