| 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/protocol/jingle_session_manager.h" | 5 #include "remoting/protocol/jingle_session_manager.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/base64.h" |
| 9 #include "base/bind.h" | 10 #include "base/bind.h" |
| 10 #include "base/message_loop_proxy.h" | 11 #include "base/message_loop_proxy.h" |
| 11 #include "base/string_util.h" | 12 #include "base/string_util.h" |
| 12 #include "base/task.h" | 13 #include "base/task.h" |
| 13 #include "remoting/base/constants.h" | 14 #include "remoting/base/constants.h" |
| 14 #include "remoting/jingle_glue/jingle_info_request.h" | 15 #include "remoting/jingle_glue/jingle_info_request.h" |
| 15 #include "remoting/jingle_glue/jingle_signaling_connector.h" | 16 #include "remoting/jingle_glue/jingle_signaling_connector.h" |
| 16 #include "remoting/jingle_glue/signal_strategy.h" | 17 #include "remoting/jingle_glue/signal_strategy.h" |
| 18 #include "remoting/protocol/authenticator.h" |
| 17 #include "third_party/libjingle/source/talk/base/basicpacketsocketfactory.h" | 19 #include "third_party/libjingle/source/talk/base/basicpacketsocketfactory.h" |
| 18 #include "third_party/libjingle/source/talk/p2p/base/constants.h" | 20 #include "third_party/libjingle/source/talk/p2p/base/constants.h" |
| 19 #include "third_party/libjingle/source/talk/p2p/base/sessionmanager.h" | 21 #include "third_party/libjingle/source/talk/p2p/base/sessionmanager.h" |
| 20 #include "third_party/libjingle/source/talk/p2p/base/transport.h" | 22 #include "third_party/libjingle/source/talk/p2p/base/transport.h" |
| 21 #include "third_party/libjingle/source/talk/p2p/client/httpportallocator.h" | 23 #include "third_party/libjingle/source/talk/p2p/client/httpportallocator.h" |
| 22 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" | 24 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" |
| 23 | 25 |
| 24 using buzz::XmlElement; | 26 using buzz::XmlElement; |
| 25 | 27 |
| 26 namespace remoting { | 28 namespace remoting { |
| 27 namespace protocol { | 29 namespace protocol { |
| 28 | 30 |
| 29 JingleSessionManager::JingleSessionManager( | 31 JingleSessionManager::JingleSessionManager( |
| 30 base::MessageLoopProxy* message_loop) | 32 base::MessageLoopProxy* message_loop) |
| 31 : message_loop_(message_loop), | 33 : message_loop_(message_loop), |
| 32 signal_strategy_(NULL), | 34 signal_strategy_(NULL), |
| 33 allow_nat_traversal_(false), | 35 allow_nat_traversal_(false), |
| 34 allow_local_ips_(false), | 36 allow_local_ips_(false), |
| 35 http_port_allocator_(NULL), | 37 http_port_allocator_(NULL), |
| 36 closed_(false), | 38 closed_(false), |
| 37 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) { | 39 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) { |
| 38 } | 40 } |
| 39 | 41 |
| 40 JingleSessionManager::~JingleSessionManager() { | 42 JingleSessionManager::~JingleSessionManager() { |
| 41 // Session manager can be destroyed only after all sessions are destroyed. | 43 // Session manager can be destroyed only after all sessions are destroyed. |
| 42 DCHECK(sessions_.empty()); | 44 DCHECK(sessions_.empty()); |
| 43 Close(); | 45 Close(); |
| 44 } | 46 } |
| 45 | 47 |
| 48 void JingleSessionManager::set_allow_local_ips(bool allow_local_ips) { |
| 49 allow_local_ips_ = allow_local_ips; |
| 50 } |
| 51 |
| 46 void JingleSessionManager::Init( | 52 void JingleSessionManager::Init( |
| 47 const std::string& local_jid, | 53 const std::string& local_jid, |
| 48 SignalStrategy* signal_strategy, | 54 SignalStrategy* signal_strategy, |
| 49 Listener* listener, | 55 Listener* listener, |
| 50 crypto::RSAPrivateKey* private_key, | |
| 51 const std::string& certificate, | |
| 52 bool allow_nat_traversal) { | 56 bool allow_nat_traversal) { |
| 53 DCHECK(CalledOnValidThread()); | 57 DCHECK(CalledOnValidThread()); |
| 54 | 58 |
| 55 DCHECK(signal_strategy); | 59 DCHECK(signal_strategy); |
| 56 DCHECK(listener); | 60 DCHECK(listener); |
| 57 | 61 |
| 58 local_jid_ = local_jid; | 62 local_jid_ = local_jid; |
| 59 signal_strategy_ = signal_strategy; | 63 signal_strategy_ = signal_strategy; |
| 60 listener_ = listener; | 64 listener_ = listener; |
| 61 private_key_.reset(private_key); | |
| 62 certificate_ = certificate; | |
| 63 allow_nat_traversal_ = allow_nat_traversal; | 65 allow_nat_traversal_ = allow_nat_traversal; |
| 64 | 66 |
| 65 if (!network_manager_.get()) { | 67 if (!network_manager_.get()) { |
| 66 VLOG(1) << "Creating talk_base::NetworkManager."; | 68 VLOG(1) << "Creating talk_base::NetworkManager."; |
| 67 network_manager_.reset(new talk_base::BasicNetworkManager()); | 69 network_manager_.reset(new talk_base::BasicNetworkManager()); |
| 68 } | 70 } |
| 69 if (!socket_factory_.get()) { | 71 if (!socket_factory_.get()) { |
| 70 VLOG(1) << "Creating talk_base::BasicPacketSocketFactory."; | 72 VLOG(1) << "Creating talk_base::BasicPacketSocketFactory."; |
| 71 socket_factory_.reset(new talk_base::BasicPacketSocketFactory( | 73 socket_factory_.reset(new talk_base::BasicPacketSocketFactory( |
| 72 talk_base::Thread::Current())); | 74 talk_base::Thread::Current())); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 void JingleSessionManager::Close() { | 115 void JingleSessionManager::Close() { |
| 114 DCHECK(CalledOnValidThread()); | 116 DCHECK(CalledOnValidThread()); |
| 115 | 117 |
| 116 if (!closed_) { | 118 if (!closed_) { |
| 117 cricket_session_manager_->RemoveClient(kChromotingXmlNamespace); | 119 cricket_session_manager_->RemoveClient(kChromotingXmlNamespace); |
| 118 jingle_signaling_connector_.reset(); | 120 jingle_signaling_connector_.reset(); |
| 119 closed_ = true; | 121 closed_ = true; |
| 120 } | 122 } |
| 121 } | 123 } |
| 122 | 124 |
| 123 void JingleSessionManager::set_allow_local_ips(bool allow_local_ips) { | 125 void JingleSessionManager::set_authenticator_factory( |
| 124 allow_local_ips_ = allow_local_ips; | 126 AuthenticatorFactory* authenticator_factory) { |
| 127 DCHECK(CalledOnValidThread()); |
| 128 authenticator_factory_.reset(authenticator_factory); |
| 125 } | 129 } |
| 126 | 130 |
| 127 Session* JingleSessionManager::Connect( | 131 Session* JingleSessionManager::Connect( |
| 128 const std::string& host_jid, | 132 const std::string& host_jid, |
| 129 const std::string& host_public_key, | 133 Authenticator* authenticator, |
| 130 const std::string& receiver_token, | |
| 131 CandidateSessionConfig* candidate_config, | 134 CandidateSessionConfig* candidate_config, |
| 132 const Session::StateChangeCallback& state_change_callback) { | 135 const Session::StateChangeCallback& state_change_callback) { |
| 133 DCHECK(CalledOnValidThread()); | 136 DCHECK(CalledOnValidThread()); |
| 134 | 137 |
| 135 // Can be called from any thread. | |
| 136 JingleSession* jingle_session = | |
| 137 JingleSession::CreateClientSession(this, host_public_key); | |
| 138 jingle_session->set_candidate_config(candidate_config); | |
| 139 jingle_session->set_receiver_token(receiver_token); | |
| 140 | |
| 141 cricket::Session* cricket_session = cricket_session_manager_->CreateSession( | 138 cricket::Session* cricket_session = cricket_session_manager_->CreateSession( |
| 142 local_jid_, kChromotingXmlNamespace); | 139 local_jid_, kChromotingXmlNamespace); |
| 140 cricket_session->set_remote_name(host_jid); |
| 143 | 141 |
| 144 // Initialize connection object before we send initiate stanza. | 142 JingleSession* jingle_session = |
| 143 new JingleSession(this, cricket_session, authenticator); |
| 144 jingle_session->set_candidate_config(candidate_config); |
| 145 jingle_session->SetStateChangeCallback(state_change_callback); | 145 jingle_session->SetStateChangeCallback(state_change_callback); |
| 146 jingle_session->Init(cricket_session); | |
| 147 sessions_.push_back(jingle_session); | 146 sessions_.push_back(jingle_session); |
| 148 | 147 |
| 149 cricket_session->Initiate(host_jid, CreateClientSessionDescription( | 148 jingle_session->Initiate(); |
| 150 jingle_session->candidate_config()->Clone(), receiver_token)); | |
| 151 | 149 |
| 152 return jingle_session; | 150 return jingle_session; |
| 153 } | 151 } |
| 154 | 152 |
| 155 void JingleSessionManager::OnSessionCreate( | 153 void JingleSessionManager::OnSessionCreate( |
| 156 cricket::Session* cricket_session, bool incoming) { | 154 cricket::Session* cricket_session, bool incoming) { |
| 157 DCHECK(CalledOnValidThread()); | 155 DCHECK(CalledOnValidThread()); |
| 158 | 156 |
| 159 // Allow local connections if neccessary. | 157 // Allow local connections if neccessary. |
| 160 cricket_session->set_allow_local_ips(allow_local_ips_); | 158 cricket_session->set_allow_local_ips(allow_local_ips_); |
| 161 | 159 |
| 162 // If this is an incoming session, create a JingleSession on top of it. | |
| 163 if (incoming) { | 160 if (incoming) { |
| 164 DCHECK(!certificate_.empty()); | 161 JingleSession* jingle_session = |
| 165 DCHECK(private_key_.get()); | 162 new JingleSession(this, cricket_session, NULL); |
| 166 | |
| 167 JingleSession* jingle_session = JingleSession::CreateServerSession( | |
| 168 this, certificate_, private_key_.get()); | |
| 169 sessions_.push_back(jingle_session); | 163 sessions_.push_back(jingle_session); |
| 170 jingle_session->Init(cricket_session); | |
| 171 } | 164 } |
| 172 } | 165 } |
| 173 | 166 |
| 174 void JingleSessionManager::OnSessionDestroy(cricket::Session* cricket_session) { | 167 void JingleSessionManager::OnSessionDestroy(cricket::Session* cricket_session) { |
| 175 DCHECK(CalledOnValidThread()); | 168 DCHECK(CalledOnValidThread()); |
| 176 | 169 |
| 177 std::list<JingleSession*>::iterator it; | 170 std::list<JingleSession*>::iterator it; |
| 178 for (it = sessions_.begin(); it != sessions_.end(); ++it) { | 171 for (it = sessions_.begin(); it != sessions_.end(); ++it) { |
| 179 if ((*it)->HasSession(cricket_session)) { | 172 if ((*it)->HasSession(cricket_session)) { |
| 180 (*it)->ReleaseSession(); | 173 (*it)->ReleaseSession(); |
| 181 return; | 174 return; |
| 182 } | 175 } |
| 183 } | 176 } |
| 184 } | 177 } |
| 185 | 178 |
| 186 bool JingleSessionManager::AcceptConnection( | 179 SessionManager::IncomingSessionResponse JingleSessionManager::AcceptConnection( |
| 187 JingleSession* jingle_session, | 180 JingleSession* jingle_session) { |
| 188 cricket::Session* cricket_session) { | |
| 189 DCHECK(CalledOnValidThread()); | 181 DCHECK(CalledOnValidThread()); |
| 190 | 182 |
| 191 // Reject connection if we are closed. | 183 // Reject connection if we are closed. |
| 192 if (closed_) { | 184 if (closed_) |
| 193 cricket_session->Reject(cricket::STR_TERMINATE_DECLINE); | 185 return SessionManager::DECLINE; |
| 194 return false; | |
| 195 } | |
| 196 | 186 |
| 197 const cricket::SessionDescription* session_description = | 187 IncomingSessionResponse response = SessionManager::DECLINE; |
| 198 cricket_session->remote_description(); | 188 listener_->OnIncomingSession(jingle_session, &response); |
| 199 const cricket::ContentInfo* content = | 189 return response; |
| 200 session_description->FirstContentByType(kChromotingXmlNamespace); | 190 } |
| 201 | 191 |
| 202 CHECK(content); | 192 Authenticator* JingleSessionManager::CreateAuthenticator( |
| 193 const std::string& jid, const buzz::XmlElement* auth_message) { |
| 194 DCHECK(CalledOnValidThread()); |
| 203 | 195 |
| 204 const ContentDescription* content_description = | 196 if (!authenticator_factory_.get()) |
| 205 static_cast<const ContentDescription*>(content->description); | 197 return NULL; |
| 206 jingle_session->set_candidate_config(content_description->config()->Clone()); | 198 return authenticator_factory_->CreateAuthenticator(jid, auth_message); |
| 207 jingle_session->set_initiator_token(content_description->auth_token()); | |
| 208 | |
| 209 // Always reject connection if there is no callback. | |
| 210 IncomingSessionResponse response = protocol::SessionManager::DECLINE; | |
| 211 | |
| 212 // Use the callback to generate a response. | |
| 213 listener_->OnIncomingSession(jingle_session, &response); | |
| 214 | |
| 215 switch (response) { | |
| 216 case SessionManager::ACCEPT: { | |
| 217 // Connection must be configured by the callback. | |
| 218 CandidateSessionConfig* candidate_config = | |
| 219 CandidateSessionConfig::CreateFrom(jingle_session->config()); | |
| 220 cricket_session->Accept( | |
| 221 CreateHostSessionDescription(candidate_config, | |
| 222 jingle_session->local_certificate())); | |
| 223 break; | |
| 224 } | |
| 225 | |
| 226 case SessionManager::INCOMPATIBLE: { | |
| 227 cricket_session->TerminateWithReason( | |
| 228 cricket::STR_TERMINATE_INCOMPATIBLE_PARAMETERS); | |
| 229 return false; | |
| 230 } | |
| 231 | |
| 232 case SessionManager::DECLINE: { | |
| 233 cricket_session->TerminateWithReason(cricket::STR_TERMINATE_DECLINE); | |
| 234 return false; | |
| 235 } | |
| 236 | |
| 237 default: { | |
| 238 NOTREACHED(); | |
| 239 } | |
| 240 } | |
| 241 | |
| 242 return true; | |
| 243 } | 199 } |
| 244 | 200 |
| 245 void JingleSessionManager::SessionDestroyed(JingleSession* jingle_session) { | 201 void JingleSessionManager::SessionDestroyed(JingleSession* jingle_session) { |
| 246 std::list<JingleSession*>::iterator it = | 202 std::list<JingleSession*>::iterator it = |
| 247 std::find(sessions_.begin(), sessions_.end(), jingle_session); | 203 std::find(sessions_.begin(), sessions_.end(), jingle_session); |
| 248 CHECK(it != sessions_.end()); | 204 CHECK(it != sessions_.end()); |
| 249 cricket::Session* cricket_session = jingle_session->ReleaseSession(); | 205 cricket::Session* cricket_session = jingle_session->ReleaseSession(); |
| 250 cricket_session_manager_->DestroySession(cricket_session); | 206 cricket_session_manager_->DestroySession(cricket_session); |
| 251 sessions_.erase(it); | 207 sessions_.erase(it); |
| 252 } | 208 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 const cricket::ContentDescription* content, | 247 const cricket::ContentDescription* content, |
| 292 XmlElement** elem, | 248 XmlElement** elem, |
| 293 cricket::WriteError* error) { | 249 cricket::WriteError* error) { |
| 294 const ContentDescription* desc = | 250 const ContentDescription* desc = |
| 295 static_cast<const ContentDescription*>(content); | 251 static_cast<const ContentDescription*>(content); |
| 296 | 252 |
| 297 *elem = desc->ToXml(); | 253 *elem = desc->ToXml(); |
| 298 return true; | 254 return true; |
| 299 } | 255 } |
| 300 | 256 |
| 301 // static | |
| 302 cricket::SessionDescription* | |
| 303 JingleSessionManager::CreateClientSessionDescription( | |
| 304 const CandidateSessionConfig* config, | |
| 305 const std::string& auth_token) { | |
| 306 cricket::SessionDescription* desc = new cricket::SessionDescription(); | |
| 307 desc->AddContent( | |
| 308 ContentDescription::kChromotingContentName, kChromotingXmlNamespace, | |
| 309 new ContentDescription(config, auth_token, "")); | |
| 310 return desc; | |
| 311 } | |
| 312 | |
| 313 // static | |
| 314 cricket::SessionDescription* JingleSessionManager::CreateHostSessionDescription( | |
| 315 const CandidateSessionConfig* config, | |
| 316 const std::string& certificate) { | |
| 317 cricket::SessionDescription* desc = new cricket::SessionDescription(); | |
| 318 desc->AddContent( | |
| 319 ContentDescription::kChromotingContentName, kChromotingXmlNamespace, | |
| 320 new ContentDescription(config, "", certificate)); | |
| 321 return desc; | |
| 322 } | |
| 323 | |
| 324 } // namespace protocol | 257 } // namespace protocol |
| 325 } // namespace remoting | 258 } // namespace remoting |
| OLD | NEW |