1 // Copyright 2013 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/socket_client_impl.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/time/time.h"
12 #include "content/common/p2p_messages.h"
13 #include "content/renderer/p2p/socket_client_delegate.h"
14 #include "content/renderer/p2p/socket_dispatcher.h"
15 #include "content/renderer/render_thread_impl.h"
16 #include "crypto/random.h"
20 uint64_t GetUniqueId(uint32 random_socket_id
, uint32 packet_id
) {
21 uint64_t uid
= random_socket_id
;
31 P2PSocketClientImpl::P2PSocketClientImpl(P2PSocketDispatcher
* dispatcher
)
32 : dispatcher_(dispatcher
),
33 ipc_task_runner_(dispatcher
->task_runner()),
34 delegate_task_runner_(base::ThreadTaskRunnerHandle::Get()),
37 state_(STATE_UNINITIALIZED
),
40 crypto::RandBytes(&random_socket_id_
, sizeof(random_socket_id_
));
43 P2PSocketClientImpl::~P2PSocketClientImpl() {
44 CHECK(state_
== STATE_CLOSED
|| state_
== STATE_UNINITIALIZED
);
47 void P2PSocketClientImpl::Init(
49 const net::IPEndPoint
& local_address
,
50 const P2PHostAndIPEndPoint
& remote_address
,
51 P2PSocketClientDelegate
* delegate
) {
52 DCHECK(delegate_task_runner_
->BelongsToCurrentThread());
54 // |delegate_| is only accessesed on |delegate_message_loop_|.
57 ipc_task_runner_
->PostTask(
58 FROM_HERE
, base::Bind(&P2PSocketClientImpl::DoInit
, this, type
,
59 local_address
, remote_address
));
62 void P2PSocketClientImpl::DoInit(P2PSocketType type
,
63 const net::IPEndPoint
& local_address
,
64 const P2PHostAndIPEndPoint
& remote_address
) {
65 DCHECK_EQ(state_
, STATE_UNINITIALIZED
);
66 state_
= STATE_OPENING
;
67 socket_id_
= dispatcher_
->RegisterClient(this);
68 dispatcher_
->SendP2PMessage(new P2PHostMsg_CreateSocket(
69 type
, socket_id_
, local_address
, remote_address
));
72 uint64_t P2PSocketClientImpl::Send(const net::IPEndPoint
& address
,
73 const std::vector
<char>& data
,
74 const rtc::PacketOptions
& options
) {
75 uint64_t unique_id
= GetUniqueId(random_socket_id_
, ++next_packet_id_
);
76 if (!ipc_task_runner_
->BelongsToCurrentThread()) {
77 ipc_task_runner_
->PostTask(
78 FROM_HERE
, base::Bind(&P2PSocketClientImpl::SendWithPacketId
, this,
79 address
, data
, options
, unique_id
));
83 // Can send data only when the socket is open.
84 DCHECK(state_
== STATE_OPEN
|| state_
== STATE_ERROR
);
85 if (state_
== STATE_OPEN
) {
86 SendWithPacketId(address
, data
, options
, unique_id
);
92 void P2PSocketClientImpl::SendWithPacketId(const net::IPEndPoint
& address
,
93 const std::vector
<char>& data
,
94 const rtc::PacketOptions
& options
,
96 TRACE_EVENT_ASYNC_BEGIN0("p2p", "Send", packet_id
);
97 dispatcher_
->SendP2PMessage(
98 new P2PHostMsg_Send(socket_id_
, address
, data
, options
, packet_id
));
101 void P2PSocketClientImpl::SetOption(P2PSocketOption option
,
103 if (!ipc_task_runner_
->BelongsToCurrentThread()) {
104 ipc_task_runner_
->PostTask(
106 base::Bind(&P2PSocketClientImpl::SetOption
, this, option
, value
));
110 DCHECK(state_
== STATE_OPEN
|| state_
== STATE_ERROR
);
111 if (state_
== STATE_OPEN
) {
112 dispatcher_
->SendP2PMessage(new P2PHostMsg_SetOption(socket_id_
,
117 void P2PSocketClientImpl::Close() {
118 DCHECK(delegate_task_runner_
->BelongsToCurrentThread());
122 ipc_task_runner_
->PostTask(FROM_HERE
,
123 base::Bind(&P2PSocketClientImpl::DoClose
, this));
126 void P2PSocketClientImpl::DoClose() {
127 DCHECK(ipc_task_runner_
->BelongsToCurrentThread());
129 if (state_
== STATE_OPEN
|| state_
== STATE_OPENING
||
130 state_
== STATE_ERROR
) {
131 dispatcher_
->SendP2PMessage(new P2PHostMsg_DestroySocket(socket_id_
));
133 dispatcher_
->UnregisterClient(socket_id_
);
136 state_
= STATE_CLOSED
;
139 int P2PSocketClientImpl::GetSocketID() const {
143 void P2PSocketClientImpl::SetDelegate(P2PSocketClientDelegate
* delegate
) {
144 DCHECK(delegate_task_runner_
->BelongsToCurrentThread());
145 delegate_
= delegate
;
148 void P2PSocketClientImpl::OnSocketCreated(
149 const net::IPEndPoint
& local_address
,
150 const net::IPEndPoint
& remote_address
) {
151 DCHECK(ipc_task_runner_
->BelongsToCurrentThread());
152 DCHECK_EQ(state_
, STATE_OPENING
);
155 delegate_task_runner_
->PostTask(
156 FROM_HERE
, base::Bind(&P2PSocketClientImpl::DeliverOnSocketCreated
, this,
157 local_address
, remote_address
));
160 void P2PSocketClientImpl::DeliverOnSocketCreated(
161 const net::IPEndPoint
& local_address
,
162 const net::IPEndPoint
& remote_address
) {
163 DCHECK(delegate_task_runner_
->BelongsToCurrentThread());
165 delegate_
->OnOpen(local_address
, remote_address
);
168 void P2PSocketClientImpl::OnIncomingTcpConnection(
169 const net::IPEndPoint
& address
) {
170 DCHECK(ipc_task_runner_
->BelongsToCurrentThread());
171 DCHECK_EQ(state_
, STATE_OPEN
);
173 scoped_refptr
<P2PSocketClientImpl
> new_client
=
174 new P2PSocketClientImpl(dispatcher_
);
175 new_client
->socket_id_
= dispatcher_
->RegisterClient(new_client
.get());
176 new_client
->state_
= STATE_OPEN
;
177 new_client
->delegate_task_runner_
= delegate_task_runner_
;
179 dispatcher_
->SendP2PMessage(new P2PHostMsg_AcceptIncomingTcpConnection(
180 socket_id_
, address
, new_client
->socket_id_
));
182 delegate_task_runner_
->PostTask(
184 base::Bind(&P2PSocketClientImpl::DeliverOnIncomingTcpConnection
, this,
185 address
, new_client
));
188 void P2PSocketClientImpl::DeliverOnIncomingTcpConnection(
189 const net::IPEndPoint
& address
,
190 scoped_refptr
<P2PSocketClient
> new_client
) {
191 DCHECK(delegate_task_runner_
->BelongsToCurrentThread());
193 delegate_
->OnIncomingTcpConnection(address
, new_client
.get());
195 // Just close the socket if there is no delegate to accept it.
200 void P2PSocketClientImpl::OnSendComplete(
201 const P2PSendPacketMetrics
& send_metrics
) {
202 DCHECK(ipc_task_runner_
->BelongsToCurrentThread());
204 delegate_task_runner_
->PostTask(
205 FROM_HERE
, base::Bind(&P2PSocketClientImpl::DeliverOnSendComplete
, this,
209 void P2PSocketClientImpl::DeliverOnSendComplete(
210 const P2PSendPacketMetrics
& send_metrics
) {
211 DCHECK(delegate_task_runner_
->BelongsToCurrentThread());
213 delegate_
->OnSendComplete(send_metrics
);
216 void P2PSocketClientImpl::OnError() {
217 DCHECK(ipc_task_runner_
->BelongsToCurrentThread());
218 state_
= STATE_ERROR
;
220 delegate_task_runner_
->PostTask(
221 FROM_HERE
, base::Bind(&P2PSocketClientImpl::DeliverOnError
, this));
224 void P2PSocketClientImpl::DeliverOnError() {
225 DCHECK(delegate_task_runner_
->BelongsToCurrentThread());
227 delegate_
->OnError();
230 void P2PSocketClientImpl::OnDataReceived(const net::IPEndPoint
& address
,
231 const std::vector
<char>& data
,
232 const base::TimeTicks
& timestamp
) {
233 DCHECK(ipc_task_runner_
->BelongsToCurrentThread());
234 DCHECK_EQ(STATE_OPEN
, state_
);
235 delegate_task_runner_
->PostTask(
236 FROM_HERE
, base::Bind(&P2PSocketClientImpl::DeliverOnDataReceived
, this,
237 address
, data
, timestamp
));
240 void P2PSocketClientImpl::DeliverOnDataReceived(
241 const net::IPEndPoint
& address
, const std::vector
<char>& data
,
242 const base::TimeTicks
& timestamp
) {
243 DCHECK(delegate_task_runner_
->BelongsToCurrentThread());
245 delegate_
->OnDataReceived(address
, data
, timestamp
);
248 void P2PSocketClientImpl::Detach() {
249 DCHECK(ipc_task_runner_
->BelongsToCurrentThread());
254 } // namespace content