// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "remoting/protocol/jingle_session_manager.h" #include #include "base/bind.h" #include "remoting/protocol/authenticator.h" #include "remoting/protocol/content_description.h" #include "remoting/protocol/jingle_messages.h" #include "remoting/protocol/jingle_session.h" #include "remoting/protocol/transport.h" #include "remoting/signaling/iq_sender.h" #include "remoting/signaling/signal_strategy.h" #include "third_party/webrtc/base/socketaddress.h" #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" using buzz::QName; namespace remoting { namespace protocol { JingleSessionManager::JingleSessionManager(SignalStrategy* signal_strategy) : signal_strategy_(signal_strategy), protocol_config_(CandidateSessionConfig::CreateDefault()), iq_sender_(new IqSender(signal_strategy_)) { signal_strategy_->AddListener(this); } JingleSessionManager::~JingleSessionManager() { DCHECK(sessions_.empty()); signal_strategy_->RemoveListener(this); } void JingleSessionManager::AcceptIncoming( const IncomingSessionCallback& incoming_session_callback) { incoming_session_callback_ = incoming_session_callback; } void JingleSessionManager::set_protocol_config( scoped_ptr config) { protocol_config_ = std::move(config); } scoped_ptr JingleSessionManager::Connect( const std::string& host_jid, scoped_ptr authenticator) { scoped_ptr session(new JingleSession(this)); session->StartConnection(host_jid, std::move(authenticator)); sessions_[session->session_id_] = session.get(); return std::move(session); } void JingleSessionManager::set_authenticator_factory( scoped_ptr authenticator_factory) { DCHECK(CalledOnValidThread()); authenticator_factory_ = std::move(authenticator_factory); } void JingleSessionManager::OnSignalStrategyStateChange( SignalStrategy::State state) {} bool JingleSessionManager::OnSignalStrategyIncomingStanza( const buzz::XmlElement* stanza) { if (!JingleMessage::IsJingleMessage(stanza)) return false; JingleMessage message; std::string error; if (!message.ParseXml(stanza, &error)) { SendReply(stanza, JingleMessageReply::BAD_REQUEST); return true; } if (message.action == JingleMessage::SESSION_INITIATE) { // Description must be present in session-initiate messages. DCHECK(message.description.get()); SendReply(stanza, JingleMessageReply::NONE); scoped_ptr authenticator = authenticator_factory_->CreateAuthenticator( signal_strategy_->GetLocalJid(), message.from); JingleSession* session = new JingleSession(this); session->InitializeIncomingConnection(message, std::move(authenticator)); sessions_[session->session_id_] = session; // Destroy the session if it was rejected due to incompatible protocol. if (session->state_ != Session::ACCEPTING) { delete session; DCHECK(sessions_.find(message.sid) == sessions_.end()); return true; } IncomingSessionResponse response = SessionManager::DECLINE; if (!incoming_session_callback_.is_null()) incoming_session_callback_.Run(session, &response); if (response == SessionManager::ACCEPT) { session->AcceptIncomingConnection(message); } else { ErrorCode error; switch (response) { case OVERLOAD: error = HOST_OVERLOAD; break; case DECLINE: error = SESSION_REJECTED; break; default: NOTREACHED(); error = SESSION_REJECTED; } session->Close(error); delete session; DCHECK(sessions_.find(message.sid) == sessions_.end()); } return true; } SessionsMap::iterator it = sessions_.find(message.sid); if (it == sessions_.end()) { SendReply(stanza, JingleMessageReply::INVALID_SID); return true; } it->second->OnIncomingMessage(message, base::Bind( &JingleSessionManager::SendReply, base::Unretained(this), stanza)); return true; } void JingleSessionManager::SendReply(const buzz::XmlElement* original_stanza, JingleMessageReply::ErrorType error) { signal_strategy_->SendStanza( JingleMessageReply(error).ToXml(original_stanza)); } void JingleSessionManager::SessionDestroyed(JingleSession* session) { sessions_.erase(session->session_id_); } } // namespace protocol } // namespace remoting