// Copyright 2015 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/ice_transport.h"

#include "base/bind.h"
#include "remoting/protocol/channel_authenticator.h"
#include "remoting/protocol/channel_multiplexer.h"
#include "remoting/protocol/pseudotcp_channel_factory.h"
#include "remoting/protocol/secure_channel_factory.h"
#include "remoting/protocol/stream_channel_factory.h"
#include "remoting/protocol/stream_message_pipe_adapter.h"
#include "remoting/protocol/transport_context.h"

namespace remoting {
namespace protocol {

// Delay after candidate creation before sending transport-info message to
// accumulate multiple candidates. This is an optimization to reduce number of
// transport-info messages.
const int kTransportInfoSendDelayMs = 20;

// Name of the multiplexed channel.
static const char kMuxChannelName[] = "mux";

IceTransport::IceTransport(scoped_refptr<TransportContext> transport_context,
                           EventHandler* event_handler)
    : transport_context_(transport_context),
      event_handler_(event_handler),
      weak_factory_(this) {
  transport_context_->set_relay_mode(TransportContext::RelayMode::GTURN);
  transport_context->Prepare();
}

IceTransport::~IceTransport() {
  channel_multiplexer_.reset();
  DCHECK(channels_.empty());
}

void IceTransport::Start(
    Authenticator* authenticator,
    SendTransportInfoCallback send_transport_info_callback) {
  DCHECK(!pseudotcp_channel_factory_);

  send_transport_info_callback_ = std::move(send_transport_info_callback);
  pseudotcp_channel_factory_.reset(new PseudoTcpChannelFactory(this));
  secure_channel_factory_.reset(new SecureChannelFactory(
      pseudotcp_channel_factory_.get(), authenticator));
  message_channel_factory_.reset(new StreamMessageChannelFactoryAdapter(
      secure_channel_factory_.get(),
      base::Bind(&IceTransport::OnChannelError, weak_factory_.GetWeakPtr())));
}

bool IceTransport::ProcessTransportInfo(buzz::XmlElement* transport_info_xml) {
  IceTransportInfo transport_info;
  if (!transport_info.ParseXml(transport_info_xml))
    return false;

  for (auto it = transport_info.ice_credentials.begin();
       it != transport_info.ice_credentials.end(); ++it) {
    ChannelsMap::iterator channel = channels_.find(it->channel);
    if (channel != channels_.end()) {
      channel->second->SetRemoteCredentials(it->ufrag, it->password);
    } else {
      // Transport info was received before the channel was created.
      // This could happen due to messages being reordered on the wire.
      pending_remote_ice_credentials_.push_back(*it);
    }
  }

  for (auto it = transport_info.candidates.begin();
       it != transport_info.candidates.end(); ++it) {
    ChannelsMap::iterator channel = channels_.find(it->name);
    if (channel != channels_.end()) {
      channel->second->AddRemoteCandidate(it->candidate);
    } else {
      // Transport info was received before the channel was created.
      // This could happen due to messages being reordered on the wire.
      pending_remote_candidates_.push_back(*it);
    }
  }

  return true;
}

MessageChannelFactory* IceTransport::GetChannelFactory() {
  return message_channel_factory_.get();
}

MessageChannelFactory* IceTransport::GetMultiplexedChannelFactory() {
  if (!channel_multiplexer_) {
    channel_multiplexer_.reset(
        new ChannelMultiplexer(secure_channel_factory_.get(), kMuxChannelName));
    mux_channel_factory_.reset(new StreamMessageChannelFactoryAdapter(
        channel_multiplexer_.get(),
        base::Bind(&IceTransport::OnChannelError, weak_factory_.GetWeakPtr())));
  }
  return mux_channel_factory_.get();
}

void IceTransport::CreateChannel(const std::string& name,
                                 const ChannelCreatedCallback& callback) {
  DCHECK(!channels_[name]);

  std::unique_ptr<IceTransportChannel> channel(
      new IceTransportChannel(transport_context_));
  channel->Connect(name, this, callback);
  AddPendingRemoteTransportInfo(channel.get());
  channels_[name] = channel.release();
}

void IceTransport::CancelChannelCreation(const std::string& name) {
  ChannelsMap::iterator it = channels_.find(name);
  if (it != channels_.end()) {
    DCHECK(!it->second->is_connected());
    delete it->second;
    DCHECK(channels_.find(name) == channels_.end());
  }
}

void IceTransport::AddPendingRemoteTransportInfo(IceTransportChannel* channel) {
  std::list<IceTransportInfo::IceCredentials>::iterator credentials =
      pending_remote_ice_credentials_.begin();
  while (credentials != pending_remote_ice_credentials_.end()) {
    if (credentials->channel == channel->name()) {
      channel->SetRemoteCredentials(credentials->ufrag, credentials->password);
      credentials = pending_remote_ice_credentials_.erase(credentials);
    } else {
      ++credentials;
    }
  }

  std::list<IceTransportInfo::NamedCandidate>::iterator candidate =
      pending_remote_candidates_.begin();
  while (candidate != pending_remote_candidates_.end()) {
    if (candidate->name == channel->name()) {
      channel->AddRemoteCandidate(candidate->candidate);
      candidate = pending_remote_candidates_.erase(candidate);
    } else {
      ++candidate;
    }
  }
}

void IceTransport::OnChannelIceCredentials(IceTransportChannel* channel,
                                           const std::string& ufrag,
                                           const std::string& password) {
  EnsurePendingTransportInfoMessage();
  pending_transport_info_message_->ice_credentials.push_back(
      IceTransportInfo::IceCredentials(channel->name(), ufrag, password));
}

void IceTransport::OnChannelCandidate(IceTransportChannel* channel,
                                      const cricket::Candidate& candidate) {
  EnsurePendingTransportInfoMessage();
  pending_transport_info_message_->candidates.push_back(
      IceTransportInfo::NamedCandidate(channel->name(), candidate));
}

void IceTransport::OnChannelRouteChange(IceTransportChannel* channel,
                                        const TransportRoute& route) {
  if (event_handler_)
    event_handler_->OnIceTransportRouteChange(channel->name(), route);
}

void IceTransport::OnChannelFailed(IceTransportChannel* channel) {
  event_handler_->OnIceTransportError(CHANNEL_CONNECTION_ERROR);
}

void IceTransport::OnChannelDeleted(IceTransportChannel* channel) {
  ChannelsMap::iterator it = channels_.find(channel->name());
  DCHECK_EQ(it->second, channel);
  channels_.erase(it);
}

void IceTransport::EnsurePendingTransportInfoMessage() {
  // |transport_info_timer_| must be running iff
  // |pending_transport_info_message_| exists.
  DCHECK_EQ(pending_transport_info_message_ != nullptr,
            transport_info_timer_.IsRunning());

  if (!pending_transport_info_message_) {
    pending_transport_info_message_.reset(new IceTransportInfo());
    // Delay sending the new candidates in case we get more candidates
    // that we can send in one message.
    transport_info_timer_.Start(
        FROM_HERE, base::TimeDelta::FromMilliseconds(kTransportInfoSendDelayMs),
        this, &IceTransport::SendTransportInfo);
  }
}

void IceTransport::SendTransportInfo() {
  DCHECK(pending_transport_info_message_);

  std::unique_ptr<buzz::XmlElement> transport_info_xml =
      pending_transport_info_message_->ToXml();
  pending_transport_info_message_.reset();
  send_transport_info_callback_.Run(std::move(transport_info_xml));
}

void IceTransport::OnChannelError(int error) {
  LOG(ERROR) << "Data channel failed, error=" << error;
  event_handler_->OnIceTransportError(CHANNEL_CONNECTION_ERROR);
}

}  // namespace protocol
}  // namespace remoting
