[email protected] | 6bad55c | 2012-01-24 20:50:27 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "remoting/protocol/pepper_session.h" |
| 6 | |
| 7 | #include "base/bind.h" |
| 8 | #include "base/rand_util.h" |
| 9 | #include "base/stl_util.h" |
| 10 | #include "base/string_number_conversions.h" |
| 11 | #include "remoting/base/constants.h" |
[email protected] | b39e182 | 2011-11-04 01:00:49 | [diff] [blame] | 12 | #include "remoting/jingle_glue/iq_sender.h" |
[email protected] | f4453851 | 2011-11-30 04:43:17 | [diff] [blame] | 13 | #include "remoting/protocol/authenticator.h" |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 14 | #include "remoting/protocol/content_description.h" |
| 15 | #include "remoting/protocol/jingle_messages.h" |
| 16 | #include "remoting/protocol/pepper_session_manager.h" |
| 17 | #include "remoting/protocol/pepper_stream_channel.h" |
| 18 | #include "third_party/libjingle/source/talk/p2p/base/candidate.h" |
| 19 | #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" |
| 20 | |
| 21 | using buzz::XmlElement; |
| 22 | |
| 23 | namespace remoting { |
| 24 | namespace protocol { |
| 25 | |
| 26 | namespace { |
| 27 | // Delay after candidate creation before sending transport-info |
| 28 | // message. This is neccessary to be able to pack multiple candidates |
| 29 | // into one transport-info messages. The value needs to be greater |
| 30 | // than zero because ports are opened asynchronously in the browser |
| 31 | // process. |
| 32 | const int kTransportInfoSendDelayMs = 2; |
| 33 | } // namespace |
| 34 | |
| 35 | PepperSession::PepperSession(PepperSessionManager* session_manager) |
| 36 | : session_manager_(session_manager), |
| 37 | state_(INITIALIZING), |
[email protected] | e3f03d0 | 2011-09-27 20:10:51 | [diff] [blame] | 38 | error_(OK) { |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 39 | } |
| 40 | |
| 41 | PepperSession::~PepperSession() { |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 42 | STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); |
| 43 | session_manager_->SessionDestroyed(this); |
| 44 | } |
| 45 | |
[email protected] | 9e2a313 | 2011-10-07 05:07:40 | [diff] [blame] | 46 | void PepperSession::SetStateChangeCallback( |
| 47 | const StateChangeCallback& callback) { |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 48 | DCHECK(CalledOnValidThread()); |
[email protected] | 9e2a313 | 2011-10-07 05:07:40 | [diff] [blame] | 49 | state_change_callback_ = callback; |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 50 | } |
| 51 | |
[email protected] | 3cb6677 | 2012-01-25 00:30:55 | [diff] [blame^] | 52 | void PepperSession::SetRouteChangeCallback( |
| 53 | const RouteChangeCallback& callback) { |
| 54 | // This callback is not used on the client side yet. |
| 55 | NOTREACHED(); |
| 56 | } |
| 57 | |
[email protected] | e3f03d0 | 2011-09-27 20:10:51 | [diff] [blame] | 58 | Session::Error PepperSession::error() { |
| 59 | DCHECK(CalledOnValidThread()); |
| 60 | return error_; |
| 61 | } |
| 62 | |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 63 | void PepperSession::StartConnection( |
| 64 | const std::string& peer_jid, |
[email protected] | 5bf5231 | 2012-01-20 04:10:52 | [diff] [blame] | 65 | scoped_ptr<Authenticator> authenticator, |
| 66 | scoped_ptr<CandidateSessionConfig> config, |
[email protected] | 9e2a313 | 2011-10-07 05:07:40 | [diff] [blame] | 67 | const StateChangeCallback& state_change_callback) { |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 68 | DCHECK(CalledOnValidThread()); |
[email protected] | 5bf5231 | 2012-01-20 04:10:52 | [diff] [blame] | 69 | DCHECK(authenticator.get()); |
[email protected] | f4453851 | 2011-11-30 04:43:17 | [diff] [blame] | 70 | DCHECK_EQ(authenticator->state(), Authenticator::MESSAGE_READY); |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 71 | |
| 72 | peer_jid_ = peer_jid; |
[email protected] | 5bf5231 | 2012-01-20 04:10:52 | [diff] [blame] | 73 | authenticator_ = authenticator.Pass(); |
| 74 | candidate_config_ = config.Pass(); |
[email protected] | 9e2a313 | 2011-10-07 05:07:40 | [diff] [blame] | 75 | state_change_callback_ = state_change_callback; |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 76 | |
| 77 | // Generate random session ID. There are usually not more than 1 |
| 78 | // concurrent session per host, so a random 64-bit integer provides |
| 79 | // enough entropy. In the worst case connection will fail when two |
| 80 | // clients generate the same session ID concurrently. |
| 81 | session_id_ = base::Int64ToString(base::RandGenerator(kint64max)); |
| 82 | |
| 83 | // Send session-initiate message. |
| 84 | JingleMessage message(peer_jid_, JingleMessage::SESSION_INITIATE, |
| 85 | session_id_); |
[email protected] | 08128a31 | 2012-01-03 21:02:39 | [diff] [blame] | 86 | message.from = session_manager_->signal_strategy_->GetLocalJid(); |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 87 | message.description.reset( |
[email protected] | f4453851 | 2011-11-30 04:43:17 | [diff] [blame] | 88 | new ContentDescription(candidate_config_->Clone(), |
| 89 | authenticator_->GetNextMessage())); |
[email protected] | b39e182 | 2011-11-04 01:00:49 | [diff] [blame] | 90 | initiate_request_.reset(session_manager_->iq_sender()->SendIq( |
| 91 | message.ToXml(), |
| 92 | base::Bind(&PepperSession::OnSessionInitiateResponse, |
| 93 | base::Unretained(this)))); |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 94 | |
| 95 | SetState(CONNECTING); |
| 96 | } |
| 97 | |
| 98 | void PepperSession::OnSessionInitiateResponse( |
| 99 | const buzz::XmlElement* response) { |
| 100 | const std::string& type = response->Attr(buzz::QName("", "type")); |
| 101 | if (type != "result") { |
| 102 | LOG(ERROR) << "Received error in response to session-initiate message: \"" |
| 103 | << response->Str() |
[email protected] | 349bea0 | 2011-11-05 00:52:27 | [diff] [blame] | 104 | << "\". Terminating the session."; |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 105 | |
| 106 | // TODO(sergeyu): There may be different reasons for error |
| 107 | // here. Parse the response stanza to find failure reason. |
[email protected] | e3f03d0 | 2011-09-27 20:10:51 | [diff] [blame] | 108 | OnError(PEER_IS_OFFLINE); |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 109 | } |
| 110 | } |
| 111 | |
| 112 | void PepperSession::OnError(Error error) { |
| 113 | error_ = error; |
| 114 | CloseInternal(true); |
| 115 | } |
| 116 | |
| 117 | void PepperSession::CreateStreamChannel( |
| 118 | const std::string& name, |
| 119 | const StreamChannelCallback& callback) { |
| 120 | DCHECK(!channels_[name]); |
| 121 | |
[email protected] | 5bf5231 | 2012-01-20 04:10:52 | [diff] [blame] | 122 | scoped_ptr<ChannelAuthenticator> channel_authenticator = |
[email protected] | f4453851 | 2011-11-30 04:43:17 | [diff] [blame] | 123 | authenticator_->CreateChannelAuthenticator(); |
| 124 | PepperStreamChannel* channel = new PepperStreamChannel( |
| 125 | this, name, callback); |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 126 | channels_[name] = channel; |
| 127 | channel->Connect(session_manager_->pp_instance_, |
[email protected] | 8d1f875 | 2011-11-23 03:58:43 | [diff] [blame] | 128 | session_manager_->transport_config_, |
[email protected] | 5bf5231 | 2012-01-20 04:10:52 | [diff] [blame] | 129 | channel_authenticator.Pass()); |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 130 | } |
| 131 | |
| 132 | void PepperSession::CreateDatagramChannel( |
| 133 | const std::string& name, |
| 134 | const DatagramChannelCallback& callback) { |
| 135 | // TODO(sergeyu): Implement datagram channel support. |
| 136 | NOTREACHED(); |
| 137 | } |
| 138 | |
[email protected] | f2d6a003 | 2011-11-17 00:48:12 | [diff] [blame] | 139 | void PepperSession::CancelChannelCreation(const std::string& name) { |
| 140 | ChannelsMap::iterator it = channels_.find(name); |
| 141 | if (it != channels_.end() && !it->second->is_connected()) { |
| 142 | delete it->second; |
| 143 | DCHECK(!channels_[name]); |
| 144 | } |
| 145 | } |
| 146 | |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 147 | const std::string& PepperSession::jid() { |
| 148 | DCHECK(CalledOnValidThread()); |
| 149 | return peer_jid_; |
| 150 | } |
| 151 | |
| 152 | const CandidateSessionConfig* PepperSession::candidate_config() { |
| 153 | DCHECK(CalledOnValidThread()); |
| 154 | return candidate_config_.get(); |
| 155 | } |
| 156 | |
| 157 | const SessionConfig& PepperSession::config() { |
| 158 | DCHECK(CalledOnValidThread()); |
| 159 | return config_; |
| 160 | } |
| 161 | |
| 162 | void PepperSession::set_config(const SessionConfig& config) { |
| 163 | DCHECK(CalledOnValidThread()); |
| 164 | // set_config() should never be called on the client. |
| 165 | NOTREACHED(); |
| 166 | } |
| 167 | |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 168 | void PepperSession::Close() { |
| 169 | DCHECK(CalledOnValidThread()); |
| 170 | |
[email protected] | 0de3700 | 2011-12-06 07:30:16 | [diff] [blame] | 171 | if (state_ == CONNECTING || state_ == CONNECTED || state_ == AUTHENTICATED) { |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 172 | // Send session-terminate message. |
| 173 | JingleMessage message(peer_jid_, JingleMessage::SESSION_TERMINATE, |
| 174 | session_id_); |
[email protected] | b39e182 | 2011-11-04 01:00:49 | [diff] [blame] | 175 | scoped_ptr<IqRequest> terminate_request( |
| 176 | session_manager_->iq_sender()->SendIq( |
| 177 | message.ToXml(), IqSender::ReplyCallback())); |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 178 | } |
| 179 | |
| 180 | CloseInternal(false); |
| 181 | } |
| 182 | |
| 183 | void PepperSession::OnIncomingMessage(const JingleMessage& message, |
| 184 | JingleMessageReply* reply) { |
| 185 | DCHECK(CalledOnValidThread()); |
| 186 | |
| 187 | if (message.from != peer_jid_) { |
| 188 | // Ignore messages received from a different Jid. |
| 189 | *reply = JingleMessageReply(JingleMessageReply::INVALID_SID); |
| 190 | return; |
| 191 | } |
| 192 | |
| 193 | switch (message.action) { |
| 194 | case JingleMessage::SESSION_ACCEPT: |
| 195 | OnAccept(message, reply); |
| 196 | break; |
| 197 | |
[email protected] | 1bc9c7c | 2011-12-14 00:13:39 | [diff] [blame] | 198 | case JingleMessage::SESSION_INFO: |
| 199 | OnSessionInfo(message, reply); |
| 200 | break; |
| 201 | |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 202 | case JingleMessage::TRANSPORT_INFO: |
| 203 | ProcessTransportInfo(message); |
| 204 | break; |
| 205 | |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 206 | case JingleMessage::SESSION_TERMINATE: |
| 207 | OnTerminate(message, reply); |
| 208 | break; |
| 209 | |
| 210 | default: |
| 211 | *reply = JingleMessageReply(JingleMessageReply::UNEXPECTED_REQUEST); |
| 212 | } |
| 213 | } |
| 214 | |
| 215 | void PepperSession::OnAccept(const JingleMessage& message, |
| 216 | JingleMessageReply* reply) { |
| 217 | if (state_ != CONNECTING) { |
| 218 | *reply = JingleMessageReply(JingleMessageReply::UNEXPECTED_REQUEST); |
| 219 | return; |
| 220 | } |
| 221 | |
[email protected] | f4453851 | 2011-11-30 04:43:17 | [diff] [blame] | 222 | const buzz::XmlElement* auth_message = |
| 223 | message.description->authenticator_message(); |
| 224 | if (!auth_message) { |
| 225 | DLOG(WARNING) << "Received session-accept without authentication message " |
| 226 | << auth_message->Str(); |
| 227 | OnError(INCOMPATIBLE_PROTOCOL); |
| 228 | return; |
| 229 | } |
| 230 | |
| 231 | DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE); |
| 232 | authenticator_->ProcessMessage(auth_message); |
[email protected] | f4453851 | 2011-11-30 04:43:17 | [diff] [blame] | 233 | |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 234 | if (!InitializeConfigFromDescription(message.description.get())) { |
[email protected] | e3f03d0 | 2011-09-27 20:10:51 | [diff] [blame] | 235 | OnError(INCOMPATIBLE_PROTOCOL); |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 236 | return; |
| 237 | } |
| 238 | |
[email protected] | 1bc9c7c | 2011-12-14 00:13:39 | [diff] [blame] | 239 | // In case there is transport information in the accept message. |
| 240 | ProcessTransportInfo(message); |
| 241 | |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 242 | SetState(CONNECTED); |
| 243 | |
[email protected] | 1bc9c7c | 2011-12-14 00:13:39 | [diff] [blame] | 244 | // Process authentication. |
| 245 | if (authenticator_->state() == Authenticator::ACCEPTED) { |
[email protected] | 0de3700 | 2011-12-06 07:30:16 | [diff] [blame] | 246 | SetState(AUTHENTICATED); |
[email protected] | 1bc9c7c | 2011-12-14 00:13:39 | [diff] [blame] | 247 | } else { |
| 248 | ProcessAuthenticationStep(); |
| 249 | } |
| 250 | } |
[email protected] | 0de3700 | 2011-12-06 07:30:16 | [diff] [blame] | 251 | |
[email protected] | 1bc9c7c | 2011-12-14 00:13:39 | [diff] [blame] | 252 | void PepperSession::OnSessionInfo(const JingleMessage& message, |
| 253 | JingleMessageReply* reply) { |
| 254 | if (message.info.get() && |
| 255 | Authenticator::IsAuthenticatorMessage(message.info.get())) { |
| 256 | if (state_ != CONNECTED || |
| 257 | authenticator_->state() != Authenticator::WAITING_MESSAGE) { |
| 258 | LOG(WARNING) << "Received unexpected authenticator message " |
| 259 | << message.info->Str(); |
| 260 | *reply = JingleMessageReply(JingleMessageReply::UNEXPECTED_REQUEST); |
| 261 | OnError(INCOMPATIBLE_PROTOCOL); |
| 262 | return; |
| 263 | } |
| 264 | |
| 265 | authenticator_->ProcessMessage(message.info.get()); |
| 266 | ProcessAuthenticationStep(); |
| 267 | } else { |
| 268 | *reply = JingleMessageReply(JingleMessageReply::UNSUPPORTED_INFO); |
| 269 | } |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 270 | } |
| 271 | |
| 272 | void PepperSession::ProcessTransportInfo(const JingleMessage& message) { |
| 273 | for (std::list<cricket::Candidate>::const_iterator it = |
| 274 | message.candidates.begin(); |
| 275 | it != message.candidates.end(); ++it) { |
| 276 | ChannelsMap::iterator channel = channels_.find(it->name()); |
| 277 | if (channel == channels_.end()) { |
| 278 | LOG(WARNING) << "Received candidate for unknown channel " << it->name(); |
| 279 | continue; |
| 280 | } |
| 281 | channel->second->AddRemoveCandidate(*it); |
| 282 | } |
| 283 | } |
| 284 | |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 285 | void PepperSession::OnTerminate(const JingleMessage& message, |
| 286 | JingleMessageReply* reply) { |
| 287 | if (state_ == CONNECTING) { |
[email protected] | e3f03d0 | 2011-09-27 20:10:51 | [diff] [blame] | 288 | switch (message.reason) { |
| 289 | case JingleMessage::DECLINE: |
| 290 | OnError(SESSION_REJECTED); |
| 291 | break; |
| 292 | |
| 293 | case JingleMessage::INCOMPATIBLE_PARAMETERS: |
| 294 | OnError(INCOMPATIBLE_PROTOCOL); |
| 295 | break; |
| 296 | |
| 297 | default: |
| 298 | LOG(WARNING) << "Received session-terminate message " |
| 299 | "with an unexpected reason."; |
| 300 | OnError(SESSION_REJECTED); |
| 301 | } |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 302 | return; |
| 303 | } |
| 304 | |
[email protected] | 1bc9c7c | 2011-12-14 00:13:39 | [diff] [blame] | 305 | if (state_ != CONNECTED && state_ != AUTHENTICATED) { |
| 306 | LOG(WARNING) << "Received unexpected session-terminate message."; |
[email protected] | 455a6168 | 2011-11-12 01:45:19 | [diff] [blame] | 307 | } |
| 308 | |
[email protected] | 1bc9c7c | 2011-12-14 00:13:39 | [diff] [blame] | 309 | if (message.reason == JingleMessage::SUCCESS) { |
| 310 | CloseInternal(false); |
| 311 | } else if (message.reason == JingleMessage::DECLINE) { |
| 312 | OnError(AUTHENTICATION_FAILED); |
| 313 | } else if (message.reason == JingleMessage::GENERAL_ERROR) { |
| 314 | OnError(CHANNEL_CONNECTION_ERROR); |
| 315 | } else if (message.reason == JingleMessage::INCOMPATIBLE_PARAMETERS) { |
| 316 | OnError(INCOMPATIBLE_PROTOCOL); |
| 317 | } else { |
| 318 | OnError(UNKNOWN_ERROR); |
| 319 | } |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 320 | } |
| 321 | |
| 322 | bool PepperSession::InitializeConfigFromDescription( |
| 323 | const ContentDescription* description) { |
| 324 | DCHECK(description); |
| 325 | |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 326 | if (!description->config()->GetFinalConfig(&config_)) { |
| 327 | LOG(ERROR) << "session-accept does not specify configuration"; |
| 328 | return false; |
| 329 | } |
| 330 | if (!candidate_config()->IsSupported(config_)) { |
| 331 | LOG(ERROR) << "session-accept specifies an invalid configuration"; |
| 332 | return false; |
| 333 | } |
| 334 | |
| 335 | return true; |
| 336 | } |
| 337 | |
[email protected] | 1bc9c7c | 2011-12-14 00:13:39 | [diff] [blame] | 338 | void PepperSession::ProcessAuthenticationStep() { |
| 339 | DCHECK_EQ(state_, CONNECTED); |
| 340 | |
| 341 | if (authenticator_->state() == Authenticator::MESSAGE_READY) { |
| 342 | JingleMessage message(peer_jid_, JingleMessage::SESSION_INFO, session_id_); |
[email protected] | 5bf5231 | 2012-01-20 04:10:52 | [diff] [blame] | 343 | message.info = authenticator_->GetNextMessage(); |
[email protected] | 1bc9c7c | 2011-12-14 00:13:39 | [diff] [blame] | 344 | DCHECK(message.info.get()); |
| 345 | |
| 346 | session_info_request_.reset(session_manager_->iq_sender()->SendIq( |
| 347 | message.ToXml(), base::Bind( |
| 348 | &PepperSession::OnSessionInfoResponse, |
| 349 | base::Unretained(this)))); |
| 350 | } |
| 351 | DCHECK_NE(authenticator_->state(), Authenticator::MESSAGE_READY); |
| 352 | |
| 353 | if (authenticator_->state() == Authenticator::ACCEPTED) { |
| 354 | SetState(AUTHENTICATED); |
| 355 | } else if (authenticator_->state() == Authenticator::REJECTED) { |
[email protected] | 6bad55c | 2012-01-24 20:50:27 | [diff] [blame] | 356 | switch (authenticator_->rejection_reason()) { |
| 357 | case Authenticator::INVALID_CREDENTIALS: |
| 358 | OnError(AUTHENTICATION_FAILED); |
| 359 | break; |
| 360 | case Authenticator::PROTOCOL_ERROR: |
| 361 | OnError(INCOMPATIBLE_PROTOCOL); |
| 362 | break; |
| 363 | } |
[email protected] | 1bc9c7c | 2011-12-14 00:13:39 | [diff] [blame] | 364 | } |
| 365 | } |
| 366 | |
| 367 | void PepperSession::OnSessionInfoResponse(const buzz::XmlElement* response) { |
| 368 | const std::string& type = response->Attr(buzz::QName("", "type")); |
| 369 | if (type != "result") { |
| 370 | LOG(ERROR) << "Received error in response to session-info message: \"" |
| 371 | << response->Str() |
| 372 | << "\". Terminating the session."; |
[email protected] | 6bad55c | 2012-01-24 20:50:27 | [diff] [blame] | 373 | OnError(INCOMPATIBLE_PROTOCOL); |
[email protected] | 1bc9c7c | 2011-12-14 00:13:39 | [diff] [blame] | 374 | } |
| 375 | } |
| 376 | |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 377 | void PepperSession::AddLocalCandidate(const cricket::Candidate& candidate) { |
| 378 | pending_candidates_.push_back(candidate); |
| 379 | |
| 380 | if (!transport_infos_timer_.IsRunning()) { |
| 381 | // Delay sending the new candidates in case we get more candidates |
| 382 | // that we can send in one message. |
| 383 | transport_infos_timer_.Start( |
| 384 | FROM_HERE, base::TimeDelta::FromMilliseconds(kTransportInfoSendDelayMs), |
| 385 | this, &PepperSession::SendTransportInfo); |
| 386 | } |
| 387 | } |
| 388 | |
[email protected] | 349bea0 | 2011-11-05 00:52:27 | [diff] [blame] | 389 | void PepperSession::OnTransportInfoResponse(const buzz::XmlElement* response) { |
| 390 | const std::string& type = response->Attr(buzz::QName("", "type")); |
| 391 | if (type != "result") { |
| 392 | LOG(ERROR) << "Received error in response to session-initiate message: \"" |
| 393 | << response->Str() |
| 394 | << "\". Terminating the session."; |
| 395 | |
| 396 | if (state_ == CONNECTING) { |
| 397 | OnError(PEER_IS_OFFLINE); |
| 398 | } else { |
| 399 | // Host has disconnected without sending session-terminate message. |
| 400 | CloseInternal(false); |
| 401 | } |
| 402 | } |
| 403 | } |
| 404 | |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 405 | void PepperSession::OnDeleteChannel(PepperChannel* channel) { |
| 406 | ChannelsMap::iterator it = channels_.find(channel->name()); |
| 407 | DCHECK_EQ(it->second, channel); |
| 408 | channels_.erase(it); |
| 409 | } |
| 410 | |
| 411 | void PepperSession::SendTransportInfo() { |
| 412 | JingleMessage message(peer_jid_, JingleMessage::TRANSPORT_INFO, session_id_); |
| 413 | message.candidates.swap(pending_candidates_); |
[email protected] | 349bea0 | 2011-11-05 00:52:27 | [diff] [blame] | 414 | transport_info_request_.reset(session_manager_->iq_sender()->SendIq( |
| 415 | message.ToXml(), base::Bind( |
| 416 | &PepperSession::OnTransportInfoResponse, |
| 417 | base::Unretained(this)))); |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 418 | } |
| 419 | |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 420 | |
| 421 | void PepperSession::CloseInternal(bool failed) { |
| 422 | DCHECK(CalledOnValidThread()); |
| 423 | |
| 424 | if (state_ != FAILED && state_ != CLOSED) { |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 425 | if (failed) |
| 426 | SetState(FAILED); |
| 427 | else |
| 428 | SetState(CLOSED); |
| 429 | } |
| 430 | } |
| 431 | |
| 432 | void PepperSession::SetState(State new_state) { |
| 433 | DCHECK(CalledOnValidThread()); |
| 434 | |
| 435 | if (new_state != state_) { |
| 436 | DCHECK_NE(state_, CLOSED); |
| 437 | DCHECK_NE(state_, FAILED); |
| 438 | |
| 439 | state_ = new_state; |
[email protected] | 9e2a313 | 2011-10-07 05:07:40 | [diff] [blame] | 440 | if (!state_change_callback_.is_null()) |
| 441 | state_change_callback_.Run(new_state); |
[email protected] | 22aae95 | 2011-09-12 23:47:51 | [diff] [blame] | 442 | } |
| 443 | } |
| 444 | |
| 445 | } // namespace protocol |
| 446 | } // namespace remoting |