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