Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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.h" | 5 #include "remoting/protocol/jingle_session.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <memory> | |
| 10 #include <utility> | 11 #include <utility> |
| 11 | 12 |
| 12 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/callback.h" | |
| 13 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
| 14 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
| 15 #include "base/strings/string_split.h" | 17 #include "base/strings/string_split.h" |
| 16 #include "base/threading/thread_task_runner_handle.h" | 18 #include "base/threading/thread_task_runner_handle.h" |
| 17 #include "base/time/time.h" | 19 #include "base/time/time.h" |
| 18 #include "remoting/base/constants.h" | 20 #include "remoting/base/constants.h" |
| 19 #include "remoting/protocol/authenticator.h" | 21 #include "remoting/protocol/authenticator.h" |
| 20 #include "remoting/protocol/content_description.h" | 22 #include "remoting/protocol/content_description.h" |
| 21 #include "remoting/protocol/jingle_messages.h" | 23 #include "remoting/protocol/jingle_messages.h" |
| 22 #include "remoting/protocol/jingle_session_manager.h" | 24 #include "remoting/protocol/jingle_session_manager.h" |
| 23 #include "remoting/protocol/session_config.h" | 25 #include "remoting/protocol/session_config.h" |
| 26 #include "remoting/protocol/session_plugin.h" | |
| 24 #include "remoting/protocol/transport.h" | 27 #include "remoting/protocol/transport.h" |
| 25 #include "remoting/signaling/iq_sender.h" | 28 #include "remoting/signaling/iq_sender.h" |
| 26 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" | 29 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" |
| 27 #include "third_party/webrtc/libjingle/xmpp/constants.h" | 30 #include "third_party/webrtc/libjingle/xmpp/constants.h" |
| 28 #include "third_party/webrtc/p2p/base/candidate.h" | 31 #include "third_party/webrtc/p2p/base/candidate.h" |
| 29 | 32 |
| 30 using buzz::XmlElement; | 33 using buzz::XmlElement; |
| 31 | 34 |
| 32 namespace remoting { | 35 namespace remoting { |
| 33 namespace protocol { | 36 namespace protocol { |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 peer_address_ = SignalingAddress(peer_jid); | 204 peer_address_ = SignalingAddress(peer_jid); |
| 202 authenticator_ = std::move(authenticator); | 205 authenticator_ = std::move(authenticator); |
| 203 | 206 |
| 204 // Generate random session ID. There are usually not more than 1 | 207 // Generate random session ID. There are usually not more than 1 |
| 205 // concurrent session per host, so a random 64-bit integer provides | 208 // concurrent session per host, so a random 64-bit integer provides |
| 206 // enough entropy. In the worst case connection will fail when two | 209 // enough entropy. In the worst case connection will fail when two |
| 207 // clients generate the same session ID concurrently. | 210 // clients generate the same session ID concurrently. |
| 208 session_id_ = base::Uint64ToString( | 211 session_id_ = base::Uint64ToString( |
| 209 base::RandGenerator(std::numeric_limits<uint64_t>::max())); | 212 base::RandGenerator(std::numeric_limits<uint64_t>::max())); |
| 210 | 213 |
| 211 // Send session-initiate message. | 214 // Delay sending session-initiate message to ensure SessionPlugin can be |
| 212 std::unique_ptr<JingleMessage> message(new JingleMessage( | 215 // attached before the message. |
| 213 peer_address_, JingleMessage::SESSION_INITIATE, session_id_)); | 216 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
| 214 message->initiator = session_manager_->signal_strategy_->GetLocalJid(); | 217 base::Bind(&JingleSession::SendSessionInitiateMessage, |
| 215 message->description.reset(new ContentDescription( | 218 weak_factory_.GetWeakPtr())); |
| 216 session_manager_->protocol_config_->Clone(), | |
| 217 authenticator_->GetNextMessage())); | |
| 218 SendMessage(std::move(message)); | |
| 219 | 219 |
| 220 SetState(CONNECTING); | 220 SetState(CONNECTING); |
| 221 } | 221 } |
| 222 | 222 |
| 223 void JingleSession::InitializeIncomingConnection( | 223 void JingleSession::InitializeIncomingConnection( |
| 224 const JingleMessage& initiate_message, | 224 const JingleMessage& initiate_message, |
| 225 std::unique_ptr<Authenticator> authenticator) { | 225 std::unique_ptr<Authenticator> authenticator) { |
| 226 DCHECK(thread_checker_.CalledOnValidThread()); | 226 DCHECK(thread_checker_.CalledOnValidThread()); |
| 227 DCHECK(initiate_message.description.get()); | 227 DCHECK(initiate_message.description.get()); |
| 228 DCHECK(authenticator.get()); | 228 DCHECK(authenticator.get()); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 242 << " because no compatible configuration has been found."; | 242 << " because no compatible configuration has been found."; |
| 243 Close(INCOMPATIBLE_PROTOCOL); | 243 Close(INCOMPATIBLE_PROTOCOL); |
| 244 return; | 244 return; |
| 245 } | 245 } |
| 246 } | 246 } |
| 247 | 247 |
| 248 void JingleSession::AcceptIncomingConnection( | 248 void JingleSession::AcceptIncomingConnection( |
| 249 const JingleMessage& initiate_message) { | 249 const JingleMessage& initiate_message) { |
| 250 DCHECK(config_); | 250 DCHECK(config_); |
| 251 | 251 |
| 252 ExecutePluginsOnIncomingMessage(initiate_message); | |
| 252 // Process the first authentication message. | 253 // Process the first authentication message. |
| 253 const buzz::XmlElement* first_auth_message = | 254 const buzz::XmlElement* first_auth_message = |
| 254 initiate_message.description->authenticator_message(); | 255 initiate_message.description->authenticator_message(); |
| 255 | 256 |
| 256 if (!first_auth_message) { | 257 if (!first_auth_message) { |
| 257 Close(INCOMPATIBLE_PROTOCOL); | 258 Close(INCOMPATIBLE_PROTOCOL); |
| 258 return; | 259 return; |
| 259 } | 260 } |
| 260 | 261 |
| 261 DCHECK_EQ(authenticator_->state(), Authenticator::WAITING_MESSAGE); | 262 DCHECK_EQ(authenticator_->state(), Authenticator::WAITING_MESSAGE); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 315 } | 316 } |
| 316 | 317 |
| 317 void JingleSession::SendTransportInfo( | 318 void JingleSession::SendTransportInfo( |
| 318 std::unique_ptr<buzz::XmlElement> transport_info) { | 319 std::unique_ptr<buzz::XmlElement> transport_info) { |
| 319 DCHECK(thread_checker_.CalledOnValidThread()); | 320 DCHECK(thread_checker_.CalledOnValidThread()); |
| 320 DCHECK_EQ(state_, AUTHENTICATED); | 321 DCHECK_EQ(state_, AUTHENTICATED); |
| 321 | 322 |
| 322 std::unique_ptr<JingleMessage> message(new JingleMessage( | 323 std::unique_ptr<JingleMessage> message(new JingleMessage( |
| 323 peer_address_, JingleMessage::TRANSPORT_INFO, session_id_)); | 324 peer_address_, JingleMessage::TRANSPORT_INFO, session_id_)); |
| 324 message->transport_info = std::move(transport_info); | 325 message->transport_info = std::move(transport_info); |
| 326 ExecutePluginsOnOutgoingMessage(message.get()); | |
| 325 | 327 |
| 326 std::unique_ptr<buzz::XmlElement> stanza = message->ToXml(); | 328 std::unique_ptr<buzz::XmlElement> stanza = message->ToXml(); |
| 327 stanza->AddAttr(buzz::QN_ID, GetNextOutgoingId()); | 329 stanza->AddAttr(buzz::QN_ID, GetNextOutgoingId()); |
| 328 | 330 |
| 329 auto request = session_manager_->iq_sender()->SendIq( | 331 auto request = session_manager_->iq_sender()->SendIq( |
| 330 std::move(stanza), base::Bind(&JingleSession::OnTransportInfoResponse, | 332 std::move(stanza), base::Bind(&JingleSession::OnTransportInfoResponse, |
| 331 base::Unretained(this))); | 333 base::Unretained(this))); |
| 332 if (request) { | 334 if (request) { |
| 333 request->SetTimeout(base::TimeDelta::FromSeconds(kTransportInfoTimeout)); | 335 request->SetTimeout(base::TimeDelta::FromSeconds(kTransportInfoTimeout)); |
| 334 transport_info_requests_.push_back(std::move(request)); | 336 transport_info_requests_.push_back(std::move(request)); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 379 | 381 |
| 380 if (state_ != FAILED && state_ != CLOSED) { | 382 if (state_ != FAILED && state_ != CLOSED) { |
| 381 if (error != OK) { | 383 if (error != OK) { |
| 382 SetState(FAILED); | 384 SetState(FAILED); |
| 383 } else { | 385 } else { |
| 384 SetState(CLOSED); | 386 SetState(CLOSED); |
| 385 } | 387 } |
| 386 } | 388 } |
| 387 } | 389 } |
| 388 | 390 |
| 391 void JingleSession::AddPlugin(SessionPlugin* plugin) { | |
| 392 DCHECK(plugin); | |
| 393 plugins_.push_back(plugin); | |
| 394 } | |
| 395 | |
| 389 void JingleSession::SendMessage(std::unique_ptr<JingleMessage> message) { | 396 void JingleSession::SendMessage(std::unique_ptr<JingleMessage> message) { |
| 390 DCHECK(thread_checker_.CalledOnValidThread()); | 397 DCHECK(thread_checker_.CalledOnValidThread()); |
| 391 | 398 |
| 399 if (message->action != JingleMessage::SESSION_TERMINATE) { | |
| 400 // When the host accepts session-initiate message from a client JID it | |
| 401 // doesn't recognize it sends session-terminate without session-accept. | |
| 402 // Attaching plugin information to this session-terminate message may lead | |
| 403 // to privacy issues (e.g. leaking Windows version to someone who does not | |
| 404 // own the host). So a simply approach is to ignore plugins when sending | |
| 405 // SESSION_TERMINATE message. | |
| 406 ExecutePluginsOnOutgoingMessage(message.get()); | |
| 407 } | |
| 392 std::unique_ptr<buzz::XmlElement> stanza = message->ToXml(); | 408 std::unique_ptr<buzz::XmlElement> stanza = message->ToXml(); |
| 393 stanza->AddAttr(buzz::QN_ID, GetNextOutgoingId()); | 409 stanza->AddAttr(buzz::QN_ID, GetNextOutgoingId()); |
| 394 | 410 |
| 395 auto request = session_manager_->iq_sender()->SendIq( | 411 auto request = session_manager_->iq_sender()->SendIq( |
| 396 std::move(stanza), base::Bind(&JingleSession::OnMessageResponse, | 412 std::move(stanza), base::Bind(&JingleSession::OnMessageResponse, |
| 397 base::Unretained(this), message->action)); | 413 base::Unretained(this), message->action)); |
| 398 | 414 |
| 399 int timeout = kDefaultMessageTimeout; | 415 int timeout = kDefaultMessageTimeout; |
| 400 if (message->action == JingleMessage::SESSION_INITIATE || | 416 if (message->action == JingleMessage::SESSION_INITIATE || |
| 401 message->action == JingleMessage::SESSION_ACCEPT) { | 417 message->action == JingleMessage::SESSION_ACCEPT) { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 475 if (type != "result") { | 491 if (type != "result") { |
| 476 LOG(ERROR) << "Received error in response to transport-info message: \"" | 492 LOG(ERROR) << "Received error in response to transport-info message: \"" |
| 477 << response->Str() << "\". Terminating the session."; | 493 << response->Str() << "\". Terminating the session."; |
| 478 Close(PEER_IS_OFFLINE); | 494 Close(PEER_IS_OFFLINE); |
| 479 } | 495 } |
| 480 } | 496 } |
| 481 | 497 |
| 482 void JingleSession::OnIncomingMessage(const std::string& id, | 498 void JingleSession::OnIncomingMessage(const std::string& id, |
| 483 std::unique_ptr<JingleMessage> message, | 499 std::unique_ptr<JingleMessage> message, |
| 484 const ReplyCallback& reply_callback) { | 500 const ReplyCallback& reply_callback) { |
| 501 ExecutePluginsOnIncomingMessage(*message); | |
| 485 std::vector<PendingMessage> ordered = message_queue_->OnIncomingMessage( | 502 std::vector<PendingMessage> ordered = message_queue_->OnIncomingMessage( |
| 486 id, PendingMessage{std::move(message), reply_callback}); | 503 id, PendingMessage{std::move(message), reply_callback}); |
| 487 base::WeakPtr<JingleSession> self = weak_factory_.GetWeakPtr(); | 504 base::WeakPtr<JingleSession> self = weak_factory_.GetWeakPtr(); |
| 488 for (auto& message : ordered) { | 505 for (auto& message : ordered) { |
| 489 ProcessIncomingMessage(std::move(message.message), message.reply_callback); | 506 ProcessIncomingMessage(std::move(message.message), message.reply_callback); |
| 490 if (!self) | 507 if (!self) |
| 491 return; | 508 return; |
| 492 } | 509 } |
| 493 } | 510 } |
| 494 | 511 |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 740 if (event_handler_) | 757 if (event_handler_) |
| 741 event_handler_->OnSessionStateChange(new_state); | 758 event_handler_->OnSessionStateChange(new_state); |
| 742 } | 759 } |
| 743 } | 760 } |
| 744 | 761 |
| 745 bool JingleSession::is_session_active() { | 762 bool JingleSession::is_session_active() { |
| 746 return state_ == CONNECTING || state_ == ACCEPTING || state_ == ACCEPTED || | 763 return state_ == CONNECTING || state_ == ACCEPTING || state_ == ACCEPTED || |
| 747 state_ == AUTHENTICATING || state_ == AUTHENTICATED; | 764 state_ == AUTHENTICATING || state_ == AUTHENTICATED; |
| 748 } | 765 } |
| 749 | 766 |
| 767 void JingleSession::ExecutePluginsOnIncomingMessage( | |
|
Sergey Ulanov
2016/12/29 00:37:58
Maybe call it ProcessIncomingAttachments() or Proc
Hzj_jie
2016/12/29 03:07:56
Done.
| |
| 768 const JingleMessage& message) { | |
| 769 if (message.attachments) { | |
|
Sergey Ulanov
2016/12/29 00:37:58
if (!messeage.attachments) {
return;
}
Hzj_jie
2016/12/29 03:07:57
Done.
| |
| 770 for (const auto& plugin : plugins_) { | |
| 771 plugin->OnIncomingMessage(*(message.attachments)); | |
| 772 } | |
| 773 } | |
| 774 } | |
| 775 | |
| 776 void JingleSession::ExecutePluginsOnOutgoingMessage(JingleMessage* message) { | |
|
Sergey Ulanov
2016/12/29 00:37:58
Maybe AddPluginAttachments() or something like tha
Hzj_jie
2016/12/29 03:07:57
Done.
| |
| 777 DCHECK(message); | |
| 778 for (const auto& plugin : plugins_) { | |
| 779 std::unique_ptr<XmlElement> attachment = plugin->GetNextMessage(); | |
| 780 if (attachment) { | |
| 781 message->AddAttachment(std::move(attachment)); | |
| 782 } | |
| 783 } | |
| 784 } | |
| 785 | |
| 786 void JingleSession::SendSessionInitiateMessage() { | |
| 787 std::unique_ptr<JingleMessage> message(new JingleMessage( | |
|
Sergey Ulanov
2016/12/29 00:37:58
Need to check here that the state_ is still CONNEC
Hzj_jie
2016/12/29 03:07:56
Done.
| |
| 788 peer_address_, JingleMessage::SESSION_INITIATE, session_id_)); | |
| 789 message->initiator = session_manager_->signal_strategy_->GetLocalJid(); | |
| 790 message->description.reset(new ContentDescription( | |
| 791 session_manager_->protocol_config_->Clone(), | |
| 792 authenticator_->GetNextMessage())); | |
| 793 SendMessage(std::move(message)); | |
| 794 } | |
| 795 | |
| 750 std::string JingleSession::GetNextOutgoingId() { | 796 std::string JingleSession::GetNextOutgoingId() { |
| 751 return outgoing_id_prefix_ + "_" + base::IntToString(++next_outgoing_id_); | 797 return outgoing_id_prefix_ + "_" + base::IntToString(++next_outgoing_id_); |
| 752 } | 798 } |
| 753 | 799 |
| 754 } // namespace protocol | 800 } // namespace protocol |
| 755 } // namespace remoting | 801 } // namespace remoting |
| OLD | NEW |