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 |