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