Disable session invalidations on Android with a flag.
[chromium-blink-merge.git] / remoting / protocol / jingle_session_manager.cc
blob58bcd4d36a91cbd478b158b986e1f730c99fdebb
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
3 // found in the LICENSE file.
5 #include "remoting/protocol/jingle_session_manager.h"
7 #include "base/bind.h"
8 #include "remoting/jingle_glue/iq_sender.h"
9 #include "remoting/jingle_glue/signal_strategy.h"
10 #include "remoting/protocol/authenticator.h"
11 #include "remoting/protocol/content_description.h"
12 #include "remoting/protocol/jingle_messages.h"
13 #include "remoting/protocol/jingle_session.h"
14 #include "remoting/protocol/transport.h"
15 #include "third_party/libjingle/source/talk/base/socketaddress.h"
16 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
18 using buzz::QName;
20 namespace remoting {
21 namespace protocol {
23 JingleSessionManager::JingleSessionManager(
24 scoped_ptr<TransportFactory> transport_factory)
25 : transport_factory_(transport_factory.Pass()),
26 signal_strategy_(NULL),
27 listener_(NULL),
28 ready_(false) {
31 JingleSessionManager::~JingleSessionManager() {
32 Close();
35 void JingleSessionManager::Init(
36 SignalStrategy* signal_strategy,
37 SessionManager::Listener* listener) {
38 listener_ = listener;
39 signal_strategy_ = signal_strategy;
40 iq_sender_.reset(new IqSender(signal_strategy_));
42 signal_strategy_->AddListener(this);
44 OnSignalStrategyStateChange(signal_strategy_->GetState());
47 scoped_ptr<Session> JingleSessionManager::Connect(
48 const std::string& host_jid,
49 scoped_ptr<Authenticator> authenticator,
50 scoped_ptr<CandidateSessionConfig> config) {
51 // Notify |transport_factory_| that it may be used soon.
52 transport_factory_->PrepareTokens();
54 scoped_ptr<JingleSession> session(new JingleSession(this));
55 session->StartConnection(host_jid, authenticator.Pass(), config.Pass());
56 sessions_[session->session_id_] = session.get();
57 return session.PassAs<Session>();
60 void JingleSessionManager::Close() {
61 DCHECK(CalledOnValidThread());
63 // Close() can be called only after all sessions are destroyed.
64 DCHECK(sessions_.empty());
66 listener_ = NULL;
68 if (signal_strategy_) {
69 signal_strategy_->RemoveListener(this);
70 signal_strategy_ = NULL;
74 void JingleSessionManager::set_authenticator_factory(
75 scoped_ptr<AuthenticatorFactory> authenticator_factory) {
76 DCHECK(CalledOnValidThread());
77 authenticator_factory_ = authenticator_factory.Pass();
80 void JingleSessionManager::OnSignalStrategyStateChange(
81 SignalStrategy::State state) {
82 if (state == SignalStrategy::CONNECTED && !ready_) {
83 ready_ = true;
84 listener_->OnSessionManagerReady();
88 bool JingleSessionManager::OnSignalStrategyIncomingStanza(
89 const buzz::XmlElement* stanza) {
90 if (!JingleMessage::IsJingleMessage(stanza))
91 return false;
93 JingleMessage message;
94 std::string error;
95 if (!message.ParseXml(stanza, &error)) {
96 SendReply(stanza, JingleMessageReply::BAD_REQUEST);
97 return true;
100 if (message.action == JingleMessage::SESSION_INITIATE) {
101 // Description must be present in session-initiate messages.
102 DCHECK(message.description.get());
104 SendReply(stanza, JingleMessageReply::NONE);
106 // Notify |transport_factory_| that it may be used soon.
107 transport_factory_->PrepareTokens();
109 scoped_ptr<Authenticator> authenticator =
110 authenticator_factory_->CreateAuthenticator(
111 signal_strategy_->GetLocalJid(), message.from,
112 message.description->authenticator_message());
114 JingleSession* session = new JingleSession(this);
115 session->InitializeIncomingConnection(message, authenticator.Pass());
116 sessions_[session->session_id_] = session;
118 IncomingSessionResponse response = SessionManager::DECLINE;
119 listener_->OnIncomingSession(session, &response);
121 if (response == SessionManager::ACCEPT) {
122 session->AcceptIncomingConnection(message);
123 } else {
124 ErrorCode error;
125 switch (response) {
126 case INCOMPATIBLE:
127 error = INCOMPATIBLE_PROTOCOL;
128 break;
130 case OVERLOAD:
131 error = HOST_OVERLOAD;
132 break;
134 case DECLINE:
135 error = SESSION_REJECTED;
136 break;
138 default:
139 NOTREACHED();
140 error = SESSION_REJECTED;
143 session->CloseInternal(error);
144 delete session;
145 DCHECK(sessions_.find(message.sid) == sessions_.end());
148 return true;
151 SessionsMap::iterator it = sessions_.find(message.sid);
152 if (it == sessions_.end()) {
153 SendReply(stanza, JingleMessageReply::INVALID_SID);
154 return true;
157 it->second->OnIncomingMessage(message, base::Bind(
158 &JingleSessionManager::SendReply, base::Unretained(this), stanza));
159 return true;
162 void JingleSessionManager::SendReply(const buzz::XmlElement* original_stanza,
163 JingleMessageReply::ErrorType error) {
164 signal_strategy_->SendStanza(
165 JingleMessageReply(error).ToXml(original_stanza));
168 void JingleSessionManager::SessionDestroyed(JingleSession* session) {
169 sessions_.erase(session->session_id_);
172 } // namespace protocol
173 } // namespace remoting