// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/protocol/jingle_session.h"

#include <stdint.h>

#include <limits>
#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "remoting/base/constants.h"
#include "remoting/protocol/authenticator.h"
#include "remoting/protocol/content_description.h"
#include "remoting/protocol/jingle_messages.h"
#include "remoting/protocol/jingle_session_manager.h"
#include "remoting/protocol/session_config.h"
#include "remoting/protocol/session_plugin.h"
#include "remoting/protocol/transport.h"
#include "remoting/signaling/iq_sender.h"
#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
#include "third_party/libjingle_xmpp/xmpp/constants.h"
#include "third_party/webrtc/api/candidate.h"

using buzz::XmlElement;

namespace remoting {
namespace protocol {

namespace {

// Timeouts have been temporarily increased for testing.
// TODO(rkjnsn): Revert default and session timeouts once done with testing.

// How long we should wait for a response from the other end. This value is used
// for all requests except |transport-info|.
// const int kDefaultMessageTimeout = 10;
const int kDefaultMessageTimeout = 35;  // For testing

// During a reconnection, it usually takes longer for the peer to respond due to
// pending messages in the channel from the previous session.  From experiment,
// it can take up to 20s for the session to reconnect. To make it safe, setting
// the timeout to 30s.
// const int kSessionInitiateAndAcceptTimeout = kDefaultMessageTimeout * 3;
const int kSessionInitiateAndAcceptTimeout = 45;  // For testing

// Timeout for the transport-info messages.
const int kTransportInfoTimeout = 10 * 60;

// Special value for an invalid sequential ID for an incoming IQ.
const int kInvalid = -1;

// Special value indicating that any sequential ID is valid for the next
// incoming IQ.
const int kAny = -1;

ErrorCode AuthRejectionReasonToErrorCode(
    Authenticator::RejectionReason reason) {
  switch (reason) {
    case Authenticator::INVALID_CREDENTIALS:
      return AUTHENTICATION_FAILED;
    case Authenticator::PROTOCOL_ERROR:
      return INCOMPATIBLE_PROTOCOL;
    case Authenticator::INVALID_ACCOUNT:
      return INVALID_ACCOUNT;
    case Authenticator::TOO_MANY_CONNECTIONS:
      return SESSION_REJECTED;
    case Authenticator::REJECTED_BY_USER:
      return SESSION_REJECTED;
  }
  NOTREACHED();
  return UNKNOWN_ERROR;
}

// Extracts a sequential id from the id attribute of the IQ stanza.
int GetSequentialId(const std::string& id) {
  std::vector<std::string> tokens =
      SplitString(id, "_", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  // Legacy endpoints does not encode the IQ ordering in the ID attribute
  if (tokens.size() != 2) {
    return kInvalid;
  }

  int result = kInvalid;
  if (!base::StringToInt(tokens[1], &result)) {
    return kInvalid;
  }
  return result;
}

}  // namespace

// A Queue that sorts incoming messages and returns them in the ascending order
// of sequence ids. The sequence id can be extracted from the ID attribute of
// an IQ stanza, which have the following format <opaque_string>_<sequence_id>.
//
// Background:
// The chromoting signaling channel does not guarantee that the incoming IQs are
// delivered in the order that it is sent.
//
// This behavior leads to transient session setup failures.  For instance,
// a <transport-info> that is sent after a <session-info> message is sometimes
// delivered to the client out of order, causing the client to close the
// session due to an unexpected request.
class JingleSession::OrderedMessageQueue {
 public:
  OrderedMessageQueue() = default;
  ~OrderedMessageQueue() = default;

  // Returns the list of messages ordered by their sequential IDs.
  std::vector<PendingMessage> OnIncomingMessage(
      const std::string& id,
      PendingMessage&& pending_message);

  // Sets the initial ID of the session initiate message.
  void SetInitialId(const std::string& id);

