/*
 *  Copyright 2004 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 "webrtc/pc/mediasession.h"

#include <algorithm>  // For std::find_if, std::sort.
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <unordered_map>
#include <utility>

#include "webrtc/base/helpers.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/media/base/cryptoparams.h"
#include "webrtc/media/base/mediaconstants.h"
#include "webrtc/p2p/base/p2pconstants.h"
#include "webrtc/pc/channelmanager.h"
#include "webrtc/pc/srtpfilter.h"

#ifdef HAVE_SCTP
#include "webrtc/media/sctp/sctpdataengine.h"
#else
static const uint32_t kMaxSctpSid = 1023;
#endif

namespace {
const char kInline[] = "inline:";

void GetSupportedCryptoSuiteNames(void (*func)(std::vector<int>*),
                                  std::vector<std::string>* names) {
#ifdef HAVE_SRTP
  std::vector<int> crypto_suites;
  func(&crypto_suites);
  for (const auto crypto : crypto_suites) {
    names->push_back(rtc::SrtpCryptoSuiteToName(crypto));
  }
#endif
}
}  // namespace

namespace cricket {


// RTP Profile names
// http://www.iana.org/assignments/rtp-parameters/rtp-parameters.xml
// RFC4585
const char kMediaProtocolAvpf[] = "RTP/AVPF";
// RFC5124
const char kMediaProtocolDtlsSavpf[] = "UDP/TLS/RTP/SAVPF";

// We always generate offers with "UDP/TLS/RTP/SAVPF" when using DTLS-SRTP,
// but we tolerate "RTP/SAVPF" in offers we receive, for compatibility.
const char kMediaProtocolSavpf[] = "RTP/SAVPF";

const char kMediaProtocolRtpPrefix[] = "RTP/";

const char kMediaProtocolSctp[] = "SCTP";
const char kMediaProtocolDtlsSctp[] = "DTLS/SCTP";
const char kMediaProtocolUdpDtlsSctp[] = "UDP/DTLS/SCTP";
const char kMediaProtocolTcpDtlsSctp[] = "TCP/DTLS/SCTP";

static bool IsMediaContentOfType(const ContentInfo* content,
                                 MediaType media_type) {
  if (!IsMediaContent(content)) {
    return false;
  }

  const MediaContentDescription* mdesc =
      static_cast<const MediaContentDescription*>(content->description);
  return mdesc && mdesc->type() == media_type;
}

static bool CreateCryptoParams(int tag, const std::string& cipher,
                               CryptoParams *out) {
  std::string key;
  key.reserve(SRTP_MASTER_KEY_BASE64_LEN);

  if (!rtc::CreateRandomString(SRTP_MASTER_KEY_BASE64_LEN, &key)) {
    return false;
  }
  out->tag = tag;
  out->cipher_suite = cipher;
  out->key_params = kInline;
  out->key_params += key;
  return true;
}

#ifdef HAVE_SRTP
static bool AddCryptoParams(const std::string& cipher_suite,
                            CryptoParamsVec *out) {
  int size = static_cast<int>(out->size());

  out->resize(size + 1);
  return CreateCryptoParams(size, cipher_suite, &out->at(size));
}

void AddMediaCryptos(const CryptoParamsVec& cryptos,
                     MediaContentDescription* media) {
  for (CryptoParamsVec::const_iterator crypto = cryptos.begin();
       crypto != cryptos.end(); ++crypto) {
    media->AddCrypto(*crypto);
  }
}

bool CreateMediaCryptos(const std::vector<std::string>& crypto_suites,
                        MediaContentDescription* media) {
  CryptoParamsVec cryptos;
  for (std::vector<std::string>::const_iterator it = crypto_suites.begin();
       it != crypto_suites.end(); ++it) {
    if (!AddCryptoParams(*it, &cryptos)) {
      return false;
    }
  }
  AddMediaCryptos(cryptos, media);
  return true;
}
#endif

const CryptoParamsVec* GetCryptos(const MediaContentDescription* media) {
  if (!media) {
    return NULL;
  }
  return &media->cryptos();
}

bool FindMatchingCrypto(const CryptoParamsVec& cryptos,
                        const CryptoParams& crypto,
                        CryptoParams* out) {
  for (CryptoParamsVec::const_iterator it = cryptos.begin();
       it != cryptos.end(); ++it) {
    if (crypto.Matches(*it)) {
      *out = *it;
      return true;
    }
  }
  return false;
}

// For audio, HMAC 32 is prefered because of the low overhead.
void GetSupportedAudioCryptoSuites(std::vector<int>* crypto_suites) {
#ifdef HAVE_SRTP
  crypto_suites->push_back(rtc::SRTP_AES128_CM_SHA1_32);
  crypto_suites->push_back(rtc::SRTP_AES128_CM_SHA1_80);
#endif
}

void GetSupportedAudioCryptoSuiteNames(
    std::vector<std::string>* crypto_suite_names) {
  GetSupportedCryptoSuiteNames(GetSupportedAudioCryptoSuites,
                               crypto_suite_names);
}

void GetSupportedVideoCryptoSuites(std::vector<int>* crypto_suites) {
  GetDefaultSrtpCryptoSuites(crypto_suites);
}

void GetSupportedVideoCryptoSuiteNames(
    std::vector<std::string>* crypto_suite_names) {
  GetSupportedCryptoSuiteNames(GetSupportedVideoCryptoSuites,
                               crypto_suite_names);
}

void GetSupportedDataCryptoSuites(std::vector<int>* crypto_suites) {
  GetDefaultSrtpCryptoSuites(crypto_suites);
}

void GetSupportedDataCryptoSuiteNames(
    std::vector<std::string>* crypto_suite_names) {
  GetSupportedCryptoSuiteNames(GetSupportedDataCryptoSuites,
                               crypto_suite_names);
}

void GetDefaultSrtpCryptoSuites(std::vector<int>* crypto_suites) {
#ifdef HAVE_SRTP
  crypto_suites->push_back(rtc::SRTP_AES128_CM_SHA1_80);
#endif
}

void GetDefaultSrtpCryptoSuiteNames(
    std::vector<std::string>* crypto_suite_names) {
  GetSupportedCryptoSuiteNames(GetDefaultSrtpCryptoSuites, crypto_suite_names);
}

// For video support only 80-bit SHA1 HMAC. For audio 32-bit HMAC is
// tolerated unless bundle is enabled because it is low overhead. Pick the
// crypto in the list that is supported.
static bool SelectCrypto(const MediaContentDescription* offer,
                         bool bundle,
                         CryptoParams *crypto) {
  bool audio = offer->type() == MEDIA_TYPE_AUDIO;
  const CryptoParamsVec& cryptos = offer->cryptos();

  for (CryptoParamsVec::const_iterator i = cryptos.begin();
       i != cryptos.end(); ++i) {
    if (rtc::CS_AES_CM_128_HMAC_SHA1_80 == i->cipher_suite ||
        (rtc::CS_AES_CM_128_HMAC_SHA1_32 == i->cipher_suite && audio &&
         !bundle)) {
      return CreateCryptoParams(i->tag, i->cipher_suite, crypto);
    }
  }
  return false;
}

// Generate random SSRC values that are not already present in |params_vec|.
// The generated values are added to |ssrcs|.
// |num_ssrcs| is the number of the SSRC will be generated.
static void GenerateSsrcs(const StreamParamsVec& params_vec,
                          int num_ssrcs,
                          std::vector<uint32_t>* ssrcs) {
  for (int i = 0; i < num_ssrcs; i++) {
    uint32_t candidate;
    do {
      candidate = rtc::CreateRandomNonZeroId();
    } while (GetStreamBySsrc(params_vec, candidate) ||
             std::count(ssrcs->begin(), ssrcs->end(), candidate) > 0);
    ssrcs->push_back(candidate);
  }
}

// Returns false if we exhaust the range of SIDs.
static bool GenerateSctpSid(const StreamParamsVec& params_vec, uint32_t* sid) {
  if (params_vec.size() > kMaxSctpSid) {
    LOG(LS_WARNING) <<
        "Could not generate an SCTP SID: too many SCTP streams.";
    return false;
  }
  while (true) {
    uint32_t candidate = rtc::CreateRandomNonZeroId() % kMaxSctpSid;
    if (!GetStreamBySsrc(params_vec, candidate)) {
      *sid = candidate;
      return true;
    }
  }
}

static bool GenerateSctpSids(const StreamParamsVec& params_vec,
                             std::vector<uint32_t>* sids) {
  uint32_t sid;
  if (!GenerateSctpSid(params_vec, &sid)) {
    LOG(LS_WARNING) << "Could not generated an SCTP SID.";
    return false;
  }
  sids->push_back(sid);
  return true;
}

// Finds all StreamParams of all media types and attach them to stream_params.
static void GetCurrentStreamParams(const SessionDescription* sdesc,
                                   StreamParamsVec* stream_params) {
  if (!sdesc)
    return;

  const ContentInfos& contents = sdesc->contents();
  for (ContentInfos::const_iterator content = contents.begin();
       content != contents.end(); ++content) {
    if (!IsMediaContent(&*content)) {
      continue;
    }
    const MediaContentDescription* media =
        static_cast<const MediaContentDescription*>(
            content->description);
    const StreamParamsVec& streams = media->streams();
    for (StreamParamsVec::const_iterator it = streams.begin();
         it != streams.end(); ++it) {
      stream_params->push_back(*it);
    }
  }
}

// Filters the data codecs for the data channel type.
void FilterDataCodecs(std::vector<DataCodec>* codecs, bool sctp) {
  // Filter RTP codec for SCTP and vice versa.
  int codec_id = sctp ? kGoogleRtpDataCodecId : kGoogleSctpDataCodecId;
  for (std::vector<DataCodec>::iterator iter = codecs->begin();
       iter != codecs->end();) {
    if (iter->id == codec_id) {
      iter = codecs->erase(iter);
    } else {
      ++iter;
    }
  }
}

template <typename IdStruct>
class UsedIds {
 public:
  UsedIds(int min_allowed_id, int max_allowed_id)
      : min_allowed_id_(min_allowed_id),
        max_allowed_id_(max_allowed_id),
        next_id_(max_allowed_id) {
  }

  // Loops through all Id in |ids| and changes its id if it is
  // already in use by another IdStruct. Call this methods with all Id
  // in a session description to make sure no duplicate ids exists.
  // Note that typename Id must be a type of IdStruct.
  template <typename Id>
  void FindAndSetIdUsed(std::vector<Id>* ids) {
    for (typename std::vector<Id>::iterator it = ids->begin();
         it != ids->end(); ++it) {
      FindAndSetIdUsed(&*it);
    }
  }

  // Finds and sets an unused id if the |idstruct| id is already in use.
  void FindAndSetIdUsed(IdStruct* idstruct) {
    const int original_id = idstruct->id;
    int new_id = idstruct->id;

    if (original_id > max_allowed_id_ || original_id < min_allowed_id_) {
      // If the original id is not in range - this is an id that can't be
      // dynamically changed.
      return;
    }

    if (IsIdUsed(original_id)) {
      new_id = FindUnusedId();
      LOG(LS_WARNING) << "Duplicate id found. Reassigning from " << original_id
          << " to " << new_id;
      idstruct->id = new_id;
    }
    SetIdUsed(new_id);
  }

 private:
  // Returns the first unused id in reverse order.
  // This hopefully reduce the risk of more collisions. We want to change the
  // default ids as little as possible.
  int FindUnusedId() {
    while (IsIdUsed(next_id_) && next_id_ >= min_allowed_id_) {
      --next_id_;
    }
    ASSERT(next_id_ >= min_allowed_id_);
    return next_id_;
  }

  bool IsIdUsed(int new_id) {
    return id_set_.find(new_id) != id_set_.end();
  }

  void SetIdUsed(int new_id) {
    id_set_.insert(new_id);
  }

  const int min_allowed_id_;
  const int max_allowed_id_;
  int next_id_;
  std::set<int> id_set_;
};

// Helper class used for finding duplicate RTP payload types among audio, video
// and data codecs. When bundle is used the payload types may not collide.
class UsedPayloadTypes : public UsedIds<Codec> {
 public:
  UsedPayloadTypes()
      : UsedIds<Codec>(kDynamicPayloadTypeMin, kDynamicPayloadTypeMax) {
  }


 private:
  static const int kDynamicPayloadTypeMin = 96;
  static const int kDynamicPayloadTypeMax = 127;
};

// Helper class used for finding duplicate RTP Header extension ids among
// audio and video extensions.
class UsedRtpHeaderExtensionIds : public UsedIds<webrtc::RtpExtension> {
 public:
  UsedRtpHeaderExtensionIds()
      : UsedIds<webrtc::RtpExtension>(kLocalIdMin, kLocalIdMax) {}

 private:
  // Min and Max local identifier for one-byte header extensions, per RFC5285.
  static const int kLocalIdMin = 1;
  static const int kLocalIdMax = 14;
};

static bool IsSctp(const MediaContentDescription* desc) {
  return ((desc->protocol() == kMediaProtocolSctp) ||
          (desc->protocol() == kMediaProtocolDtlsSctp));
}

// Adds a StreamParams for each Stream in Streams with media type
// media_type to content_description.
// |current_params| - All currently known StreamParams of any media type.
template <class C>
static bool AddStreamParams(MediaType media_type,
                            const MediaSessionOptions& options,
                            StreamParamsVec* current_streams,
                            MediaContentDescriptionImpl<C>* content_description,
                            const bool add_legacy_stream) {
  const bool include_rtx_streams =
      ContainsRtxCodec(content_description->codecs());

  const MediaSessionOptions::Streams& streams = options.streams;
  if (streams.empty() && add_legacy_stream) {
    // TODO(perkj): Remove this legacy stream when all apps use StreamParams.
    std::vector<uint32_t> ssrcs;
    if (IsSctp(content_description)) {
      GenerateSctpSids(*current_streams, &ssrcs);
    } else {
      int num_ssrcs = include_rtx_streams ? 2 : 1;
      GenerateSsrcs(*current_streams, num_ssrcs, &ssrcs);
    }
    if (include_rtx_streams) {
      content_description->AddLegacyStream(ssrcs[0], ssrcs[1]);
      content_description->set_multistream(true);
    } else {
      content_description->AddLegacyStream(ssrcs[0]);
    }
    return true;
  }

  MediaSessionOptions::Streams::const_iterator stream_it;
  for (stream_it = streams.begin();
       stream_it != streams.end(); ++stream_it) {
    if (stream_it->type != media_type)
      continue;  // Wrong media type.

    const StreamParams* param =
        GetStreamByIds(*current_streams, "", stream_it->id);
    // groupid is empty for StreamParams generated using
    // MediaSessionDescriptionFactory.
    if (!param) {
      // This is a new stream.
      std::vector<uint32_t> ssrcs;
      if (IsSctp(content_description)) {
        GenerateSctpSids(*current_streams, &ssrcs);
      } else {
        GenerateSsrcs(*current_streams, stream_it->num_sim_layers, &ssrcs);
      }
      StreamParams stream_param;
      stream_param.id = stream_it->id;
      // Add the generated ssrc.
      for (size_t i = 0; i < ssrcs.size(); ++i) {
        stream_param.ssrcs.push_back(ssrcs[i]);
      }
      if (stream_it->num_sim_layers > 1) {
        SsrcGroup group(kSimSsrcGroupSemantics, stream_param.ssrcs);
        stream_param.ssrc_groups.push_back(group);
      }
      // Generate extra ssrcs for include_rtx_streams case.
      if (include_rtx_streams) {
        // Generate an RTX ssrc for every ssrc in the group.
        std::vector<uint32_t> rtx_ssrcs;
        GenerateSsrcs(*current_streams, static_cast<int>(ssrcs.size()),
                      &rtx_ssrcs);
        for (size_t i = 0; i < ssrcs.size(); ++i) {
          stream_param.AddFidSsrc(ssrcs[i], rtx_ssrcs[i]);
        }
        content_description->set_multistream(true);
      }
      stream_param.cname = options.rtcp_cname;
      stream_param.sync_label = stream_it->sync_label;
      content_description->AddStream(stream_param);

      // Store the new StreamParams in current_streams.
      // This is necessary so that we can use the CNAME for other media types.
      current_streams->push_back(stream_param);
    } else {
      content_description->AddStream(*param);
    }
  }
  return true;
}

// Updates the transport infos of the |sdesc| according to the given
// |bundle_group|. The transport infos of the content names within the
// |bundle_group| should be updated to use the ufrag, pwd and DTLS role of the
// first content within the |bundle_group|.
static bool UpdateTransportInfoForBundle(const ContentGroup& bundle_group,
                                         SessionDescription* sdesc) {
  // The bundle should not be empty.
  if (!sdesc || !bundle_group.FirstContentName()) {
    return false;
  }

  // We should definitely have a transport for the first content.
  const std::string& selected_content_name = *bundle_group.FirstContentName();
  const TransportInfo* selected_transport_info =
      sdesc->GetTransportInfoByName(selected_content_name);
  if (!selected_transport_info) {
    return false;
  }

  // Set the other contents to use the same ICE credentials.
  const std::string& selected_ufrag =
      selected_transport_info->description.ice_ufrag;
  const std::string& selected_pwd =
      selected_transport_info->description.ice_pwd;
  ConnectionRole selected_connection_role =
      selected_transport_info->description.connection_role;
  for (TransportInfos::iterator it =
           sdesc->transport_infos().begin();
       it != sdesc->transport_infos().end(); ++it) {
    if (bundle_group.HasContentName(it->content_name) &&
        it->content_name != selected_content_name) {
      it->description.ice_ufrag = selected_ufrag;
      it->description.ice_pwd = selected_pwd;
      it->description.connection_role = selected_connection_role;
    }
  }
  return true;
}

// Gets the CryptoParamsVec of the given |content_name| from |sdesc|, and
// sets it to |cryptos|.
static bool GetCryptosByName(const SessionDescription* sdesc,
                             const std::string& content_name,
                             CryptoParamsVec* cryptos) {
  if (!sdesc || !cryptos) {
    return false;
  }

  const ContentInfo* content = sdesc->GetContentByName(content_name);
  if (!IsMediaContent(content) || !content->description) {
    return false;
  }

  const MediaContentDescription* media_desc =
      static_cast<const MediaContentDescription*>(content->description);
  *cryptos = media_desc->cryptos();
  return true;
}

// Predicate function used by the remove_if.
// Returns true if the |crypto|'s cipher_suite is not found in |filter|.
static bool CryptoNotFound(const CryptoParams crypto,
                           const CryptoParamsVec* filter) {
  if (filter == NULL) {
    return true;
  }
  for (CryptoParamsVec::const_iterator it = filter->begin();
       it != filter->end(); ++it) {
    if (it->cipher_suite == crypto.cipher_suite) {
      return false;
    }
  }
  return true;
}

// Prunes the |target_cryptos| by removing the crypto params (cipher_suite)
// which are not available in |filter|.
static void PruneCryptos(const CryptoParamsVec& filter,
                         CryptoParamsVec* target_cryptos) {
  if (!target_cryptos) {
    return;
  }
  target_cryptos->erase(std::remove_if(target_cryptos->begin(),
                                       target_cryptos->end(),
                                       bind2nd(ptr_fun(CryptoNotFound),
                                               &filter)),
                        target_cryptos->end());
}

static bool IsRtpProtocol(const std::string& protocol) {
  return protocol.empty() ||
         (protocol.find(cricket::kMediaProtocolRtpPrefix) != std::string::npos);
}

static bool IsRtpContent(SessionDescription* sdesc,
                         const std::string& content_name) {
  bool is_rtp = false;
  ContentInfo* content = sdesc->GetContentByName(content_name);
  if (IsMediaContent(content)) {
    MediaContentDescription* media_desc =
        static_cast<MediaContentDescription*>(content->description);
    if (!media_desc) {
      return false;
    }
    is_rtp = IsRtpProtocol(media_desc->protocol());
  }
  return is_rtp;
}

// Updates the crypto parameters of the |sdesc| according to the given
// |bundle_group|. The crypto parameters of all the contents within the
// |bundle_group| should be updated to use the common subset of the
// available cryptos.
static bool UpdateCryptoParamsForBundle(const ContentGroup& bundle_group,
                                        SessionDescription* sdesc) {
  // The bundle should not be empty.
  if (!sdesc || !bundle_group.FirstContentName()) {
    return false;
  }

  bool common_cryptos_needed = false;
  // Get the common cryptos.
  const ContentNames& content_names = bundle_group.content_names();
  CryptoParamsVec common_cryptos;
  for (ContentNames::const_iterator it = content_names.begin();
       it != content_names.end(); ++it) {
    if (!IsRtpContent(sdesc, *it)) {
      continue;
    }
    // The common cryptos are needed if any of the content does not have DTLS
    // enabled.
    if (!sdesc->GetTransportInfoByName(*it)->description.secure()) {
      common_cryptos_needed = true;
    }
    if (it == content_names.begin()) {
      // Initial the common_cryptos with the first content in the bundle group.
      if (!GetCryptosByName(sdesc, *it, &common_cryptos)) {
        return false;
      }
      if (common_cryptos.empty()) {
        // If there's no crypto params, we should just return.
        return true;
      }
    } else {
      CryptoParamsVec cryptos;
      if (!GetCryptosByName(sdesc, *it, &cryptos)) {
        return false;
      }
      PruneCryptos(cryptos, &common_cryptos);
    }
  }

  if (common_cryptos.empty() && common_cryptos_needed) {
    return false;
  }

  // Update to use the common cryptos.
  for (ContentNames::const_iterator it = content_names.begin();
       it != content_names.end(); ++it) {
    if (!IsRtpContent(sdesc, *it)) {
      continue;
    }
    ContentInfo* content = sdesc->GetContentByName(*it);
    if (IsMediaContent(content)) {
      MediaContentDescription* media_desc =
          static_cast<MediaContentDescription*>(content->description);
      if (!media_desc) {
        return false;
      }
      media_desc->set_cryptos(common_cryptos);
    }
  }
  return true;
}

template <class C>
static bool ContainsRtxCodec(const std::vector<C>& codecs) {
  typename std::vector<C>::const_iterator it;
  for (it = codecs.begin(); it != codecs.end(); ++it) {
    if (IsRtxCodec(*it)) {
      return true;
    }
  }
  return false;
}

template <class C>
static bool IsRtxCodec(const C& codec) {
  return stricmp(codec.name.c_str(), kRtxCodecName) == 0;
}

static TransportOptions GetTransportOptions(const MediaSessionOptions& options,
                                            const std::string& content_name) {
  auto it = options.transport_options.find(content_name);
  if (it == options.transport_options.end()) {
    return TransportOptions();
  }
  return it->second;
}

// Create a media content to be offered in a session-initiate,
// according to the given options.rtcp_mux, options.is_muc,
// options.streams, codecs, secure_transport, crypto, and streams.  If we don't
// currently have crypto (in current_cryptos) and it is enabled (in
// secure_policy), crypto is created (according to crypto_suites).  If
// add_legacy_stream is true, and current_streams is empty, a legacy
// stream is created.  The created content is added to the offer.
template <class C>
static bool CreateMediaContentOffer(
    const MediaSessionOptions& options,
    const std::vector<C>& codecs,
    const SecurePolicy& secure_policy,
    const CryptoParamsVec* current_cryptos,
    const std::vector<std::string>& crypto_suites,
    const RtpHeaderExtensions& rtp_extensions,
    bool add_legacy_stream,
    StreamParamsVec* current_streams,
    MediaContentDescriptionImpl<C>* offer) {
  offer->AddCodecs(codecs);

  if (secure_policy == SEC_REQUIRED) {
    offer->set_crypto_required(CT_SDES);
  }
  offer->set_rtcp_mux(options.rtcp_mux_enabled);
  if (offer->type() == cricket::MEDIA_TYPE_VIDEO) {
    offer->set_rtcp_reduced_size(true);
  }
  offer->set_multistream(options.is_muc);
  offer->set_rtp_header_extensions(rtp_extensions);

  if (!AddStreamParams(offer->type(), options, current_streams, offer,
                       add_legacy_stream)) {
    return false;
  }

#ifdef HAVE_SRTP
  if (secure_policy != SEC_DISABLED) {
    if (current_cryptos) {
      AddMediaCryptos(*current_cryptos, offer);
    }
    if (offer->cryptos().empty()) {
      if (!CreateMediaCryptos(crypto_suites, offer)) {
        return false;
      }
    }
  }
#endif

  if (offer->crypto_required() == CT_SDES && offer->cryptos().empty()) {
    return false;
  }
  return true;
}

template <class C>
static bool ReferencedCodecsMatch(const std::vector<C>& codecs1,
                                  const std::string& codec1_id_str,
                                  const std::vector<C>& codecs2,
                                  const std::string& codec2_id_str) {
  int codec1_id;
  int codec2_id;
  C codec1;
  C codec2;
  if (!rtc::FromString(codec1_id_str, &codec1_id) ||
      !rtc::FromString(codec2_id_str, &codec2_id) ||
      !FindCodecById(codecs1, codec1_id, &codec1) ||
      !FindCodecById(codecs2, codec2_id, &codec2)) {
    return false;
  }
  return codec1.Matches(codec2);
}

template <class C>
static void NegotiateCodecs(const std::vector<C>& local_codecs,
                            const std::vector<C>& offered_codecs,
                            std::vector<C>* negotiated_codecs) {
  for (const C& ours : local_codecs) {
    C theirs;
    // Note that we intentionally only find one matching codec for each of our
    // local codecs, in case the remote offer contains duplicate codecs.
    if (FindMatchingCodec(local_codecs, offered_codecs, ours, &theirs)) {
      C negotiated = ours;
      negotiated.IntersectFeedbackParams(theirs);
      if (IsRtxCodec(negotiated)) {
        std::string offered_apt_value;
        theirs.GetParam(kCodecParamAssociatedPayloadType, &offered_apt_value);
        // FindMatchingCodec shouldn't return something with no apt value.
        RTC_DCHECK(!offered_apt_value.empty());
        negotiated.SetParam(kCodecParamAssociatedPayloadType,
                            offered_apt_value);
      }
      negotiated.id = theirs.id;
      negotiated_codecs->push_back(negotiated);
    }
  }
  // RFC3264: Although the answerer MAY list the formats in their desired
  // order of preference, it is RECOMMENDED that unless there is a
  // specific reason, the answerer list formats in the same relative order
  // they were present in the offer.
  std::unordered_map<int, int> payload_type_preferences;
  int preference = static_cast<int>(offered_codecs.size() + 1);
  for (const C& codec : offered_codecs) {
    payload_type_preferences[codec.id] = preference--;
  }
  std::sort(negotiated_codecs->begin(), negotiated_codecs->end(),
            [&payload_type_preferences](const C& a, const C& b) {
              return payload_type_preferences[a.id] >
                     payload_type_preferences[b.id];
            });
}

// Finds a codec in |codecs2| that matches |codec_to_match|, which is
// a member of |codecs1|. If |codec_to_match| is an RTX codec, both
// the codecs themselves and their associated codecs must match.
template <class C>
static bool FindMatchingCodec(const std::vector<C>& codecs1,
                              const std::vector<C>& codecs2,
                              const C& codec_to_match,
                              C* found_codec) {
  for (const C& potential_match : codecs2) {
    if (potential_match.Matches(codec_to_match)) {
      if (IsRtxCodec(codec_to_match)) {
        std::string apt_value_1;
        std::string apt_value_2;
        if (!codec_to_match.GetParam(kCodecParamAssociatedPayloadType,
                                     &apt_value_1) ||
            !potential_match.GetParam(kCodecParamAssociatedPayloadType,
                                      &apt_value_2)) {
          LOG(LS_WARNING) << "RTX missing associated payload type.";
          continue;
        }
        if (!ReferencedCodecsMatch(codecs1, apt_value_1, codecs2,
                                   apt_value_2)) {
          continue;
        }
      }
      if (found_codec) {
        *found_codec = potential_match;
      }
      return true;
    }
  }
  return false;
}

// Adds all codecs from |reference_codecs| to |offered_codecs| that dont'
// already exist in |offered_codecs| and ensure the payload types don't
// collide.
template <class C>
static void FindCodecsToOffer(
    const std::vector<C>& reference_codecs,
    std::vector<C>* offered_codecs,
    UsedPayloadTypes* used_pltypes) {

  // Add all new codecs that are not RTX codecs.
  for (const C& reference_codec : reference_codecs) {
    if (!IsRtxCodec(reference_codec) &&
        !FindMatchingCodec<C>(reference_codecs, *offered_codecs,
                              reference_codec, nullptr)) {
      C codec = reference_codec;
      used_pltypes->FindAndSetIdUsed(&codec);
      offered_codecs->push_back(codec);
    }
  }

  // Add all new RTX codecs.
  for (const C& reference_codec : reference_codecs) {
    if (IsRtxCodec(reference_codec) &&
        !FindMatchingCodec<C>(reference_codecs, *offered_codecs,
                              reference_codec, nullptr)) {
      C rtx_codec = reference_codec;

      std::string associated_pt_str;
      if (!rtx_codec.GetParam(kCodecParamAssociatedPayloadType,
                              &associated_pt_str)) {
        LOG(LS_WARNING) << "RTX codec " << rtx_codec.name
                        << " is missing an associated payload type.";
        continue;
      }

      int associated_pt;
      if (!rtc::FromString(associated_pt_str, &associated_pt)) {
        LOG(LS_WARNING) << "Couldn't convert payload type " << associated_pt_str
                        << " of RTX codec " << rtx_codec.name
                        << " to an integer.";
        continue;
      }

      // Find the associated reference codec for the reference RTX codec.
      C associated_codec;
      if (!FindCodecById(reference_codecs, associated_pt, &associated_codec)) {
        LOG(LS_WARNING) << "Couldn't find associated codec with payload type "
                        << associated_pt << " for RTX codec " << rtx_codec.name
                        << ".";
        continue;
      }

      // Find a codec in the offered list that matches the reference codec.
      // Its payload type may be different than the reference codec.
      C matching_codec;
      if (!FindMatchingCodec<C>(reference_codecs, *offered_codecs,
                               associated_codec, &matching_codec)) {
        LOG(LS_WARNING) << "Couldn't find matching " << associated_codec.name
                        << " codec.";
        continue;
      }

      rtx_codec.params[kCodecParamAssociatedPayloadType] =
          rtc::ToString(matching_codec.id);
      used_pltypes->FindAndSetIdUsed(&rtx_codec);
      offered_codecs->push_back(rtx_codec);
    }
  }
}

static bool FindByUri(const RtpHeaderExtensions& extensions,
                      const webrtc::RtpExtension& ext_to_match,
                      webrtc::RtpExtension* found_extension) {
  for (RtpHeaderExtensions::const_iterator it = extensions.begin();
       it  != extensions.end(); ++it) {
    // We assume that all URIs are given in a canonical format.
    if (it->uri == ext_to_match.uri) {
      if (found_extension != NULL) {
        *found_extension = *it;
      }
      return true;
    }
  }
  return false;
}

// Iterates through |offered_extensions|, adding each one to |all_extensions|
// and |used_ids|, and resolving ID conflicts. If an offered extension has the
// same URI as one in |all_extensions|, it will re-use the same ID and won't be
// treated as a conflict.
static void FindAndSetRtpHdrExtUsed(RtpHeaderExtensions* offered_extensions,
                                    RtpHeaderExtensions* all_extensions,
                                    UsedRtpHeaderExtensionIds* used_ids) {
  for (auto& extension : *offered_extensions) {
    webrtc::RtpExtension existing;
    if (FindByUri(*all_extensions, extension, &existing)) {
      extension.id = existing.id;
    } else {
      used_ids->FindAndSetIdUsed(&extension);
      all_extensions->push_back(extension);
    }
  }
}

// Adds |reference_extensions| to |offered_extensions|, while updating
// |all_extensions| and |used_ids|.
static void FindRtpHdrExtsToOffer(
    const RtpHeaderExtensions& reference_extensions,
    RtpHeaderExtensions* offered_extensions,
    RtpHeaderExtensions* all_extensions,
    UsedRtpHeaderExtensionIds* used_ids) {
  for (auto reference_extension : reference_extensions) {
    if (!FindByUri(*offered_extensions, reference_extension, NULL)) {
      webrtc::RtpExtension existing;
      if (FindByUri(*all_extensions, reference_extension, &existing)) {
        offered_extensions->push_back(existing);
      } else {
        used_ids->FindAndSetIdUsed(&reference_extension);
        all_extensions->push_back(reference_extension);
        offered_extensions->push_back(reference_extension);
      }
    }
  }
}

static void NegotiateRtpHeaderExtensions(
    const RtpHeaderExtensions& local_extensions,
    const RtpHeaderExtensions& offered_extensions,
    RtpHeaderExtensions* negotiated_extenstions) {
  RtpHeaderExtensions::const_iterator ours;
  for (ours = local_extensions.begin();
       ours != local_extensions.end(); ++ours) {
    webrtc::RtpExtension theirs;
    if (FindByUri(offered_extensions, *ours, &theirs)) {
      // We respond with their RTP header extension id.
      negotiated_extenstions->push_back(theirs);
    }
  }
}

static void StripCNCodecs(AudioCodecs* audio_codecs) {
  AudioCodecs::iterator iter = audio_codecs->begin();
  while (iter != audio_codecs->end()) {
    if (stricmp(iter->name.c_str(), kComfortNoiseCodecName) == 0) {
      iter = audio_codecs->erase(iter);
    } else {
      ++iter;
    }
  }
}

// Create a media content to be answered in a session-accept,
// according to the given options.rtcp_mux, options.streams, codecs,
// crypto, and streams.  If we don't currently have crypto (in
// current_cryptos) and it is enabled (in secure_policy), crypto is
// created (according to crypto_suites).  If add_legacy_stream is
// true, and current_streams is empty, a legacy stream is created.
// The codecs, rtcp_mux, and crypto are all negotiated with the offer
// from the incoming session-initiate.  If the negotiation fails, this
// method returns false.  The created content is added to the offer.
template <class C>
static bool CreateMediaContentAnswer(
    const MediaContentDescriptionImpl<C>* offer,
    const MediaSessionOptions& options,
    const std::vector<C>& local_codecs,
    const SecurePolicy& sdes_policy,
    const CryptoParamsVec* current_cryptos,
    const RtpHeaderExtensions& local_rtp_extenstions,
    StreamParamsVec* current_streams,
    bool add_legacy_stream,
    bool bundle_enabled,
    MediaContentDescriptionImpl<C>* answer) {
  std::vector<C> negotiated_codecs;
  NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs);
  answer->AddCodecs(negotiated_codecs);
  answer->set_protocol(offer->protocol());
  RtpHeaderExtensions negotiated_rtp_extensions;
  NegotiateRtpHeaderExtensions(local_rtp_extenstions,
                               offer->rtp_header_extensions(),
                               &negotiated_rtp_extensions);
  answer->set_rtp_header_extensions(negotiated_rtp_extensions);

  answer->set_rtcp_mux(options.rtcp_mux_enabled && offer->rtcp_mux());
  if (answer->type() == cricket::MEDIA_TYPE_VIDEO) {
    answer->set_rtcp_reduced_size(offer->rtcp_reduced_size());
  }

  if (sdes_policy != SEC_DISABLED) {
    CryptoParams crypto;
    if (SelectCrypto(offer, bundle_enabled, &crypto)) {
      if (current_cryptos) {
        FindMatchingCrypto(*current_cryptos, crypto, &crypto);
      }
      answer->AddCrypto(crypto);
    }
  }

  if (answer->cryptos().empty() &&
      (offer->crypto_required() == CT_SDES || sdes_policy == SEC_REQUIRED)) {
    return false;
  }

  if (!AddStreamParams(answer->type(), options, current_streams, answer,
                       add_legacy_stream)) {
    return false;  // Something went seriously wrong.
  }

  // Make sure the answer media content direction is per default set as
  // described in RFC3264 section 6.1.
  switch (offer->direction()) {
    case MD_INACTIVE:
      answer->set_direction(MD_INACTIVE);
      break;
    case MD_SENDONLY:
      answer->set_direction(MD_RECVONLY);
      break;
    case MD_RECVONLY:
      answer->set_direction(IsRtpProtocol(answer->protocol()) &&
                                    answer->streams().empty()
                                ? MD_INACTIVE
                                : MD_SENDONLY);
      break;
    case MD_SENDRECV:
      answer->set_direction(IsRtpProtocol(answer->protocol()) &&
                                    answer->streams().empty()
                                ? MD_RECVONLY
                                : MD_SENDRECV);
      break;
    default:
      RTC_DCHECK(false && "MediaContentDescription has unexpected direction.");
      break;
  }

  return true;
}

static bool IsDtlsRtp(const std::string& protocol) {
  // Most-likely values first.
  return protocol == "UDP/TLS/RTP/SAVPF" || protocol == "TCP/TLS/RTP/SAVPF" ||
         protocol == "UDP/TLS/RTP/SAVP" || protocol == "TCP/TLS/RTP/SAVP";
}

static bool IsPlainRtp(const std::string& protocol) {
  // Most-likely values first.
  return protocol == "RTP/SAVPF" || protocol == "RTP/AVPF" ||
         protocol == "RTP/SAVP" || protocol == "RTP/AVP";
}

static bool IsDtlsSctp(const std::string& protocol) {
  return protocol == "DTLS/SCTP";
}

static bool IsPlainSctp(const std::string& protocol) {
  return protocol == "SCTP";
}

static bool IsMediaProtocolSupported(MediaType type,
                                     const std::string& protocol,
                                     bool secure_transport) {
  // Since not all applications serialize and deserialize the media protocol,
  // we will have to accept |protocol| to be empty.
  if (protocol.empty()) {
    return true;
  }

  if (type == MEDIA_TYPE_DATA) {
    // Check for SCTP, but also for RTP for RTP-based data channels.
    // TODO(pthatcher): Remove RTP once RTP-based data channels are gone.
    if (secure_transport) {
      // Most likely scenarios first.
      return IsDtlsSctp(protocol) || IsDtlsRtp(protocol) ||
             IsPlainRtp(protocol);
    } else {
      return IsPlainSctp(protocol) || IsPlainRtp(protocol);
    }
  }

  // Allow for non-DTLS RTP protocol even when using DTLS because that's what
  // JSEP specifies.
  if (secure_transport) {
    // Most likely scenarios first.
    return IsDtlsRtp(protocol) || IsPlainRtp(protocol);
  } else {
    return IsPlainRtp(protocol);
  }
}

static void SetMediaProtocol(bool secure_transport,
                             MediaContentDescription* desc) {
  if (!desc->cryptos().empty())
    desc->set_protocol(kMediaProtocolSavpf);
  else if (secure_transport)
    desc->set_protocol(kMediaProtocolDtlsSavpf);
  else
    desc->set_protocol(kMediaProtocolAvpf);
}

// Gets the TransportInfo of the given |content_name| from the
// |current_description|. If doesn't exist, returns a new one.
static const TransportDescription* GetTransportDescription(
    const std::string& content_name,
    const SessionDescription* current_description) {
  const TransportDescription* desc = NULL;
  if (current_description) {
    const TransportInfo* info =
        current_description->GetTransportInfoByName(content_name);
    if (info) {
      desc = &info->description;
    }
  }
  return desc;
}

// Gets the current DTLS state from the transport description.
static bool IsDtlsActive(
    const std::string& content_name,
    const SessionDescription* current_description) {
  if (!current_description)
    return false;

  const ContentInfo* content =
      current_description->GetContentByName(content_name);
  if (!content)
    return false;

  const TransportDescription* current_tdesc =
      GetTransportDescription(content_name, current_description);
  if (!current_tdesc)
    return false;

  return current_tdesc->secure();
}

std::string MediaTypeToString(MediaType type) {
  std::string type_str;
  switch (type) {
    case MEDIA_TYPE_AUDIO:
      type_str = "audio";
      break;
    case MEDIA_TYPE_VIDEO:
      type_str = "video";
      break;
    case MEDIA_TYPE_DATA:
      type_str = "data";
      break;
    default:
      ASSERT(false);
      break;
  }
  return type_str;
}

void MediaSessionOptions::AddSendStream(MediaType type,
                                    const std::string& id,
                                    const std::string& sync_label) {
  AddSendStreamInternal(type, id, sync_label, 1);
}

void MediaSessionOptions::AddSendVideoStream(
    const std::string& id,
    const std::string& sync_label,
    int num_sim_layers) {
  AddSendStreamInternal(MEDIA_TYPE_VIDEO, id, sync_label, num_sim_layers);
}

void MediaSessionOptions::AddSendStreamInternal(
    MediaType type,
    const std::string& id,
    const std::string& sync_label,
    int num_sim_layers) {
  streams.push_back(Stream(type, id, sync_label, num_sim_layers));

  // If we haven't already set the data_channel_type, and we add a
  // stream, we assume it's an RTP data stream.
  if (type == MEDIA_TYPE_DATA && data_channel_type == DCT_NONE)
    data_channel_type = DCT_RTP;
}

void MediaSessionOptions::RemoveSendStream(MediaType type,
                                       const std::string& id) {
  Streams::iterator stream_it = streams.begin();
  for (; stream_it != streams.end(); ++stream_it) {
    if (stream_it->type == type && stream_it->id == id) {
      streams.erase(stream_it);
      return;
    }
  }
  ASSERT(false);
}

bool MediaSessionOptions::HasSendMediaStream(MediaType type) const {
  Streams::const_iterator stream_it = streams.begin();
  for (; stream_it != streams.end(); ++stream_it) {
    if (stream_it->type == type) {
      return true;
    }
  }
  return false;
}

MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
    const TransportDescriptionFactory* transport_desc_factory)
    : secure_(SEC_DISABLED),
      add_legacy_(true),
      transport_desc_factory_(transport_desc_factory) {
}

MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
    ChannelManager* channel_manager,
    const TransportDescriptionFactory* transport_desc_factory)
    : secure_(SEC_DISABLED),
      add_legacy_(true),
      transport_desc_factory_(transport_desc_factory) {
  channel_manager->GetSupportedAudioCodecs(&audio_codecs_);
  channel_manager->GetSupportedAudioRtpHeaderExtensions(&audio_rtp_extensions_);
  channel_manager->GetSupportedVideoCodecs(&video_codecs_);
  channel_manager->GetSupportedVideoRtpHeaderExtensions(&video_rtp_extensions_);
  channel_manager->GetSupportedDataCodecs(&data_codecs_);
}

SessionDescription* MediaSessionDescriptionFactory::CreateOffer(
    const MediaSessionOptions& options,
    const SessionDescription* current_description) const {
  std::unique_ptr<SessionDescription> offer(new SessionDescription());

  StreamParamsVec current_streams;
  GetCurrentStreamParams(current_description, &current_streams);

  AudioCodecs audio_codecs;
  VideoCodecs video_codecs;
  DataCodecs data_codecs;
  GetCodecsToOffer(current_description, &audio_codecs, &video_codecs,
                   &data_codecs);

  if (!options.vad_enabled) {
    // If application doesn't want CN codecs in offer.
    StripCNCodecs(&audio_codecs);
  }

  RtpHeaderExtensions audio_rtp_extensions;
  RtpHeaderExtensions video_rtp_extensions;
  GetRtpHdrExtsToOffer(current_description, &audio_rtp_extensions,
                       &video_rtp_extensions);

  bool audio_added = false;
  bool video_added = false;
  bool data_added = false;

  // Iterate through the contents of |current_description| to maintain the order
  // of the m-lines in the new offer.
  if (current_description) {
    ContentInfos::const_iterator it = current_description->contents().begin();
    for (; it != current_description->contents().end(); ++it) {
      if (IsMediaContentOfType(&*it, MEDIA_TYPE_AUDIO)) {
        if (!AddAudioContentForOffer(options, current_description,
                                     audio_rtp_extensions, audio_codecs,
                                     &current_streams, offer.get())) {
          return NULL;
        }
        audio_added = true;
      } else if (IsMediaContentOfType(&*it, MEDIA_TYPE_VIDEO)) {
        if (!AddVideoContentForOffer(options, current_description,
                                     video_rtp_extensions, video_codecs,
                                     &current_streams, offer.get())) {
          return NULL;
        }
        video_added = true;
      } else if (IsMediaContentOfType(&*it, MEDIA_TYPE_DATA)) {
        MediaSessionOptions options_copy(options);
        if (IsSctp(static_cast<const MediaContentDescription*>(
                it->description))) {
          options_copy.data_channel_type = DCT_SCTP;
        }
        if (!AddDataContentForOffer(options_copy, current_description,
                                    &data_codecs, &current_streams,
                                    offer.get())) {
          return NULL;
        }
        data_added = true;
      } else {
        ASSERT(false);
      }
    }
  }

  // Append contents that are not in |current_description|.
  if (!audio_added && options.has_audio() &&
      !AddAudioContentForOffer(options, current_description,
                               audio_rtp_extensions, audio_codecs,
                               &current_streams, offer.get())) {
    return NULL;
  }
  if (!video_added && options.has_video() &&
      !AddVideoContentForOffer(options, current_description,
                               video_rtp_extensions, video_codecs,
                               &current_streams, offer.get())) {
    return NULL;
  }
  if (!data_added && options.has_data() &&
      !AddDataContentForOffer(options, current_description, &data_codecs,
                              &current_streams, offer.get())) {
    return NULL;
  }

  // Bundle the contents together, if we've been asked to do so, and update any
  // parameters that need to be tweaked for BUNDLE.
  if (options.bundle_enabled) {
    ContentGroup offer_bundle(GROUP_TYPE_BUNDLE);
    for (ContentInfos::const_iterator content = offer->contents().begin();
       content != offer->contents().end(); ++content) {
      offer_bundle.AddContentName(content->name);
    }
    offer->AddGroup(offer_bundle);
    if (!UpdateTransportInfoForBundle(offer_bundle, offer.get())) {
      LOG(LS_ERROR) << "CreateOffer failed to UpdateTransportInfoForBundle.";
      return NULL;
    }
    if (!UpdateCryptoParamsForBundle(offer_bundle, offer.get())) {
      LOG(LS_ERROR) << "CreateOffer failed to UpdateCryptoParamsForBundle.";
      return NULL;
    }
  }

  return offer.release();
}

SessionDescription* MediaSessionDescriptionFactory::CreateAnswer(
    const SessionDescription* offer, const MediaSessionOptions& options,
    const SessionDescription* current_description) const {
  // The answer contains the intersection of the codecs in the offer with the
  // codecs we support. As indicated by XEP-0167, we retain the same payload ids
  // from the offer in the answer.
  std::unique_ptr<SessionDescription> answer(new SessionDescription());

  StreamParamsVec current_streams;
  GetCurrentStreamParams(current_description, &current_streams);

  if (offer) {
    ContentInfos::const_iterator it = offer->contents().begin();
    for (; it != offer->contents().end(); ++it) {
      if (IsMediaContentOfType(&*it, MEDIA_TYPE_AUDIO)) {
        if (!AddAudioContentForAnswer(offer, options, current_description,
                                  &current_streams, answer.get())) {
          return NULL;
        }
      } else if (IsMediaContentOfType(&*it, MEDIA_TYPE_VIDEO)) {
        if (!AddVideoContentForAnswer(offer, options, current_description,
                                      &current_streams, answer.get())) {
          return NULL;
        }
      } else {
        ASSERT(IsMediaContentOfType(&*it, MEDIA_TYPE_DATA));
        if (!AddDataContentForAnswer(offer, options, current_description,
                                     &current_streams, answer.get())) {
          return NULL;
        }
      }
    }
  }

  // If the offer supports BUNDLE, and we want to use it too, create a BUNDLE
  // group in the answer with the appropriate content names.
  if (offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled) {
    const ContentGroup* offer_bundle = offer->GetGroupByName(GROUP_TYPE_BUNDLE);
    ContentGroup answer_bundle(GROUP_TYPE_BUNDLE);
    for (ContentInfos::const_iterator content = answer->contents().begin();
       content != answer->contents().end(); ++content) {
      if (!content->rejected && offer_bundle->HasContentName(content->name)) {
        answer_bundle.AddContentName(content->name);
      }
    }
    if (answer_bundle.FirstContentName()) {
      answer->AddGroup(answer_bundle);

      // Share the same ICE credentials and crypto params across all contents,
      // as BUNDLE requires.
      if (!UpdateTransportInfoForBundle(answer_bundle, answer.get())) {
        LOG(LS_ERROR) << "CreateAnswer failed to UpdateTransportInfoForBundle.";
        return NULL;
      }

      if (!UpdateCryptoParamsForBundle(answer_bundle, answer.get())) {
        LOG(LS_ERROR) << "CreateAnswer failed to UpdateCryptoParamsForBundle.";
        return NULL;
      }
    }
  }

  return answer.release();
}

void MediaSessionDescriptionFactory::GetCodecsToOffer(
    const SessionDescription* current_description,
    AudioCodecs* audio_codecs,
    VideoCodecs* video_codecs,
    DataCodecs* data_codecs) const {
  UsedPayloadTypes used_pltypes;
  audio_codecs->clear();
  video_codecs->clear();
  data_codecs->clear();


  // First - get all codecs from the current description if the media type
  // is used.
  // Add them to |used_pltypes| so the payloadtype is not reused if a new media
  // type is added.
  if (current_description) {
    const AudioContentDescription* audio =
        GetFirstAudioContentDescription(current_description);
    if (audio) {
      *audio_codecs = audio->codecs();
      used_pltypes.FindAndSetIdUsed<AudioCodec>(audio_codecs);
    }
    const VideoContentDescription* video =
        GetFirstVideoContentDescription(current_description);
    if (video) {
      *video_codecs = video->codecs();
      used_pltypes.FindAndSetIdUsed<VideoCodec>(video_codecs);
    }
    const DataContentDescription* data =
        GetFirstDataContentDescription(current_description);
    if (data) {
      *data_codecs = data->codecs();
      used_pltypes.FindAndSetIdUsed<DataCodec>(data_codecs);
    }
  }

  // Add our codecs that are not in |current_description|.
  FindCodecsToOffer<AudioCodec>(audio_codecs_, audio_codecs, &used_pltypes);
  FindCodecsToOffer<VideoCodec>(video_codecs_, video_codecs, &used_pltypes);
  FindCodecsToOffer<DataCodec>(data_codecs_, data_codecs, &used_pltypes);
}

void MediaSessionDescriptionFactory::GetRtpHdrExtsToOffer(
    const SessionDescription* current_description,
    RtpHeaderExtensions* audio_extensions,
    RtpHeaderExtensions* video_extensions) const {
  // All header extensions allocated from the same range to avoid potential
  // issues when using BUNDLE.
  UsedRtpHeaderExtensionIds used_ids;
  RtpHeaderExtensions all_extensions;
  audio_extensions->clear();
  video_extensions->clear();

  // First - get all extensions from the current description if the media type
  // is used.
  // Add them to |used_ids| so the local ids are not reused if a new media
  // type is added.
  if (current_description) {
    const AudioContentDescription* audio =
        GetFirstAudioContentDescription(current_description);
    if (audio) {
      *audio_extensions = audio->rtp_header_extensions();
      FindAndSetRtpHdrExtUsed(audio_extensions, &all_extensions, &used_ids);
    }
    const VideoContentDescription* video =
        GetFirstVideoContentDescription(current_description);
    if (video) {
      *video_extensions = video->rtp_header_extensions();
      FindAndSetRtpHdrExtUsed(video_extensions, &all_extensions, &used_ids);
    }
  }

  // Add our default RTP header extensions that are not in
  // |current_description|.
  FindRtpHdrExtsToOffer(audio_rtp_header_extensions(), audio_extensions,
                        &all_extensions, &used_ids);
  FindRtpHdrExtsToOffer(video_rtp_header_extensions(), video_extensions,
                        &all_extensions, &used_ids);
}

bool MediaSessionDescriptionFactory::AddTransportOffer(
  const std::string& content_name,
  const TransportOptions& transport_options,
  const SessionDescription* current_desc,
  SessionDescription* offer_desc) const {
  if (!transport_desc_factory_)
     return false;
  const TransportDescription* current_tdesc =
      GetTransportDescription(content_name, current_desc);
  std::unique_ptr<TransportDescription> new_tdesc(
      transport_desc_factory_->CreateOffer(transport_options, current_tdesc));
  bool ret = (new_tdesc.get() != NULL &&
      offer_desc->AddTransportInfo(TransportInfo(content_name, *new_tdesc)));
  if (!ret) {
    LOG(LS_ERROR)
        << "Failed to AddTransportOffer, content name=" << content_name;
  }
  return ret;
}

TransportDescription* MediaSessionDescriptionFactory::CreateTransportAnswer(
    const std::string& content_name,
    const SessionDescription* offer_desc,
    const TransportOptions& transport_options,
    const SessionDescription* current_desc) const {
  if (!transport_desc_factory_)
    return NULL;
  const TransportDescription* offer_tdesc =
      GetTransportDescription(content_name, offer_desc);
  const TransportDescription* current_tdesc =
      GetTransportDescription(content_name, current_desc);
  return
      transport_desc_factory_->CreateAnswer(offer_tdesc, transport_options,
                                            current_tdesc);
}

bool MediaSessionDescriptionFactory::AddTransportAnswer(
    const std::string& content_name,
    const TransportDescription& transport_desc,
    SessionDescription* answer_desc) const {
  if (!answer_desc->AddTransportInfo(TransportInfo(content_name,
                                                   transport_desc))) {
    LOG(LS_ERROR)
        << "Failed to AddTransportAnswer, content name=" << content_name;
    return false;
  }
  return true;
}

bool MediaSessionDescriptionFactory::AddAudioContentForOffer(
    const MediaSessionOptions& options,
    const SessionDescription* current_description,
    const RtpHeaderExtensions& audio_rtp_extensions,
    const AudioCodecs& audio_codecs,
    StreamParamsVec* current_streams,
    SessionDescription* desc) const {
  const ContentInfo* current_audio_content =
      GetFirstAudioContent(current_description);
  std::string content_name =
      current_audio_content ? current_audio_content->name : CN_AUDIO;

  cricket::SecurePolicy sdes_policy =
      IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED
                                                      : secure();

  std::unique_ptr<AudioContentDescription> audio(new AudioContentDescription());
  std::vector<std::string> crypto_suites;
  GetSupportedAudioCryptoSuiteNames(&crypto_suites);
  if (!CreateMediaContentOffer(
          options,
          audio_codecs,
          sdes_policy,
          GetCryptos(GetFirstAudioContentDescription(current_description)),
          crypto_suites,
          audio_rtp_extensions,
          add_legacy_,
          current_streams,
          audio.get())) {
    return false;
  }
  audio->set_lang(lang_);

  bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
  SetMediaProtocol(secure_transport, audio.get());

  if (!audio->streams().empty()) {
    if (options.recv_audio) {
      audio->set_direction(MD_SENDRECV);
    } else {
      audio->set_direction(MD_SENDONLY);
    }
  } else {
    if (options.recv_audio) {
      audio->set_direction(MD_RECVONLY);
    } else {
      audio->set_direction(MD_INACTIVE);
    }
  }

  desc->AddContent(content_name, NS_JINGLE_RTP, audio.release());
  if (!AddTransportOffer(content_name,
                         GetTransportOptions(options, content_name),
                         current_description, desc)) {
    return false;
  }

  return true;
}

bool MediaSessionDescriptionFactory::AddVideoContentForOffer(
    const MediaSessionOptions& options,
    const SessionDescription* current_description,
    const RtpHeaderExtensions& video_rtp_extensions,
    const VideoCodecs& video_codecs,
    StreamParamsVec* current_streams,
    SessionDescription* desc) const {
  const ContentInfo* current_video_content =
      GetFirstVideoContent(current_description);
  std::string content_name =
      current_video_content ? current_video_content->name : CN_VIDEO;

  cricket::SecurePolicy sdes_policy =
      IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED
                                                      : secure();

  std::unique_ptr<VideoContentDescription> video(new VideoContentDescription());
  std::vector<std::string> crypto_suites;
  GetSupportedVideoCryptoSuiteNames(&crypto_suites);
  if (!CreateMediaContentOffer(
          options,
          video_codecs,
          sdes_policy,
          GetCryptos(GetFirstVideoContentDescription(current_description)),
          crypto_suites,
          video_rtp_extensions,
          add_legacy_,
          current_streams,
          video.get())) {
    return false;
  }

  video->set_bandwidth(options.video_bandwidth);

  bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
  SetMediaProtocol(secure_transport, video.get());

  if (!video->streams().empty()) {
    if (options.recv_video) {
      video->set_direction(MD_SENDRECV);
    } else {
      video->set_direction(MD_SENDONLY);
    }
  } else {
    if (options.recv_video) {
      video->set_direction(MD_RECVONLY);
    } else {
      video->set_direction(MD_INACTIVE);
    }
  }

  desc->AddContent(content_name, NS_JINGLE_RTP, video.release());
  if (!AddTransportOffer(content_name,
                         GetTransportOptions(options, content_name),
                         current_description, desc)) {
    return false;
  }

  return true;
}

bool MediaSessionDescriptionFactory::AddDataContentForOffer(
    const MediaSessionOptions& options,
    const SessionDescription* current_description,
    DataCodecs* data_codecs,
    StreamParamsVec* current_streams,
    SessionDescription* desc) const {
  bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);

  std::unique_ptr<DataContentDescription> data(new DataContentDescription());
  bool is_sctp = (options.data_channel_type == DCT_SCTP);

  FilterDataCodecs(data_codecs, is_sctp);

  const ContentInfo* current_data_content =
      GetFirstDataContent(current_description);
  std::string content_name =
      current_data_content ? current_data_content->name : CN_DATA;

  cricket::SecurePolicy sdes_policy =
      IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED
                                                      : secure();
  std::vector<std::string> crypto_suites;
  if (is_sctp) {
    // SDES doesn't make sense for SCTP, so we disable it, and we only
    // get SDES crypto suites for RTP-based data channels.
    sdes_policy = cricket::SEC_DISABLED;
    // Unlike SetMediaProtocol below, we need to set the protocol
    // before we call CreateMediaContentOffer.  Otherwise,
    // CreateMediaContentOffer won't know this is SCTP and will
    // generate SSRCs rather than SIDs.
    data->set_protocol(
        secure_transport ? kMediaProtocolDtlsSctp : kMediaProtocolSctp);
  } else {
    GetSupportedDataCryptoSuiteNames(&crypto_suites);
  }

  if (!CreateMediaContentOffer(
          options,
          *data_codecs,
          sdes_policy,
          GetCryptos(GetFirstDataContentDescription(current_description)),
          crypto_suites,
          RtpHeaderExtensions(),
          add_legacy_,
          current_streams,
          data.get())) {
    return false;
  }

  if (is_sctp) {
    desc->AddContent(content_name, NS_JINGLE_DRAFT_SCTP, data.release());
  } else {
    data->set_bandwidth(options.data_bandwidth);
    SetMediaProtocol(secure_transport, data.get());
    desc->AddContent(content_name, NS_JINGLE_RTP, data.release());
  }
  if (!AddTransportOffer(content_name,
                         GetTransportOptions(options, content_name),
                         current_description, desc)) {
    return false;
  }
  return true;
}

bool MediaSessionDescriptionFactory::AddAudioContentForAnswer(
    const SessionDescription* offer,
    const MediaSessionOptions& options,
    const SessionDescription* current_description,
    StreamParamsVec* current_streams,
    SessionDescription* answer) const {
  const ContentInfo* audio_content = GetFirstAudioContent(offer);

  std::unique_ptr<TransportDescription> audio_transport(CreateTransportAnswer(
      audio_content->name, offer,
      GetTransportOptions(options, audio_content->name), current_description));
  if (!audio_transport) {
    return false;
  }

  AudioCodecs audio_codecs = audio_codecs_;
  if (!options.vad_enabled) {
    StripCNCodecs(&audio_codecs);
  }

  bool bundle_enabled =
      offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled;
  std::unique_ptr<AudioContentDescription> audio_answer(
      new AudioContentDescription());
  // Do not require or create SDES cryptos if DTLS is used.
  cricket::SecurePolicy sdes_policy =
      audio_transport->secure() ? cricket::SEC_DISABLED : secure();
  if (!CreateMediaContentAnswer(
          static_cast<const AudioContentDescription*>(
              audio_content->description),
          options,
          audio_codecs,
          sdes_policy,
          GetCryptos(GetFirstAudioContentDescription(current_description)),
          audio_rtp_extensions_,
          current_streams,
          add_legacy_,
          bundle_enabled,
          audio_answer.get())) {
    return false;  // Fails the session setup.
  }

  bool rejected = !options.has_audio() || audio_content->rejected ||
      !IsMediaProtocolSupported(MEDIA_TYPE_AUDIO,
                                audio_answer->protocol(),
                                audio_transport->secure());
  if (!rejected) {
    AddTransportAnswer(audio_content->name, *(audio_transport.get()), answer);
  } else {
    // RFC 3264
    // The answer MUST contain the same number of m-lines as the offer.
    LOG(LS_INFO) << "Audio is not supported in the answer.";
  }

  answer->AddContent(audio_content->name, audio_content->type, rejected,
                     audio_answer.release());
  return true;
}

bool MediaSessionDescriptionFactory::AddVideoContentForAnswer(
    const SessionDescription* offer,
    const MediaSessionOptions& options,
    const SessionDescription* current_description,
    StreamParamsVec* current_streams,
    SessionDescription* answer) const {
  const ContentInfo* video_content = GetFirstVideoContent(offer);
  std::unique_ptr<TransportDescription> video_transport(CreateTransportAnswer(
      video_content->name, offer,
      GetTransportOptions(options, video_content->name), current_description));
  if (!video_transport) {
    return false;
  }

  std::unique_ptr<VideoContentDescription> video_answer(
      new VideoContentDescription());
  // Do not require or create SDES cryptos if DTLS is used.
  cricket::SecurePolicy sdes_policy =
      video_transport->secure() ? cricket::SEC_DISABLED : secure();
  bool bundle_enabled =
      offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled;
  if (!CreateMediaContentAnswer(
          static_cast<const VideoContentDescription*>(
              video_content->description),
          options,
          video_codecs_,
          sdes_policy,
          GetCryptos(GetFirstVideoContentDescription(current_description)),
          video_rtp_extensions_,
          current_streams,
          add_legacy_,
          bundle_enabled,
          video_answer.get())) {
    return false;
  }
  bool rejected = !options.has_video() || video_content->rejected ||
      !IsMediaProtocolSupported(MEDIA_TYPE_VIDEO,
                                video_answer->protocol(),
                                video_transport->secure());
  if (!rejected) {
    if (!AddTransportAnswer(video_content->name, *(video_transport.get()),
                            answer)) {
      return false;
    }
    video_answer->set_bandwidth(options.video_bandwidth);
  } else {
    // RFC 3264
    // The answer MUST contain the same number of m-lines as the offer.
    LOG(LS_INFO) << "Video is not supported in the answer.";
  }
  answer->AddContent(video_content->name, video_content->type, rejected,
                     video_answer.release());
  return true;
}

bool MediaSessionDescriptionFactory::AddDataContentForAnswer(
    const SessionDescription* offer,
    const MediaSessionOptions& options,
    const SessionDescription* current_description,
    StreamParamsVec* current_streams,
    SessionDescription* answer) const {
  const ContentInfo* data_content = GetFirstDataContent(offer);
  std::unique_ptr<TransportDescription> data_transport(CreateTransportAnswer(
      data_content->name, offer,
      GetTransportOptions(options, data_content->name), current_description));
  if (!data_transport) {
    return false;
  }
  bool is_sctp = (options.data_channel_type == DCT_SCTP);
  std::vector<DataCodec> data_codecs(data_codecs_);
  FilterDataCodecs(&data_codecs, is_sctp);

  std::unique_ptr<DataContentDescription> data_answer(
      new DataContentDescription());
  // Do not require or create SDES cryptos if DTLS is used.
  cricket::SecurePolicy sdes_policy =
      data_transport->secure() ? cricket::SEC_DISABLED : secure();
  bool bundle_enabled =
      offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled;
  if (!CreateMediaContentAnswer(
          static_cast<const DataContentDescription*>(
              data_content->description),
          options,
          data_codecs_,
          sdes_policy,
          GetCryptos(GetFirstDataContentDescription(current_description)),
          RtpHeaderExtensions(),
          current_streams,
          add_legacy_,
          bundle_enabled,
          data_answer.get())) {
    return false;  // Fails the session setup.
  }

  bool rejected = !options.has_data() || data_content->rejected ||
      !IsMediaProtocolSupported(MEDIA_TYPE_DATA,
                                data_answer->protocol(),
                                data_transport->secure());
  if (!rejected) {
    data_answer->set_bandwidth(options.data_bandwidth);
    if (!AddTransportAnswer(data_content->name, *(data_transport.get()),
                            answer)) {
      return false;
    }
  } else {
    // RFC 3264
    // The answer MUST contain the same number of m-lines as the offer.
    LOG(LS_INFO) << "Data is not supported in the answer.";
  }
  answer->AddContent(data_content->name, data_content->type, rejected,
                     data_answer.release());
  return true;
}

bool IsMediaContent(const ContentInfo* content) {
  return (content &&
          (content->type == NS_JINGLE_RTP ||
           content->type == NS_JINGLE_DRAFT_SCTP));
}

bool IsAudioContent(const ContentInfo* content) {
  return IsMediaContentOfType(content, MEDIA_TYPE_AUDIO);
}

bool IsVideoContent(const ContentInfo* content) {
  return IsMediaContentOfType(content, MEDIA_TYPE_VIDEO);
}

bool IsDataContent(const ContentInfo* content) {
  return IsMediaContentOfType(content, MEDIA_TYPE_DATA);
}

const ContentInfo* GetFirstMediaContent(const ContentInfos& contents,
                                        MediaType media_type) {
  for (const ContentInfo& content : contents) {
    if (IsMediaContentOfType(&content, media_type)) {
      return &content;
    }
  }
  return nullptr;
}

const ContentInfo* GetFirstAudioContent(const ContentInfos& contents) {
  return GetFirstMediaContent(contents, MEDIA_TYPE_AUDIO);
}

const ContentInfo* GetFirstVideoContent(const ContentInfos& contents) {
  return GetFirstMediaContent(contents, MEDIA_TYPE_VIDEO);
}

const ContentInfo* GetFirstDataContent(const ContentInfos& contents) {
  return GetFirstMediaContent(contents, MEDIA_TYPE_DATA);
}

static const ContentInfo* GetFirstMediaContent(const SessionDescription* sdesc,
                                               MediaType media_type) {
  if (sdesc == nullptr) {
    return nullptr;
  }

  return GetFirstMediaContent(sdesc->contents(), media_type);
}

const ContentInfo* GetFirstAudioContent(const SessionDescription* sdesc) {
  return GetFirstMediaContent(sdesc, MEDIA_TYPE_AUDIO);
}

const ContentInfo* GetFirstVideoContent(const SessionDescription* sdesc) {
  return GetFirstMediaContent(sdesc, MEDIA_TYPE_VIDEO);
}

const ContentInfo* GetFirstDataContent(const SessionDescription* sdesc) {
  return GetFirstMediaContent(sdesc, MEDIA_TYPE_DATA);
}

const MediaContentDescription* GetFirstMediaContentDescription(
    const SessionDescription* sdesc, MediaType media_type) {
  const ContentInfo* content = GetFirstMediaContent(sdesc, media_type);
  const ContentDescription* description = content ? content->description : NULL;
  return static_cast<const MediaContentDescription*>(description);
}

const AudioContentDescription* GetFirstAudioContentDescription(
    const SessionDescription* sdesc) {
  return static_cast<const AudioContentDescription*>(
      GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO));
}

const VideoContentDescription* GetFirstVideoContentDescription(
    const SessionDescription* sdesc) {
  return static_cast<const VideoContentDescription*>(
      GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO));
}

const DataContentDescription* GetFirstDataContentDescription(
    const SessionDescription* sdesc) {
  return static_cast<const DataContentDescription*>(
      GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA));
}

//
// Non-const versions of the above functions.
//

ContentInfo* GetFirstMediaContent(ContentInfos& contents,
                                  MediaType media_type) {
  for (ContentInfo& content : contents) {
    if (IsMediaContentOfType(&content, media_type)) {
      return &content;
    }
  }
  return nullptr;
}

ContentInfo* GetFirstAudioContent(ContentInfos& contents) {
  return GetFirstMediaContent(contents, MEDIA_TYPE_AUDIO);
}

ContentInfo* GetFirstVideoContent(ContentInfos& contents) {
  return GetFirstMediaContent(contents, MEDIA_TYPE_VIDEO);
}

ContentInfo* GetFirstDataContent(ContentInfos& contents) {
  return GetFirstMediaContent(contents, MEDIA_TYPE_DATA);
}

static ContentInfo* GetFirstMediaContent(SessionDescription* sdesc,
                                         MediaType media_type) {
  if (sdesc == nullptr) {
    return nullptr;
  }

  return GetFirstMediaContent(sdesc->contents(), media_type);
}

ContentInfo* GetFirstAudioContent(SessionDescription* sdesc) {
  return GetFirstMediaContent(sdesc, MEDIA_TYPE_AUDIO);
}

ContentInfo* GetFirstVideoContent(SessionDescription* sdesc) {
  return GetFirstMediaContent(sdesc, MEDIA_TYPE_VIDEO);
}

ContentInfo* GetFirstDataContent(SessionDescription* sdesc) {
  return GetFirstMediaContent(sdesc, MEDIA_TYPE_DATA);
}

MediaContentDescription* GetFirstMediaContentDescription(
    SessionDescription* sdesc,
    MediaType media_type) {
  ContentInfo* content = GetFirstMediaContent(sdesc, media_type);
  ContentDescription* description = content ? content->description : NULL;
  return static_cast<MediaContentDescription*>(description);
}

AudioContentDescription* GetFirstAudioContentDescription(
    SessionDescription* sdesc) {
  return static_cast<AudioContentDescription*>(
      GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO));
}

VideoContentDescription* GetFirstVideoContentDescription(
    SessionDescription* sdesc) {
  return static_cast<VideoContentDescription*>(
      GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO));
}

DataContentDescription* GetFirstDataContentDescription(
    SessionDescription* sdesc) {
  return static_cast<DataContentDescription*>(
      GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA));
}

}  // namespace cricket
