/*
 * libjingle
 * Copyright 2004 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/session/media/mediasession.h"

#include <functional>
#include <map>
#include <set>
#include <utility>

#include "talk/media/base/constants.h"
#include "talk/media/base/cryptoparams.h"
#include "talk/session/media/channelmanager.h"
#include "talk/session/media/srtpfilter.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/p2p/base/constants.h"

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

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

namespace cricket {

using rtc::scoped_ptr;

// 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";

// This should be replaced by "UDP/TLS/RTP/SAVPF", but we need to support it for
// now to be compatible with previous Chrome versions.
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<std::string>* crypto_suites) {
#ifdef HAVE_SRTP
  crypto_suites->push_back(CS_AES_CM_128_HMAC_SHA1_32);
  crypto_suites->push_back(CS_AES_CM_128_HMAC_SHA1_80);
#endif
}

void GetSupportedVideoCryptoSuites(
    std::vector<std::string>* crypto_suites) {
  GetSupportedDefaultCryptoSuites(crypto_suites);
}

void GetSupportedDataCryptoSuites(
    std::vector<std::string>* crypto_suites) {
  GetSupportedDefaultCryptoSuites(crypto_suites);
}

void GetSupportedDefaultCryptoSuites(
    std::vector<std::string>* crypto_suites) {
#ifdef HAVE_SRTP
  crypto_suites->push_back(CS_AES_CM_128_HMAC_SHA1_80);
#endif
}

// 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 (CS_AES_CM_128_HMAC_SHA1_80 == i->cipher_suite ||
        (CS_AES_CM_128_HMAC_SHA1_32 == i->cipher_suite && audio && !bundle)) {
      return CreateCryptoParams(i->tag, i->cipher_suite, crypto);
    }
  }
  return false;
}

static const StreamParams* FindFirstStreamParamsByCname(
    const StreamParamsVec& params_vec,
    const std::string& cname) {
  for (StreamParamsVec::const_iterator it = params_vec.begin();
       it != params_vec.end(); ++it) {
    if (cname == it->cname)
      return &*it;
  }
  return NULL;
}

// Generates a new CNAME or the CNAME of an already existing StreamParams
// if a StreamParams exist for another Stream in streams with sync_label
// sync_label.
static bool GenerateCname(const StreamParamsVec& params_vec,
                          const MediaSessionOptions::Streams& streams,
                          const std::string& synch_label,
                          std::string* cname) {
  ASSERT(cname != NULL);
  if (!cname)
    return false;

  // Check if a CNAME exist for any of the other synched streams.
  for (MediaSessionOptions::Streams::const_iterator stream_it = streams.begin();
       stream_it != streams.end() ; ++stream_it) {
    if (synch_label != stream_it->sync_label)
      continue;

    // groupid is empty for StreamParams generated using
    // MediaSessionDescriptionFactory.
    const StreamParams* param = GetStreamByIds(params_vec, "", stream_it->id);
    if (param) {
      *cname = param->cname;
      return true;
    }
  }
  // No other stream seems to exist that we should sync with.
  // Generate a random string for the RTCP CNAME, as stated in RFC 6222.
  // This string is only used for synchronization, and therefore is opaque.
  do {
    if (!rtc::CreateRandomString(16, cname)) {
      ASSERT(false);
      return false;
    }
  } while (FindFirstStreamParamsByCname(params_vec, *cname));

  return true;
}

// 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>* ssrcs) {
  for (int i = 0; i < num_ssrcs; i++) {
    uint32 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* sid) {
  if (params_vec.size() > kMaxSctpSid) {
    LOG(LS_WARNING) <<
        "Could not generate an SCTP SID: too many SCTP streams.";
    return false;
  }
  while (true) {
    uint32 candidate = rtc::CreateRandomNonZeroId() % kMaxSctpSid;
    if (!GetStreamBySsrc(params_vec, candidate)) {
      *sid = candidate;
      return true;
    }
  }
}

static bool GenerateSctpSids(const StreamParamsVec& params_vec,
                             std::vector<uint32>* sids) {
  uint32 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<RtpHeaderExtension> {
 public:
  UsedRtpHeaderExtensionIds()
      : UsedIds<RtpHeaderExtension>(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::Streams& streams,
    StreamParamsVec* current_streams,
    MediaContentDescriptionImpl<C>* content_description,
    const bool add_legacy_stream) {
  const bool include_rtx_stream =
    ContainsRtxCodec(content_description->codecs());

  if (streams.empty() && add_legacy_stream) {
    // TODO(perkj): Remove this legacy stream when all apps use StreamParams.
    std::vector<uint32> ssrcs;
    if (IsSctp(content_description)) {
      GenerateSctpSids(*current_streams, &ssrcs);
    } else {
      int num_ssrcs = include_rtx_stream ? 2 : 1;
      GenerateSsrcs(*current_streams, num_ssrcs, &ssrcs);
    }
    if (include_rtx_stream) {
      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.
      // Get a CNAME. Either new or same as one of the other synched streams.
      std::string cname;
      if (!GenerateCname(*current_streams, streams, stream_it->sync_label,
                         &cname)) {
        return false;
      }

      std::vector<uint32> 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 an extra ssrc for include_rtx_stream case.
      if (include_rtx_stream) {
        std::vector<uint32> rtx_ssrc;
        GenerateSsrcs(*current_streams, 1, &rtx_ssrc);
        stream_param.AddFidSsrc(ssrcs[0], rtx_ssrc[0]);
        content_description->set_multistream(true);
      }
      stream_param.cname = 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 and pwd 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.
  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;
  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;
    }
  }
  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 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 = media_desc->protocol().empty() ||
             rtc::starts_with(media_desc->protocol().data(),
                                    kMediaProtocolRtpPrefix);
  }
  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;
}

// 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);
  offer->SortCodecs();

  if (secure_policy == SEC_REQUIRED) {
    offer->set_crypto_required(CT_SDES);
  }
  offer->set_rtcp_mux(options.rtcp_mux_enabled);
  offer->set_multistream(options.is_muc);
  offer->set_rtp_header_extensions(rtp_extensions);

  if (!AddStreamParams(
          offer->type(), options.streams, 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) {
  typename std::vector<C>::const_iterator ours;
  for (ours = local_codecs.begin();
       ours != local_codecs.end(); ++ours) {
    typename std::vector<C>::const_iterator theirs;
    for (theirs = offered_codecs.begin();
         theirs != offered_codecs.end(); ++theirs) {
      if (ours->Matches(*theirs)) {
        C negotiated = *ours;
        negotiated.IntersectFeedbackParams(*theirs);
        if (IsRtxCodec(negotiated)) {
          std::string offered_apt_value;
          std::string local_apt_value;
          if (!ours->GetParam(kCodecParamAssociatedPayloadType,
                              &local_apt_value) ||
              !theirs->GetParam(kCodecParamAssociatedPayloadType,
                                &offered_apt_value)) {
            LOG(LS_WARNING) << "RTX missing associated payload type.";
            continue;
          }
          // Only negotiate RTX if kCodecParamAssociatedPayloadType has been
          // set in local and remote codecs, and they match.
          if (!ReferencedCodecsMatch(local_codecs, local_apt_value,
                                     offered_codecs, offered_apt_value)) {
            LOG(LS_WARNING) << "RTX associated codecs don't match.";
            continue;
          }
          negotiated.SetParam(kCodecParamAssociatedPayloadType,
                              offered_apt_value);
        }

        negotiated.id = theirs->id;
        // 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.
        negotiated.preference = theirs->preference;
        negotiated_codecs->push_back(negotiated);
      }
    }
  }
}

template <class C>
static bool FindMatchingCodec(const std::vector<C>& codecs,
                              const C& codec_to_match,
                              C* found_codec) {
  for (typename std::vector<C>::const_iterator it = codecs.begin();
       it  != codecs.end(); ++it) {
    if (it->Matches(codec_to_match)) {
      if (found_codec != NULL) {
        *found_codec= *it;
      }
      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) {

  typedef std::map<int, C> RtxCodecReferences;
  RtxCodecReferences new_rtx_codecs;

  // Find all new RTX codecs.
  for (typename std::vector<C>::const_iterator it = reference_codecs.begin();
       it != reference_codecs.end(); ++it) {
    if (!FindMatchingCodec<C>(*offered_codecs, *it, NULL) && IsRtxCodec(*it)) {
      C rtx_codec = *it;
      int referenced_pl_type =
          rtc::FromString<int>(0,
              rtx_codec.params[kCodecParamAssociatedPayloadType]);
      new_rtx_codecs.insert(std::pair<int, C>(referenced_pl_type,
                                              rtx_codec));
    }
  }

  // Add all new codecs that are not RTX codecs.
  for (typename std::vector<C>::const_iterator it = reference_codecs.begin();
       it != reference_codecs.end(); ++it) {
    if (!FindMatchingCodec<C>(*offered_codecs, *it, NULL) && !IsRtxCodec(*it)) {
      C codec = *it;
      int original_payload_id = codec.id;
      used_pltypes->FindAndSetIdUsed(&codec);
      offered_codecs->push_back(codec);

      // If this codec is referenced by a new RTX codec, update the reference
      // in the RTX codec with the new payload type.
      typename RtxCodecReferences::iterator rtx_it =
          new_rtx_codecs.find(original_payload_id);
      if (rtx_it != new_rtx_codecs.end()) {
        C& rtx_codec = rtx_it->second;
        rtx_codec.params[kCodecParamAssociatedPayloadType] =
            rtc::ToString(codec.id);
      }
    }
  }

  // Add all new RTX codecs.
  for (typename RtxCodecReferences::iterator it = new_rtx_codecs.begin();
       it != new_rtx_codecs.end(); ++it) {
    C& rtx_codec = it->second;
    used_pltypes->FindAndSetIdUsed(&rtx_codec);
    offered_codecs->push_back(rtx_codec);
  }
}


static bool FindByUri(const RtpHeaderExtensions& extensions,
                      const RtpHeaderExtension& ext_to_match,
                      RtpHeaderExtension* 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;
}

static void FindAndSetRtpHdrExtUsed(
  const RtpHeaderExtensions& reference_extensions,
  RtpHeaderExtensions* offered_extensions,
  const RtpHeaderExtensions& other_extensions,
  UsedRtpHeaderExtensionIds* used_extensions) {
  for (RtpHeaderExtensions::const_iterator it = reference_extensions.begin();
      it != reference_extensions.end(); ++it) {
    if (!FindByUri(*offered_extensions, *it, NULL)) {
      RtpHeaderExtension ext;
      if (!FindByUri(other_extensions, *it, &ext)) {
        ext = *it;
        used_extensions->FindAndSetIdUsed(&ext);
      }
      offered_extensions->push_back(ext);
    }
  }
}

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) {
    RtpHeaderExtension 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->SortCodecs();
  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 (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.streams, 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(MD_SENDONLY);
      break;
    case MD_SENDRECV:
      answer->set_direction(MD_SENDRECV);
      break;
    default:
      break;
  }

  return true;
}

static bool IsMediaProtocolSupported(MediaType type,
                                     const std::string& protocol,
                                     bool secure_transport) {
  // Data channels can have a protocol of SCTP or SCTP/DTLS.
  if (type == MEDIA_TYPE_DATA &&
      ((protocol == kMediaProtocolSctp && !secure_transport)||
       (protocol == kMediaProtocolDtlsSctp && secure_transport))) {
    return true;
  }

  // Since not all applications serialize and deserialize the media protocol,
  // we will have to accept |protocol| to be empty.
  return protocol == kMediaProtocolAvpf || protocol.empty() ||
      protocol == kMediaProtocolSavpf ||
      (protocol == kMediaProtocolDtlsSavpf && secure_transport);
}

static void SetMediaProtocol(bool secure_transport,
                             MediaContentDescription* desc) {
  if (!desc->cryptos().empty() || secure_transport)
    desc->set_protocol(kMediaProtocolSavpf);
  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 {
  scoped_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, ordered by our local preference. As indicated by
  // XEP-0167, we retain the same payload ids from the offer in the answer.
  scoped_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;
  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();
      used_ids.FindAndSetIdUsed(audio_extensions);
    }
    const VideoContentDescription* video =
        GetFirstVideoContentDescription(current_description);
    if (video) {
      *video_extensions = video->rtp_header_extensions();
      used_ids.FindAndSetIdUsed(video_extensions);
    }
  }

  // Add our default RTP header extensions that are not in
  // |current_description|.
  FindAndSetRtpHdrExtUsed(audio_rtp_header_extensions(), audio_extensions,
                          *video_extensions, &used_ids);
  FindAndSetRtpHdrExtUsed(video_rtp_header_extensions(), video_extensions,
                          *audio_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);
  rtc::scoped_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 {
  cricket::SecurePolicy sdes_policy =
      IsDtlsActive(CN_AUDIO, current_description) ?
          cricket::SEC_DISABLED : secure();

  scoped_ptr<AudioContentDescription> audio(new AudioContentDescription());
  std::vector<std::string> crypto_suites;
  GetSupportedAudioCryptoSuites(&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 (!options.recv_audio) {
    audio->set_direction(MD_SENDONLY);
  }

  desc->AddContent(CN_AUDIO, NS_JINGLE_RTP, audio.release());
  if (!AddTransportOffer(CN_AUDIO, options.transport_options,
                         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 {
  cricket::SecurePolicy sdes_policy =
      IsDtlsActive(CN_VIDEO, current_description) ?
          cricket::SEC_DISABLED : secure();

  scoped_ptr<VideoContentDescription> video(new VideoContentDescription());
  std::vector<std::string> crypto_suites;
  GetSupportedVideoCryptoSuites(&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 (!options.recv_video) {
    video->set_direction(MD_SENDONLY);
  }

  desc->AddContent(CN_VIDEO, NS_JINGLE_RTP, video.release());
  if (!AddTransportOffer(CN_VIDEO, options.transport_options,
                         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);

  scoped_ptr<DataContentDescription> data(new DataContentDescription());
  bool is_sctp = (options.data_channel_type == DCT_SCTP);

  FilterDataCodecs(data_codecs, is_sctp);

  cricket::SecurePolicy sdes_policy =
      IsDtlsActive(CN_DATA, 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 {
    GetSupportedDataCryptoSuites(&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(CN_DATA, NS_JINGLE_DRAFT_SCTP, data.release());
  } else {
    data->set_bandwidth(options.data_bandwidth);
    SetMediaProtocol(secure_transport, data.get());
    desc->AddContent(CN_DATA, NS_JINGLE_RTP, data.release());
  }
  if (!AddTransportOffer(CN_DATA, options.transport_options,
                         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);

  scoped_ptr<TransportDescription> audio_transport(
      CreateTransportAnswer(audio_content->name, offer,
                            options.transport_options,
                            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;
  scoped_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);
  scoped_ptr<TransportDescription> video_transport(
      CreateTransportAnswer(video_content->name, offer,
                            options.transport_options,
                            current_description));
  if (!video_transport) {
    return false;
  }

  scoped_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);
  scoped_ptr<TransportDescription> data_transport(
      CreateTransportAnswer(data_content->name, offer,
                            options.transport_options,
                            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);

  scoped_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);
}

static const ContentInfo* GetFirstMediaContent(const ContentInfos& contents,
                                               MediaType media_type) {
  for (ContentInfos::const_iterator content = contents.begin();
       content != contents.end(); content++) {
    if (IsMediaContentOfType(&*content, media_type)) {
      return &*content;
    }
  }
  return NULL;
}

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 == NULL)
    return NULL;

  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));
}

bool GetMediaChannelNameFromComponent(
    int component, MediaType media_type, std::string* channel_name) {
  if (media_type == MEDIA_TYPE_AUDIO) {
    if (component == ICE_CANDIDATE_COMPONENT_RTP) {
      *channel_name = GICE_CHANNEL_NAME_RTP;
      return true;
    } else if (component == ICE_CANDIDATE_COMPONENT_RTCP) {
      *channel_name = GICE_CHANNEL_NAME_RTCP;
      return true;
    }
  } else if (media_type == MEDIA_TYPE_VIDEO) {
    if (component == ICE_CANDIDATE_COMPONENT_RTP) {
      *channel_name = GICE_CHANNEL_NAME_VIDEO_RTP;
      return true;
    } else if (component == ICE_CANDIDATE_COMPONENT_RTCP) {
      *channel_name = GICE_CHANNEL_NAME_VIDEO_RTCP;
      return true;
    }
  } else if (media_type == MEDIA_TYPE_DATA) {
    if (component == ICE_CANDIDATE_COMPONENT_RTP) {
      *channel_name = GICE_CHANNEL_NAME_DATA_RTP;
      return true;
    } else if (component == ICE_CANDIDATE_COMPONENT_RTCP) {
      *channel_name = GICE_CHANNEL_NAME_DATA_RTCP;
      return true;
    }
  }

  return false;
}

bool GetMediaComponentFromChannelName(
    const std::string& channel_name, int* component) {
  if (channel_name == GICE_CHANNEL_NAME_RTP ||
      channel_name == GICE_CHANNEL_NAME_VIDEO_RTP ||
      channel_name == GICE_CHANNEL_NAME_DATA_RTP) {
    *component = ICE_CANDIDATE_COMPONENT_RTP;
    return true;
  } else if (channel_name == GICE_CHANNEL_NAME_RTCP ||
             channel_name == GICE_CHANNEL_NAME_VIDEO_RTCP ||
             channel_name == GICE_CHANNEL_NAME_DATA_RTP) {
    *component = ICE_CANDIDATE_COMPONENT_RTCP;
    return true;
  }

  return false;
}

bool GetMediaTypeFromChannelName(
    const std::string& channel_name, MediaType* media_type) {
  if (channel_name == GICE_CHANNEL_NAME_RTP ||
      channel_name == GICE_CHANNEL_NAME_RTCP) {
    *media_type = MEDIA_TYPE_AUDIO;
    return true;
  } else if (channel_name == GICE_CHANNEL_NAME_VIDEO_RTP ||
             channel_name == GICE_CHANNEL_NAME_VIDEO_RTCP) {
    *media_type = MEDIA_TYPE_VIDEO;
    return true;
  } else if (channel_name == GICE_CHANNEL_NAME_DATA_RTP ||
             channel_name == GICE_CHANNEL_NAME_DATA_RTCP) {
    *media_type = MEDIA_TYPE_DATA;
    return true;
  }

  return false;
}

}  // namespace cricket
