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"
10 #include "base/compiler_specific.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/message_loop/message_loop_proxy.h"
13 #include "base/metrics/field_trial.h"
14 #include "base/metrics/histogram.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/threading/non_thread_safe.h"
18 #include "base/trace_event/trace_event.h"
19 #include "content/renderer/media/webrtc_logging.h"
20 #include "content/renderer/p2p/host_address_request.h"
21 #include "content/renderer/p2p/socket_client_delegate.h"
22 #include "content/renderer/p2p/socket_client_impl.h"
23 #include "content/renderer/p2p/socket_dispatcher.h"
24 #include "jingle/glue/utils.h"
25 #include "third_party/webrtc/base/asyncpacketsocket.h"
31 const int kDefaultNonSetOptionValue
= -1;
33 bool IsTcpClientSocket(P2PSocketType type
) {
34 return (type
== P2P_SOCKET_STUN_TCP_CLIENT
) ||
35 (type
== P2P_SOCKET_TCP_CLIENT
) ||
36 (type
== P2P_SOCKET_STUN_SSLTCP_CLIENT
) ||
37 (type
== P2P_SOCKET_SSLTCP_CLIENT
) ||
38 (type
== P2P_SOCKET_TLS_CLIENT
) ||
39 (type
== P2P_SOCKET_STUN_TLS_CLIENT
);
42 bool JingleSocketOptionToP2PSocketOption(rtc::Socket::Option option
,
43 P2PSocketOption
* ipc_option
) {
45 case rtc::Socket::OPT_RCVBUF
:
46 *ipc_option
= P2P_SOCKET_OPT_RCVBUF
;
48 case rtc::Socket::OPT_SNDBUF
:
49 *ipc_option
= P2P_SOCKET_OPT_SNDBUF
;
51 case rtc::Socket::OPT_DSCP
:
52 *ipc_option
= P2P_SOCKET_OPT_DSCP
;
54 case rtc::Socket::OPT_DONTFRAGMENT
:
55 case rtc::Socket::OPT_NODELAY
:
56 case rtc::Socket::OPT_IPV6_V6ONLY
:
57 case rtc::Socket::OPT_RTP_SENDTIME_EXTN_ID
:
58 return false; // Not supported by the chrome sockets.
66 // TODO(miu): This needs tuning. http://crbug.com/237960
67 // http://crbug.com/427555
68 const size_t kMaximumInFlightBytes
= 64 * 1024; // 64 KB
70 // IpcPacketSocket implements rtc::AsyncPacketSocket interface
71 // using P2PSocketClient that works over IPC-channel. It must be used
72 // on the thread it was created.
73 class IpcPacketSocket
: public rtc::AsyncPacketSocket
,
74 public P2PSocketClientDelegate
{
77 ~IpcPacketSocket() override
;
79 // Struct to track information when a packet is received by this socket for
80 // send. The information tracked here will be used to match with the
81 // P2PSendPacketMetrics from the underneath system socket.
82 struct InFlightPacketRecord
{
83 InFlightPacketRecord(uint64_t packet_id
, size_t packet_size
)
84 : packet_id(packet_id
), packet_size(packet_size
) {}
90 typedef std::list
<InFlightPacketRecord
> InFlightPacketList
;
92 // Always takes ownership of client even if initialization fails.
93 bool Init(P2PSocketType type
, P2PSocketClientImpl
* client
,
94 const rtc::SocketAddress
& local_address
,
95 const rtc::SocketAddress
& remote_address
);
97 // rtc::AsyncPacketSocket interface.
98 rtc::SocketAddress
GetLocalAddress() const override
;
99 rtc::SocketAddress
GetRemoteAddress() const override
;
100 int Send(const void* pv
,
102 const rtc::PacketOptions
& options
) override
;
103 int SendTo(const void* pv
,
105 const rtc::SocketAddress
& addr
,
106 const rtc::PacketOptions
& options
) override
;
107 int Close() override
;
108 State
GetState() const override
;
109 int GetOption(rtc::Socket::Option option
, int* value
) override
;
110 int SetOption(rtc::Socket::Option option
, int value
) override
;
111 int GetError() const override
;
112 void SetError(int error
) override
;
114 // P2PSocketClientDelegate implementation.
115 void OnOpen(const net::IPEndPoint
& local_address
,
116 const net::IPEndPoint
& remote_address
) override
;
117 void OnIncomingTcpConnection(const net::IPEndPoint
& address
,
118 P2PSocketClient
* client
) override
;
119 void OnSendComplete(const P2PSendPacketMetrics
& send_metrics
) override
;
120 void OnError() override
;
121 void OnDataReceived(const net::IPEndPoint
& address
,
122 const std::vector
<char>& data
,
123 const base::TimeTicks
& timestamp
) override
;
134 // Increment the counter for consecutive bytes discarded as socket is running
136 void IncrementDiscardCounters(size_t bytes_discarded
);
138 // Update trace of send throttling internal state. This should be called
139 // immediately after any changes to |send_bytes_available_| and/or
140 // |in_flight_packet_records_|.
141 void TraceSendThrottlingState() const;
143 void InitAcceptedTcp(P2PSocketClient
* client
,
144 const rtc::SocketAddress
& local_address
,
145 const rtc::SocketAddress
& remote_address
);
147 int DoSetOption(P2PSocketOption option
, int value
);
149 // Allow a finch experiment to control the initial value of
150 // send_bytes_available_;
151 void AdjustUdpSendBufferSize();
155 // Message loop on which this socket was created and being used.
156 base::MessageLoop
* message_loop_
;
158 // Corresponding P2P socket client.
159 scoped_refptr
<P2PSocketClient
> client_
;
161 // Local address is allocated by the browser process, and the
162 // renderer side doesn't know the address until it receives OnOpen()
163 // event from the browser.
164 rtc::SocketAddress local_address_
;
166 // Remote address for client TCP connections.
167 rtc::SocketAddress remote_address_
;
169 // Current state of the object.
170 InternalState state_
;
172 // Track the number of bytes allowed to be sent non-blocking. This is used to
173 // throttle the sending of packets to the browser process. For each packet
174 // sent, the value is decreased. As callbacks to OnSendComplete() (as IPCs
175 // from the browser process) are made, the value is increased back. This
176 // allows short bursts of high-rate sending without dropping packets, but
177 // quickly restricts the client to a sustainable steady-state rate.
178 size_t send_bytes_available_
;
180 // Used to detect when browser doesn't send SendComplete message for some
181 // packets. In normal case, the first packet should be the one that we're
182 // going to receive the next completion signal.
183 InFlightPacketList in_flight_packet_records_
;
185 // Set to true once EWOULDBLOCK was returned from Send(). Indicates that the
186 // caller expects SignalWritable notification.
187 bool writable_signal_expected_
;
189 // Current error code. Valid when state_ == IS_ERROR.
191 int options_
[P2P_SOCKET_OPT_MAX
];
193 // Track the maximum and current consecutive bytes discarded due to not enough
194 // send_bytes_available_.
195 size_t max_discard_bytes_sequence_
;
196 size_t current_discard_bytes_sequence_
;
198 // Track the total number of packets and the number of packets discarded.
199 size_t packets_discarded_
;
200 size_t total_packets_
;
202 DISALLOW_COPY_AND_ASSIGN(IpcPacketSocket
);
205 // Simple wrapper around P2PAsyncAddressResolver. The main purpose of this
206 // class is to send SignalDone, after OnDone callback from
207 // P2PAsyncAddressResolver. Libjingle sig slots are not thread safe. In case
208 // of MT sig slots clients must call disconnect. This class is to make sure
209 // we destruct from the same thread on which is created.
210 class AsyncAddressResolverImpl
: public base::NonThreadSafe
,
211 public rtc::AsyncResolverInterface
{
213 AsyncAddressResolverImpl(P2PSocketDispatcher
* dispatcher
);
214 ~AsyncAddressResolverImpl() override
;
216 // rtc::AsyncResolverInterface interface.
217 void Start(const rtc::SocketAddress
& addr
) override
;
218 bool GetResolvedAddress(int family
, rtc::SocketAddress
* addr
) const override
;
219 int GetError() const override
;
220 void Destroy(bool wait
) override
;
223 virtual void OnAddressResolved(const net::IPAddressList
& addresses
);
225 scoped_refptr
<P2PAsyncAddressResolver
> resolver_
;
226 int port_
; // Port number in |addr| from Start() method.
227 std::vector
<rtc::IPAddress
> addresses_
; // Resolved addresses.
230 IpcPacketSocket::IpcPacketSocket()
231 : type_(P2P_SOCKET_UDP
),
232 message_loop_(base::MessageLoop::current()),
233 state_(IS_UNINITIALIZED
),
234 send_bytes_available_(kMaximumInFlightBytes
),
235 writable_signal_expected_(false),
237 max_discard_bytes_sequence_(0),
238 current_discard_bytes_sequence_(0),
239 packets_discarded_(0),
241 static_assert(kMaximumInFlightBytes
> 0, "would send at zero rate");
242 std::fill_n(options_
, static_cast<int> (P2P_SOCKET_OPT_MAX
),
243 kDefaultNonSetOptionValue
);
246 IpcPacketSocket::~IpcPacketSocket() {
247 if (state_
== IS_OPENING
|| state_
== IS_OPEN
||
248 state_
== IS_ERROR
) {
252 UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.ApplicationMaxConsecutiveBytesDiscard.v2",
253 max_discard_bytes_sequence_
, 1, 1000000, 200);
254 if (total_packets_
> 0) {
255 UMA_HISTOGRAM_PERCENTAGE("WebRTC.ApplicationPercentPacketsDiscarded",
256 (packets_discarded_
* 100) / total_packets_
);
260 void IpcPacketSocket::TraceSendThrottlingState() const {
261 TRACE_COUNTER_ID1("p2p", "P2PSendBytesAvailable", local_address_
.port(),
262 send_bytes_available_
);
263 TRACE_COUNTER_ID1("p2p", "P2PSendPacketsInFlight", local_address_
.port(),
264 in_flight_packet_records_
.size());
267 void IpcPacketSocket::IncrementDiscardCounters(size_t bytes_discarded
) {
268 current_discard_bytes_sequence_
+= bytes_discarded
;
269 packets_discarded_
++;
271 if (current_discard_bytes_sequence_
> max_discard_bytes_sequence_
) {
272 max_discard_bytes_sequence_
= current_discard_bytes_sequence_
;
276 void IpcPacketSocket::AdjustUdpSendBufferSize() {
277 DCHECK_EQ(type_
, P2P_SOCKET_UDP
);
278 unsigned int send_buffer_size
= 0;
281 base::FieldTrialList::FindFullName("WebRTC-ApplicationUDPSendSocketSize"),
284 if (send_buffer_size
> 0) {
285 send_bytes_available_
= send_buffer_size
;
289 bool IpcPacketSocket::Init(P2PSocketType type
,
290 P2PSocketClientImpl
* client
,
291 const rtc::SocketAddress
& local_address
,
292 const rtc::SocketAddress
& remote_address
) {
293 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
294 DCHECK_EQ(state_
, IS_UNINITIALIZED
);
298 local_address_
= local_address
;
299 remote_address_
= remote_address
;
302 net::IPEndPoint local_endpoint
;
303 if (!jingle_glue::SocketAddressToIPEndPoint(
304 local_address
, &local_endpoint
)) {
308 if (type_
== P2P_SOCKET_UDP
) {
309 AdjustUdpSendBufferSize();
312 net::IPEndPoint remote_endpoint
;
313 if (!remote_address
.IsNil()) {
314 DCHECK(IsTcpClientSocket(type_
));
316 if (remote_address
.IsUnresolvedIP()) {
318 net::IPEndPoint(net::IPAddressNumber(), remote_address
.port());
320 if (!jingle_glue::SocketAddressToIPEndPoint(remote_address
,
327 // We need to send both resolved and unresolved address in Init. Unresolved
328 // address will be used in case of TLS for certificate hostname matching.
329 // Certificate will be tied to domain name not to IP address.
330 P2PHostAndIPEndPoint
remote_info(remote_address
.hostname(), remote_endpoint
);
332 client
->Init(type
, local_endpoint
, remote_info
, this);
337 void IpcPacketSocket::InitAcceptedTcp(
338 P2PSocketClient
* client
,
339 const rtc::SocketAddress
& local_address
,
340 const rtc::SocketAddress
& remote_address
) {
341 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
342 DCHECK_EQ(state_
, IS_UNINITIALIZED
);
345 local_address_
= local_address
;
346 remote_address_
= remote_address
;
348 TraceSendThrottlingState();
349 client_
->SetDelegate(this);
352 // rtc::AsyncPacketSocket interface.
353 rtc::SocketAddress
IpcPacketSocket::GetLocalAddress() const {
354 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
355 return local_address_
;
358 rtc::SocketAddress
IpcPacketSocket::GetRemoteAddress() const {
359 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
360 return remote_address_
;
363 int IpcPacketSocket::Send(const void *data
, size_t data_size
,
364 const rtc::PacketOptions
& options
) {
365 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
366 return SendTo(data
, data_size
, remote_address_
, options
);
369 int IpcPacketSocket::SendTo(const void *data
, size_t data_size
,
370 const rtc::SocketAddress
& address
,
371 const rtc::PacketOptions
& options
) {
372 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
375 case IS_UNINITIALIZED
:
385 // Continue sending the packet.
389 if (data_size
== 0) {
396 if (data_size
> send_bytes_available_
) {
397 TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock",
398 TRACE_EVENT_SCOPE_THREAD
,
400 client_
->GetSocketID());
401 if (!writable_signal_expected_
) {
402 WebRtcLogMessage(base::StringPrintf(
403 "IpcPacketSocket: sending is blocked. %d packets_in_flight.",
404 static_cast<int>(in_flight_packet_records_
.size())));
406 writable_signal_expected_
= true;
409 error_
= EWOULDBLOCK
;
410 IncrementDiscardCounters(data_size
);
413 current_discard_bytes_sequence_
= 0;
416 net::IPEndPoint address_chrome
;
417 if (address
.IsUnresolvedIP()) {
418 address_chrome
= net::IPEndPoint(net::IPAddressNumber(), address
.port());
420 if (!jingle_glue::SocketAddressToIPEndPoint(address
, &address_chrome
)) {
421 LOG(WARNING
) << "Failed to convert remote address to IPEndPoint: address="
422 << address
.ipaddr().ToSensitiveString()
423 << ", remote_address_="
424 << remote_address_
.ipaddr().ToSensitiveString();
431 send_bytes_available_
-= data_size
;
433 const char* data_char
= reinterpret_cast<const char*>(data
);
434 std::vector
<char> data_vector(data_char
, data_char
+ data_size
);
435 uint64_t packet_id
= client_
->Send(address_chrome
, data_vector
, options
);
437 // Ensure packet_id is not 0. It can't be the case according to
438 // P2PSocketClientImpl::Send().
439 DCHECK_NE(packet_id
, 0uL);
441 in_flight_packet_records_
.push_back(
442 InFlightPacketRecord(packet_id
, data_size
));
443 TraceSendThrottlingState();
445 // Fake successful send. The caller ignores result anyway.
449 int IpcPacketSocket::Close() {
450 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
458 rtc::AsyncPacketSocket::State
IpcPacketSocket::GetState() const {
459 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
462 case IS_UNINITIALIZED
:
467 return STATE_BINDING
;
470 if (IsTcpClientSocket(type_
)) {
471 return STATE_CONNECTED
;
485 int IpcPacketSocket::GetOption(rtc::Socket::Option option
, int* value
) {
486 P2PSocketOption p2p_socket_option
= P2P_SOCKET_OPT_MAX
;
487 if (!JingleSocketOptionToP2PSocketOption(option
, &p2p_socket_option
)) {
488 // unsupported option.
492 *value
= options_
[p2p_socket_option
];
496 int IpcPacketSocket::SetOption(rtc::Socket::Option option
, int value
) {
497 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
499 P2PSocketOption p2p_socket_option
= P2P_SOCKET_OPT_MAX
;
500 if (!JingleSocketOptionToP2PSocketOption(option
, &p2p_socket_option
)) {
501 // Option is not supported.
505 options_
[p2p_socket_option
] = value
;
507 if (state_
== IS_OPEN
) {
508 // Options will be applied when state becomes IS_OPEN in OnOpen.
509 return DoSetOption(p2p_socket_option
, value
);
514 int IpcPacketSocket::DoSetOption(P2PSocketOption option
, int value
) {
515 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
516 DCHECK_EQ(state_
, IS_OPEN
);
518 client_
->SetOption(option
, value
);
522 int IpcPacketSocket::GetError() const {
523 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
527 void IpcPacketSocket::SetError(int error
) {
528 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
532 void IpcPacketSocket::OnOpen(const net::IPEndPoint
& local_address
,
533 const net::IPEndPoint
& remote_address
) {
534 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
536 if (!jingle_glue::IPEndPointToSocketAddress(local_address
, &local_address_
)) {
537 // Always expect correct IPv4 address to be allocated.
544 TraceSendThrottlingState();
546 // Set all pending options if any.
547 for (int i
= 0; i
< P2P_SOCKET_OPT_MAX
; ++i
) {
548 if (options_
[i
] != kDefaultNonSetOptionValue
)
549 DoSetOption(static_cast<P2PSocketOption
> (i
), options_
[i
]);
552 SignalAddressReady(this, local_address_
);
553 if (IsTcpClientSocket(type_
)) {
554 // If remote address is unresolved, set resolved remote IP address received
555 // in the callback. This address will be used while sending the packets
557 if (remote_address_
.IsUnresolvedIP()) {
558 rtc::SocketAddress jingle_socket_address
;
559 // |remote_address| could be unresolved if the connection is behind a
561 if (!remote_address
.address().empty() &&
562 jingle_glue::IPEndPointToSocketAddress(
563 remote_address
, &jingle_socket_address
)) {
564 // Set only the IP address.
565 remote_address_
.SetResolvedIP(jingle_socket_address
.ipaddr());
569 // SignalConnect after updating the |remote_address_| so that the listener
570 // can get the resolved remote address.
575 void IpcPacketSocket::OnIncomingTcpConnection(
576 const net::IPEndPoint
& address
,
577 P2PSocketClient
* client
) {
578 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
580 scoped_ptr
<IpcPacketSocket
> socket(new IpcPacketSocket());
582 rtc::SocketAddress remote_address
;
583 if (!jingle_glue::IPEndPointToSocketAddress(address
, &remote_address
)) {
584 // Always expect correct IPv4 address to be allocated.
587 socket
->InitAcceptedTcp(client
, local_address_
, remote_address
);
588 SignalNewConnection(this, socket
.release());
591 void IpcPacketSocket::OnSendComplete(const P2PSendPacketMetrics
& send_metrics
) {
592 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
594 CHECK(!in_flight_packet_records_
.empty());
596 const InFlightPacketRecord
& record
= in_flight_packet_records_
.front();
598 // Tracking is not turned on for TCP so it's always 0. For UDP, this will
599 // cause a crash when the packet ids don't match.
600 CHECK(send_metrics
.packet_id
== 0 ||
601 record
.packet_id
== send_metrics
.packet_id
);
603 send_bytes_available_
+= record
.packet_size
;
605 DCHECK_LE(send_bytes_available_
, kMaximumInFlightBytes
);
607 in_flight_packet_records_
.pop_front();
608 TraceSendThrottlingState();
610 if (writable_signal_expected_
&& send_bytes_available_
> 0) {
611 WebRtcLogMessage(base::StringPrintf(
612 "IpcPacketSocket: sending is unblocked. %d packets in flight.",
613 static_cast<int>(in_flight_packet_records_
.size())));
615 SignalReadyToSend(this);
616 writable_signal_expected_
= false;
620 void IpcPacketSocket::OnError() {
621 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
622 bool was_closed
= (state_
== IS_ERROR
|| state_
== IS_CLOSED
);
624 error_
= ECONNABORTED
;
626 SignalClose(this, 0);
630 void IpcPacketSocket::OnDataReceived(const net::IPEndPoint
& address
,
631 const std::vector
<char>& data
,
632 const base::TimeTicks
& timestamp
) {
633 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
635 rtc::SocketAddress address_lj
;
637 if (address
.address().empty()) {
638 DCHECK(IsTcpClientSocket(type_
));
639 // |address| could be empty for TCP connections behind a proxy.
640 address_lj
= remote_address_
;
642 if (!jingle_glue::IPEndPointToSocketAddress(address
, &address_lj
)) {
643 // We should always be able to convert address here because we
644 // don't expect IPv6 address on IPv4 connections.
650 rtc::PacketTime
packet_time(timestamp
.ToInternalValue(), 0);
651 SignalReadPacket(this, &data
[0], data
.size(), address_lj
,
655 AsyncAddressResolverImpl::AsyncAddressResolverImpl(
656 P2PSocketDispatcher
* dispatcher
)
657 : resolver_(new P2PAsyncAddressResolver(dispatcher
)) {
660 AsyncAddressResolverImpl::~AsyncAddressResolverImpl() {
663 void AsyncAddressResolverImpl::Start(const rtc::SocketAddress
& addr
) {
664 DCHECK(CalledOnValidThread());
665 // Copy port number from |addr|. |port_| must be copied
666 // when resolved address is returned in GetResolvedAddress.
669 resolver_
->Start(addr
, base::Bind(
670 &AsyncAddressResolverImpl::OnAddressResolved
,
671 base::Unretained(this)));
674 bool AsyncAddressResolverImpl::GetResolvedAddress(
675 int family
, rtc::SocketAddress
* addr
) const {
676 DCHECK(CalledOnValidThread());
678 if (addresses_
.empty())
681 for (size_t i
= 0; i
< addresses_
.size(); ++i
) {
682 if (family
== addresses_
[i
].family()) {
683 addr
->SetResolvedIP(addresses_
[i
]);
684 addr
->SetPort(port_
);
691 int AsyncAddressResolverImpl::GetError() const {
692 DCHECK(CalledOnValidThread());
693 return addresses_
.empty() ? -1 : 0;
696 void AsyncAddressResolverImpl::Destroy(bool wait
) {
697 DCHECK(CalledOnValidThread());
699 // Libjingle doesn't need this object any more and it's not going to delete
704 void AsyncAddressResolverImpl::OnAddressResolved(
705 const net::IPAddressList
& addresses
) {
706 DCHECK(CalledOnValidThread());
707 for (size_t i
= 0; i
< addresses
.size(); ++i
) {
708 rtc::SocketAddress socket_address
;
709 if (!jingle_glue::IPEndPointToSocketAddress(
710 net::IPEndPoint(addresses
[i
], 0), &socket_address
)) {
713 addresses_
.push_back(socket_address
.ipaddr());
720 IpcPacketSocketFactory::IpcPacketSocketFactory(
721 P2PSocketDispatcher
* socket_dispatcher
)
722 : socket_dispatcher_(socket_dispatcher
) {
725 IpcPacketSocketFactory::~IpcPacketSocketFactory() {
728 rtc::AsyncPacketSocket
* IpcPacketSocketFactory::CreateUdpSocket(
729 const rtc::SocketAddress
& local_address
, uint16 min_port
, uint16 max_port
) {
730 rtc::SocketAddress crome_address
;
731 P2PSocketClientImpl
* socket_client
=
732 new P2PSocketClientImpl(socket_dispatcher_
);
733 scoped_ptr
<IpcPacketSocket
> socket(new IpcPacketSocket());
734 // TODO(sergeyu): Respect local_address and port limits here (need
735 // to pass them over IPC channel to the browser).
736 if (!socket
->Init(P2P_SOCKET_UDP
, socket_client
,
737 local_address
, rtc::SocketAddress())) {
740 return socket
.release();
743 rtc::AsyncPacketSocket
* IpcPacketSocketFactory::CreateServerTcpSocket(
744 const rtc::SocketAddress
& local_address
, uint16 min_port
, uint16 max_port
,
746 // TODO(sergeyu): Implement SSL support.
747 if (opts
& rtc::PacketSocketFactory::OPT_SSLTCP
)
750 P2PSocketType type
= (opts
& rtc::PacketSocketFactory::OPT_STUN
) ?
751 P2P_SOCKET_STUN_TCP_SERVER
: P2P_SOCKET_TCP_SERVER
;
752 P2PSocketClientImpl
* socket_client
=
753 new P2PSocketClientImpl(socket_dispatcher_
);
754 scoped_ptr
<IpcPacketSocket
> socket(new IpcPacketSocket());
755 if (!socket
->Init(type
, socket_client
, local_address
,
756 rtc::SocketAddress())) {
759 return socket
.release();
762 rtc::AsyncPacketSocket
* IpcPacketSocketFactory::CreateClientTcpSocket(
763 const rtc::SocketAddress
& local_address
,
764 const rtc::SocketAddress
& remote_address
,
765 const rtc::ProxyInfo
& proxy_info
,
766 const std::string
& user_agent
, int opts
) {
768 if (opts
& rtc::PacketSocketFactory::OPT_SSLTCP
) {
769 type
= (opts
& rtc::PacketSocketFactory::OPT_STUN
) ?
770 P2P_SOCKET_STUN_SSLTCP_CLIENT
: P2P_SOCKET_SSLTCP_CLIENT
;
771 } else if (opts
& rtc::PacketSocketFactory::OPT_TLS
) {
772 type
= (opts
& rtc::PacketSocketFactory::OPT_STUN
) ?
773 P2P_SOCKET_STUN_TLS_CLIENT
: P2P_SOCKET_TLS_CLIENT
;
775 type
= (opts
& rtc::PacketSocketFactory::OPT_STUN
) ?
776 P2P_SOCKET_STUN_TCP_CLIENT
: P2P_SOCKET_TCP_CLIENT
;
778 P2PSocketClientImpl
* socket_client
=
779 new P2PSocketClientImpl(socket_dispatcher_
);
780 scoped_ptr
<IpcPacketSocket
> socket(new IpcPacketSocket());
781 if (!socket
->Init(type
, socket_client
, local_address
, remote_address
))
783 return socket
.release();
786 rtc::AsyncResolverInterface
*
787 IpcPacketSocketFactory::CreateAsyncResolver() {
788 scoped_ptr
<AsyncAddressResolverImpl
> resolver(
789 new AsyncAddressResolverImpl(socket_dispatcher_
));
790 return resolver
.release();
793 } // namespace content