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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
11 #include "remoting/base/constants.h" | 11 #include "remoting/base/constants.h" |
12 #include "remoting/base/encoder.h" | 12 #include "remoting/base/encoder.h" |
13 #include "remoting/base/encoder_row_based.h" | 13 #include "remoting/base/encoder_row_based.h" |
14 #include "remoting/base/encoder_vp8.h" | 14 #include "remoting/base/encoder_vp8.h" |
15 #include "remoting/base/logger.h" | |
16 #include "remoting/host/chromoting_host_context.h" | 15 #include "remoting/host/chromoting_host_context.h" |
17 #include "remoting/host/curtain.h" | 16 #include "remoting/host/curtain.h" |
18 #include "remoting/host/desktop_environment.h" | 17 #include "remoting/host/desktop_environment.h" |
19 #include "remoting/host/event_executor.h" | 18 #include "remoting/host/event_executor.h" |
20 #include "remoting/host/host_config.h" | 19 #include "remoting/host/host_config.h" |
21 #include "remoting/host/host_key_pair.h" | 20 #include "remoting/host/host_key_pair.h" |
22 #include "remoting/host/screen_recorder.h" | 21 #include "remoting/host/screen_recorder.h" |
23 #include "remoting/host/user_authenticator.h" | 22 #include "remoting/host/user_authenticator.h" |
24 #include "remoting/jingle_glue/xmpp_signal_strategy.h" | 23 #include "remoting/jingle_glue/xmpp_signal_strategy.h" |
25 #include "remoting/proto/auth.pb.h" | 24 #include "remoting/proto/auth.pb.h" |
26 #include "remoting/protocol/connection_to_client.h" | 25 #include "remoting/protocol/connection_to_client.h" |
27 #include "remoting/protocol/client_stub.h" | 26 #include "remoting/protocol/client_stub.h" |
28 #include "remoting/protocol/host_stub.h" | 27 #include "remoting/protocol/host_stub.h" |
29 #include "remoting/protocol/input_stub.h" | 28 #include "remoting/protocol/input_stub.h" |
30 #include "remoting/protocol/jingle_session_manager.h" | 29 #include "remoting/protocol/jingle_session_manager.h" |
31 #include "remoting/protocol/session_config.h" | 30 #include "remoting/protocol/session_config.h" |
32 | 31 |
33 using remoting::protocol::ConnectionToClient; | 32 using remoting::protocol::ConnectionToClient; |
34 using remoting::protocol::InputStub; | 33 using remoting::protocol::InputStub; |
35 | 34 |
36 namespace remoting { | 35 namespace remoting { |
37 | 36 |
38 // static | 37 // static |
39 ChromotingHost* ChromotingHost::Create(ChromotingHostContext* context, | 38 ChromotingHost* ChromotingHost::Create(ChromotingHostContext* context, |
40 MutableHostConfig* config, | 39 MutableHostConfig* config, |
41 DesktopEnvironment* environment, | 40 DesktopEnvironment* environment, |
42 AccessVerifier* access_verifier, | 41 AccessVerifier* access_verifier, |
43 Logger* logger, | |
44 bool allow_nat_traversal) { | 42 bool allow_nat_traversal) { |
45 return new ChromotingHost(context, config, environment, access_verifier, | 43 return new ChromotingHost(context, config, environment, access_verifier, |
46 logger, allow_nat_traversal); | 44 allow_nat_traversal); |
47 } | 45 } |
48 | 46 |
49 ChromotingHost::ChromotingHost(ChromotingHostContext* context, | 47 ChromotingHost::ChromotingHost(ChromotingHostContext* context, |
50 MutableHostConfig* config, | 48 MutableHostConfig* config, |
51 DesktopEnvironment* environment, | 49 DesktopEnvironment* environment, |
52 AccessVerifier* access_verifier, | 50 AccessVerifier* access_verifier, |
53 Logger* logger, | |
54 bool allow_nat_traversal) | 51 bool allow_nat_traversal) |
55 : context_(context), | 52 : context_(context), |
56 desktop_environment_(environment), | 53 desktop_environment_(environment), |
57 config_(config), | 54 config_(config), |
58 access_verifier_(access_verifier), | 55 access_verifier_(access_verifier), |
59 logger_(logger), | |
60 allow_nat_traversal_(allow_nat_traversal), | 56 allow_nat_traversal_(allow_nat_traversal), |
61 state_(kInitial), | 57 state_(kInitial), |
62 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()), | 58 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()), |
63 is_curtained_(false), | 59 is_curtained_(false), |
64 is_it2me_(false) { | 60 is_it2me_(false) { |
65 DCHECK(desktop_environment_); | 61 DCHECK(desktop_environment_); |
66 desktop_environment_->set_host(this); | 62 desktop_environment_->set_host(this); |
67 logger_->SetThread(MessageLoop::current()); | |
68 } | 63 } |
69 | 64 |
70 ChromotingHost::~ChromotingHost() { | 65 ChromotingHost::~ChromotingHost() { |
71 } | 66 } |
72 | 67 |
73 void ChromotingHost::Start() { | 68 void ChromotingHost::Start() { |
74 if (MessageLoop::current() != context_->network_message_loop()) { | 69 if (MessageLoop::current() != context_->network_message_loop()) { |
75 context_->network_message_loop()->PostTask( | 70 context_->network_message_loop()->PostTask( |
76 FROM_HERE, base::Bind(&ChromotingHost::Start, this)); | 71 FROM_HERE, base::Bind(&ChromotingHost::Start, this)); |
77 return; | 72 return; |
78 } | 73 } |
79 | 74 |
80 logger_->Log(logging::LOG_INFO, "Starting host"); | 75 LOG(INFO) << "Starting host"; |
81 DCHECK(!signal_strategy_.get()); | 76 DCHECK(!signal_strategy_.get()); |
82 DCHECK(access_verifier_.get()); | 77 DCHECK(access_verifier_.get()); |
83 | 78 |
84 // Make sure this object is not started. | 79 // Make sure this object is not started. |
85 { | 80 { |
86 base::AutoLock auto_lock(lock_); | 81 base::AutoLock auto_lock(lock_); |
87 if (state_ != kInitial) | 82 if (state_ != kInitial) |
88 return; | 83 return; |
89 state_ = kStarted; | 84 state_ = kStarted; |
90 } | 85 } |
91 | 86 |
92 // Use an XMPP connection to the Talk network for session signalling. | 87 // Use an XMPP connection to the Talk network for session signalling. |
93 std::string xmpp_login; | 88 std::string xmpp_login; |
94 std::string xmpp_auth_token; | 89 std::string xmpp_auth_token; |
95 std::string xmpp_auth_service; | 90 std::string xmpp_auth_service; |
96 if (!config_->GetString(kXmppLoginConfigPath, &xmpp_login) || | 91 if (!config_->GetString(kXmppLoginConfigPath, &xmpp_login) || |
97 !config_->GetString(kXmppAuthTokenConfigPath, &xmpp_auth_token) || | 92 !config_->GetString(kXmppAuthTokenConfigPath, &xmpp_auth_token) || |
98 !config_->GetString(kXmppAuthServiceConfigPath, &xmpp_auth_service)) { | 93 !config_->GetString(kXmppAuthServiceConfigPath, &xmpp_auth_service)) { |
99 logger_->Log(logging::LOG_ERROR, | 94 LOG(ERROR) << "XMPP credentials are not defined in the config."; |
100 "XMPP credentials are not defined in the config."); | |
101 return; | 95 return; |
102 } | 96 } |
103 | 97 |
104 signal_strategy_.reset( | 98 signal_strategy_.reset( |
105 new XmppSignalStrategy(context_->jingle_thread(), xmpp_login, | 99 new XmppSignalStrategy(context_->jingle_thread(), xmpp_login, |
106 xmpp_auth_token, | 100 xmpp_auth_token, |
107 xmpp_auth_service)); | 101 xmpp_auth_service)); |
108 signal_strategy_->Init(this); | 102 signal_strategy_->Init(this); |
109 } | 103 } |
110 | 104 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 | 146 |
153 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) { | 147 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) { |
154 DCHECK_EQ(state_, kInitial); | 148 DCHECK_EQ(state_, kInitial); |
155 status_observers_.push_back(observer); | 149 status_observers_.push_back(observer); |
156 } | 150 } |
157 | 151 |
158 //////////////////////////////////////////////////////////////////////////// | 152 //////////////////////////////////////////////////////////////////////////// |
159 // protocol::ConnectionToClient::EventHandler implementations | 153 // protocol::ConnectionToClient::EventHandler implementations |
160 void ChromotingHost::OnConnectionOpened(ConnectionToClient* connection) { | 154 void ChromotingHost::OnConnectionOpened(ConnectionToClient* connection) { |
161 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); | 155 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); |
162 logger_->VLog(1, "Connection to client established."); | 156 VLOG(1) << "Connection to client established."; |
163 // TODO(wez): ChromotingHost shouldn't need to know about Me2Mom. | 157 // TODO(wez): ChromotingHost shouldn't need to know about Me2Mom. |
164 if (is_it2me_) { | 158 if (is_it2me_) { |
165 context_->main_message_loop()->PostTask( | 159 context_->main_message_loop()->PostTask( |
166 FROM_HERE, base::Bind(&ChromotingHost::ProcessPreAuthentication, this, | 160 FROM_HERE, base::Bind(&ChromotingHost::ProcessPreAuthentication, this, |
167 make_scoped_refptr(connection))); | 161 make_scoped_refptr(connection))); |
168 } | 162 } |
169 } | 163 } |
170 | 164 |
171 void ChromotingHost::OnConnectionClosed(ConnectionToClient* connection) { | 165 void ChromotingHost::OnConnectionClosed(ConnectionToClient* connection) { |
172 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); | 166 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); |
173 | 167 |
174 logger_->VLog(1, "Connection to client closed."); | 168 VLOG(1) << "Connection to client closed."; |
175 context_->main_message_loop()->PostTask( | 169 context_->main_message_loop()->PostTask( |
176 FROM_HERE, base::Bind(&ChromotingHost::OnClientDisconnected, this, | 170 FROM_HERE, base::Bind(&ChromotingHost::OnClientDisconnected, this, |
177 make_scoped_refptr(connection))); | 171 make_scoped_refptr(connection))); |
178 } | 172 } |
179 | 173 |
180 void ChromotingHost::OnConnectionFailed(ConnectionToClient* connection) { | 174 void ChromotingHost::OnConnectionFailed(ConnectionToClient* connection) { |
181 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); | 175 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); |
182 | 176 |
183 logger_->Log(logging::LOG_ERROR, "Connection failed unexpectedly."); | 177 LOG(ERROR) << "Connection failed unexpectedly."; |
184 context_->main_message_loop()->PostTask( | 178 context_->main_message_loop()->PostTask( |
185 FROM_HERE, base::Bind(&ChromotingHost::OnClientDisconnected, this, | 179 FROM_HERE, base::Bind(&ChromotingHost::OnClientDisconnected, this, |
186 make_scoped_refptr(connection))); | 180 make_scoped_refptr(connection))); |
187 } | 181 } |
188 | 182 |
189 void ChromotingHost::OnSequenceNumberUpdated(ConnectionToClient* connection, | 183 void ChromotingHost::OnSequenceNumberUpdated(ConnectionToClient* connection, |
190 int64 sequence_number) { | 184 int64 sequence_number) { |
191 // Update the sequence number in ScreenRecorder. | 185 // Update the sequence number in ScreenRecorder. |
192 if (MessageLoop::current() != context_->main_message_loop()) { | 186 if (MessageLoop::current() != context_->main_message_loop()) { |
193 context_->main_message_loop()->PostTask( | 187 context_->main_message_loop()->PostTask( |
194 FROM_HERE, base::Bind(&ChromotingHost::OnSequenceNumberUpdated, this, | 188 FROM_HERE, base::Bind(&ChromotingHost::OnSequenceNumberUpdated, this, |
195 make_scoped_refptr(connection), sequence_number)); | 189 make_scoped_refptr(connection), sequence_number)); |
196 return; | 190 return; |
197 } | 191 } |
198 | 192 |
199 if (recorder_.get()) | 193 if (recorder_.get()) |
200 recorder_->UpdateSequenceNumber(sequence_number); | 194 recorder_->UpdateSequenceNumber(sequence_number); |
201 } | 195 } |
202 | 196 |
203 //////////////////////////////////////////////////////////////////////////// | 197 //////////////////////////////////////////////////////////////////////////// |
204 // SignalStrategy::StatusObserver implementations | 198 // SignalStrategy::StatusObserver implementations |
205 void ChromotingHost::OnStateChange( | 199 void ChromotingHost::OnStateChange( |
206 SignalStrategy::StatusObserver::State state) { | 200 SignalStrategy::StatusObserver::State state) { |
207 DCHECK_EQ(MessageLoop::current(), context_->network_message_loop()); | 201 DCHECK_EQ(MessageLoop::current(), context_->network_message_loop()); |
208 | 202 |
209 if (state == SignalStrategy::StatusObserver::CONNECTED) { | 203 if (state == SignalStrategy::StatusObserver::CONNECTED) { |
210 logger_->Log(logging::LOG_INFO, "Host connected as %s", local_jid_.c_str()); | 204 LOG(INFO) << "Host connected as " << local_jid_; |
211 | 205 |
212 // Create and start session manager. | 206 // Create and start session manager. |
213 protocol::JingleSessionManager* server = | 207 protocol::JingleSessionManager* server = |
214 protocol::JingleSessionManager::CreateNotSandboxed(); | 208 protocol::JingleSessionManager::CreateNotSandboxed(); |
215 // TODO(ajwong): Make this a command switch when we're more stable. | 209 // TODO(ajwong): Make this a command switch when we're more stable. |
216 server->set_allow_local_ips(true); | 210 server->set_allow_local_ips(true); |
217 | 211 |
218 // Assign key and certificate to server. | 212 // Assign key and certificate to server. |
219 HostKeyPair key_pair; | 213 HostKeyPair key_pair; |
220 CHECK(key_pair.Load(config_)) | 214 CHECK(key_pair.Load(config_)) |
221 << "Failed to load server authentication data"; | 215 << "Failed to load server authentication data"; |
222 | 216 |
223 server->Init(local_jid_, signal_strategy_.get(), this, | 217 server->Init(local_jid_, signal_strategy_.get(), this, |
224 key_pair.CopyPrivateKey(), key_pair.GenerateCertificate(), | 218 key_pair.CopyPrivateKey(), key_pair.GenerateCertificate(), |
225 allow_nat_traversal_); | 219 allow_nat_traversal_); |
226 | 220 |
227 session_manager_.reset(server); | 221 session_manager_.reset(server); |
228 | 222 |
229 for (StatusObserverList::iterator it = status_observers_.begin(); | 223 for (StatusObserverList::iterator it = status_observers_.begin(); |
230 it != status_observers_.end(); ++it) { | 224 it != status_observers_.end(); ++it) { |
231 (*it)->OnSignallingConnected(signal_strategy_.get(), local_jid_); | 225 (*it)->OnSignallingConnected(signal_strategy_.get(), local_jid_); |
232 } | 226 } |
233 } else if (state == SignalStrategy::StatusObserver::CLOSED) { | 227 } else if (state == SignalStrategy::StatusObserver::CLOSED) { |
234 logger_->Log(logging::LOG_INFO, "Host disconnected from talk network."); | 228 LOG(INFO) << "Host disconnected from talk network."; |
235 for (StatusObserverList::iterator it = status_observers_.begin(); | 229 for (StatusObserverList::iterator it = status_observers_.begin(); |
236 it != status_observers_.end(); ++it) { | 230 it != status_observers_.end(); ++it) { |
237 (*it)->OnSignallingDisconnected(); | 231 (*it)->OnSignallingDisconnected(); |
238 } | 232 } |
239 // TODO(sergeyu): Don't shutdown the host and let the upper level | 233 // TODO(sergeyu): Don't shutdown the host and let the upper level |
240 // decide what needs to be done when signalling channel is | 234 // decide what needs to be done when signalling channel is |
241 // disconnected. | 235 // disconnected. |
242 Shutdown(NULL); | 236 Shutdown(NULL); |
243 } | 237 } |
244 } | 238 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 | 281 |
288 // TODO(simonmorris): The resolution is set in the video stream now, | 282 // TODO(simonmorris): The resolution is set in the video stream now, |
289 // so it doesn't need to be set here. | 283 // so it doesn't need to be set here. |
290 *protocol_config_->mutable_initial_resolution() = | 284 *protocol_config_->mutable_initial_resolution() = |
291 protocol::ScreenResolution(2048, 2048); | 285 protocol::ScreenResolution(2048, 2048); |
292 // TODO(sergeyu): Respect resolution requested by the client if supported. | 286 // TODO(sergeyu): Respect resolution requested by the client if supported. |
293 protocol::SessionConfig* config = protocol_config_->Select( | 287 protocol::SessionConfig* config = protocol_config_->Select( |
294 session->candidate_config(), true /* force_host_resolution */); | 288 session->candidate_config(), true /* force_host_resolution */); |
295 | 289 |
296 if (!config) { | 290 if (!config) { |
297 logger_->Log(logging::LOG_WARNING, | 291 LOG(WARNING) << "Rejecting connection from " << session->jid() |
298 "Rejecting connection from %s because no compatible" | 292 << " because no compatible configuration has been found."; |
299 " configuration has been found.", session->jid().c_str()); | |
300 *response = protocol::SessionManager::INCOMPATIBLE; | 293 *response = protocol::SessionManager::INCOMPATIBLE; |
301 return; | 294 return; |
302 } | 295 } |
303 | 296 |
304 session->set_config(config); | 297 session->set_config(config); |
305 session->set_receiver_token( | 298 session->set_receiver_token( |
306 GenerateHostAuthToken(session->initiator_token())); | 299 GenerateHostAuthToken(session->initiator_token())); |
307 | 300 |
308 // Provide the Access Code as shared secret for SSL channel authentication. | 301 // Provide the Access Code as shared secret for SSL channel authentication. |
309 session->set_shared_secret(access_code_); | 302 session->set_shared_secret(access_code_); |
310 | 303 |
311 *response = protocol::SessionManager::ACCEPT; | 304 *response = protocol::SessionManager::ACCEPT; |
312 | 305 |
313 logger_->Log(logging::LOG_INFO, "Client connected: %s", | 306 LOG(INFO) << "Client connected: " << session->jid(); |
314 session->jid().c_str()); | |
315 | 307 |
316 // We accept the connection, so create a connection object. | 308 // We accept the connection, so create a connection object. |
317 ConnectionToClient* connection = new ConnectionToClient( | 309 ConnectionToClient* connection = new ConnectionToClient( |
318 context_->network_message_loop(), this); | 310 context_->network_message_loop(), this); |
319 | 311 |
320 // Create a client object. | 312 // Create a client object. |
321 ClientSession* client = new ClientSession( | 313 ClientSession* client = new ClientSession( |
322 this, | 314 this, |
323 UserAuthenticator::Create(), | 315 UserAuthenticator::Create(), |
324 connection, | 316 connection, |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 | 603 |
612 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin(); | 604 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin(); |
613 it != shutdown_tasks_.end(); ++it) { | 605 it != shutdown_tasks_.end(); ++it) { |
614 (*it)->Run(); | 606 (*it)->Run(); |
615 delete *it; | 607 delete *it; |
616 } | 608 } |
617 shutdown_tasks_.clear(); | 609 shutdown_tasks_.clear(); |
618 } | 610 } |
619 | 611 |
620 } // namespace remoting | 612 } // namespace remoting |
OLD | NEW |