Home | History | Annotate | Download | only in p2p
      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