 private:
  // Implements an ordered list by using map with the |sequence_id| as the key,
  // so that |queue_| is always sorted by |sequence_id|.
  std::map<int, PendingMessage> queue_;

  int next_incoming_ = kAny;

  DISALLOW_COPY_AND_ASSIGN(OrderedMessageQueue);
};

std::vector<JingleSession::PendingMessage>
JingleSession::OrderedMessageQueue::OnIncomingMessage(
    const std::string& id,
    JingleSession::PendingMessage&& message) {
  std::vector<JingleSession::PendingMessage> result;
  int current = GetSequentialId(id);
  // If there is no sequencing order encoded in the id, just return the
  // message.
  if (current == kInvalid) {
    result.push_back(std::move(message));
    return result;
  }

  if (next_incoming_ == kAny) {
    next_incoming_ = current;
  }

  // Ensure there are no duplicate sequence ids.
  DCHECK_GE(current, next_incoming_);
  DCHECK(queue_.find(current) == queue_.end());

  queue_.insert(std::make_pair(current, std::move(message)));

  auto it = queue_.begin();
  while (it != queue_.end() && it->first == next_incoming_) {
    result.push_back(std::move(it->second));
    it = queue_.erase(it);
    next_incoming_++;
  }

  if (current - next_incoming_ >= 3) {
    LOG(WARNING) << "Multiple messages are missing: expected= "
                 << next_incoming_ << " current= " << current;
  }
  return result;
};

void JingleSession::OrderedMessageQueue::SetInitialId(const std::string& id) {
  int current = GetSequentialId(id);
  if (current != kInvalid)
    next_incoming_ = current + 1;
}

JingleSession::PendingMessage::PendingMessage() = default;
JingleSession::PendingMessage::PendingMessage(PendingMessage&& moved) = default;
JingleSession::PendingMessage::PendingMessage(
    std::unique_ptr<JingleMessage> message,
    const ReplyCallback& reply_callback)
    : message(std::move(message)), reply_callback(reply_callback) {}
JingleSession::PendingMessage::~PendingMessage() = default;

JingleSession::PendingMessage& JingleSession::PendingMessage::operator=(
    PendingMessage&& moved) = default;

JingleSession::JingleSession(JingleSessionManager* session_manager)
    : session_manager_(session_manager),
      event_handler_(nullptr),
      state_(INITIALIZING),
      error_(OK),
      message_queue_(new OrderedMessageQueue),
      weak_factory_(this) {}

JingleSession::~JingleSession() {
  DCHECK(thread_checker_.CalledOnValidThread());
  session_manager_->SessionDestroyed(this);
}

void JingleSession::SetEventHandler(Session::EventHandler* event_handler) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(event_handler);
  event_handler_ = event_handler;
}

ErrorCode JingleSession::error() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return error_;
}

void JingleSession::StartConnection(
    const SignalingAddress& peer_address,
    std::unique_ptr<Authenticator> authenticator) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(authenticator.get());
  DCHECK_EQ(authenticator->state(), Authenticator::MESSAGE_READY);

  peer_address_ = peer_address;
  authenticator_ = std::move(authenticator);

  // Generate random session ID. There are usually not more than 1
  // concurrent session per host, so a random 64-bit integer provides
  // enough entropy. In the worst case connection will fail when two
  // clients generate the same session ID concurrently.
  session_id_ = base::NumberToString(
      base::RandGenerator(std::numeric_limits<uint64_t>::max()));

  // Delay sending session-initiate message to ensure SessionPlugin can be
  // attached before the message.
  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
      base::Bind(&JingleSession::SendSessionInitiateMessage,
                 weak_factory_.GetWeakPtr()));

  SetState(CONNECTING);
}

