1 // Copyright (c) 2011 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. 4 5 #include "content/renderer/p2p/socket_client.h" 6 7 #include "base/bind.h" 8 #include "base/message_loop/message_loop_proxy.h" 9 #include "content/common/p2p_messages.h" 10 #include "content/renderer/p2p/socket_dispatcher.h" 11 12 namespace content { 13 14 P2PSocketClient::P2PSocketClient(P2PSocketDispatcher* dispatcher) 15 : dispatcher_(dispatcher), 16 ipc_message_loop_(dispatcher->message_loop()), 17 delegate_message_loop_(base::MessageLoopProxy::current()), 18 socket_id_(0), delegate_(NULL), 19 state_(STATE_UNINITIALIZED) { 20 } 21 22 P2PSocketClient::~P2PSocketClient() { 23 CHECK(state_ == STATE_CLOSED || state_ == STATE_UNINITIALIZED); 24 } 25 26 void P2PSocketClient::Init( 27 P2PSocketType type, 28 const net::IPEndPoint& local_address, 29 const net::IPEndPoint& remote_address, 30 P2PSocketClient::Delegate* delegate) { 31 DCHECK(delegate_message_loop_->BelongsToCurrentThread()); 32 // |delegate_| is only accessesed on |delegate_message_loop_|. 33 delegate_ = delegate; 34 35 ipc_message_loop_->PostTask( 36 FROM_HERE, base::Bind(&P2PSocketClient::DoInit, this, type, local_address, 37 remote_address)); 38 } 39 40 void P2PSocketClient::DoInit(P2PSocketType type, 41 const net::IPEndPoint& local_address, 42 const net::IPEndPoint& remote_address) { 43 DCHECK_EQ(state_, STATE_UNINITIALIZED); 44 DCHECK(delegate_); 45 state_ = STATE_OPENING; 46 socket_id_ = dispatcher_->RegisterClient(this); 47 dispatcher_->SendP2PMessage(new P2PHostMsg_CreateSocket( 48 type, socket_id_, local_address, remote_address)); 49 } 50 51 void P2PSocketClient::Send(const net::IPEndPoint& address, 52 const std::vector<char>& data) { 53 if (!ipc_message_loop_->BelongsToCurrentThread()) { 54 ipc_message_loop_->PostTask( 55 FROM_HERE, base::Bind(&P2PSocketClient::Send, this, address, data)); 56 return; 57 } 58 59 // Can send data only when the socket is open. 60 DCHECK(state_ == STATE_OPEN || state_ == STATE_ERROR); 61 if (state_ == STATE_OPEN) { 62 dispatcher_->SendP2PMessage(new P2PHostMsg_Send(socket_id_, address, data)); 63 } 64 } 65 66 void P2PSocketClient::Close() { 67 DCHECK(delegate_message_loop_->BelongsToCurrentThread()); 68 69 delegate_ = NULL; 70 71 ipc_message_loop_->PostTask( 72 FROM_HERE, base::Bind(&P2PSocketClient::DoClose, this)); 73 } 74 75 void P2PSocketClient::DoClose() { 76 DCHECK(ipc_message_loop_->BelongsToCurrentThread()); 77 if (dispatcher_) { 78 if (state_ == STATE_OPEN || state_ == STATE_OPENING || 79 state_ == STATE_ERROR) { 80 dispatcher_->SendP2PMessage(new P2PHostMsg_DestroySocket(socket_id_)); 81 } 82 dispatcher_->UnregisterClient(socket_id_); 83 } 84 85 state_ = STATE_CLOSED; 86 } 87 88 void P2PSocketClient::set_delegate(Delegate* delegate) { 89 DCHECK(delegate_message_loop_->BelongsToCurrentThread()); 90 delegate_ = delegate; 91 } 92 93 void P2PSocketClient::OnSocketCreated(const net::IPEndPoint& address) { 94 DCHECK(ipc_message_loop_->BelongsToCurrentThread()); 95 DCHECK_EQ(state_, STATE_OPENING); 96 state_ = STATE_OPEN; 97 98 delegate_message_loop_->PostTask( 99 FROM_HERE, 100 base::Bind(&P2PSocketClient::DeliverOnSocketCreated, this, address)); 101 } 102 103 void P2PSocketClient::DeliverOnSocketCreated(const net::IPEndPoint& address) { 104 DCHECK(delegate_message_loop_->BelongsToCurrentThread()); 105 if (delegate_) 106 delegate_->OnOpen(address); 107 } 108 109 void P2PSocketClient::OnIncomingTcpConnection(const net::IPEndPoint& address) { 110 DCHECK(ipc_message_loop_->BelongsToCurrentThread()); 111 DCHECK_EQ(state_, STATE_OPEN); 112 113 scoped_refptr<P2PSocketClient> new_client = new P2PSocketClient(dispatcher_); 114 new_client->socket_id_ = dispatcher_->RegisterClient(new_client.get()); 115 new_client->state_ = STATE_OPEN; 116 new_client->delegate_message_loop_ = delegate_message_loop_; 117 118 dispatcher_->SendP2PMessage(new P2PHostMsg_AcceptIncomingTcpConnection( 119 socket_id_, address, new_client->socket_id_)); 120 121 delegate_message_loop_->PostTask( 122 FROM_HERE, base::Bind(&P2PSocketClient::DeliverOnIncomingTcpConnection, 123 this, address, new_client)); 124 } 125 126 void P2PSocketClient::DeliverOnIncomingTcpConnection( 127 const net::IPEndPoint& address, scoped_refptr<P2PSocketClient> new_client) { 128 DCHECK(delegate_message_loop_->BelongsToCurrentThread()); 129 if (delegate_) { 130 delegate_->OnIncomingTcpConnection(address, new_client.get()); 131 } else { 132 // Just close the socket if there is no delegate to accept it. 133 new_client->Close(); 134 } 135 } 136 137 void P2PSocketClient::OnSendComplete() { 138 DCHECK(ipc_message_loop_->BelongsToCurrentThread()); 139 140 delegate_message_loop_->PostTask( 141 FROM_HERE, base::Bind(&P2PSocketClient::DeliverOnSendComplete, this)); 142 } 143 144 void P2PSocketClient::DeliverOnSendComplete() { 145 DCHECK(delegate_message_loop_->BelongsToCurrentThread()); 146 if (delegate_) 147 delegate_->OnSendComplete(); 148 } 149 150 void P2PSocketClient::OnError() { 151 DCHECK(ipc_message_loop_->BelongsToCurrentThread()); 152 state_ = STATE_ERROR; 153 154 delegate_message_loop_->PostTask( 155 FROM_HERE, base::Bind(&P2PSocketClient::DeliverOnError, this)); 156 } 157 158 void P2PSocketClient::DeliverOnError() { 159 DCHECK(delegate_message_loop_->BelongsToCurrentThread()); 160 if (delegate_) 161 delegate_->OnError(); 162 } 163 164 void P2PSocketClient::OnDataReceived(const net::IPEndPoint& address, 165 const std::vector<char>& data) { 166 DCHECK(ipc_message_loop_->BelongsToCurrentThread()); 167 DCHECK_EQ(STATE_OPEN, state_); 168 delegate_message_loop_->PostTask( 169 FROM_HERE, 170 base::Bind(&P2PSocketClient::DeliverOnDataReceived, this, address, data)); 171 } 172 173 void P2PSocketClient::DeliverOnDataReceived(const net::IPEndPoint& address, 174 const std::vector<char>& data) { 175 DCHECK(delegate_message_loop_->BelongsToCurrentThread()); 176 if (delegate_) 177 delegate_->OnDataReceived(address, data); 178 } 179 180 void P2PSocketClient::Detach() { 181 DCHECK(ipc_message_loop_->BelongsToCurrentThread()); 182 dispatcher_ = NULL; 183 OnError(); 184 } 185 186 } // namespace content 187