15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/jingle_session.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/single_thread_task_runner.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
12c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/thread_task_runner_handle.h"
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/constants.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/authenticator.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/channel_authenticator.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/channel_multiplexer.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/content_description.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/jingle_messages.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/jingle_session_manager.h"
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "remoting/protocol/pseudotcp_channel_factory.h"
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "remoting/protocol/secure_channel_factory.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/session_config.h"
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "remoting/protocol/stream_channel_factory.h"
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "remoting/signaling/iq_sender.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/libjingle/source/talk/p2p/base/candidate.h"
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using buzz::XmlElement;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protocol {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Delay after candidate creation before sending transport-info
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// message. This is neccessary to be able to pack multiple candidates
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// into one transport-info messages. The value needs to be greater
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// than zero because ports are opened asynchronously in the browser
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// process.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTransportInfoSendDelayMs = 2;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// How long we should wait for a response from the other end. This value is used
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// for all requests except |transport-info|.
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kDefaultMessageTimeout = 10;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// During a reconnection, it usually takes longer for the peer to respond due to
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// pending messages in the channel from the previous session.  From experiment,
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// it can take up to 20s for the session to reconnect. To make it safe, setting
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// the timeout to 30s.
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst int kSessionInitiateAndAcceptTimeout = kDefaultMessageTimeout * 3;
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Timeout for the transport-info messages.
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kTransportInfoTimeout = 10 * 60;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Name of the multiplexed channel.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMuxChannelName[] = "mux";
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ErrorCode AuthRejectionReasonToErrorCode(
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Authenticator::RejectionReason reason) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (reason) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case Authenticator::INVALID_CREDENTIALS:
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return AUTHENTICATION_FAILED;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case Authenticator::PROTOCOL_ERROR:
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return INCOMPATIBLE_PROTOCOL;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return UNKNOWN_ERROR;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JingleSession::JingleSession(JingleSessionManager* session_manager)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : session_manager_(session_manager),
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_handler_(NULL),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_(INITIALIZING),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_(OK),
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      config_is_set_(false),
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      weak_factory_(this) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JingleSession::~JingleSession() {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_multiplexer_.reset();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPointers(pending_requests_.begin(),
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             pending_requests_.end());
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteContainerPointers(transport_info_requests_.begin(),
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             transport_info_requests_.end());
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(channels_.empty());
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_manager_->SessionDestroyed(this);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::SetEventHandler(Session::EventHandler* event_handler) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(event_handler);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_handler_ = event_handler;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ErrorCode JingleSession::error() {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error_;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::StartConnection(
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& peer_jid,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<Authenticator> authenticator,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<CandidateSessionConfig> config) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(authenticator.get());
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(authenticator->state(), Authenticator::MESSAGE_READY);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  peer_jid_ = peer_jid;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  authenticator_ = authenticator.Pass();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  candidate_config_ = config.Pass();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate random session ID. There are usually not more than 1
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // concurrent session per host, so a random 64-bit integer provides
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // enough entropy. In the worst case connection will fail when two
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // clients generate the same session ID concurrently.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_id_ = base::Int64ToString(base::RandGenerator(kint64max));
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send session-initiate message.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JingleMessage message(peer_jid_, JingleMessage::SESSION_INITIATE,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        session_id_);
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  message.initiator = session_manager_->signal_strategy_->GetLocalJid();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message.description.reset(
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ContentDescription(candidate_config_->Clone(),
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             authenticator_->GetNextMessage()));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendMessage(message);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetState(CONNECTING);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::InitializeIncomingConnection(
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const JingleMessage& initiate_message,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<Authenticator> authenticator) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initiate_message.description.get());
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(authenticator.get());
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(authenticator->state(), Authenticator::WAITING_MESSAGE);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  peer_jid_ = initiate_message.from;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  authenticator_ = authenticator.Pass();
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_id_ = initiate_message.sid;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  candidate_config_ = initiate_message.description->config()->Clone();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetState(ACCEPTING);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::AcceptIncomingConnection(
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const JingleMessage& initiate_message) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(config_is_set_);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Process the first authentication message.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const buzz::XmlElement* first_auth_message =
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initiate_message.description->authenticator_message();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!first_auth_message) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseInternal(INCOMPATIBLE_PROTOCOL);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(authenticator_->state(), Authenticator::WAITING_MESSAGE);
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |authenticator_| is owned, so Unretained() is safe here.
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  authenticator_->ProcessMessage(first_auth_message, base::Bind(
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &JingleSession::ContinueAcceptIncomingConnection,
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Unretained(this)));
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void JingleSession::ContinueAcceptIncomingConnection() {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(authenticator_->state(), Authenticator::PROCESSING_MESSAGE);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (authenticator_->state() == Authenticator::REJECTED) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseInternal(AuthRejectionReasonToErrorCode(
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        authenticator_->rejection_reason()));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send the session-accept message.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JingleMessage message(peer_jid_, JingleMessage::SESSION_ACCEPT,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        session_id_);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<buzz::XmlElement> auth_message;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (authenticator_->state() == Authenticator::MESSAGE_READY)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    auth_message = authenticator_->GetNextMessage();
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message.description.reset(
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ContentDescription(CandidateSessionConfig::CreateFrom(config_),
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             auth_message.Pass()));
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendMessage(message);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update state.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetState(CONNECTED);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (authenticator_->state() == Authenticator::ACCEPTED) {
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    OnAuthenticated();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(authenticator_->state(), Authenticator::WAITING_MESSAGE);
198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (authenticator_->started()) {
199c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      SetState(AUTHENTICATING);
200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string& JingleSession::jid() {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return peer_jid_;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const CandidateSessionConfig* JingleSession::candidate_config() {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return candidate_config_.get();
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SessionConfig& JingleSession::config() {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return config_;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::set_config(const SessionConfig& config) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!config_is_set_);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_ = config;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_is_set_ = true;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciStreamChannelFactory* JingleSession::GetTransportChannelFactory() {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return secure_channel_factory_.get();
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciStreamChannelFactory* JingleSession::GetMultiplexedChannelFactory() {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!channel_multiplexer_.get()) {
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    channel_multiplexer_.reset(
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new ChannelMultiplexer(GetTransportChannelFactory(), kMuxChannelName));
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return channel_multiplexer_.get();
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::Close() {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseInternal(OK);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid JingleSession::AddPendingRemoteCandidates(Transport* channel,
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                               const std::string& name) {
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::list<JingleMessage::NamedCandidate>::iterator it =
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      pending_remote_candidates_.begin();
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  while(it != pending_remote_candidates_.end()) {
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (it->name == name) {
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      channel->AddRemoteCandidate(it->candidate);
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      it = pending_remote_candidates_.erase(it);
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      ++it;
2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid JingleSession::CreateChannel(const std::string& name,
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  const ChannelCreatedCallback& callback) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!channels_[name]);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<Transport> channel =
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      session_manager_->transport_factory_->CreateTransport();
2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  channel->Connect(name, this, callback);
2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  AddPendingRemoteCandidates(channel.get(), name);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channels_[name] = channel.release();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::CancelChannelCreation(const std::string& name) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChannelsMap::iterator it = channels_.find(name);
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (it != channels_.end()) {
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK(!it->second->is_connected());
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete it->second;
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK(channels_.find(name) == channels_.end());
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::OnTransportCandidate(Transport* transport,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const cricket::Candidate& candidate) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_candidates_.push_back(JingleMessage::NamedCandidate(
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport->name(), candidate));
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!transport_infos_timer_.IsRunning()) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Delay sending the new candidates in case we get more candidates
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // that we can send in one message.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_infos_timer_.Start(
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::TimeDelta::FromMilliseconds(kTransportInfoSendDelayMs),
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this, &JingleSession::SendTransportInfo);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::OnTransportRouteChange(Transport* transport,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const TransportRoute& route) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event_handler_)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_handler_->OnSessionRouteChange(transport->name(), route);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid JingleSession::OnTransportFailed(Transport* transport) {
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CloseInternal(CHANNEL_CONNECTION_ERROR);
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::OnTransportDeleted(Transport* transport) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChannelsMap::iterator it = channels_.find(transport->name());
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(it->second, transport);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channels_.erase(it);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::SendMessage(const JingleMessage& message) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<IqRequest> request = session_manager_->iq_sender()->SendIq(
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message.ToXml(),
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&JingleSession::OnMessageResponse,
3145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 base::Unretained(this),
3155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 message.action));
3165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  int timeout = kDefaultMessageTimeout;
3185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (message.action == JingleMessage::SESSION_INITIATE ||
3195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      message.action == JingleMessage::SESSION_ACCEPT) {
3205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    timeout = kSessionInitiateAndAcceptTimeout;
3215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (request) {
3235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    request->SetTimeout(base::TimeDelta::FromSeconds(timeout));
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_requests_.insert(request.release());
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to send a "
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << JingleMessage::GetActionName(message.action) << " message";
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::OnMessageResponse(
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JingleMessage::ActionType request_type,
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IqRequest* request,
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const buzz::XmlElement* response) {
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Delete the request from the list of pending requests.
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_requests_.erase(request);
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete request;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Ignore all responses after session was closed.
3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (state_ == CLOSED || state_ == FAILED)
3411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string type_str = JingleMessage::GetActionName(request_type);
3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |response| will be NULL if the request timed out.
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response) {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << type_str << " request timed out.";
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseInternal(SIGNALING_TIMEOUT);
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& type =
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response->Attr(buzz::QName(std::string(), "type"));
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type != "result") {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Received error in response to " << type_str
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << " message: \"" << response->Str()
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << "\". Terminating the session.";
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // TODO(sergeyu): There may be different reasons for error
3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // here. Parse the response stanza to find failure reason.
3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      CloseInternal(PEER_IS_OFFLINE);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void JingleSession::SendTransportInfo() {
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  JingleMessage message(peer_jid_, JingleMessage::TRANSPORT_INFO, session_id_);
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message.candidates.swap(pending_candidates_);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<IqRequest> request = session_manager_->iq_sender()->SendIq(
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      message.ToXml(),
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&JingleSession::OnTransportInfoResponse,
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(this)));
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (request) {
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    request->SetTimeout(base::TimeDelta::FromSeconds(kTransportInfoTimeout));
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    transport_info_requests_.push_back(request.release());
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Failed to send a transport-info message";
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void JingleSession::OnTransportInfoResponse(IqRequest* request,
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            const buzz::XmlElement* response) {
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!transport_info_requests_.empty());
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Consider transport-info requests sent before this one lost and delete
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // corresponding IqRequest objects.
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (transport_info_requests_.front() != request) {
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete transport_info_requests_.front();
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    transport_info_requests_.pop_front();
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delete the |request| itself.
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(request, transport_info_requests_.front());
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete request;
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transport_info_requests_.pop_front();
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ignore transport-info timeouts.
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!response) {
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "transport-info request has timed out.";
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string& type = response->Attr(buzz::QName(std::string(), "type"));
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (type != "result") {
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Received error in response to transport-info message: \""
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               << response->Str() << "\". Terminating the session.";
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CloseInternal(PEER_IS_OFFLINE);
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::OnIncomingMessage(const JingleMessage& message,
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const ReplyCallback& reply_callback) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message.from != peer_jid_) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ignore messages received from a different Jid.
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply_callback.Run(JingleMessageReply::INVALID_SID);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (message.action) {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case JingleMessage::SESSION_ACCEPT:
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnAccept(message, reply_callback);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case JingleMessage::SESSION_INFO:
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnSessionInfo(message, reply_callback);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case JingleMessage::TRANSPORT_INFO:
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reply_callback.Run(JingleMessageReply::NONE);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProcessTransportInfo(message);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case JingleMessage::SESSION_TERMINATE:
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnTerminate(message, reply_callback);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::OnAccept(const JingleMessage& message,
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const ReplyCallback& reply_callback) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ != CONNECTING) {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reply_callback.Run(JingleMessageReply::NONE);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const buzz::XmlElement* auth_message =
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message.description->authenticator_message();
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!auth_message) {
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DLOG(WARNING) << "Received session-accept without authentication message ";
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseInternal(INCOMPATIBLE_PROTOCOL);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!InitializeConfigFromDescription(message.description.get())) {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseInternal(INCOMPATIBLE_PROTOCOL);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In case there is transport information in the accept message.
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessTransportInfo(message);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetState(CONNECTED);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE);
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  authenticator_->ProcessMessage(auth_message, base::Bind(
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &JingleSession::ProcessAuthenticationStep,base::Unretained(this)));
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::OnSessionInfo(const JingleMessage& message,
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const ReplyCallback& reply_callback) {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!message.info.get() ||
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !Authenticator::IsAuthenticatorMessage(message.info.get())) {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply_callback.Run(JingleMessageReply::UNSUPPORTED_INFO);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
484c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if ((state_ != CONNECTED && state_ != AUTHENTICATING) ||
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      authenticator_->state() != Authenticator::WAITING_MESSAGE) {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Received unexpected authenticator message "
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << message.info->Str();
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseInternal(INCOMPATIBLE_PROTOCOL);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reply_callback.Run(JingleMessageReply::NONE);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  authenticator_->ProcessMessage(message.info.get(), base::Bind(
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &JingleSession::ProcessAuthenticationStep, base::Unretained(this)));
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::ProcessTransportInfo(const JingleMessage& message) {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::list<JingleMessage::NamedCandidate>::const_iterator it =
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           message.candidates.begin();
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != message.candidates.end(); ++it) {
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChannelsMap::iterator channel = channels_.find(it->name);
5047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (channel != channels_.end()) {
5057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      channel->second->AddRemoteCandidate(it->candidate);
5067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
5077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // Transport info was received before the channel was created.
5087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // This could happen due to messages being reordered on the wire.
5097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      pending_remote_candidates_.push_back(*it);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::OnTerminate(const JingleMessage& message,
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const ReplyCallback& reply_callback) {
516c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!is_session_active()) {
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Received unexpected session-terminate message.";
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST);
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reply_callback.Run(JingleMessageReply::NONE);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (message.reason) {
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case JingleMessage::SUCCESS:
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (state_ == CONNECTING) {
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        error_ = SESSION_REJECTED;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        error_ = OK;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case JingleMessage::DECLINE:
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_ = AUTHENTICATION_FAILED;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case JingleMessage::CANCEL:
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_ = HOST_OVERLOAD;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case JingleMessage::GENERAL_ERROR:
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_ = CHANNEL_CONNECTION_ERROR;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case JingleMessage::INCOMPATIBLE_PARAMETERS:
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_ = INCOMPATIBLE_PROTOCOL;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_ = UNKNOWN_ERROR;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error_ != OK) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetState(FAILED);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetState(CLOSED);
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JingleSession::InitializeConfigFromDescription(
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ContentDescription* description) {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(description);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!description->config()->GetFinalConfig(&config_)) {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "session-accept does not specify configuration";
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!candidate_config()->IsSupported(config_)) {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "session-accept specifies an invalid configuration";
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::ProcessAuthenticationStep() {
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(authenticator_->state(), Authenticator::PROCESSING_MESSAGE);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (state_ != CONNECTED && state_ != AUTHENTICATING) {
576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(state_ == FAILED || state_ == CLOSED);
577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // The remote host closed the connection while the authentication was being
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // processed asynchronously, nothing to do.
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (authenticator_->state() == Authenticator::MESSAGE_READY) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JingleMessage message(peer_jid_, JingleMessage::SESSION_INFO, session_id_);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message.info = authenticator_->GetNextMessage();
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(message.info.get());
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendMessage(message);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(authenticator_->state(), Authenticator::MESSAGE_READY);
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
590c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // The current JingleSession object can be destroyed by event_handler of
591c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // SetState(AUTHENTICATING) and cause subsequent dereferencing of the this
592c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // pointer to crash.  To protect against it, we run ContinueAuthenticationStep
593c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // asychronously using a weak pointer.
594c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::ThreadTaskRunnerHandle::Get()->PostTask(
595c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    FROM_HERE,
596c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    base::Bind(&JingleSession::ContinueAuthenticationStep,
597c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               weak_factory_.GetWeakPtr()));
598c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
599c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (authenticator_->started()) {
600c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    SetState(AUTHENTICATING);
601c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
602c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
603c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
604c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid JingleSession::ContinueAuthenticationStep() {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (authenticator_->state() == Authenticator::ACCEPTED) {
6061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    OnAuthenticated();
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (authenticator_->state() == Authenticator::REJECTED) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseInternal(AuthRejectionReasonToErrorCode(
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        authenticator_->rejection_reason()));
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid JingleSession::OnAuthenticated() {
6141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  pseudotcp_channel_factory_.reset(new PseudoTcpChannelFactory(this));
6151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  secure_channel_factory_.reset(
6161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new SecureChannelFactory(pseudotcp_channel_factory_.get(),
6171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               authenticator_.get()));
6181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SetState(AUTHENTICATED);
6201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
6211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::CloseInternal(ErrorCode error) {
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (is_session_active()) {
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send session-terminate message with the appropriate error code.
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JingleMessage::Reason reason;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (error) {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case OK:
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reason = JingleMessage::SUCCESS;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SESSION_REJECTED:
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case AUTHENTICATION_FAILED:
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reason = JingleMessage::DECLINE;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case INCOMPATIBLE_PROTOCOL:
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reason = JingleMessage::INCOMPATIBLE_PARAMETERS;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case HOST_OVERLOAD:
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reason = JingleMessage::CANCEL;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reason = JingleMessage::GENERAL_ERROR;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JingleMessage message(peer_jid_, JingleMessage::SESSION_TERMINATE,
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          session_id_);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message.reason = reason;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendMessage(message);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error_ = error;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ != FAILED && state_ != CLOSED) {
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error != OK) {
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetState(FAILED);
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetState(CLOSED);
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JingleSession::SetState(State new_state) {
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_state != state_) {
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(state_, CLOSED);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(state_, FAILED);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_ = new_state;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (event_handler_)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_handler_->OnSessionStateChange(new_state);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
676c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool JingleSession::is_session_active() {
677c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return state_ == CONNECTING || state_ == ACCEPTING || state_ == CONNECTED ||
678c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        state_ == AUTHENTICATING || state_ == AUTHENTICATED;
679c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
680c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace protocol
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
683