/*
 *  Copyright 2012 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "p2p/base/transport_description_factory.h"

#include <memory>
#include <string>

#include "api/field_trials_view.h"
#include "p2p/base/ice_credentials_iterator.h"
#include "p2p/base/transport_description.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/ssl_fingerprint.h"
#include "rtc_base/ssl_stream_adapter.h"

namespace webrtc {

TransportDescriptionFactory::TransportDescriptionFactory(
    const FieldTrialsView& field_trials)
    : field_trials_(field_trials) {}

TransportDescriptionFactory::~TransportDescriptionFactory() = default;

std::unique_ptr<TransportDescription> TransportDescriptionFactory::CreateOffer(
    const TransportOptions& options,
    const TransportDescription* current_description,
    IceCredentialsIterator* ice_credentials) const {
  auto desc = std::make_unique<TransportDescription>();

  // Generate the ICE credentials if we don't already have them.
  if (!current_description || options.ice_restart) {
    IceParameters credentials = ice_credentials->GetIceCredentials();
    desc->ice_ufrag = credentials.ufrag;
    desc->ice_pwd = credentials.pwd;
  } else {
    desc->ice_ufrag = current_description->ice_ufrag;
    desc->ice_pwd = current_description->ice_pwd;
  }
  desc->AddOption(ICE_OPTION_TRICKLE);
  if (options.enable_ice_renomination) {
    desc->AddOption(ICE_OPTION_RENOMINATION);
  }
  if (options.dtls_handshake_in_stun) {
    desc->AddOption(ICE_OPTION_SPED);
  }

  if (SSLStreamAdapter::IsBoringSsl() &&
      field_trials_.IsEnabled("WebRTC-IceHandshakeDtls") &&
      (!current_description ||
       current_description->HasOption(ICE_OPTION_GOOG_SPED_V1))) {
    desc->AddOption(ICE_OPTION_GOOG_SPED_V1);
  }

  // If we are not trying to establish a secure transport, don't add a
  // fingerprint.
  if (insecure_ && !certificate_) {
    return desc;
  }
  // Fail if we can't create the fingerprint.
  // If we are the initiator set role to "actpass".
  if (!SetSecurityInfo(desc.get(), CONNECTIONROLE_ACTPASS)) {
    return nullptr;
  }

  return desc;
}

std::unique_ptr<TransportDescription> TransportDescriptionFactory::CreateAnswer(
    const TransportDescription* offer,
    const TransportOptions& options,
    bool require_transport_attributes,
    const TransportDescription* current_description,
    IceCredentialsIterator* ice_credentials) const {
  // TODO(juberti): Figure out why we get NULL offers, and fix this upstream.
  if (!offer) {
    RTC_LOG(LS_WARNING) << "Failed to create TransportDescription answer "
                           "because offer is NULL";
    return nullptr;
  }

  auto desc = std::make_unique<TransportDescription>();
  // Generate the ICE credentials if we don't already have them or ice is
  // being restarted.
  if (!current_description || options.ice_restart) {
    IceParameters credentials = ice_credentials->GetIceCredentials();
    desc->ice_ufrag = credentials.ufrag;
    desc->ice_pwd = credentials.pwd;
  } else {
    desc->ice_ufrag = current_description->ice_ufrag;
    desc->ice_pwd = current_description->ice_pwd;
  }
  desc->AddOption(ICE_OPTION_TRICKLE);
  if (options.enable_ice_renomination) {
    desc->AddOption(ICE_OPTION_RENOMINATION);
  }
  if (options.dtls_handshake_in_stun && offer->HasOption(ICE_OPTION_SPED)) {
    desc->AddOption(ICE_OPTION_SPED);
  }

  if (SSLStreamAdapter::IsBoringSsl() &&
      field_trials_.IsEnabled("WebRTC-IceHandshakeDtls") &&
      offer->HasOption(ICE_OPTION_GOOG_SPED_V1) &&
      (current_description == nullptr ||
       current_description->HasOption(ICE_OPTION_GOOG_SPED_V1))) {
    desc->AddOption(ICE_OPTION_GOOG_SPED_V1);
  }

  // Special affordance for testing: Answer without DTLS params
  // if we are insecure without a certificate, or if we are
  // insecure with a non-DTLS offer.
  if ((!certificate_ || !offer->identity_fingerprint) && insecure()) {
    return desc;
  }
  if (!offer->identity_fingerprint) {
    if (require_transport_attributes) {
      // We require DTLS, but the other side didn't offer it. Fail.
      RTC_LOG(LS_WARNING) << "Failed to create TransportDescription answer "
                             "because of incompatible security settings";
      return nullptr;
    }
    // This may be a bundled section, fingerprint may legitimately be missing.
    return desc;
  }
  // Negotiate security params.
  // The offer supports DTLS, so answer with DTLS.
  RTC_CHECK(certificate_);
  ConnectionRole role = CONNECTIONROLE_NONE;
  // If the offer does not constrain the role, go with preference.
  if (offer->connection_role == CONNECTIONROLE_ACTPASS) {
    role = (options.prefer_passive_role) ? CONNECTIONROLE_PASSIVE
                                         : CONNECTIONROLE_ACTIVE;
  } else if (offer->connection_role == CONNECTIONROLE_ACTIVE) {
    role = CONNECTIONROLE_PASSIVE;
  } else if (offer->connection_role == CONNECTIONROLE_PASSIVE) {
    role = CONNECTIONROLE_ACTIVE;
  } else if (offer->connection_role == CONNECTIONROLE_NONE) {
    // This case may be reached if a=setup is not present in the SDP.
    RTC_LOG(LS_WARNING) << "Remote offer connection role is NONE, which is "
                           "a protocol violation";
    role = (options.prefer_passive_role) ? CONNECTIONROLE_PASSIVE
                                         : CONNECTIONROLE_ACTIVE;
  } else {
    RTC_LOG(LS_ERROR) << "Remote offer connection role is " << role
                      << " which is a protocol violation";
    RTC_DCHECK_NOTREACHED();
    return nullptr;
  }
  if (!SetSecurityInfo(desc.get(), role)) {
    return nullptr;
  }
  return desc;
}

bool TransportDescriptionFactory::SetSecurityInfo(TransportDescription* desc,
                                                  ConnectionRole role) const {
  if (!certificate_) {
    RTC_LOG(LS_ERROR) << "Cannot create identity digest with no certificate";
    return false;
  }

  // This digest algorithm is used to produce the a=fingerprint lines in SDP.
  // RFC 4572 Section 5 requires that those lines use the same hash function as
  // the certificate's signature, which is what CreateFromCertificate does.
  desc->identity_fingerprint =
      SSLFingerprint::CreateFromCertificate(*certificate_);
  if (!desc->identity_fingerprint) {
    return false;
  }

  // Assign security role.
  desc->connection_role = role;
  return true;
}

}  // namespace webrtc
