1// Copyright 2012 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 "remoting/protocol/connection_to_client.h" 6 7#include "base/bind.h" 8#include "base/location.h" 9#include "base/message_loop/message_loop_proxy.h" 10#include "net/base/io_buffer.h" 11#include "remoting/protocol/clipboard_stub.h" 12#include "remoting/protocol/host_control_dispatcher.h" 13#include "remoting/protocol/host_event_dispatcher.h" 14#include "remoting/protocol/host_stub.h" 15#include "remoting/protocol/host_video_dispatcher.h" 16#include "remoting/protocol/input_stub.h" 17 18namespace remoting { 19namespace protocol { 20 21ConnectionToClient::ConnectionToClient(protocol::Session* session) 22 : handler_(NULL), 23 clipboard_stub_(NULL), 24 host_stub_(NULL), 25 input_stub_(NULL), 26 session_(session) { 27 session_->SetEventHandler(this); 28} 29 30ConnectionToClient::~ConnectionToClient() { 31} 32 33void ConnectionToClient::SetEventHandler(EventHandler* event_handler) { 34 DCHECK(CalledOnValidThread()); 35 handler_ = event_handler; 36} 37 38protocol::Session* ConnectionToClient::session() { 39 DCHECK(CalledOnValidThread()); 40 return session_.get(); 41} 42 43void ConnectionToClient::Disconnect() { 44 DCHECK(CalledOnValidThread()); 45 46 CloseChannels(); 47 48 // This should trigger OnConnectionClosed() event and this object 49 // may be destroyed as the result. 50 session_->Close(); 51} 52 53void ConnectionToClient::UpdateSequenceNumber(int64 sequence_number) { 54 DCHECK(CalledOnValidThread()); 55 handler_->OnSequenceNumberUpdated(this, sequence_number); 56} 57 58VideoStub* ConnectionToClient::video_stub() { 59 DCHECK(CalledOnValidThread()); 60 return video_dispatcher_.get(); 61} 62 63AudioStub* ConnectionToClient::audio_stub() { 64 DCHECK(CalledOnValidThread()); 65 return audio_writer_.get(); 66} 67 68// Return pointer to ClientStub. 69ClientStub* ConnectionToClient::client_stub() { 70 DCHECK(CalledOnValidThread()); 71 return control_dispatcher_.get(); 72} 73 74void ConnectionToClient::set_clipboard_stub( 75 protocol::ClipboardStub* clipboard_stub) { 76 DCHECK(CalledOnValidThread()); 77 clipboard_stub_ = clipboard_stub; 78} 79 80ClipboardStub* ConnectionToClient::clipboard_stub() { 81 DCHECK(CalledOnValidThread()); 82 return clipboard_stub_; 83} 84 85void ConnectionToClient::set_host_stub(protocol::HostStub* host_stub) { 86 DCHECK(CalledOnValidThread()); 87 host_stub_ = host_stub; 88} 89 90HostStub* ConnectionToClient::host_stub() { 91 DCHECK(CalledOnValidThread()); 92 return host_stub_; 93} 94 95void ConnectionToClient::set_input_stub(protocol::InputStub* input_stub) { 96 DCHECK(CalledOnValidThread()); 97 input_stub_ = input_stub; 98} 99 100InputStub* ConnectionToClient::input_stub() { 101 DCHECK(CalledOnValidThread()); 102 return input_stub_; 103} 104 105void ConnectionToClient::OnSessionStateChange(Session::State state) { 106 DCHECK(CalledOnValidThread()); 107 108 DCHECK(handler_); 109 switch(state) { 110 case Session::INITIALIZING: 111 case Session::CONNECTING: 112 case Session::ACCEPTING: 113 case Session::CONNECTED: 114 // Don't care about these events. 115 break; 116 case Session::AUTHENTICATING: 117 handler_->OnConnectionAuthenticating(this); 118 break; 119 case Session::AUTHENTICATED: 120 // Initialize channels. 121 control_dispatcher_.reset(new HostControlDispatcher()); 122 control_dispatcher_->Init( 123 session_.get(), session_->config().control_config(), 124 base::Bind(&ConnectionToClient::OnChannelInitialized, 125 base::Unretained(this))); 126 control_dispatcher_->set_clipboard_stub(clipboard_stub_); 127 control_dispatcher_->set_host_stub(host_stub_); 128 129 event_dispatcher_.reset(new HostEventDispatcher()); 130 event_dispatcher_->Init( 131 session_.get(), session_->config().event_config(), 132 base::Bind(&ConnectionToClient::OnChannelInitialized, 133 base::Unretained(this))); 134 event_dispatcher_->set_input_stub(input_stub_); 135 event_dispatcher_->set_sequence_number_callback(base::Bind( 136 &ConnectionToClient::UpdateSequenceNumber, base::Unretained(this))); 137 138 video_dispatcher_.reset(new HostVideoDispatcher()); 139 video_dispatcher_->Init( 140 session_.get(), session_->config().video_config(), 141 base::Bind(&ConnectionToClient::OnChannelInitialized, 142 base::Unretained(this))); 143 144 audio_writer_ = AudioWriter::Create(session_->config()); 145 if (audio_writer_.get()) { 146 audio_writer_->Init( 147 session_.get(), session_->config().audio_config(), 148 base::Bind(&ConnectionToClient::OnChannelInitialized, 149 base::Unretained(this))); 150 } 151 152 // Notify the handler after initializing the channels, so that 153 // ClientSession can get a client clipboard stub. 154 handler_->OnConnectionAuthenticated(this); 155 break; 156 157 case Session::CLOSED: 158 Close(OK); 159 break; 160 161 case Session::FAILED: 162 Close(session_->error()); 163 break; 164 } 165} 166 167void ConnectionToClient::OnSessionRouteChange( 168 const std::string& channel_name, 169 const TransportRoute& route) { 170 handler_->OnRouteChange(this, channel_name, route); 171} 172 173void ConnectionToClient::OnChannelInitialized(bool successful) { 174 DCHECK(CalledOnValidThread()); 175 176 if (!successful) { 177 LOG(ERROR) << "Failed to connect a channel"; 178 Close(CHANNEL_CONNECTION_ERROR); 179 return; 180 } 181 182 NotifyIfChannelsReady(); 183} 184 185void ConnectionToClient::NotifyIfChannelsReady() { 186 DCHECK(CalledOnValidThread()); 187 188 if (!control_dispatcher_.get() || !control_dispatcher_->is_connected()) 189 return; 190 if (!event_dispatcher_.get() || !event_dispatcher_->is_connected()) 191 return; 192 if (!video_dispatcher_.get() || !video_dispatcher_->is_connected()) 193 return; 194 if ((!audio_writer_.get() || !audio_writer_->is_connected()) && 195 session_->config().is_audio_enabled()) { 196 return; 197 } 198 handler_->OnConnectionChannelsConnected(this); 199} 200 201void ConnectionToClient::Close(ErrorCode error) { 202 CloseChannels(); 203 handler_->OnConnectionClosed(this, error); 204} 205 206void ConnectionToClient::CloseChannels() { 207 control_dispatcher_.reset(); 208 event_dispatcher_.reset(); 209 video_dispatcher_.reset(); 210 audio_writer_.reset(); 211} 212 213} // namespace protocol 214} // namespace remoting 215