telemetry: Support custom 'out' directory
[chromium-blink-merge.git] / remoting / protocol / jingle_session_manager.cc
blob7cb158671e59747fae86028fc72158b7aa8c9d3e
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/jingle_info_request.h"
10 #include "remoting/jingle_glue/signal_strategy.h"
11 #include "remoting/protocol/authenticator.h"
12 #include "remoting/protocol/content_description.h"
13 #include "remoting/protocol/jingle_messages.h"
14 #include "remoting/protocol/jingle_session.h"
15 #include "remoting/protocol/transport.h"
16 #include "remoting/protocol/transport_config.h"
17 #include "third_party/libjingle/source/talk/base/socketaddress.h"
18 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
20 using buzz::QName;
22 namespace remoting {
23 namespace protocol {
25 JingleSessionManager::JingleSessionManager(
26 scoped_ptr<TransportFactory> transport_factory,
27 bool fetch_stun_relay_config)
28 : transport_factory_(transport_factory.Pass()),
29 fetch_stun_relay_config_(fetch_stun_relay_config),
30 signal_strategy_(NULL),
31 listener_(NULL),
32 ready_(false) {
35 JingleSessionManager::~JingleSessionManager() {
36 Close();
39 void JingleSessionManager::Init(
40 SignalStrategy* signal_strategy,
41 SessionManager::Listener* listener) {
42 listener_ = listener;
43 signal_strategy_ = signal_strategy;
44 iq_sender_.reset(new IqSender(signal_strategy_));
46 signal_strategy_->AddListener(this);
48 OnSignalStrategyStateChange(signal_strategy_->GetState());
51 void JingleSessionManager::OnJingleInfo(
52 const std::string& relay_token,
53 const std::vector<std::string>& relay_hosts,
54 const std::vector<talk_base::SocketAddress>& stun_hosts) {
55 DCHECK(CalledOnValidThread());
57 // TODO(sergeyu): Add support for multiple STUN/relay servers when
58 // it's implemented in libjingle and P2P Transport API.
59 TransportConfig config;
60 config.stun_server = stun_hosts[0].ToString();
61 config.relay_server = relay_hosts[0];
62 config.relay_token = relay_token;
63 transport_factory_->SetTransportConfig(config);
65 VLOG(1) << "STUN server: " << config.stun_server
66 << " Relay server: " << config.relay_server
67 << " Relay token: " << config.relay_token;
70 if (!ready_) {
71 ready_ = true;
72 listener_->OnSessionManagerReady();
76 scoped_ptr<Session> JingleSessionManager::Connect(
77 const std::string& host_jid,
78 scoped_ptr<Authenticator> authenticator,
79 scoped_ptr<CandidateSessionConfig> config) {
80 scoped_ptr<JingleSession> session(new JingleSession(this));
81 session->StartConnection(host_jid, authenticator.Pass(), config.Pass());
82 sessions_[session->session_id_] = session.get();
83 return session.PassAs<Session>();
86 void JingleSessionManager::Close() {
87 DCHECK(CalledOnValidThread());
89 // Close() can be called only after all sessions are destroyed.
90 DCHECK(sessions_.empty());
92 listener_ = NULL;
93 jingle_info_request_.reset();
95 if (signal_strategy_) {
96 signal_strategy_->RemoveListener(this);
97 signal_strategy_ = NULL;
101 void JingleSessionManager::set_authenticator_factory(
102 scoped_ptr<AuthenticatorFactory> authenticator_factory) {
103 DCHECK(CalledOnValidThread());
104 authenticator_factory_ = authenticator_factory.Pass();
107 void JingleSessionManager::OnSignalStrategyStateChange(
108 SignalStrategy::State state) {
109 if (state == SignalStrategy::CONNECTED) {
110 // Request STUN/Relay info if necessary.
111 if (fetch_stun_relay_config_) {
112 jingle_info_request_.reset(new JingleInfoRequest(signal_strategy_));
113 jingle_info_request_->Send(base::Bind(&JingleSessionManager::OnJingleInfo,
114 base::Unretained(this)));
115 } else if (!ready_) {
116 ready_ = true;
117 listener_->OnSessionManagerReady();
122 bool JingleSessionManager::OnSignalStrategyIncomingStanza(
123 const buzz::XmlElement* stanza) {
124 if (!JingleMessage::IsJingleMessage(stanza))
125 return false;
127 JingleMessage message;
128 std::string error;
129 if (!message.ParseXml(stanza, &error)) {
130 SendReply(stanza, JingleMessageReply::BAD_REQUEST);
131 return true;
134 if (message.action == JingleMessage::SESSION_INITIATE) {
135 // Description must be present in session-initiate messages.
136 DCHECK(message.description.get());
138 SendReply(stanza, JingleMessageReply::NONE);
140 scoped_ptr<Authenticator> authenticator =
141 authenticator_factory_->CreateAuthenticator(
142 signal_strategy_->GetLocalJid(), message.from,
143 message.description->authenticator_message());
145 JingleSession* session = new JingleSession(this);
146 session->InitializeIncomingConnection(message, authenticator.Pass());
147 sessions_[session->session_id_] = session;
149 IncomingSessionResponse response = SessionManager::DECLINE;
150 listener_->OnIncomingSession(session, &response);
152 if (response == SessionManager::ACCEPT) {
153 session->AcceptIncomingConnection(message);
154 } else {
155 ErrorCode error;
156 switch (response) {
157 case INCOMPATIBLE:
158 error = INCOMPATIBLE_PROTOCOL;
159 break;
161 case OVERLOAD:
162 error = HOST_OVERLOAD;
163 break;
165 case DECLINE:
166 error = SESSION_REJECTED;
167 break;
169 default:
170 NOTREACHED();
171 error = SESSION_REJECTED;
174 session->CloseInternal(error);
175 delete session;
176 DCHECK(sessions_.find(message.sid) == sessions_.end());
179 return true;
182 SessionsMap::iterator it = sessions_.find(message.sid);
183 if (it == sessions_.end()) {
184 SendReply(stanza, JingleMessageReply::INVALID_SID);
185 return true;
188 it->second->OnIncomingMessage(message, base::Bind(
189 &JingleSessionManager::SendReply, base::Unretained(this), stanza));
190 return true;
193 void JingleSessionManager::SendReply(const buzz::XmlElement* original_stanza,
194 JingleMessageReply::ErrorType error) {
195 signal_strategy_->SendStanza(
196 JingleMessageReply(error).ToXml(original_stanza));
199 void JingleSessionManager::SessionDestroyed(JingleSession* session) {
200 sessions_.erase(session->session_id_);
203 } // namespace protocol
204 } // namespace remoting