Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(217)

Side by Side Diff: remoting/host/chromoting_host.cc

Issue 6711033: A new authenticated connection evicts an old one. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove redundant member of HostMessageDispatcher. Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/chromoting_host.h" 5 #include "remoting/host/chromoting_host.h"
6 6
7 #include "base/stl_util-inl.h" 7 #include "base/stl_util-inl.h"
8 #include "base/task.h" 8 #include "base/task.h"
9 #include "build/build_config.h" 9 #include "build/build_config.h"
10 #include "remoting/base/constants.h" 10 #include "remoting/base/constants.h"
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 50
51 ChromotingHost::ChromotingHost(ChromotingHostContext* context, 51 ChromotingHost::ChromotingHost(ChromotingHostContext* context,
52 MutableHostConfig* config, 52 MutableHostConfig* config,
53 DesktopEnvironment* environment) 53 DesktopEnvironment* environment)
54 : context_(context), 54 : context_(context),
55 config_(config), 55 config_(config),
56 desktop_environment_(environment), 56 desktop_environment_(environment),
57 state_(kInitial), 57 state_(kInitial),
58 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()) { 58 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()) {
59 DCHECK(desktop_environment_.get()); 59 DCHECK(desktop_environment_.get());
60 desktop_environment_->set_event_handler(this);
61 } 60 }
62 61
63 ChromotingHost::~ChromotingHost() { 62 ChromotingHost::~ChromotingHost() {
64 } 63 }
65 64
66 void ChromotingHost::Start(Task* shutdown_task) { 65 void ChromotingHost::Start(Task* shutdown_task) {
67 if (MessageLoop::current() != context_->main_message_loop()) { 66 if (MessageLoop::current() != context_->main_message_loop()) {
68 context_->main_message_loop()->PostTask( 67 context_->main_message_loop()->PostTask(
69 FROM_HERE, 68 FROM_HERE,
70 NewRunnableMethod(this, &ChromotingHost::Start, shutdown_task)); 69 NewRunnableMethod(this, &ChromotingHost::Start, shutdown_task));
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 return; 132 return;
134 } 133 }
135 state_ = kStopped; 134 state_ = kStopped;
136 } 135 }
137 136
138 // Make sure ScreenRecorder doesn't write to the connection. 137 // Make sure ScreenRecorder doesn't write to the connection.
139 if (recorder_.get()) { 138 if (recorder_.get()) {
140 recorder_->RemoveAllConnections(); 139 recorder_->RemoveAllConnections();
141 } 140 }
142 141
143 // Disconnect the client. 142 // Disconnect the clients.
144 if (connection_) { 143 for (size_t i = 0; i < clients_.size(); i++) {
145 connection_->Disconnect(); 144 clients_[i]->Disconnect();
146 } 145 }
awong 2011/03/22 15:11:56 Do we care to call clients_.clear() here to drop a
simonmorris 2011/03/23 10:35:20 Added clients_.clear() .
147 146
148 // Stop the heartbeat sender. 147 // Stop the heartbeat sender.
149 if (heartbeat_sender_) { 148 if (heartbeat_sender_) {
150 heartbeat_sender_->Stop(); 149 heartbeat_sender_->Stop();
151 } 150 }
152 151
153 // Stop chromotocol session manager. 152 // Stop chromotocol session manager.
154 if (session_manager_) { 153 if (session_manager_) {
155 session_manager_->Close( 154 session_manager_->Close(
156 NewRunnableMethod(this, &ChromotingHost::OnServerClosed)); 155 NewRunnableMethod(this, &ChromotingHost::OnServerClosed));
157 } 156 }
158 157
159 // Disconnect from the talk network. 158 // Disconnect from the talk network.
160 if (jingle_client_) { 159 if (jingle_client_) {
161 jingle_client_->Close(); 160 jingle_client_->Close();
162 } 161 }
163 162
164 if (recorder_.get()) { 163 if (recorder_.get()) {
165 recorder_->Stop(shutdown_task_.release()); 164 recorder_->Stop(shutdown_task_.release());
166 } else { 165 } else {
167 shutdown_task_->Run(); 166 shutdown_task_->Run();
168 shutdown_task_.reset(); 167 shutdown_task_.reset();
169 } 168 }
170 } 169 }
171 170
172 // This method is called when a client connects. 171 // This method is called when a client connects.
173 void ChromotingHost::OnClientConnected(ConnectionToClient* connection) { 172 void ChromotingHost::OnClientConnected(ConnectionToClient* connection) {
174 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); 173 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current());
175
176 // Create a new RecordSession if there was none.
177 if (!recorder_.get()) {
178 // Then we create a ScreenRecorder passing the message loops that
179 // it should run on.
180 DCHECK(desktop_environment_->capturer());
181
182 Encoder* encoder = CreateEncoder(connection->session()->config());
183
184 recorder_ = new ScreenRecorder(context_->main_message_loop(),
185 context_->encode_message_loop(),
186 context_->network_message_loop(),
187 desktop_environment_->capturer(),
188 encoder);
189 }
190
191 // Immediately add the connection and start the session.
192 recorder_->AddConnection(connection);
193 } 174 }
194 175
195 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { 176 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) {
196 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); 177 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current());
197 178
198 // Remove the connection from the session manager and stop the session. 179 // Remove the connection from the session manager and stop the session.
199 // TODO(hclam): Stop only if the last connection disconnected.
Sergey Ulanov 2011/03/22 23:19:14 I don't think we can remove this TODO yet. Recorde
simonmorris 2011/03/23 10:35:20 Done.
200 if (recorder_.get()) { 180 if (recorder_.get()) {
201 recorder_->RemoveConnection(connection); 181 recorder_->RemoveConnection(connection);
202 recorder_->Stop(NULL); 182 // If the client is authenticated, then it was the only reason for running
203 recorder_ = NULL; 183 // the recorder.
awong 2011/03/22 15:11:56 Not completely sure what this means: "the only
simonmorris 2011/03/23 10:35:20 Clarified comment. I don't think that scenario ca
184 if (connection->client_authenticated()) {
185 recorder_->Stop(NULL);
186 recorder_ = NULL;
187 }
204 } 188 }
205 189
206 // Close the connection to connection just to be safe. 190 // Close the connection to connection just to be safe.
207 connection->Disconnect(); 191 connection->Disconnect();
208 192
209 // Also remove reference to ConnectionToClient from this object. 193 // Also remove reference to ConnectionToClient from this object.
210 connection_ = NULL; 194 std::vector<scoped_refptr<ClientSession> >::iterator it;
195 for (it = clients_.begin(); it != clients_.end(); ++it) {
196 if (it->get()->connection() == connection) {
197 clients_.erase(it);
198 break;
199 }
200 }
211 } 201 }
212 202
213 //////////////////////////////////////////////////////////////////////////// 203 ////////////////////////////////////////////////////////////////////////////
214 // protocol::ConnectionToClient::EventHandler implementations 204 // protocol::ConnectionToClient::EventHandler implementations
215 void ChromotingHost::OnConnectionOpened(ConnectionToClient* connection) { 205 void ChromotingHost::OnConnectionOpened(ConnectionToClient* connection) {
216 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); 206 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current());
217 207
218 // Completes the connection to the client. 208 // Completes the connection to the client.
219 VLOG(1) << "Connection to client established."; 209 VLOG(1) << "Connection to client established.";
220 context_->main_message_loop()->PostTask( 210 context_->main_message_loop()->PostTask(
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 // TODO(sergeyu): We should try reconnecting here instead of terminating 270 // TODO(sergeyu): We should try reconnecting here instead of terminating
281 // the host. 271 // the host.
282 Shutdown(); 272 Shutdown();
283 } 273 }
284 } 274 }
285 275
286 void ChromotingHost::OnNewClientSession( 276 void ChromotingHost::OnNewClientSession(
287 protocol::Session* session, 277 protocol::Session* session,
288 protocol::SessionManager::IncomingSessionResponse* response) { 278 protocol::SessionManager::IncomingSessionResponse* response) {
289 base::AutoLock auto_lock(lock_); 279 base::AutoLock auto_lock(lock_);
290 // TODO(hclam): Allow multiple clients to connect to the host. 280 if (state_ != kStarted) {
291 if (connection_.get() || state_ != kStarted) {
292 *response = protocol::SessionManager::DECLINE; 281 *response = protocol::SessionManager::DECLINE;
293 return; 282 return;
294 } 283 }
295 284
296 // Check that the client has access to the host. 285 // Check that the client has access to the host.
297 if (!access_verifier_.VerifyPermissions(session->jid(), 286 if (!access_verifier_.VerifyPermissions(session->jid(),
298 session->initiator_token())) { 287 session->initiator_token())) {
299 *response = protocol::SessionManager::DECLINE; 288 *response = protocol::SessionManager::DECLINE;
300 return; 289 return;
301 } 290 }
(...skipping 14 matching lines...) Expand all
316 } 305 }
317 306
318 session->set_config(config); 307 session->set_config(config);
319 session->set_receiver_token( 308 session->set_receiver_token(
320 GenerateHostAuthToken(session->initiator_token())); 309 GenerateHostAuthToken(session->initiator_token()));
321 310
322 *response = protocol::SessionManager::ACCEPT; 311 *response = protocol::SessionManager::ACCEPT;
323 312
324 VLOG(1) << "Client connected: " << session->jid(); 313 VLOG(1) << "Client connected: " << session->jid();
325 314
326 // If we accept the connected then create a connection object. 315 // We accept the connection, so create a connection object.
327 connection_ = new ConnectionToClient(context_->network_message_loop(), 316 ConnectionToClient* connection = new ConnectionToClient(
328 this, 317 context_->network_message_loop(),
329 desktop_environment_.get(), 318 this,
330 desktop_environment_->input_stub()); 319 NULL,
awong 2011/03/22 15:11:56 Is this parameter ever non-NULL now?
simonmorris 2011/03/23 10:35:20 Only in unit tests, and it's better to be more con
331 connection_->Init(session); 320 desktop_environment_->input_stub());
321
322 // Create a client object.
323 ClientSession* client = new ClientSession(this, connection);
324 connection->set_host_stub(client);
325
326 connection->Init(session);
327
328 clients_.push_back(client);
332 } 329 }
333 330
334 void ChromotingHost::set_protocol_config( 331 void ChromotingHost::set_protocol_config(
335 protocol::CandidateSessionConfig* config) { 332 protocol::CandidateSessionConfig* config) {
336 DCHECK(config_.get()); 333 DCHECK(config_.get());
337 DCHECK_EQ(state_, kInitial); 334 DCHECK_EQ(state_, kInitial);
338 protocol_config_.reset(config); 335 protocol_config_.reset(config);
339 } 336 }
340 337
341 protocol::HostStub* ChromotingHost::host_stub() const {
342 return desktop_environment_.get();
343 }
344
345 void ChromotingHost::OnServerClosed() { 338 void ChromotingHost::OnServerClosed() {
346 // Don't need to do anything here. 339 // Don't need to do anything here.
347 } 340 }
348 341
349 // TODO(sergeyu): Move this to SessionManager? 342 // TODO(sergeyu): Move this to SessionManager?
350 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig* config) { 343 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig* config) {
351 const protocol::ChannelConfig& video_config = config->video_config(); 344 const protocol::ChannelConfig& video_config = config->video_config();
352 345
353 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { 346 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
354 return EncoderRowBased::CreateVerbatimEncoder(); 347 return EncoderRowBased::CreateVerbatimEncoder();
355 } else if (video_config.codec == protocol::ChannelConfig::CODEC_ZIP) { 348 } else if (video_config.codec == protocol::ChannelConfig::CODEC_ZIP) {
356 return EncoderRowBased::CreateZlibEncoder(); 349 return EncoderRowBased::CreateZlibEncoder();
357 } 350 }
358 // TODO(sergeyu): Enable VP8 on ARM builds. 351 // TODO(sergeyu): Enable VP8 on ARM builds.
359 #if !defined(ARCH_CPU_ARM_FAMILY) 352 #if !defined(ARCH_CPU_ARM_FAMILY)
360 else if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) { 353 else if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) {
361 return new remoting::EncoderVp8(); 354 return new remoting::EncoderVp8();
362 } 355 }
363 #endif 356 #endif
364 357
365 return NULL; 358 return NULL;
366 } 359 }
367 360
368 std::string ChromotingHost::GenerateHostAuthToken( 361 std::string ChromotingHost::GenerateHostAuthToken(
369 const std::string& encoded_client_token) { 362 const std::string& encoded_client_token) {
370 // TODO(ajwong): Return the signature of this instead. 363 // TODO(ajwong): Return the signature of this instead.
371 return encoded_client_token; 364 return encoded_client_token;
372 } 365 }
373 366
374 void ChromotingHost::LocalLoginSucceeded() { 367 void ChromotingHost::LocalLoginSucceeded(
368 scoped_refptr<ConnectionToClient> connection) {
375 if (MessageLoop::current() != context_->main_message_loop()) { 369 if (MessageLoop::current() != context_->main_message_loop()) {
376 context_->main_message_loop()->PostTask( 370 context_->main_message_loop()->PostTask(
377 FROM_HERE, 371 FROM_HERE,
378 NewRunnableMethod(this, &ChromotingHost::LocalLoginSucceeded)); 372 NewRunnableMethod(this,
373 &ChromotingHost::LocalLoginSucceeded,
374 connection));
379 return; 375 return;
380 } 376 }
381 377
382 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); 378 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus();
383 status->set_success(true); 379 status->set_success(true);
384 connection_->client_stub()->BeginSessionResponse( 380 connection->client_stub()->BeginSessionResponse(
385 status, new DeleteTask<protocol::LocalLoginStatus>(status)); 381 status, new DeleteTask<protocol::LocalLoginStatus>(status));
386 382
387 connection_->OnClientAuthenticated(); 383 connection->OnClientAuthenticated();
384
385 // Disconnect all other clients.
386 std::vector<scoped_refptr<ClientSession> > clients_copy(clients_);
awong 2011/03/22 15:11:56 Add a note for why we need to copy |clients_|.
simonmorris 2011/03/23 10:35:20 Done.
387 std::vector<scoped_refptr<ClientSession> >::const_iterator client;
388 for (client = clients_copy.begin(); client != clients_copy.end(); client++) {
389 ConnectionToClient* connection_other = client->get()->connection();
390 if (connection_other != connection) {
391 OnClientDisconnected(connection_other);
392 }
393 }
394 // Those disconnections should have killed the screen recorder.
395 DCHECK(recorder_.get() == NULL);
awong 2011/03/22 15:11:56 This should be a hard requirement right? I would
simonmorris 2011/03/23 10:35:20 Done.
396
397 // Create a new RecordSession if there was none.
398 if (!recorder_.get()) {
399 // Then we create a ScreenRecorder passing the message loops that
400 // it should run on.
401 DCHECK(desktop_environment_->capturer());
awong 2011/03/22 15:11:56 It's not obvious why we're checking for the existe
simonmorris 2011/03/23 10:35:20 A comment elsewhere suggests that this test is a r
402
403 Encoder* encoder = CreateEncoder(connection->session()->config());
404
405 recorder_ = new ScreenRecorder(context_->main_message_loop(),
406 context_->encode_message_loop(),
407 context_->network_message_loop(),
408 desktop_environment_->capturer(),
409 encoder);
410 }
411
412 // Immediately add the connection and start the session.
413 recorder_->AddConnection(connection);
388 recorder_->Start(); 414 recorder_->Start();
389 } 415 }
390 416
391 void ChromotingHost::LocalLoginFailed() { 417 void ChromotingHost::LocalLoginFailed(
418 scoped_refptr<ConnectionToClient> connection) {
392 if (MessageLoop::current() != context_->main_message_loop()) { 419 if (MessageLoop::current() != context_->main_message_loop()) {
393 context_->main_message_loop()->PostTask( 420 context_->main_message_loop()->PostTask(
394 FROM_HERE, 421 FROM_HERE,
395 NewRunnableMethod(this, &ChromotingHost::LocalLoginFailed)); 422 NewRunnableMethod(this, &ChromotingHost::LocalLoginFailed, connection));
396 return; 423 return;
397 } 424 }
398 425
399 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); 426 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus();
400 status->set_success(false); 427 status->set_success(false);
401 connection_->client_stub()->BeginSessionResponse( 428 connection->client_stub()->BeginSessionResponse(
402 status, new DeleteTask<protocol::LocalLoginStatus>(status)); 429 status, new DeleteTask<protocol::LocalLoginStatus>(status));
403 } 430 }
404 431
405 } // namespace remoting 432 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698