OLD | NEW |
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 "build/build_config.h" | 7 #include "build/build_config.h" |
8 #include "remoting/base/constants.h" | 8 #include "remoting/base/constants.h" |
9 #include "remoting/base/encoder.h" | 9 #include "remoting/base/encoder.h" |
10 #include "remoting/base/encoder_row_based.h" | 10 #include "remoting/base/encoder_row_based.h" |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 // Connect to the talk network with a JingleClient. | 100 // Connect to the talk network with a JingleClient. |
101 signal_strategy_.reset( | 101 signal_strategy_.reset( |
102 new XmppSignalStrategy(context_->jingle_thread(), xmpp_login, | 102 new XmppSignalStrategy(context_->jingle_thread(), xmpp_login, |
103 xmpp_auth_token, | 103 xmpp_auth_token, |
104 kChromotingTokenServiceName)); | 104 kChromotingTokenServiceName)); |
105 jingle_client_ = new JingleClient(context_->jingle_thread(), | 105 jingle_client_ = new JingleClient(context_->jingle_thread(), |
106 signal_strategy_.get(), | 106 signal_strategy_.get(), |
107 NULL, | 107 NULL, |
108 this); | 108 this); |
109 jingle_client_->Init(); | 109 jingle_client_->Init(); |
110 | |
111 heartbeat_sender_ = | |
112 new HeartbeatSender(context_->jingle_thread()->message_loop(), | |
113 jingle_client_.get(), config_); | |
114 if (!heartbeat_sender_->Init()) { | |
115 LOG(ERROR) << "Failed to initialize HeartbeatSender."; | |
116 return; | |
117 } | |
118 } | 110 } |
119 | 111 |
120 // This method is called when we need to destroy the host process. | 112 // This method is called when we need to destroy the host process. |
121 void ChromotingHost::Shutdown() { | 113 void ChromotingHost::Shutdown() { |
122 if (MessageLoop::current() != context_->main_message_loop()) { | 114 if (MessageLoop::current() != context_->main_message_loop()) { |
123 context_->main_message_loop()->PostTask( | 115 context_->main_message_loop()->PostTask( |
124 FROM_HERE, | 116 FROM_HERE, |
125 NewRunnableMethod(this, &ChromotingHost::Shutdown)); | 117 NewRunnableMethod(this, &ChromotingHost::Shutdown)); |
126 return; | 118 return; |
127 } | 119 } |
(...skipping 12 matching lines...) Expand all Loading... |
140 if (recorder_.get()) { | 132 if (recorder_.get()) { |
141 recorder_->RemoveAllConnections(); | 133 recorder_->RemoveAllConnections(); |
142 } | 134 } |
143 | 135 |
144 // Disconnect the clients. | 136 // Disconnect the clients. |
145 for (size_t i = 0; i < clients_.size(); i++) { | 137 for (size_t i = 0; i < clients_.size(); i++) { |
146 clients_[i]->Disconnect(); | 138 clients_[i]->Disconnect(); |
147 } | 139 } |
148 clients_.clear(); | 140 clients_.clear(); |
149 | 141 |
150 // Stop the heartbeat sender. | 142 // Notify observers. |
151 if (heartbeat_sender_) { | 143 for (StatusObserverList::iterator it = status_observers_.begin(); |
152 heartbeat_sender_->Stop(); | 144 it != status_observers_.end(); ++it) { |
| 145 (*it)->OnShutdown(); |
153 } | 146 } |
154 | 147 |
155 // Stop chromotocol session manager. | 148 // Stop chromotocol session manager. |
156 if (session_manager_) { | 149 if (session_manager_) { |
157 session_manager_->Close( | 150 session_manager_->Close( |
158 NewRunnableMethod(this, &ChromotingHost::OnServerClosed)); | 151 NewRunnableMethod(this, &ChromotingHost::OnServerClosed)); |
159 } | 152 } |
160 | 153 |
161 // Disconnect from the talk network. | 154 // Disconnect from the talk network. |
162 if (jingle_client_) { | 155 if (jingle_client_) { |
163 jingle_client_->Close(); | 156 jingle_client_->Close(); |
164 } | 157 } |
165 | 158 |
166 if (recorder_.get()) { | 159 if (recorder_.get()) { |
167 recorder_->Stop(shutdown_task_.release()); | 160 recorder_->Stop(shutdown_task_.release()); |
168 } else { | 161 } else { |
169 shutdown_task_->Run(); | 162 shutdown_task_->Run(); |
170 shutdown_task_.reset(); | 163 shutdown_task_.reset(); |
171 } | 164 } |
172 } | 165 } |
173 | 166 |
| 167 void ChromotingHost::AddStatusObserver( |
| 168 const scoped_refptr<HostStatusObserver>& observer) { |
| 169 DCHECK_EQ(state_, kInitial); |
| 170 status_observers_.push_back(observer); |
| 171 } |
| 172 |
174 //////////////////////////////////////////////////////////////////////////// | 173 //////////////////////////////////////////////////////////////////////////// |
175 // protocol::ConnectionToClient::EventHandler implementations | 174 // protocol::ConnectionToClient::EventHandler implementations |
176 void ChromotingHost::OnConnectionOpened(ConnectionToClient* connection) { | 175 void ChromotingHost::OnConnectionOpened(ConnectionToClient* connection) { |
177 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); | 176 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); |
178 VLOG(1) << "Connection to client established."; | 177 VLOG(1) << "Connection to client established."; |
179 } | 178 } |
180 | 179 |
181 void ChromotingHost::OnConnectionClosed(ConnectionToClient* connection) { | 180 void ChromotingHost::OnConnectionClosed(ConnectionToClient* connection) { |
182 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); | 181 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); |
183 | 182 |
(...skipping 12 matching lines...) Expand all Loading... |
196 FROM_HERE, | 195 FROM_HERE, |
197 NewRunnableMethod(this, &ChromotingHost::OnClientDisconnected, | 196 NewRunnableMethod(this, &ChromotingHost::OnClientDisconnected, |
198 make_scoped_refptr(connection))); | 197 make_scoped_refptr(connection))); |
199 } | 198 } |
200 | 199 |
201 //////////////////////////////////////////////////////////////////////////// | 200 //////////////////////////////////////////////////////////////////////////// |
202 // JingleClient::Callback implementations | 201 // JingleClient::Callback implementations |
203 void ChromotingHost::OnStateChange(JingleClient* jingle_client, | 202 void ChromotingHost::OnStateChange(JingleClient* jingle_client, |
204 JingleClient::State state) { | 203 JingleClient::State state) { |
205 if (state == JingleClient::CONNECTED) { | 204 if (state == JingleClient::CONNECTED) { |
| 205 std::string jid = jingle_client->GetFullJid(); |
| 206 |
206 DCHECK_EQ(jingle_client_.get(), jingle_client); | 207 DCHECK_EQ(jingle_client_.get(), jingle_client); |
207 VLOG(1) << "Host connected as " << jingle_client->GetFullJid(); | 208 VLOG(1) << "Host connected as " << jid; |
208 | 209 |
209 // Create and start session manager. | 210 // Create and start session manager. |
210 protocol::JingleSessionManager* server = | 211 protocol::JingleSessionManager* server = |
211 new protocol::JingleSessionManager(context_->jingle_thread()); | 212 new protocol::JingleSessionManager(context_->jingle_thread()); |
| 213 // TODO(ajwong): Make this a command switch when we're more stable. |
| 214 server->set_allow_local_ips(true); |
212 | 215 |
213 // Assign key and certificate to server. | 216 // Assign key and certificate to server. |
214 HostKeyPair key_pair; | 217 HostKeyPair key_pair; |
215 CHECK(key_pair.Load(config_)) | 218 CHECK(key_pair.Load(config_)) |
216 << "Failed to load server authentication data"; | 219 << "Failed to load server authentication data"; |
217 | 220 |
218 // TODO(ajwong): Make this a command switch when we're more stable. | 221 server->Init(jid, jingle_client->session_manager(), |
219 server->set_allow_local_ips(true); | |
220 server->Init(jingle_client->GetFullJid(), | |
221 jingle_client->session_manager(), | |
222 NewCallback(this, &ChromotingHost::OnNewClientSession), | 222 NewCallback(this, &ChromotingHost::OnNewClientSession), |
223 key_pair.CopyPrivateKey(), | 223 key_pair.CopyPrivateKey(), key_pair.GenerateCertificate()); |
224 key_pair.GenerateCertificate()); | |
225 | 224 |
226 session_manager_ = server; | 225 session_manager_ = server; |
227 // Start heartbeating. | 226 |
228 heartbeat_sender_->Start(); | 227 for (StatusObserverList::iterator it = status_observers_.begin(); |
| 228 it != status_observers_.end(); ++it) { |
| 229 (*it)->OnSignallingConnected(signal_strategy_.get(), jid); |
| 230 } |
229 } else if (state == JingleClient::CLOSED) { | 231 } else if (state == JingleClient::CLOSED) { |
230 VLOG(1) << "Host disconnected from talk network."; | 232 VLOG(1) << "Host disconnected from talk network."; |
231 | 233 |
232 // Stop heartbeating. | 234 for (StatusObserverList::iterator it = status_observers_.begin(); |
233 heartbeat_sender_->Stop(); | 235 it != status_observers_.end(); ++it) { |
234 | 236 (*it)->OnSignallingDisconnected(); |
| 237 } |
235 // TODO(sergeyu): We should try reconnecting here instead of terminating | 238 // TODO(sergeyu): We should try reconnecting here instead of terminating |
236 // the host. | 239 // the host. |
237 Shutdown(); | 240 Shutdown(); |
238 } | 241 } |
239 } | 242 } |
240 | 243 |
241 void ChromotingHost::OnNewClientSession( | 244 void ChromotingHost::OnNewClientSession( |
242 protocol::Session* session, | 245 protocol::Session* session, |
243 protocol::SessionManager::IncomingSessionResponse* response) { | 246 protocol::SessionManager::IncomingSessionResponse* response) { |
244 base::AutoLock auto_lock(lock_); | 247 base::AutoLock auto_lock(lock_); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 } | 306 } |
304 | 307 |
305 void ChromotingHost::OnServerClosed() { | 308 void ChromotingHost::OnServerClosed() { |
306 // Don't need to do anything here. | 309 // Don't need to do anything here. |
307 } | 310 } |
308 | 311 |
309 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { | 312 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { |
310 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); | 313 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); |
311 | 314 |
312 // Find the client session corresponding to the given connection. | 315 // Find the client session corresponding to the given connection. |
313 std::vector<scoped_refptr<ClientSession> >::iterator client; | 316 ClientList::iterator client; |
314 for (client = clients_.begin(); client != clients_.end(); ++client) { | 317 for (client = clients_.begin(); client != clients_.end(); |
| 318 ++client) { |
315 if (client->get()->connection() == connection) | 319 if (client->get()->connection() == connection) |
316 break; | 320 break; |
317 } | 321 } |
318 if (client == clients_.end()) | 322 if (client == clients_.end()) |
319 return; | 323 return; |
320 | 324 |
321 // Remove the connection from the session manager and stop the session. | 325 // Remove the connection from the session manager and stop the session. |
322 // TODO(hclam): Stop only if the last connection disconnected. | 326 // TODO(hclam): Stop only if the last connection disconnected. |
323 if (recorder_.get()) { | 327 if (recorder_.get()) { |
324 recorder_->RemoveConnection(connection); | 328 recorder_->RemoveConnection(connection); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 return NULL; | 363 return NULL; |
360 } | 364 } |
361 | 365 |
362 std::string ChromotingHost::GenerateHostAuthToken( | 366 std::string ChromotingHost::GenerateHostAuthToken( |
363 const std::string& encoded_client_token) { | 367 const std::string& encoded_client_token) { |
364 // TODO(ajwong): Return the signature of this instead. | 368 // TODO(ajwong): Return the signature of this instead. |
365 return encoded_client_token; | 369 return encoded_client_token; |
366 } | 370 } |
367 | 371 |
368 bool ChromotingHost::HasAuthenticatedClients() const { | 372 bool ChromotingHost::HasAuthenticatedClients() const { |
369 std::vector<scoped_refptr<ClientSession> >::const_iterator it; | 373 for (ClientList::const_iterator it = clients_.begin(); it != clients_.end(); |
370 for (it = clients_.begin(); it != clients_.end(); ++it) { | 374 ++it) { |
371 if (it->get()->authenticated()) | 375 if (it->get()->authenticated()) |
372 return true; | 376 return true; |
373 } | 377 } |
374 return false; | 378 return false; |
375 } | 379 } |
376 | 380 |
377 void ChromotingHost::EnableCurtainMode(bool enable) { | 381 void ChromotingHost::EnableCurtainMode(bool enable) { |
378 // TODO(jamiewalch): This will need to be more sophisticated when we think | 382 // TODO(jamiewalch): This will need to be more sophisticated when we think |
379 // about proper crash recovery and daemon mode. | 383 // about proper crash recovery and daemon mode. |
380 if (enable == is_curtained_) | 384 if (enable == is_curtained_) |
(...skipping 14 matching lines...) Expand all Loading... |
395 } | 399 } |
396 | 400 |
397 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); | 401 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); |
398 status->set_success(true); | 402 status->set_success(true); |
399 connection->client_stub()->BeginSessionResponse( | 403 connection->client_stub()->BeginSessionResponse( |
400 status, new DeleteTask<protocol::LocalLoginStatus>(status)); | 404 status, new DeleteTask<protocol::LocalLoginStatus>(status)); |
401 | 405 |
402 // Disconnect all other clients. | 406 // Disconnect all other clients. |
403 // Iterate over a copy of the list of clients, to avoid mutating the list | 407 // Iterate over a copy of the list of clients, to avoid mutating the list |
404 // while iterating over it. | 408 // while iterating over it. |
405 std::vector<scoped_refptr<ClientSession> > clients_copy(clients_); | 409 ClientList clients_copy(clients_); |
406 std::vector<scoped_refptr<ClientSession> >::const_iterator client; | 410 for (ClientList::const_iterator client = clients_copy.begin(); |
407 for (client = clients_copy.begin(); client != clients_copy.end(); client++) { | 411 client != clients_copy.end(); client++) { |
408 ConnectionToClient* connection_other = client->get()->connection(); | 412 ConnectionToClient* connection_other = client->get()->connection(); |
409 if (connection_other != connection) { | 413 if (connection_other != connection) { |
410 OnClientDisconnected(connection_other); | 414 OnClientDisconnected(connection_other); |
411 } | 415 } |
412 } | 416 } |
413 // Those disconnections should have killed the screen recorder. | 417 // Those disconnections should have killed the screen recorder. |
414 CHECK(recorder_.get() == NULL); | 418 CHECK(recorder_.get() == NULL); |
415 | 419 |
416 // Create a new RecordSession if there was none. | 420 // Create a new RecordSession if there was none. |
417 if (!recorder_.get()) { | 421 if (!recorder_.get()) { |
(...skipping 23 matching lines...) Expand all Loading... |
441 return; | 445 return; |
442 } | 446 } |
443 | 447 |
444 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); | 448 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); |
445 status->set_success(false); | 449 status->set_success(false); |
446 connection->client_stub()->BeginSessionResponse( | 450 connection->client_stub()->BeginSessionResponse( |
447 status, new DeleteTask<protocol::LocalLoginStatus>(status)); | 451 status, new DeleteTask<protocol::LocalLoginStatus>(status)); |
448 } | 452 } |
449 | 453 |
450 } // namespace remoting | 454 } // namespace remoting |
OLD | NEW |