void JingleSession::InitializeIncomingConnection(
    const std::string& message_id,
    const JingleMessage& initiate_message,
    std::unique_ptr<Authenticator> authenticator) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(initiate_message.description.get());
  DCHECK(authenticator.get());
  DCHECK_EQ(authenticator->state(), Authenticator::WAITING_MESSAGE);

  peer_address_ = initiate_message.from;
  authenticator_ = std::move(authenticator);
  session_id_ = initiate_message.sid;
  message_queue_->SetInitialId(message_id);

  SetState(ACCEPTING);

  config_ =
      SessionConfig::SelectCommon(initiate_message.description->config(),
                                  session_manager_->protocol_config_.get());
  if (!config_) {
    LOG(WARNING) << "Rejecting connection from " << peer_address_.id()
                 << " because no compatible configuration has been found.";
    Close(INCOMPATIBLE_PROTOCOL);
    return;
  }
}

void JingleSession::AcceptIncomingConnection(
    const JingleMessage& initiate_message) {
  DCHECK(config_);

  ProcessIncomingPluginMessage(initiate_message);
  // Process the first authentication message.
  const buzz::XmlElement* first_auth_message =
      initiate_message.description->authenticator_message();

  if (!first_auth_message) {
    Close(INCOMPATIBLE_PROTOCOL);
    return;
  }

  DCHECK_EQ(authenticator_->state(), Authenticator::WAITING_MESSAGE);
  // |authenticator_| is owned, so Unretained() is safe here.
  authenticator_->ProcessMessage(first_auth_message, base::Bind(
      &JingleSession::ContinueAcceptIncomingConnection,
      base::Unretained(this)));
}

void JingleSession::ContinueAcceptIncomingConnection() {
  DCHECK_NE(authenticator_->state(), Authenticator::PROCESSING_MESSAGE);
  if (authenticator_->state() == Authenticator::REJECTED) {
    Close(AuthRejectionReasonToErrorCode(authenticator_->rejection_reason()));
    return;
  }

  // Send the session-accept message.
  std::unique_ptr<JingleMessage> message(new JingleMessage(
      peer_address_, JingleMessage::SESSION_ACCEPT, session_id_));

  std::unique_ptr<buzz::XmlElement> auth_message;
  if (authenticator_->state() == Authenticator::MESSAGE_READY)
    auth_message = authenticator_->GetNextMessage();

  message->description.reset(new ContentDescription(
      CandidateSessionConfig::CreateFrom(*config_), std::move(auth_message)));
  SendMessage(std::move(message));

  // Update state.
  SetState(ACCEPTED);

  if (authenticator_->state() == Authenticator::ACCEPTED) {
    OnAuthenticated();
  } else {
    DCHECK_EQ(authenticator_->state(), Authenticator::WAITING_MESSAGE);
    if (authenticator_->started()) {
      SetState(AUTHENTICATING);
    }
  }
}

const std::string& JingleSession::jid() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return peer_address_.id();
}

const SessionConfig& JingleSession::config() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return *config_;
}

void JingleSession::SetTransport(Transport* transport) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!transport_);
  DCHECK(transport);
  transport_ = transport;
}

void JingleSession::SendTransportInfo(
    std::unique_ptr<buzz::XmlElement> transport_info) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_EQ(state_, AUTHENTICATED);

  std::unique_ptr<JingleMessage> message(new JingleMessage(
      peer_address_, JingleMessage::TRANSPORT_INFO, session_id_));
  message->transport_info = std::move(transport_info);
  AddPluginAttachments(message.get());

  std::unique_ptr<buzz::XmlElement> stanza = message->ToXml();
  stanza->AddAttr(buzz::QN_ID, GetNextOutgoingId());

  auto request = session_manager_->iq_sender()->SendIq(
      std::move(stanza), base::Bind(&JingleSession::OnTransportInfoResponse,
                                    base::Unretained(this)));
  if (request) {
    request->SetTimeout(base::TimeDelta::FromSeconds(kTransportInfoTimeout));
    transport_info_requests_.push_back(std::move(request));
  } else {
    LOG(ERROR) << "Failed to send a transport-info message";
  }
}

