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

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: Sync. 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
« no previous file with comments | « remoting/host/chromoting_host.h ('k') | remoting/host/chromoting_host_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 }
146 clients_.clear();
147 147
148 // Stop the heartbeat sender. 148 // Stop the heartbeat sender.
149 if (heartbeat_sender_) { 149 if (heartbeat_sender_) {
150 heartbeat_sender_->Stop(); 150 heartbeat_sender_->Stop();
151 } 151 }
152 152
153 // Stop chromotocol session manager. 153 // Stop chromotocol session manager.
154 if (session_manager_) { 154 if (session_manager_) {
155 session_manager_->Close( 155 session_manager_->Close(
156 NewRunnableMethod(this, &ChromotingHost::OnServerClosed)); 156 NewRunnableMethod(this, &ChromotingHost::OnServerClosed));
157 } 157 }
158 158
159 // Disconnect from the talk network. 159 // Disconnect from the talk network.
160 if (jingle_client_) { 160 if (jingle_client_) {
161 jingle_client_->Close(); 161 jingle_client_->Close();
162 } 162 }
163 163
164 if (recorder_.get()) { 164 if (recorder_.get()) {
165 recorder_->Stop(shutdown_task_.release()); 165 recorder_->Stop(shutdown_task_.release());
166 } else { 166 } else {
167 shutdown_task_->Run(); 167 shutdown_task_->Run();
168 shutdown_task_.reset(); 168 shutdown_task_.reset();
169 } 169 }
170 } 170 }
171 171
172 // This method is called when a client connects. 172 // This method is called when a client connects.
173 void ChromotingHost::OnClientConnected(ConnectionToClient* connection) { 173 void ChromotingHost::OnClientConnected(ConnectionToClient* connection) {
174 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); 174 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 } 175 }
194 176
195 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { 177 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) {
196 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); 178 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current());
197 179
198 // Remove the connection from the session manager and stop the session. 180 // Remove the connection from the session manager and stop the session.
199 // TODO(hclam): Stop only if the last connection disconnected. 181 // TODO(hclam): Stop only if the last connection disconnected.
200 if (recorder_.get()) { 182 if (recorder_.get()) {
201 recorder_->RemoveConnection(connection); 183 recorder_->RemoveConnection(connection);
202 recorder_->Stop(NULL); 184 // The recorder only exists to serve the unique authenticated client.
203 recorder_ = NULL; 185 // If that client has disconnected, then we can kill the recorder.
186 if (connection->client_authenticated()) {
187 recorder_->Stop(NULL);
188 recorder_ = NULL;
189 }
204 } 190 }
205 191
206 // Close the connection to connection just to be safe. 192 // Close the connection to connection just to be safe.
207 connection->Disconnect(); 193 connection->Disconnect();
208 194
209 // Also remove reference to ConnectionToClient from this object. 195 // Also remove reference to ConnectionToClient from this object.
210 connection_ = NULL; 196 std::vector<scoped_refptr<ClientSession> >::iterator it;
197 for (it = clients_.begin(); it != clients_.end(); ++it) {
198 if (it->get()->connection() == connection) {
199 clients_.erase(it);
200 break;
201 }
202 }
211 } 203 }
212 204
213 //////////////////////////////////////////////////////////////////////////// 205 ////////////////////////////////////////////////////////////////////////////
214 // protocol::ConnectionToClient::EventHandler implementations 206 // protocol::ConnectionToClient::EventHandler implementations
215 void ChromotingHost::OnConnectionOpened(ConnectionToClient* connection) { 207 void ChromotingHost::OnConnectionOpened(ConnectionToClient* connection) {
216 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); 208 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current());
217 209
218 // Completes the connection to the client. 210 // Completes the connection to the client.
219 VLOG(1) << "Connection to client established."; 211 VLOG(1) << "Connection to client established.";
220 context_->main_message_loop()->PostTask( 212 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 272 // TODO(sergeyu): We should try reconnecting here instead of terminating
281 // the host. 273 // the host.
282 Shutdown(); 274 Shutdown();
283 } 275 }
284 } 276 }
285 277
286 void ChromotingHost::OnNewClientSession( 278 void ChromotingHost::OnNewClientSession(
287 protocol::Session* session, 279 protocol::Session* session,
288 protocol::SessionManager::IncomingSessionResponse* response) { 280 protocol::SessionManager::IncomingSessionResponse* response) {
289 base::AutoLock auto_lock(lock_); 281 base::AutoLock auto_lock(lock_);
290 // TODO(hclam): Allow multiple clients to connect to the host. 282 if (state_ != kStarted) {
291 if (connection_.get() || state_ != kStarted) {
292 *response = protocol::SessionManager::DECLINE; 283 *response = protocol::SessionManager::DECLINE;
293 return; 284 return;
294 } 285 }
295 286
296 // Check that the client has access to the host. 287 // Check that the client has access to the host.
297 if (!access_verifier_.VerifyPermissions(session->jid(), 288 if (!access_verifier_.VerifyPermissions(session->jid(),
298 session->initiator_token())) { 289 session->initiator_token())) {
299 *response = protocol::SessionManager::DECLINE; 290 *response = protocol::SessionManager::DECLINE;
300 return; 291 return;
301 } 292 }
(...skipping 14 matching lines...) Expand all
316 } 307 }
317 308
318 session->set_config(config); 309 session->set_config(config);
319 session->set_receiver_token( 310 session->set_receiver_token(
320 GenerateHostAuthToken(session->initiator_token())); 311 GenerateHostAuthToken(session->initiator_token()));
321 312
322 *response = protocol::SessionManager::ACCEPT; 313 *response = protocol::SessionManager::ACCEPT;
323 314
324 VLOG(1) << "Client connected: " << session->jid(); 315 VLOG(1) << "Client connected: " << session->jid();
325 316
326 // If we accept the connected then create a connection object. 317 // We accept the connection, so create a connection object.
327 connection_ = new ConnectionToClient(context_->network_message_loop(), 318 ConnectionToClient* connection = new ConnectionToClient(
328 this, 319 context_->network_message_loop(),
329 desktop_environment_.get(), 320 this,
330 desktop_environment_->input_stub()); 321 desktop_environment_->input_stub());
331 connection_->Init(session); 322
323 // Create a client object.
324 ClientSession* client = new ClientSession(this, connection);
325 connection->set_host_stub(client);
326
327 connection->Init(session);
328
329 clients_.push_back(client);
332 } 330 }
333 331
334 void ChromotingHost::set_protocol_config( 332 void ChromotingHost::set_protocol_config(
335 protocol::CandidateSessionConfig* config) { 333 protocol::CandidateSessionConfig* config) {
336 DCHECK(config_.get()); 334 DCHECK(config_.get());
337 DCHECK_EQ(state_, kInitial); 335 DCHECK_EQ(state_, kInitial);
338 protocol_config_.reset(config); 336 protocol_config_.reset(config);
339 } 337 }
340 338
341 protocol::HostStub* ChromotingHost::host_stub() const { 339 void ChromotingHost::AddClient(ClientSession* client) {
342 return desktop_environment_.get(); 340 clients_.push_back(client);
343 } 341 }
344 342
345 void ChromotingHost::OnServerClosed() { 343 void ChromotingHost::OnServerClosed() {
346 // Don't need to do anything here. 344 // Don't need to do anything here.
347 } 345 }
348 346
349 // TODO(sergeyu): Move this to SessionManager? 347 // TODO(sergeyu): Move this to SessionManager?
350 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig* config) { 348 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig* config) {
351 const protocol::ChannelConfig& video_config = config->video_config(); 349 const protocol::ChannelConfig& video_config = config->video_config();
352 350
(...skipping 11 matching lines...) Expand all
364 362
365 return NULL; 363 return NULL;
366 } 364 }
367 365
368 std::string ChromotingHost::GenerateHostAuthToken( 366 std::string ChromotingHost::GenerateHostAuthToken(
369 const std::string& encoded_client_token) { 367 const std::string& encoded_client_token) {
370 // TODO(ajwong): Return the signature of this instead. 368 // TODO(ajwong): Return the signature of this instead.
371 return encoded_client_token; 369 return encoded_client_token;
372 } 370 }
373 371
374 void ChromotingHost::LocalLoginSucceeded() { 372 void ChromotingHost::LocalLoginSucceeded(
373 scoped_refptr<ConnectionToClient> connection) {
375 if (MessageLoop::current() != context_->main_message_loop()) { 374 if (MessageLoop::current() != context_->main_message_loop()) {
376 context_->main_message_loop()->PostTask( 375 context_->main_message_loop()->PostTask(
377 FROM_HERE, 376 FROM_HERE,
378 NewRunnableMethod(this, &ChromotingHost::LocalLoginSucceeded)); 377 NewRunnableMethod(this,
378 &ChromotingHost::LocalLoginSucceeded,
379 connection));
379 return; 380 return;
380 } 381 }
381 382
382 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); 383 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus();
383 status->set_success(true); 384 status->set_success(true);
384 connection_->client_stub()->BeginSessionResponse( 385 connection->client_stub()->BeginSessionResponse(
385 status, new DeleteTask<protocol::LocalLoginStatus>(status)); 386 status, new DeleteTask<protocol::LocalLoginStatus>(status));
386 387
387 connection_->OnClientAuthenticated(); 388 connection->OnClientAuthenticated();
389
390 // Disconnect all other clients.
391 // Iterate over a copy of the list of clients, to avoid mutating the list
392 // while iterating over it.
393 std::vector<scoped_refptr<ClientSession> > clients_copy(clients_);
394 std::vector<scoped_refptr<ClientSession> >::const_iterator client;
395 for (client = clients_copy.begin(); client != clients_copy.end(); client++) {
396 ConnectionToClient* connection_other = client->get()->connection();
397 if (connection_other != connection) {
398 OnClientDisconnected(connection_other);
399 }
400 }
401 // Those disconnections should have killed the screen recorder.
402 CHECK(recorder_.get() == NULL);
403
404 // Create a new RecordSession if there was none.
405 if (!recorder_.get()) {
406 // Then we create a ScreenRecorder passing the message loops that
407 // it should run on.
408 Encoder* encoder = CreateEncoder(connection->session()->config());
409
410 recorder_ = new ScreenRecorder(context_->main_message_loop(),
411 context_->encode_message_loop(),
412 context_->network_message_loop(),
413 desktop_environment_->capturer(),
414 encoder);
415 }
416
417 // Immediately add the connection and start the session.
418 recorder_->AddConnection(connection);
388 recorder_->Start(); 419 recorder_->Start();
389 } 420 }
390 421
391 void ChromotingHost::LocalLoginFailed() { 422 void ChromotingHost::LocalLoginFailed(
423 scoped_refptr<ConnectionToClient> connection) {
392 if (MessageLoop::current() != context_->main_message_loop()) { 424 if (MessageLoop::current() != context_->main_message_loop()) {
393 context_->main_message_loop()->PostTask( 425 context_->main_message_loop()->PostTask(
394 FROM_HERE, 426 FROM_HERE,
395 NewRunnableMethod(this, &ChromotingHost::LocalLoginFailed)); 427 NewRunnableMethod(this, &ChromotingHost::LocalLoginFailed, connection));
396 return; 428 return;
397 } 429 }
398 430
399 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); 431 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus();
400 status->set_success(false); 432 status->set_success(false);
401 connection_->client_stub()->BeginSessionResponse( 433 connection->client_stub()->BeginSessionResponse(
402 status, new DeleteTask<protocol::LocalLoginStatus>(status)); 434 status, new DeleteTask<protocol::LocalLoginStatus>(status));
403 } 435 }
404 436
405 } // namespace remoting 437 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/chromoting_host.h ('k') | remoting/host/chromoting_host_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698