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 18 namespace remoting { 19 namespace protocol { 20 21 ConnectionToClient::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 30 ConnectionToClient::~ConnectionToClient() { 31 } 32 33 void ConnectionToClient::SetEventHandler(EventHandler* event_handler) { 34 DCHECK(CalledOnValidThread()); 35 handler_ = event_handler; 36 } 37 38 protocol::Session* ConnectionToClient::session() { 39 DCHECK(CalledOnValidThread()); 40 return session_.get(); 41 } 42 43 void 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 53 void ConnectionToClient::UpdateSequenceNumber(int64 sequence_number) { 54 DCHECK(CalledOnValidThread()); 55 handler_->OnSequenceNumberUpdated(this, sequence_number); 56 } 57 58 VideoStub* ConnectionToClient::video_stub() { 59 DCHECK(CalledOnValidThread()); 60 return video_dispatcher_.get(); 61 } 62 63 AudioStub* ConnectionToClient::audio_stub() { 64 DCHECK(CalledOnValidThread()); 65 return audio_writer_.get(); 66 } 67 68 // Return pointer to ClientStub. 69 ClientStub* ConnectionToClient::client_stub() { 70 DCHECK(CalledOnValidThread()); 71 return control_dispatcher_.get(); 72 } 73 74 void ConnectionToClient::set_clipboard_stub( 75 protocol::ClipboardStub* clipboard_stub) { 76 DCHECK(CalledOnValidThread()); 77 clipboard_stub_ = clipboard_stub; 78 } 79 80 ClipboardStub* ConnectionToClient::clipboard_stub() { 81 DCHECK(CalledOnValidThread()); 82 return clipboard_stub_; 83 } 84 85 void ConnectionToClient::set_host_stub(protocol::HostStub* host_stub) { 86 DCHECK(CalledOnValidThread()); 87 host_stub_ = host_stub; 88 } 89 90 HostStub* ConnectionToClient::host_stub() { 91 DCHECK(CalledOnValidThread()); 92 return host_stub_; 93 } 94 95 void ConnectionToClient::set_input_stub(protocol::InputStub* input_stub) { 96 DCHECK(CalledOnValidThread()); 97 input_stub_ = input_stub; 98 } 99 100 InputStub* ConnectionToClient::input_stub() { 101 DCHECK(CalledOnValidThread()); 102 return input_stub_; 103 } 104 105 void 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 167 void ConnectionToClient::OnSessionRouteChange( 168 const std::string& channel_name, 169 const TransportRoute& route) { 170 handler_->OnRouteChange(this, channel_name, route); 171 } 172 173 void 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 185 void 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 201 void ConnectionToClient::Close(ErrorCode error) { 202 CloseChannels(); 203 handler_->OnConnectionClosed(this, error); 204 } 205 206 void 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