void JingleSession::Close(protocol::ErrorCode error) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (is_session_active()) {
    // Send session-terminate message with the appropriate error code.
    JingleMessage::Reason reason;
    switch (error) {
      case OK:
        reason = JingleMessage::SUCCESS;
        break;
      case SESSION_REJECTED:
      case AUTHENTICATION_FAILED:
      case INVALID_ACCOUNT:
        reason = JingleMessage::DECLINE;
        break;
      case INCOMPATIBLE_PROTOCOL:
        reason = JingleMessage::INCOMPATIBLE_PARAMETERS;
        break;
      case HOST_OVERLOAD:
        reason = JingleMessage::CANCEL;
        break;
      case MAX_SESSION_LENGTH:
        reason = JingleMessage::EXPIRED;
        break;
      case HOST_CONFIGURATION_ERROR:
        reason = JingleMessage::FAILED_APPLICATION;
        break;
      default:
        reason = JingleMessage::GENERAL_ERROR;
    }

    std::unique_ptr<JingleMessage> message(new JingleMessage(
        peer_address_, JingleMessage::SESSION_TERMINATE, session_id_));
    message->reason = reason;
    message->error_code = error;
    SendMessage(std::move(message));
  }

  error_ = error;

  if (state_ != FAILED && state_ != CLOSED) {
    if (error != OK) {
      SetState(FAILED);
    } else {
      SetState(CLOSED);
    }
  }
}

void JingleSession::AddPlugin(SessionPlugin* plugin) {
  DCHECK(plugin);
  plugins_.push_back(plugin);
}

void JingleSession::SendMessage(std::unique_ptr<JingleMessage> message) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (message->action != JingleMessage::SESSION_TERMINATE) {
    // When the host accepts session-initiate message from a client JID it
    // doesn't recognize it sends session-terminate without session-accept.
    // Attaching plugin information to this session-terminate message may lead
    // to privacy issues (e.g. leaking Windows version to someone who does not
    // own the host). So a simply approach is to ignore plugins when sending
    // SESSION_TERMINATE message.
    AddPluginAttachments(message.get());
  }
  std::unique_ptr<buzz::XmlElement> stanza = message->ToXml();
  stanza->AddAttr(buzz::QN_ID, GetNextOutgoingId());

  auto request = session_manager_->iq_sender()->SendIq(
      std::move(stanza), base::Bind(&JingleSession::OnMessageResponse,
                                    base::Unretained(this), message->action));

  int timeout = kDefaultMessageTimeout;
  if (message->action == JingleMessage::SESSION_INITIATE ||
      message->action == JingleMessage::SESSION_ACCEPT) {
    timeout = kSessionInitiateAndAcceptTimeout;
  }
  if (request) {
    request->SetTimeout(base::TimeDelta::FromSeconds(timeout));
    pending_requests_.push_back(std::move(request));
  } else {
    LOG(ERROR) << "Failed to send a "
               << JingleMessage::GetActionName(message->action) << " message";
  }
}

void JingleSession::OnMessageResponse(
    JingleMessage::ActionType request_type,
    IqRequest* request,
    const buzz::XmlElement* response) {
  DCHECK(thread_checker_.CalledOnValidThread());

  // Delete the request from the list of pending requests.
  pending_requests_.erase(
      std::find_if(pending_requests_.begin(), pending_requests_.end(),
                   [request](const std::unique_ptr<IqRequest>& ptr) {
                     return ptr.get() == request;
                   }));

  // Ignore all responses after session was closed.
  if (state_ == CLOSED || state_ == FAILED)
    return;

  std::string type_str = JingleMessage::GetActionName(request_type);

  // |response| will be nullptr if the request timed out.
  if (!response) {
    LOG(ERROR) << type_str << " request timed out.";
    Close(SIGNALING_TIMEOUT);
    return;
  } else {
    const std::string& type =
        response->Attr(buzz::QName(std::string(), "type"));
    if (type != "result") {
      LOG(ERROR) << "Received error in response to " << type_str
                 << " message: \"" << response->Str()
                 << "\". Terminating the session.";

      // TODO(sergeyu): There may be different reasons for error
      // here. Parse the response stanza to find failure reason.
      Close(PEER_IS_OFFLINE);
    }
  }
}

