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"
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"
23 JingleSessionManager::JingleSessionManager(
24 scoped_ptr
<TransportFactory
> transport_factory
)
25 : transport_factory_(transport_factory
.Pass()),
26 signal_strategy_(NULL
),
31 JingleSessionManager::~JingleSessionManager() {
35 void JingleSessionManager::Init(
36 SignalStrategy
* signal_strategy
,
37 SessionManager::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());
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_
) {
84 listener_
->OnSessionManagerReady();
88 bool JingleSessionManager::OnSignalStrategyIncomingStanza(
89 const buzz::XmlElement
* stanza
) {
90 if (!JingleMessage::IsJingleMessage(stanza
))
93 JingleMessage message
;
95 if (!message
.ParseXml(stanza
, &error
)) {
96 SendReply(stanza
, JingleMessageReply::BAD_REQUEST
);
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
);
127 error
= INCOMPATIBLE_PROTOCOL
;
131 error
= HOST_OVERLOAD
;
135 error
= SESSION_REJECTED
;
140 error
= SESSION_REJECTED
;
143 session
->CloseInternal(error
);
145 DCHECK(sessions_
.find(message
.sid
) == sessions_
.end());
151 SessionsMap::iterator it
= sessions_
.find(message
.sid
);
152 if (it
== sessions_
.end()) {
153 SendReply(stanza
, JingleMessageReply::INVALID_SID
);
157 it
->second
->OnIncomingMessage(message
, base::Bind(
158 &JingleSessionManager::SendReply
, base::Unretained(this), stanza
));
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