[ServiceWorker] Implement WebServiceWorkerContextClient::openWindow().
[chromium-blink-merge.git] / content / renderer / p2p / socket_client_impl.cc
blob2dc0c7cbdeb59cf84b77222fa76499f20c2b44fe
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"
7 #include "base/bind.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"
16 namespace {
18 uint64_t GetUniqueId(uint32 random_socket_id, uint32 packet_id) {
19 uint64_t uid = random_socket_id;
20 uid <<= 32;
21 uid |= packet_id;
22 return uid;
25 } // namespace
27 namespace content {
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),
35 random_socket_id_(0),
36 next_packet_id_(0) {
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(
45 P2PSocketType type,
46 const net::IPEndPoint& local_address,
47 const P2PHostAndIPEndPoint& remote_address,
48 P2PSocketClientDelegate* delegate) {
49 DCHECK(delegate_message_loop_->BelongsToCurrentThread());
50 DCHECK(delegate);
51 // |delegate_| is only accessesed on |delegate_message_loop_|.
52 delegate_ = delegate;
54 ipc_message_loop_->PostTask(
55 FROM_HERE, base::Bind(&P2PSocketClientImpl::DoInit,
56 this,
57 type,
58 local_address,
59 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_message_loop_->BelongsToCurrentThread()) {
77 ipc_message_loop_->PostTask(
78 FROM_HERE, base::Bind(&P2PSocketClientImpl::SendWithPacketId, this,
79 address, data, options, unique_id));
80 return 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);
89 return unique_id;
92 void P2PSocketClientImpl::SendWithPacketId(const net::IPEndPoint& address,
93 const std::vector<char>& data,
94 const rtc::PacketOptions& options,
95 uint64_t packet_id) {
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,
102 int value) {
103 if (!ipc_message_loop_->BelongsToCurrentThread()) {
104 ipc_message_loop_->PostTask(
105 FROM_HERE, base::Bind(
106 &P2PSocketClientImpl::SetOption, this, option, value));
107 return;
110 DCHECK(state_ == STATE_OPEN || state_ == STATE_ERROR);
111 if (state_ == STATE_OPEN) {
112 dispatcher_->SendP2PMessage(new P2PHostMsg_SetOption(socket_id_,
113 option, value));
117 void P2PSocketClientImpl::Close() {
118 DCHECK(delegate_message_loop_->BelongsToCurrentThread());
120 delegate_ = NULL;
122 ipc_message_loop_->PostTask(
123 FROM_HERE, base::Bind(&P2PSocketClientImpl::DoClose, this));
126 void P2PSocketClientImpl::DoClose() {
127 DCHECK(ipc_message_loop_->BelongsToCurrentThread());
128 if (dispatcher_) {
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 {
140 return socket_id_;
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);
153 state_ = STATE_OPEN;
155 delegate_message_loop_->PostTask(
156 FROM_HERE,
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());
165 if (delegate_)
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());
193 if (delegate_) {
194 delegate_->OnIncomingTcpConnection(address, new_client.get());
195 } else {
196 // Just close the socket if there is no delegate to accept it.
197 new_client->Close();
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,
207 send_metrics));
210 void P2PSocketClientImpl::DeliverOnSendComplete(
211 const P2PSendPacketMetrics& send_metrics) {
212 DCHECK(delegate_message_loop_->BelongsToCurrentThread());
213 if (delegate_)
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());
227 if (delegate_)
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(
237 FROM_HERE,
238 base::Bind(&P2PSocketClientImpl::DeliverOnDataReceived,
239 this,
240 address,
241 data,
242 timestamp));
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());
249 if (delegate_)
250 delegate_->OnDataReceived(address, data, timestamp);
253 void P2PSocketClientImpl::Detach() {
254 DCHECK(ipc_message_loop_->BelongsToCurrentThread());
255 dispatcher_ = NULL;
256 OnError();
259 } // namespace content