void JingleSession::OnTransportInfoResponse(IqRequest* request,
                                            const buzz::XmlElement* response) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!transport_info_requests_.empty());

  // Consider transport-info requests sent before this one lost and delete
  // all IqRequest objects in front of |request|.
  auto request_it = std::find_if(
      transport_info_requests_.begin(), transport_info_requests_.end(),
      [request](const std::unique_ptr<IqRequest>& ptr) {
        return ptr.get() == request;
      });
  DCHECK(request_it != transport_info_requests_.end());
  transport_info_requests_.erase(transport_info_requests_.begin(),
                                 request_it + 1);

  // Ignore transport-info timeouts.
  if (!response) {
    LOG(ERROR) << "transport-info request has timed out.";
    return;
  }

  const std::string& type = response->Attr(buzz::QName(std::string(), "type"));
  if (type != "result") {
    LOG(ERROR) << "Received error in response to transport-info message: \""
               << response->Str() << "\". Terminating the session.";
    Close(PEER_IS_OFFLINE);
  }
}

void JingleSession::OnIncomingMessage(const std::string& id,
                                      std::unique_ptr<JingleMessage> message,
                                      const ReplyCallback& reply_callback) {
  ProcessIncomingPluginMessage(*message);
  std::vector<PendingMessage> ordered = message_queue_->OnIncomingMessage(
      id, PendingMessage{std::move(message), reply_callback});
  base::WeakPtr<JingleSession> self = weak_factory_.GetWeakPtr();
  for (auto& message : ordered) {
    ProcessIncomingMessage(std::move(message.message), message.reply_callback);
    if (!self)
      return;
  }
}

void JingleSession::ProcessIncomingMessage(
    std::unique_ptr<JingleMessage> message,
    const ReplyCallback& reply_callback) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (peer_address_ != message->from) {
    // Ignore messages received from a different Jid.
    reply_callback.Run(JingleMessageReply::INVALID_SID);
    return;
  }

  switch (message->action) {
    case JingleMessage::SESSION_ACCEPT:
      OnAccept(std::move(message), reply_callback);
      break;

    case JingleMessage::SESSION_INFO:
      OnSessionInfo(std::move(message), reply_callback);
      break;

    case JingleMessage::TRANSPORT_INFO:
      OnTransportInfo(std::move(message), reply_callback);
      break;

    case JingleMessage::SESSION_TERMINATE:
      OnTerminate(std::move(message), reply_callback);
      break;

    default:
      reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST);
  }
}

void JingleSession::OnAccept(std::unique_ptr<JingleMessage> message,
                             const ReplyCallback& reply_callback) {
  if (state_ != CONNECTING) {
    reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST);
    return;
  }

  reply_callback.Run(JingleMessageReply::NONE);

  const buzz::XmlElement* auth_message =
      message->description->authenticator_message();
  if (!auth_message) {
    DLOG(WARNING) << "Received session-accept without authentication message ";
    Close(INCOMPATIBLE_PROTOCOL);
    return;
  }

  if (!InitializeConfigFromDescription(message->description.get())) {
    Close(INCOMPATIBLE_PROTOCOL);
    return;
  }

  SetState(ACCEPTED);

  DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE);
  authenticator_->ProcessMessage(
      auth_message, base::Bind(&JingleSession::ProcessAuthenticationStep,
                               base::Unretained(this)));
}

