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/debug/trace_event.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/threading/non_thread_safe.h"
16 #include "content/renderer/media/webrtc_logging.h"
17 #include "content/renderer/p2p/host_address_request.h"
18 #include "content/renderer/p2p/socket_client_delegate.h"
19 #include "content/renderer/p2p/socket_client_impl.h"
20 #include "content/renderer/p2p/socket_dispatcher.h"
21 #include "jingle/glue/utils.h"
22 #include "third_party/webrtc/base/asyncpacketsocket.h"
28 const int kDefaultNonSetOptionValue
= -1;
30 bool IsTcpClientSocket(P2PSocketType type
) {
31 return (type
== P2P_SOCKET_STUN_TCP_CLIENT
) ||
32 (type
== P2P_SOCKET_TCP_CLIENT
) ||
33 (type
== P2P_SOCKET_STUN_SSLTCP_CLIENT
) ||
34 (type
== P2P_SOCKET_SSLTCP_CLIENT
) ||
35 (type
== P2P_SOCKET_TLS_CLIENT
) ||
36 (type
== P2P_SOCKET_STUN_TLS_CLIENT
);
39 bool JingleSocketOptionToP2PSocketOption(rtc::Socket::Option option
,
40 P2PSocketOption
* ipc_option
) {
42 case rtc::Socket::OPT_RCVBUF
:
43 *ipc_option
= P2P_SOCKET_OPT_RCVBUF
;
45 case rtc::Socket::OPT_SNDBUF
:
46 *ipc_option
= P2P_SOCKET_OPT_SNDBUF
;
48 case rtc::Socket::OPT_DSCP
:
49 *ipc_option
= P2P_SOCKET_OPT_DSCP
;
51 case rtc::Socket::OPT_DONTFRAGMENT
:
52 case rtc::Socket::OPT_NODELAY
:
53 case rtc::Socket::OPT_IPV6_V6ONLY
:
54 case rtc::Socket::OPT_RTP_SENDTIME_EXTN_ID
:
55 return false; // Not supported by the chrome sockets.
63 // TODO(miu): This needs tuning. http://crbug.com/237960
64 const size_t kMaximumInFlightBytes
= 64 * 1024; // 64 KB
66 // IpcPacketSocket implements rtc::AsyncPacketSocket interface
67 // using P2PSocketClient that works over IPC-channel. It must be used
68 // on the thread it was created.
69 class IpcPacketSocket
: public rtc::AsyncPacketSocket
,
70 public P2PSocketClientDelegate
{
73 virtual ~IpcPacketSocket();
75 // Always takes ownership of client even if initialization fails.
76 bool Init(P2PSocketType type
, P2PSocketClientImpl
* client
,
77 const rtc::SocketAddress
& local_address
,
78 const rtc::SocketAddress
& remote_address
);
80 // rtc::AsyncPacketSocket interface.
81 virtual rtc::SocketAddress
GetLocalAddress() const OVERRIDE
;
82 virtual rtc::SocketAddress
GetRemoteAddress() const OVERRIDE
;
83 virtual int Send(const void *pv
, size_t cb
,
84 const rtc::PacketOptions
& options
) OVERRIDE
;
85 virtual int SendTo(const void *pv
, size_t cb
,
86 const rtc::SocketAddress
& addr
,
87 const rtc::PacketOptions
& options
) OVERRIDE
;
88 virtual int Close() OVERRIDE
;
89 virtual State
GetState() const OVERRIDE
;
90 virtual int GetOption(rtc::Socket::Option option
, int* value
) OVERRIDE
;
91 virtual int SetOption(rtc::Socket::Option option
, int value
) OVERRIDE
;
92 virtual int GetError() const OVERRIDE
;
93 virtual void SetError(int error
) OVERRIDE
;
95 // P2PSocketClientDelegate implementation.
96 virtual void OnOpen(const net::IPEndPoint
& local_address
,
97 const net::IPEndPoint
& remote_address
) OVERRIDE
;
98 virtual void OnIncomingTcpConnection(
99 const net::IPEndPoint
& address
,
100 P2PSocketClient
* client
) OVERRIDE
;
101 virtual void OnSendComplete() OVERRIDE
;
102 virtual void OnError() OVERRIDE
;
103 virtual void OnDataReceived(const net::IPEndPoint
& address
,
104 const std::vector
<char>& data
,
105 const base::TimeTicks
& timestamp
) OVERRIDE
;
116 // Update trace of send throttling internal state. This should be called
117 // immediately after any changes to |send_bytes_available_| and/or
118 // |in_flight_packet_sizes_|.
119 void TraceSendThrottlingState() const;
121 void InitAcceptedTcp(P2PSocketClient
* client
,
122 const rtc::SocketAddress
& local_address
,
123 const rtc::SocketAddress
& remote_address
);
125 int DoSetOption(P2PSocketOption option
, int value
);
129 // Message loop on which this socket was created and being used.
130 base::MessageLoop
* message_loop_
;
132 // Corresponding P2P socket client.
133 scoped_refptr
<P2PSocketClient
> client_
;
135 // Local address is allocated by the browser process, and the
136 // renderer side doesn't know the address until it receives OnOpen()
137 // event from the browser.
138 rtc::SocketAddress local_address_
;
140 // Remote address for client TCP connections.
141 rtc::SocketAddress remote_address_
;
143 // Current state of the object.
144 InternalState state_
;
146 // Track the number of bytes allowed to be sent non-blocking. This is used to
147 // throttle the sending of packets to the browser process. For each packet
148 // sent, the value is decreased. As callbacks to OnSendComplete() (as IPCs
149 // from the browser process) are made, the value is increased back. This
150 // allows short bursts of high-rate sending without dropping packets, but
151 // quickly restricts the client to a sustainable steady-state rate.
152 size_t send_bytes_available_
;
153 std::deque
<size_t> in_flight_packet_sizes_
;
155 // Set to true once EWOULDBLOCK was returned from Send(). Indicates that the
156 // caller expects SignalWritable notification.
157 bool writable_signal_expected_
;
159 // Current error code. Valid when state_ == IS_ERROR.
161 int options_
[P2P_SOCKET_OPT_MAX
];
163 DISALLOW_COPY_AND_ASSIGN(IpcPacketSocket
);
166 // Simple wrapper around P2PAsyncAddressResolver. The main purpose of this
167 // class is to send SignalDone, after OnDone callback from
168 // P2PAsyncAddressResolver. Libjingle sig slots are not thread safe. In case
169 // of MT sig slots clients must call disconnect. This class is to make sure
170 // we destruct from the same thread on which is created.
171 class AsyncAddressResolverImpl
: public base::NonThreadSafe
,
172 public rtc::AsyncResolverInterface
{
174 AsyncAddressResolverImpl(P2PSocketDispatcher
* dispatcher
);
175 virtual ~AsyncAddressResolverImpl();
177 // rtc::AsyncResolverInterface interface.
178 virtual void Start(const rtc::SocketAddress
& addr
) OVERRIDE
;
179 virtual bool GetResolvedAddress(
180 int family
, rtc::SocketAddress
* addr
) const OVERRIDE
;
181 virtual int GetError() const OVERRIDE
;
182 virtual void Destroy(bool wait
) OVERRIDE
;
185 virtual void OnAddressResolved(const net::IPAddressList
& addresses
);
187 scoped_refptr
<P2PAsyncAddressResolver
> resolver_
;
188 int port_
; // Port number in |addr| from Start() method.
189 std::vector
<rtc::IPAddress
> addresses_
; // Resolved addresses.
192 IpcPacketSocket::IpcPacketSocket()
193 : type_(P2P_SOCKET_UDP
),
194 message_loop_(base::MessageLoop::current()),
195 state_(IS_UNINITIALIZED
),
196 send_bytes_available_(kMaximumInFlightBytes
),
197 writable_signal_expected_(false),
199 COMPILE_ASSERT(kMaximumInFlightBytes
> 0, would_send_at_zero_rate
);
200 std::fill_n(options_
, static_cast<int> (P2P_SOCKET_OPT_MAX
),
201 kDefaultNonSetOptionValue
);
204 IpcPacketSocket::~IpcPacketSocket() {
205 if (state_
== IS_OPENING
|| state_
== IS_OPEN
||
206 state_
== IS_ERROR
) {
211 void IpcPacketSocket::TraceSendThrottlingState() const {
212 TRACE_COUNTER_ID1("p2p", "P2PSendBytesAvailable", local_address_
.port(),
213 send_bytes_available_
);
214 TRACE_COUNTER_ID1("p2p", "P2PSendPacketsInFlight", local_address_
.port(),
215 in_flight_packet_sizes_
.size());
218 bool IpcPacketSocket::Init(P2PSocketType type
,
219 P2PSocketClientImpl
* client
,
220 const rtc::SocketAddress
& local_address
,
221 const rtc::SocketAddress
& remote_address
) {
222 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
223 DCHECK_EQ(state_
, IS_UNINITIALIZED
);
227 local_address_
= local_address
;
228 remote_address_
= remote_address
;
231 net::IPEndPoint local_endpoint
;
232 if (!jingle_glue::SocketAddressToIPEndPoint(
233 local_address
, &local_endpoint
)) {
237 net::IPEndPoint remote_endpoint
;
238 if (!remote_address
.IsNil()) {
239 DCHECK(IsTcpClientSocket(type_
));
241 if (remote_address
.IsUnresolvedIP()) {
243 net::IPEndPoint(net::IPAddressNumber(), remote_address
.port());
245 if (!jingle_glue::SocketAddressToIPEndPoint(remote_address
,
252 // We need to send both resolved and unresolved address in Init. Unresolved
253 // address will be used in case of TLS for certificate hostname matching.
254 // Certificate will be tied to domain name not to IP address.
255 P2PHostAndIPEndPoint
remote_info(remote_address
.hostname(), remote_endpoint
);
257 client
->Init(type
, local_endpoint
, remote_info
, this);
262 void IpcPacketSocket::InitAcceptedTcp(
263 P2PSocketClient
* client
,
264 const rtc::SocketAddress
& local_address
,
265 const rtc::SocketAddress
& remote_address
) {
266 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
267 DCHECK_EQ(state_
, IS_UNINITIALIZED
);
270 local_address_
= local_address
;
271 remote_address_
= remote_address
;
273 TraceSendThrottlingState();
274 client_
->SetDelegate(this);
277 // rtc::AsyncPacketSocket interface.
278 rtc::SocketAddress
IpcPacketSocket::GetLocalAddress() const {
279 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
280 return local_address_
;
283 rtc::SocketAddress
IpcPacketSocket::GetRemoteAddress() const {
284 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
285 return remote_address_
;
288 int IpcPacketSocket::Send(const void *data
, size_t data_size
,
289 const rtc::PacketOptions
& options
) {
290 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
291 return SendTo(data
, data_size
, remote_address_
, options
);
294 int IpcPacketSocket::SendTo(const void *data
, size_t data_size
,
295 const rtc::SocketAddress
& address
,
296 const rtc::PacketOptions
& options
) {
297 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
300 case IS_UNINITIALIZED
:
310 // Continue sending the packet.
314 if (data_size
== 0) {
319 if (data_size
> send_bytes_available_
) {
320 TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock",
321 TRACE_EVENT_SCOPE_THREAD
,
323 client_
->GetSocketID());
324 if (!writable_signal_expected_
) {
325 WebRtcLogMessage(base::StringPrintf(
326 "IpcPacketSocket: sending is blocked. %d packets_in_flight.",
327 static_cast<int>(in_flight_packet_sizes_
.size())));
329 writable_signal_expected_
= true;
332 error_
= EWOULDBLOCK
;
336 net::IPEndPoint address_chrome
;
337 if (!jingle_glue::SocketAddressToIPEndPoint(address
, &address_chrome
)) {
343 send_bytes_available_
-= data_size
;
344 in_flight_packet_sizes_
.push_back(data_size
);
345 TraceSendThrottlingState();
347 const char* data_char
= reinterpret_cast<const char*>(data
);
348 std::vector
<char> data_vector(data_char
, data_char
+ data_size
);
349 client_
->SendWithDscp(address_chrome
, data_vector
, options
);
351 // Fake successful send. The caller ignores result anyway.
355 int IpcPacketSocket::Close() {
356 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
364 rtc::AsyncPacketSocket::State
IpcPacketSocket::GetState() const {
365 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
368 case IS_UNINITIALIZED
:
373 return STATE_BINDING
;
376 if (IsTcpClientSocket(type_
)) {
377 return STATE_CONNECTED
;
391 int IpcPacketSocket::GetOption(rtc::Socket::Option option
, int* value
) {
392 P2PSocketOption p2p_socket_option
= P2P_SOCKET_OPT_MAX
;
393 if (!JingleSocketOptionToP2PSocketOption(option
, &p2p_socket_option
)) {
394 // unsupported option.
398 *value
= options_
[p2p_socket_option
];
402 int IpcPacketSocket::SetOption(rtc::Socket::Option option
, int value
) {
403 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
405 P2PSocketOption p2p_socket_option
= P2P_SOCKET_OPT_MAX
;
406 if (!JingleSocketOptionToP2PSocketOption(option
, &p2p_socket_option
)) {
407 // Option is not supported.
411 options_
[p2p_socket_option
] = value
;
413 if (state_
== IS_OPEN
) {
414 // Options will be applied when state becomes IS_OPEN in OnOpen.
415 return DoSetOption(p2p_socket_option
, value
);
420 int IpcPacketSocket::DoSetOption(P2PSocketOption option
, int value
) {
421 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
422 DCHECK_EQ(state_
, IS_OPEN
);
424 client_
->SetOption(option
, value
);
428 int IpcPacketSocket::GetError() const {
429 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
433 void IpcPacketSocket::SetError(int error
) {
434 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
438 void IpcPacketSocket::OnOpen(const net::IPEndPoint
& local_address
,
439 const net::IPEndPoint
& remote_address
) {
440 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
442 if (!jingle_glue::IPEndPointToSocketAddress(local_address
, &local_address_
)) {
443 // Always expect correct IPv4 address to be allocated.
450 TraceSendThrottlingState();
452 // Set all pending options if any.
453 for (int i
= 0; i
< P2P_SOCKET_OPT_MAX
; ++i
) {
454 if (options_
[i
] != kDefaultNonSetOptionValue
)
455 DoSetOption(static_cast<P2PSocketOption
> (i
), options_
[i
]);
458 SignalAddressReady(this, local_address_
);
459 if (IsTcpClientSocket(type_
)) {
461 // If remote address is unresolved, set resolved remote IP address received
462 // in the callback. This address will be used while sending the packets
464 if (remote_address_
.IsUnresolvedIP()) {
465 rtc::SocketAddress jingle_socket_address
;
466 if (!jingle_glue::IPEndPointToSocketAddress(
467 remote_address
, &jingle_socket_address
)) {
470 // Set only the IP address.
471 remote_address_
.SetResolvedIP(jingle_socket_address
.ipaddr());
476 void IpcPacketSocket::OnIncomingTcpConnection(
477 const net::IPEndPoint
& address
,
478 P2PSocketClient
* client
) {
479 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
481 scoped_ptr
<IpcPacketSocket
> socket(new IpcPacketSocket());
483 rtc::SocketAddress remote_address
;
484 if (!jingle_glue::IPEndPointToSocketAddress(address
, &remote_address
)) {
485 // Always expect correct IPv4 address to be allocated.
488 socket
->InitAcceptedTcp(client
, local_address_
, remote_address
);
489 SignalNewConnection(this, socket
.release());
492 void IpcPacketSocket::OnSendComplete() {
493 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
495 CHECK(!in_flight_packet_sizes_
.empty());
496 send_bytes_available_
+= in_flight_packet_sizes_
.front();
498 DCHECK_LE(send_bytes_available_
, kMaximumInFlightBytes
);
500 in_flight_packet_sizes_
.pop_front();
501 TraceSendThrottlingState();
503 if (writable_signal_expected_
&& send_bytes_available_
> 0) {
504 WebRtcLogMessage(base::StringPrintf(
505 "IpcPacketSocket: sending is unblocked. %d packets in flight.",
506 static_cast<int>(in_flight_packet_sizes_
.size())));
508 SignalReadyToSend(this);
509 writable_signal_expected_
= false;
513 void IpcPacketSocket::OnError() {
514 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
515 bool was_closed
= (state_
== IS_ERROR
|| state_
== IS_CLOSED
);
517 error_
= ECONNABORTED
;
519 SignalClose(this, 0);
523 void IpcPacketSocket::OnDataReceived(const net::IPEndPoint
& address
,
524 const std::vector
<char>& data
,
525 const base::TimeTicks
& timestamp
) {
526 DCHECK_EQ(base::MessageLoop::current(), message_loop_
);
528 rtc::SocketAddress address_lj
;
529 if (!jingle_glue::IPEndPointToSocketAddress(address
, &address_lj
)) {
530 // We should always be able to convert address here because we
531 // don't expect IPv6 address on IPv4 connections.
536 rtc::PacketTime
packet_time(timestamp
.ToInternalValue(), 0);
537 SignalReadPacket(this, &data
[0], data
.size(), address_lj
,
541 AsyncAddressResolverImpl::AsyncAddressResolverImpl(
542 P2PSocketDispatcher
* dispatcher
)
543 : resolver_(new P2PAsyncAddressResolver(dispatcher
)) {
546 AsyncAddressResolverImpl::~AsyncAddressResolverImpl() {
549 void AsyncAddressResolverImpl::Start(const rtc::SocketAddress
& addr
) {
550 DCHECK(CalledOnValidThread());
551 // Copy port number from |addr|. |port_| must be copied
552 // when resolved address is returned in GetResolvedAddress.
555 resolver_
->Start(addr
, base::Bind(
556 &AsyncAddressResolverImpl::OnAddressResolved
,
557 base::Unretained(this)));
560 bool AsyncAddressResolverImpl::GetResolvedAddress(
561 int family
, rtc::SocketAddress
* addr
) const {
562 DCHECK(CalledOnValidThread());
564 if (addresses_
.empty())
567 for (size_t i
= 0; i
< addresses_
.size(); ++i
) {
568 if (family
== addresses_
[i
].family()) {
569 addr
->SetResolvedIP(addresses_
[i
]);
570 addr
->SetPort(port_
);
577 int AsyncAddressResolverImpl::GetError() const {
578 DCHECK(CalledOnValidThread());
579 return addresses_
.empty() ? -1 : 0;
582 void AsyncAddressResolverImpl::Destroy(bool wait
) {
583 DCHECK(CalledOnValidThread());
585 // Libjingle doesn't need this object any more and it's not going to delete
590 void AsyncAddressResolverImpl::OnAddressResolved(
591 const net::IPAddressList
& addresses
) {
592 DCHECK(CalledOnValidThread());
593 for (size_t i
= 0; i
< addresses
.size(); ++i
) {
594 rtc::SocketAddress socket_address
;
595 if (!jingle_glue::IPEndPointToSocketAddress(
596 net::IPEndPoint(addresses
[i
], 0), &socket_address
)) {
599 addresses_
.push_back(socket_address
.ipaddr());
606 IpcPacketSocketFactory::IpcPacketSocketFactory(
607 P2PSocketDispatcher
* socket_dispatcher
)
608 : socket_dispatcher_(socket_dispatcher
) {
611 IpcPacketSocketFactory::~IpcPacketSocketFactory() {
614 rtc::AsyncPacketSocket
* IpcPacketSocketFactory::CreateUdpSocket(
615 const rtc::SocketAddress
& local_address
, int min_port
, int max_port
) {
616 rtc::SocketAddress crome_address
;
617 P2PSocketClientImpl
* socket_client
=
618 new P2PSocketClientImpl(socket_dispatcher_
);
619 scoped_ptr
<IpcPacketSocket
> socket(new IpcPacketSocket());
620 // TODO(sergeyu): Respect local_address and port limits here (need
621 // to pass them over IPC channel to the browser).
622 if (!socket
->Init(P2P_SOCKET_UDP
, socket_client
,
623 local_address
, rtc::SocketAddress())) {
626 return socket
.release();
629 rtc::AsyncPacketSocket
* IpcPacketSocketFactory::CreateServerTcpSocket(
630 const rtc::SocketAddress
& local_address
, int min_port
, int max_port
,
632 // TODO(sergeyu): Implement SSL support.
633 if (opts
& rtc::PacketSocketFactory::OPT_SSLTCP
)
636 P2PSocketType type
= (opts
& rtc::PacketSocketFactory::OPT_STUN
) ?
637 P2P_SOCKET_STUN_TCP_SERVER
: P2P_SOCKET_TCP_SERVER
;
638 P2PSocketClientImpl
* socket_client
=
639 new P2PSocketClientImpl(socket_dispatcher_
);
640 scoped_ptr
<IpcPacketSocket
> socket(new IpcPacketSocket());
641 if (!socket
->Init(type
, socket_client
, local_address
,
642 rtc::SocketAddress())) {
645 return socket
.release();
648 rtc::AsyncPacketSocket
* IpcPacketSocketFactory::CreateClientTcpSocket(
649 const rtc::SocketAddress
& local_address
,
650 const rtc::SocketAddress
& remote_address
,
651 const rtc::ProxyInfo
& proxy_info
,
652 const std::string
& user_agent
, int opts
) {
654 if (opts
& rtc::PacketSocketFactory::OPT_SSLTCP
) {
655 type
= (opts
& rtc::PacketSocketFactory::OPT_STUN
) ?
656 P2P_SOCKET_STUN_SSLTCP_CLIENT
: P2P_SOCKET_SSLTCP_CLIENT
;
657 } else if (opts
& rtc::PacketSocketFactory::OPT_TLS
) {
658 type
= (opts
& rtc::PacketSocketFactory::OPT_STUN
) ?
659 P2P_SOCKET_STUN_TLS_CLIENT
: P2P_SOCKET_TLS_CLIENT
;
661 type
= (opts
& rtc::PacketSocketFactory::OPT_STUN
) ?
662 P2P_SOCKET_STUN_TCP_CLIENT
: P2P_SOCKET_TCP_CLIENT
;
664 P2PSocketClientImpl
* socket_client
=
665 new P2PSocketClientImpl(socket_dispatcher_
);
666 scoped_ptr
<IpcPacketSocket
> socket(new IpcPacketSocket());
667 if (!socket
->Init(type
, socket_client
, local_address
, remote_address
))
669 return socket
.release();
672 rtc::AsyncResolverInterface
*
673 IpcPacketSocketFactory::CreateAsyncResolver() {
674 scoped_ptr
<AsyncAddressResolverImpl
> resolver(
675 new AsyncAddressResolverImpl(socket_dispatcher_
));
676 return resolver
.release();
679 } // namespace content