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