void JingleSession::OnSessionInfo(std::unique_ptr<JingleMessage> message,
                                  const ReplyCallback& reply_callback) {
  if (!message->info.get() ||
      !Authenticator::IsAuthenticatorMessage(message->info.get())) {
    reply_callback.Run(JingleMessageReply::UNSUPPORTED_INFO);
    return;
  }

  if ((state_ != ACCEPTED && state_ != AUTHENTICATING) ||
      authenticator_->state() != Authenticator::WAITING_MESSAGE) {
    LOG(WARNING) << "Received unexpected authenticator message "
                 << message->info->Str();
    reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST);
    Close(INCOMPATIBLE_PROTOCOL);
    return;
  }

  reply_callback.Run(JingleMessageReply::NONE);

  authenticator_->ProcessMessage(
      message->info.get(), base::Bind(&JingleSession::ProcessAuthenticationStep,
                                      base::Unretained(this)));
}

void JingleSession::OnTransportInfo(std::unique_ptr<JingleMessage> message,
                                    const ReplyCallback& reply_callback) {
  if (!message->transport_info) {
    reply_callback.Run(JingleMessageReply::BAD_REQUEST);
    return;
  }

  if (state_ == AUTHENTICATING) {
    pending_transport_info_.push_back(
        PendingMessage{std::move(message), reply_callback});
  } else if (state_ == AUTHENTICATED) {
    reply_callback.Run(
        transport_->ProcessTransportInfo(message->transport_info.get())
            ? JingleMessageReply::NONE
            : JingleMessageReply::BAD_REQUEST);
  } else {
    LOG(ERROR) << "Received unexpected transport-info message.";
    reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST);
  }
}

void JingleSession::OnTerminate(std::unique_ptr<JingleMessage> message,
                                const ReplyCallback& reply_callback) {
  if (!is_session_active()) {
    LOG(WARNING) << "Received unexpected session-terminate message.";
    reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST);
    return;
  }

  reply_callback.Run(JingleMessageReply::NONE);

  error_ = message->error_code;
  if (error_ == UNKNOWN_ERROR) {
    // get error code from message.reason for compatibility with older versions
    // that do not add <error-code>.
    switch (message->reason) {
      case JingleMessage::SUCCESS:
        if (state_ == CONNECTING) {
          error_ = SESSION_REJECTED;
        } else {
          error_ = OK;
        }
        break;
      case JingleMessage::DECLINE:
        error_ = AUTHENTICATION_FAILED;
        break;
      case JingleMessage::CANCEL:
        error_ = HOST_OVERLOAD;
        break;
      case JingleMessage::EXPIRED:
        error_ = MAX_SESSION_LENGTH;
        break;
      case JingleMessage::INCOMPATIBLE_PARAMETERS:
        error_ = INCOMPATIBLE_PROTOCOL;
        break;
      case JingleMessage::FAILED_APPLICATION:
        error_ = HOST_CONFIGURATION_ERROR;
        break;
      case JingleMessage::GENERAL_ERROR:
        error_ = CHANNEL_CONNECTION_ERROR;
        break;
      default:
        error_ = UNKNOWN_ERROR;
    }
  } else if (error_ == SESSION_REJECTED) {
    // For backward compatibility, we still use AUTHENTICATION_FAILED for
    // SESSION_REJECTED error.
    // TODO(zijiehe): Handle SESSION_REJECTED error in WebApp. Tracked by
    // http://crbug.com/618036.
    error_ = AUTHENTICATION_FAILED;
  }

  if (error_ != OK) {
    SetState(FAILED);
  } else {
    SetState(CLOSED);
  }
}

bool JingleSession::InitializeConfigFromDescription(
    const ContentDescription* description) {
  DCHECK(description);
  config_ = SessionConfig::GetFinalConfig(description->config());
  if (!config_) {
    LOG(ERROR) << "session-accept does not specify configuration";
    return false;
  }
  if (!session_manager_->protocol_config_->IsSupported(*config_)) {
    LOG(ERROR) << "session-accept specifies an invalid configuration";
    return false;
  }

  return true;
}

