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/protocol/authenticator.h"
9 #include "remoting/protocol/content_description.h"
10 #include "remoting/protocol/jingle_messages.h"
11 #include "remoting/protocol/jingle_session.h"
12 #include "remoting/protocol/transport.h"
13 #include "remoting/signaling/iq_sender.h"
14 #include "remoting/signaling/signal_strategy.h"
15 #include "third_party/webrtc/base/socketaddress.h"
16 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
23 JingleSessionManager::JingleSessionManager(
24 scoped_ptr
<TransportFactory
> transport_factory
)
25 : protocol_config_(CandidateSessionConfig::CreateDefault()),
26 transport_factory_(transport_factory
.Pass()),
27 signal_strategy_(nullptr),
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 void JingleSessionManager::set_protocol_config(
48 scoped_ptr
<CandidateSessionConfig
> config
) {
49 protocol_config_
= config
.Pass();
52 scoped_ptr
<Session
> JingleSessionManager::Connect(
53 const std::string
& host_jid
,
54 scoped_ptr
<Authenticator
> authenticator
) {
55 // Notify |transport_factory_| that it may be used soon.
56 transport_factory_
->PrepareTokens();
58 scoped_ptr
<JingleSession
> session(new JingleSession(this));
59 session
->StartConnection(host_jid
, authenticator
.Pass());
60 sessions_
[session
->session_id_
] = session
.get();
61 return session
.Pass();
64 void JingleSessionManager::Close() {
65 DCHECK(CalledOnValidThread());
67 // Close() can be called only after all sessions are destroyed.
68 DCHECK(sessions_
.empty());
72 if (signal_strategy_
) {
73 signal_strategy_
->RemoveListener(this);
74 signal_strategy_
= nullptr;
78 void JingleSessionManager::set_authenticator_factory(
79 scoped_ptr
<AuthenticatorFactory
> authenticator_factory
) {
80 DCHECK(CalledOnValidThread());
81 authenticator_factory_
= authenticator_factory
.Pass();
84 void JingleSessionManager::OnSignalStrategyStateChange(
85 SignalStrategy::State state
) {
86 if (state
== SignalStrategy::CONNECTED
&& !ready_
) {
88 listener_
->OnSessionManagerReady();
92 bool JingleSessionManager::OnSignalStrategyIncomingStanza(
93 const buzz::XmlElement
* stanza
) {
94 if (!JingleMessage::IsJingleMessage(stanza
))
97 JingleMessage message
;
99 if (!message
.ParseXml(stanza
, &error
)) {
100 SendReply(stanza
, JingleMessageReply::BAD_REQUEST
);
104 if (message
.action
== JingleMessage::SESSION_INITIATE
) {
105 // Description must be present in session-initiate messages.
106 DCHECK(message
.description
.get());
108 SendReply(stanza
, JingleMessageReply::NONE
);
110 // Notify |transport_factory_| that it may be used soon.
111 transport_factory_
->PrepareTokens();
113 scoped_ptr
<Authenticator
> authenticator
=
114 authenticator_factory_
->CreateAuthenticator(
115 signal_strategy_
->GetLocalJid(), message
.from
,
116 message
.description
->authenticator_message());
118 JingleSession
* session
= new JingleSession(this);
119 session
->InitializeIncomingConnection(message
, authenticator
.Pass());
120 sessions_
[session
->session_id_
] = session
;
122 // Destroy the session if it was rejected due to incompatible protocol.
123 if (session
->state_
!= Session::ACCEPTING
) {
125 DCHECK(sessions_
.find(message
.sid
) == sessions_
.end());
129 IncomingSessionResponse response
= SessionManager::DECLINE
;
130 listener_
->OnIncomingSession(session
, &response
);
132 if (response
== SessionManager::ACCEPT
) {
133 session
->AcceptIncomingConnection(message
);
138 error
= HOST_OVERLOAD
;
142 error
= SESSION_REJECTED
;
147 error
= SESSION_REJECTED
;
150 session
->CloseInternal(error
);
152 DCHECK(sessions_
.find(message
.sid
) == sessions_
.end());
158 SessionsMap::iterator it
= sessions_
.find(message
.sid
);
159 if (it
== sessions_
.end()) {
160 SendReply(stanza
, JingleMessageReply::INVALID_SID
);
164 it
->second
->OnIncomingMessage(message
, base::Bind(
165 &JingleSessionManager::SendReply
, base::Unretained(this), stanza
));
169 void JingleSessionManager::SendReply(const buzz::XmlElement
* original_stanza
,
170 JingleMessageReply::ErrorType error
) {
171 signal_strategy_
->SendStanza(
172 JingleMessageReply(error
).ToXml(original_stanza
));
175 void JingleSessionManager::SessionDestroyed(JingleSession
* session
) {
176 sessions_
.erase(session
->session_id_
);
179 } // namespace protocol
180 } // namespace remoting