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/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"
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
) {
44 case rtc::Socket::OPT_RCVBUF
:
45 *ipc_option
= P2P_SOCKET_OPT_RCVBUF
;
47 case rtc::Socket::OPT_SNDBUF
:
48 *ipc_option
= P2P_SOCKET_OPT_SNDBUF
;
50 case rtc::Socket::OPT_DSCP
:
51 *ipc_option
= P2P_SOCKET_OPT_DSCP
;
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.
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
{
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
) {}
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
,
101 const rtc::PacketOptions
& options
) override
;
102 int SendTo(const void* pv
,
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
;
133 // Increment the counter for consecutive bytes discarded as socket is running
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();
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.
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
{
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
;
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),
236 max_discard_bytes_sequence_(0),
237 current_discard_bytes_sequence_(0),
238 packets_discarded_(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
) {
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;
280 base::FieldTrialList::FindFullName("WebRTC-ApplicationUDPSendSocketSize"),
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
);
297 local_address_
= local_address
;
298 remote_address_
= remote_address
;
301 net::IPEndPoint local_endpoint
;
302 if (!jingle_glue::SocketAddressToIPEndPoint(
303 local_address
, &local_endpoint
)) {
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()) {
317 net::IPEndPoint(net::IPAddressNumber(), remote_address
.port());
319 if (!jingle_glue::SocketAddressToIPEndPoint(remote_address
,
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);
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
);
344 local_address_
= local_address
;
345 remote_address_
= remote_address
;
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_
);
374 case IS_UNINITIALIZED
:
376 error_
= EWOULDBLOCK
;
379 error_
= EWOULDBLOCK
;
387 // Continue sending the packet.
391 if (data_size
== 0) {
398 if (data_size
> send_bytes_available_
) {
399 TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock",
400 TRACE_EVENT_SCOPE_THREAD
,
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
);
415 current_discard_bytes_sequence_
= 0;
418 net::IPEndPoint address_chrome
;
419 if (address
.IsUnresolvedIP()) {
420 address_chrome
= net::IPEndPoint(net::IPAddressNumber(), address
.port());
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();
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.
451 int IpcPacketSocket::Close() {
452 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
460 rtc::AsyncPacketSocket::State
IpcPacketSocket::GetState() const {
461 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
464 case IS_UNINITIALIZED
:
469 return STATE_BINDING
;
472 if (IsTcpClientSocket(type_
)) {
473 return STATE_CONNECTED
;
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.
494 *value
= options_
[p2p_socket_option
];
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.
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
);
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
);
524 int IpcPacketSocket::GetError() const {
525 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
529 void IpcPacketSocket::SetError(int error
) {
530 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
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.
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
559 if (remote_address_
.IsUnresolvedIP()) {
560 rtc::SocketAddress jingle_socket_address
;
561 // |remote_address| could be unresolved if the connection is behind a
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.
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.
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
);
626 error_
= ECONNABORTED
;
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_
;
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.
652 rtc::PacketTime
packet_time(timestamp
.ToInternalValue(), 0);
653 SignalReadPacket(this, &data
[0], data
.size(), address_lj
,
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.
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())
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_
);
693 int AsyncAddressResolverImpl::GetError() const {
694 DCHECK(CalledOnValidThread());
695 return addresses_
.empty() ? -1 : 0;
698 void AsyncAddressResolverImpl::Destroy(bool wait
) {
699 DCHECK(CalledOnValidThread());
701 // Libjingle doesn't need this object any more and it's not going to delete
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
)) {
715 addresses_
.push_back(socket_address
.ipaddr());
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())) {
742 return socket
.release();
745 rtc::AsyncPacketSocket
* IpcPacketSocketFactory::CreateServerTcpSocket(
746 const rtc::SocketAddress
& local_address
, uint16 min_port
, uint16 max_port
,
748 // TODO(sergeyu): Implement SSL support.
749 if (opts
& rtc::PacketSocketFactory::OPT_SSLTCP
)
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())) {
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
) {
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
;
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
))
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