void JingleSession::ProcessAuthenticationStep() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_NE(authenticator_->state(), Authenticator::PROCESSING_MESSAGE);

  if (state_ != ACCEPTED && state_ != AUTHENTICATING) {
    DCHECK(state_ == FAILED || state_ == CLOSED);
    // The remote host closed the connection while the authentication was being
    // processed asynchronously, nothing to do.
    return;
  }

  if (authenticator_->state() == Authenticator::MESSAGE_READY) {
    std::unique_ptr<JingleMessage> message(new JingleMessage(
        peer_address_, JingleMessage::SESSION_INFO, session_id_));
    message->info = authenticator_->GetNextMessage();
    DCHECK(message->info.get());
    SendMessage(std::move(message));
  }
  DCHECK_NE(authenticator_->state(), Authenticator::MESSAGE_READY);

  if (authenticator_->started()) {
    base::WeakPtr<JingleSession> self = weak_factory_.GetWeakPtr();
    SetState(AUTHENTICATING);
    if (!self)
      return;
  }

  if (authenticator_->state() == Authenticator::ACCEPTED) {
    OnAuthenticated();
  } else if (authenticator_->state() == Authenticator::REJECTED) {
    Close(AuthRejectionReasonToErrorCode(
        authenticator_->rejection_reason()));
  }
}

void JingleSession::OnAuthenticated() {
  transport_->Start(authenticator_.get(),
                    base::Bind(&JingleSession::SendTransportInfo,
                               weak_factory_.GetWeakPtr()));

  base::WeakPtr<JingleSession> self = weak_factory_.GetWeakPtr();
  std::vector<PendingMessage> messages_to_process;
  std::swap(messages_to_process, pending_transport_info_);
  for (auto& message : messages_to_process) {
    message.reply_callback.Run(
        transport_->ProcessTransportInfo(message.message->transport_info.get())
            ? JingleMessageReply::NONE
            : JingleMessageReply::BAD_REQUEST);
    if (!self)
      return;
  }

  SetState(AUTHENTICATED);
}

void JingleSession::SetState(State new_state) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (new_state != state_) {
    DCHECK_NE(state_, CLOSED);
    DCHECK_NE(state_, FAILED);

    state_ = new_state;
    if (event_handler_)
      event_handler_->OnSessionStateChange(new_state);
  }
}

bool JingleSession::is_session_active() {
  return state_ == CONNECTING || state_ == ACCEPTING || state_ == ACCEPTED ||
        state_ == AUTHENTICATING || state_ == AUTHENTICATED;
}

void JingleSession::ProcessIncomingPluginMessage(
    const JingleMessage& message) {
  if (!message.attachments) {
    return;
  }
  for (auto* plugin : plugins_) {
    plugin->OnIncomingMessage(*(message.attachments));
  }
}

void JingleSession::AddPluginAttachments(JingleMessage* message) {
  DCHECK(message);
  for (auto* plugin : plugins_) {
    std::unique_ptr<XmlElement> attachment = plugin->GetNextMessage();
    if (attachment) {
      message->AddAttachment(std::move(attachment));
    }
  }
}

void JingleSession::SendSessionInitiateMessage() {
  if (state_ != CONNECTING) {
    return;
  }
  std::unique_ptr<JingleMessage> message(new JingleMessage(
      peer_address_, JingleMessage::SESSION_INITIATE, session_id_));
  message->initiator =
      session_manager_->signal_strategy_->GetLocalAddress().jid();
  message->description.reset(new ContentDescription(
      session_manager_->protocol_config_->Clone(),
      authenticator_->GetNextMessage()));
  SendMessage(std::move(message));
}

std::string JingleSession::GetNextOutgoingId() {
  return outgoing_id_prefix_ + "_" + base::IntToString(++next_outgoing_id_);
}

}  // namespace protocol
}  // namespace remoting
