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
GetUniqueId(uint32 random_socket_id
, uint32 packet_id
) {
19 uint64 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 void P2PSocketClientImpl::SendWithDscp(
73 const net::IPEndPoint
& address
,
74 const std::vector
<char>& data
,
75 const rtc::PacketOptions
& options
) {
76 if (!ipc_message_loop_
->BelongsToCurrentThread()) {
77 ipc_message_loop_
->PostTask(
78 FROM_HERE
, base::Bind(
79 &P2PSocketClientImpl::SendWithDscp
, this, address
, data
, options
));
83 // Can send data only when the socket is open.
84 DCHECK(state_
== STATE_OPEN
|| state_
== STATE_ERROR
);
85 if (state_
== STATE_OPEN
) {
86 uint64 unique_id
= GetUniqueId(random_socket_id_
, ++next_packet_id_
);
87 TRACE_EVENT_ASYNC_BEGIN0("p2p", "Send", unique_id
);
88 dispatcher_
->SendP2PMessage(new P2PHostMsg_Send(socket_id_
, address
, data
,
93 void P2PSocketClientImpl::Send(const net::IPEndPoint
& address
,
94 const std::vector
<char>& data
) {
95 rtc::PacketOptions
options(rtc::DSCP_DEFAULT
);
96 SendWithDscp(address
, data
, options
);
99 void P2PSocketClientImpl::SetOption(P2PSocketOption option
,
101 if (!ipc_message_loop_
->BelongsToCurrentThread()) {
102 ipc_message_loop_
->PostTask(
103 FROM_HERE
, base::Bind(
104 &P2PSocketClientImpl::SetOption
, this, option
, value
));
108 DCHECK(state_
== STATE_OPEN
|| state_
== STATE_ERROR
);
109 if (state_
== STATE_OPEN
) {
110 dispatcher_
->SendP2PMessage(new P2PHostMsg_SetOption(socket_id_
,
115 void P2PSocketClientImpl::Close() {
116 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
120 ipc_message_loop_
->PostTask(
121 FROM_HERE
, base::Bind(&P2PSocketClientImpl::DoClose
, this));
124 void P2PSocketClientImpl::DoClose() {
125 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
127 if (state_
== STATE_OPEN
|| state_
== STATE_OPENING
||
128 state_
== STATE_ERROR
) {
129 dispatcher_
->SendP2PMessage(new P2PHostMsg_DestroySocket(socket_id_
));
131 dispatcher_
->UnregisterClient(socket_id_
);
134 state_
= STATE_CLOSED
;
137 int P2PSocketClientImpl::GetSocketID() const {
141 void P2PSocketClientImpl::SetDelegate(P2PSocketClientDelegate
* delegate
) {
142 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
143 delegate_
= delegate
;
146 void P2PSocketClientImpl::OnSocketCreated(
147 const net::IPEndPoint
& local_address
,
148 const net::IPEndPoint
& remote_address
) {
149 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
150 DCHECK_EQ(state_
, STATE_OPENING
);
153 delegate_message_loop_
->PostTask(
155 base::Bind(&P2PSocketClientImpl::DeliverOnSocketCreated
, this,
156 local_address
, remote_address
));
159 void P2PSocketClientImpl::DeliverOnSocketCreated(
160 const net::IPEndPoint
& local_address
,
161 const net::IPEndPoint
& remote_address
) {
162 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
164 delegate_
->OnOpen(local_address
, remote_address
);
167 void P2PSocketClientImpl::OnIncomingTcpConnection(
168 const net::IPEndPoint
& address
) {
169 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
170 DCHECK_EQ(state_
, STATE_OPEN
);
172 scoped_refptr
<P2PSocketClientImpl
> new_client
=
173 new P2PSocketClientImpl(dispatcher_
);
174 new_client
->socket_id_
= dispatcher_
->RegisterClient(new_client
.get());
175 new_client
->state_
= STATE_OPEN
;
176 new_client
->delegate_message_loop_
= delegate_message_loop_
;
178 dispatcher_
->SendP2PMessage(new P2PHostMsg_AcceptIncomingTcpConnection(
179 socket_id_
, address
, new_client
->socket_id_
));
181 delegate_message_loop_
->PostTask(
182 FROM_HERE
, base::Bind(
183 &P2PSocketClientImpl::DeliverOnIncomingTcpConnection
,
184 this, address
, new_client
));
187 void P2PSocketClientImpl::DeliverOnIncomingTcpConnection(
188 const net::IPEndPoint
& address
,
189 scoped_refptr
<P2PSocketClient
> new_client
) {
190 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
192 delegate_
->OnIncomingTcpConnection(address
, new_client
.get());
194 // Just close the socket if there is no delegate to accept it.
199 void P2PSocketClientImpl::OnSendComplete() {
200 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
202 delegate_message_loop_
->PostTask(
203 FROM_HERE
, base::Bind(&P2PSocketClientImpl::DeliverOnSendComplete
, this));
206 void P2PSocketClientImpl::DeliverOnSendComplete() {
207 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
209 delegate_
->OnSendComplete();
212 void P2PSocketClientImpl::OnError() {
213 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
214 state_
= STATE_ERROR
;
216 delegate_message_loop_
->PostTask(
217 FROM_HERE
, base::Bind(&P2PSocketClientImpl::DeliverOnError
, this));
220 void P2PSocketClientImpl::DeliverOnError() {
221 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
223 delegate_
->OnError();
226 void P2PSocketClientImpl::OnDataReceived(const net::IPEndPoint
& address
,
227 const std::vector
<char>& data
,
228 const base::TimeTicks
& timestamp
) {
229 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
230 DCHECK_EQ(STATE_OPEN
, state_
);
231 delegate_message_loop_
->PostTask(
233 base::Bind(&P2PSocketClientImpl::DeliverOnDataReceived
,
240 void P2PSocketClientImpl::DeliverOnDataReceived(
241 const net::IPEndPoint
& address
, const std::vector
<char>& data
,
242 const base::TimeTicks
& timestamp
) {
243 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
245 delegate_
->OnDataReceived(address
, data
, timestamp
);
248 void P2PSocketClientImpl::Detach() {
249 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
254 } // namespace content