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 talk_base::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 talk_base::PacketOptions
options(talk_base::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(const net::IPEndPoint
& address
) {
147 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
148 DCHECK_EQ(state_
, STATE_OPENING
);
151 delegate_message_loop_
->PostTask(
153 base::Bind(&P2PSocketClientImpl::DeliverOnSocketCreated
, this, address
));
156 void P2PSocketClientImpl::DeliverOnSocketCreated(
157 const net::IPEndPoint
& address
) {
158 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
160 delegate_
->OnOpen(address
);
163 void P2PSocketClientImpl::OnIncomingTcpConnection(
164 const net::IPEndPoint
& address
) {
165 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
166 DCHECK_EQ(state_
, STATE_OPEN
);
168 scoped_refptr
<P2PSocketClientImpl
> new_client
=
169 new P2PSocketClientImpl(dispatcher_
);
170 new_client
->socket_id_
= dispatcher_
->RegisterClient(new_client
.get());
171 new_client
->state_
= STATE_OPEN
;
172 new_client
->delegate_message_loop_
= delegate_message_loop_
;
174 dispatcher_
->SendP2PMessage(new P2PHostMsg_AcceptIncomingTcpConnection(
175 socket_id_
, address
, new_client
->socket_id_
));
177 delegate_message_loop_
->PostTask(
178 FROM_HERE
, base::Bind(
179 &P2PSocketClientImpl::DeliverOnIncomingTcpConnection
,
180 this, address
, new_client
));
183 void P2PSocketClientImpl::DeliverOnIncomingTcpConnection(
184 const net::IPEndPoint
& address
,
185 scoped_refptr
<P2PSocketClient
> new_client
) {
186 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
188 delegate_
->OnIncomingTcpConnection(address
, new_client
.get());
190 // Just close the socket if there is no delegate to accept it.
195 void P2PSocketClientImpl::OnSendComplete() {
196 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
198 delegate_message_loop_
->PostTask(
199 FROM_HERE
, base::Bind(&P2PSocketClientImpl::DeliverOnSendComplete
, this));
202 void P2PSocketClientImpl::DeliverOnSendComplete() {
203 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
205 delegate_
->OnSendComplete();
208 void P2PSocketClientImpl::OnError() {
209 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
210 state_
= STATE_ERROR
;
212 delegate_message_loop_
->PostTask(
213 FROM_HERE
, base::Bind(&P2PSocketClientImpl::DeliverOnError
, this));
216 void P2PSocketClientImpl::DeliverOnError() {
217 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
219 delegate_
->OnError();
222 void P2PSocketClientImpl::OnDataReceived(const net::IPEndPoint
& address
,
223 const std::vector
<char>& data
,
224 const base::TimeTicks
& timestamp
) {
225 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
226 DCHECK_EQ(STATE_OPEN
, state_
);
227 delegate_message_loop_
->PostTask(
229 base::Bind(&P2PSocketClientImpl::DeliverOnDataReceived
,
236 void P2PSocketClientImpl::DeliverOnDataReceived(
237 const net::IPEndPoint
& address
, const std::vector
<char>& data
,
238 const base::TimeTicks
& timestamp
) {
239 DCHECK(delegate_message_loop_
->BelongsToCurrentThread());
241 delegate_
->OnDataReceived(address
, data
, timestamp
);
244 void P2PSocketClientImpl::Detach() {
245 DCHECK(ipc_message_loop_
->BelongsToCurrentThread());
250 } // namespace content