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/message_loop/message_loop_proxy.h"
9 #include "base/time/time.h"
10 #include "content/common/p2p_messages.h"
11 #include "content/renderer/p2p/socket_client_delegate.h"
12 #include "content/renderer/p2p/socket_dispatcher.h"
13 #include "content/renderer/render_thread_impl.h"
14 #include "crypto/random.h"
18 uint64_t GetUniqueId(uint32 random_socket_id
, uint32 packet_id
) {
19 uint64_t uid
= random_socket_id
;
29 P2PSocketClientImpl::P2PSocketClientImpl(P2PSocketDispatcher
* dispatcher
)
30 : dispatcher_(dispatcher
),
31 ipc_message_loop_(dispatcher
->message_loop()),
32 delegate_message_loop_(base::MessageLoopProxy::current()),
33 socket_id_(0), delegate_(NULL
),
34 state_(STATE_UNINITIALIZED
),
37 crypto::RandBytes(&random_socket_id_
, sizeof(random_socket_id_
));
40 P2PSocketClientImpl::~P2PSocketClientImpl() {
41 CHECK(state_
== STATE_CLOSED
|| state_
== STATE_UNINITIALIZED
);
44 void P2PSocketClientImpl::Init(
46 const net::IPEndPoint
& local_address
,
47 const P2PHostAndIPEndPoint
& remote_address
,
48 P2PSocketClientDelegate
* delegate
) {
49 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
51 // |delegate_| is only accessesed on |delegate_message_loop_|.
54 ipc_message_loop_
->PostTask(
55 FROM_HERE
, base::Bind(&P2PSocketClientImpl::DoInit
,
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_message_loop_
->BelongsToCurrentThread()) {
77 ipc_message_loop_
->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_message_loop_
->BelongsToCurrentThread()) {
104 ipc_message_loop_
->PostTask(
105 FROM_HERE
, base::Bind(
106 &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_message_loop_
->BelongsToCurrentThread());
122 ipc_message_loop_
->PostTask(
123 FROM_HERE
, base::Bind(&P2PSocketClientImpl::DoClose
, this));
126 void P2PSocketClientImpl::DoClose() {
127 DCHECK(ipc_message_loop_
->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_message_loop_
->BelongsToCurrentThread());
145 delegate_
= delegate
;
148 void P2PSocketClientImpl::OnSocketCreated(
149 const net::IPEndPoint
& local_address
,
150 const net::IPEndPoint
& remote_address
) {
151 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
152 DCHECK_EQ(state_
, STATE_OPENING
);
155 delegate_message_loop_
->PostTask(
157 base::Bind(&P2PSocketClientImpl::DeliverOnSocketCreated
, this,
158 local_address
, remote_address
));
161 void P2PSocketClientImpl::DeliverOnSocketCreated(
162 const net::IPEndPoint
& local_address
,
163 const net::IPEndPoint
& remote_address
) {
164 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
166 delegate_
->OnOpen(local_address
, remote_address
);
169 void P2PSocketClientImpl::OnIncomingTcpConnection(
170 const net::IPEndPoint
& address
) {
171 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
172 DCHECK_EQ(state_
, STATE_OPEN
);
174 scoped_refptr
<P2PSocketClientImpl
> new_client
=
175 new P2PSocketClientImpl(dispatcher_
);
176 new_client
->socket_id_
= dispatcher_
->RegisterClient(new_client
.get());
177 new_client
->state_
= STATE_OPEN
;
178 new_client
->delegate_message_loop_
= delegate_message_loop_
;
180 dispatcher_
->SendP2PMessage(new P2PHostMsg_AcceptIncomingTcpConnection(
181 socket_id_
, address
, new_client
->socket_id_
));
183 delegate_message_loop_
->PostTask(
184 FROM_HERE
, base::Bind(
185 &P2PSocketClientImpl::DeliverOnIncomingTcpConnection
,
186 this, address
, new_client
));
189 void P2PSocketClientImpl::DeliverOnIncomingTcpConnection(
190 const net::IPEndPoint
& address
,
191 scoped_refptr
<P2PSocketClient
> new_client
) {
192 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
194 delegate_
->OnIncomingTcpConnection(address
, new_client
.get());
196 // Just close the socket if there is no delegate to accept it.
201 void P2PSocketClientImpl::OnSendComplete(
202 const P2PSendPacketMetrics
& send_metrics
) {
203 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
205 delegate_message_loop_
->PostTask(
206 FROM_HERE
, base::Bind(&P2PSocketClientImpl::DeliverOnSendComplete
, this,
210 void P2PSocketClientImpl::DeliverOnSendComplete(
211 const P2PSendPacketMetrics
& send_metrics
) {
212 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
214 delegate_
->OnSendComplete(send_metrics
);
217 void P2PSocketClientImpl::OnError() {
218 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
219 state_
= STATE_ERROR
;
221 delegate_message_loop_
->PostTask(
222 FROM_HERE
, base::Bind(&P2PSocketClientImpl::DeliverOnError
, this));
225 void P2PSocketClientImpl::DeliverOnError() {
226 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
228 delegate_
->OnError();
231 void P2PSocketClientImpl::OnDataReceived(const net::IPEndPoint
& address
,
232 const std::vector
<char>& data
,
233 const base::TimeTicks
& timestamp
) {
234 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
235 DCHECK_EQ(STATE_OPEN
, state_
);
236 delegate_message_loop_
->PostTask(
238 base::Bind(&P2PSocketClientImpl::DeliverOnDataReceived
,
245 void P2PSocketClientImpl::DeliverOnDataReceived(
246 const net::IPEndPoint
& address
, const std::vector
<char>& data
,
247 const base::TimeTicks
& timestamp
) {
248 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
250 delegate_
->OnDataReceived(address
, data
, timestamp
);
253 void P2PSocketClientImpl::Detach() {
254 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
259 } // namespace content