/*
 * libjingle
 * Copyright 2004--2005, 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/phone/mediasession.h"

#include "talk/base/helpers.h"
#include "talk/base/logging.h"
#include "talk/base/scoped_ptr.h"
#include "talk/p2p/base/constants.h"
#include "talk/session/phone/channelmanager.h"
#include "talk/session/phone/cryptoparams.h"
#include "talk/session/phone/srtpfilter.h"
#include "talk/xmpp/constants.h"

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

namespace cricket {

using talk_base::scoped_ptr;

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

  if (!talk_base::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 = out->size();

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

// For audio, HMAC 32 is prefered because of the low overhead.
static bool GetSupportedAudioCryptos(CryptoParamsVec* cryptos) {
#ifdef HAVE_SRTP
  return AddCryptoParams(CS_AES_CM_128_HMAC_SHA1_32, cryptos) &&
      AddCryptoParams(CS_AES_CM_128_HMAC_SHA1_80, cryptos);
#else
  return false;
#endif
}

static bool GetSupportedVideoCryptos(CryptoParamsVec* cryptos) {
#ifdef HAVE_SRTP
  return AddCryptoParams(CS_AES_CM_128_HMAC_SHA1_80, cryptos);
#else
  return false;
#endif
}

// For video support only 80-bit SHA1 HMAC. For audio 32-bit HMAC is
// tolerated because it is low overhead. Pick the crypto in the list
// that is supported.
static bool SelectCrypto(const MediaContentDescription* offer,
                         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)) {
      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;

    StreamParams param;
    // nick is empty for StreamParams generated using
    // MediaSessionDescriptionFactory.
    if (GetStreamByNickAndName(params_vec, "", stream_it->name,
                               &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 (!talk_base::CreateRandomString(16, cname)) {
      ASSERT(false);
      return false;
    }
  } while (FindFirstStreamParamsByCname(params_vec, *cname));

  return true;
}

// Generate a new SSRC and make sure it does not exist in params_vec.
static uint32 GenerateSsrc(const StreamParamsVec& params_vec) {
  uint32 ssrc = 0;
  do {
    ssrc = talk_base::CreateRandomNonZeroId();
  } while (GetStreamBySsrc(params_vec, ssrc, NULL));
  return ssrc;
}

// 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 (!IsAudioContent(&*content) && !IsVideoContent(&*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);
    }
  }
}

// Adds a StreamParams for each Stream in Streams with media type
// media_type to content_description.
// current_parms - All currently known StreamParams of any media type.
static bool AddStreamParams(
    MediaType media_type,
    const MediaSessionOptions::Streams& streams,
    StreamParamsVec* current_params,
    MediaContentDescription* content_description) {
  for (MediaSessionOptions::Streams::const_iterator stream_it = streams.begin();
       stream_it != streams.end(); ++stream_it) {
    if (stream_it->type != media_type)
      continue;  // Wrong media type.

    StreamParams param;
    // nick is empty for StreamParams generated using
    // MediaSessionDescriptionFactory.
    if (!GetStreamByNickAndName(*current_params, "", stream_it->name, &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_params, streams, stream_it->sync_label,
                         &cname)) {
        return false;
      }
      uint32 ssrc = GenerateSsrc(*current_params);
      // TODO: Generate the more complex types of stream_params.

      StreamParams stream_param;
      stream_param.name = stream_it->name;
      stream_param.ssrcs.push_back(ssrc);
      stream_param.cname = cname;
      stream_param.sync_label = stream_it->sync_label;
      content_description->AddStream(stream_param);

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

void MediaSessionOptions::AddStream(MediaType type,
                                    const std::string& name,
                                    const std::string& sync_label) {
  streams.push_back(Stream(type, name, sync_label));

  if (type == MEDIA_TYPE_VIDEO)
    has_video = true;
  else if (type == MEDIA_TYPE_AUDIO)
    has_audio = true;
}

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

MediaSessionDescriptionFactory::MediaSessionDescriptionFactory()
    : secure_(SEC_DISABLED),
      add_legacy_(true) {
}

MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
    ChannelManager* channel_manager)
    : secure_(SEC_DISABLED),
      add_legacy_(true) {
  channel_manager->GetSupportedAudioCodecs(&audio_codecs_);
  channel_manager->GetSupportedVideoCodecs(&video_codecs_);
}

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

  StreamParamsVec current_params;
  GetCurrentStreamParams(current_description, &current_params);

  if (options.has_audio) {
    scoped_ptr<AudioContentDescription> audio(new AudioContentDescription());
    for (AudioCodecs::const_iterator codec = audio_codecs_.begin();
         codec != audio_codecs_.end(); ++codec) {
      audio->AddCodec(*codec);
    }
    audio->SortCodecs();
    if (!AddStreamParams(MEDIA_TYPE_AUDIO, options.streams, &current_params,
                         audio.get())) {
      return NULL;  // Abort, something went seriously wrong.
    }

    if (options.streams.empty() && add_legacy_) {
      // TODO: Remove this legacy stream when all apps use StreamParams.
      audio->AddLegacyStream(talk_base::CreateRandomNonZeroId());
    }
    audio->set_multistream(options.is_muc);
    audio->set_rtcp_mux(options.rtcp_mux_enabled);
    audio->set_lang(lang_);

    if (secure() != SEC_DISABLED) {
      CryptoParamsVec audio_cryptos;
      if (current_description) {
        // Copy crypto parameters from the previous offer.
        const ContentInfo* info =
            GetFirstAudioContent(current_description);
        if (info) {
          const AudioContentDescription* desc =
              static_cast<const AudioContentDescription*>(info->description);
          audio_cryptos = desc->cryptos();
        }
      }
      if (audio_cryptos.empty())
        GetSupportedAudioCryptos(&audio_cryptos);  // Generate new cryptos.

      for (CryptoParamsVec::const_iterator crypto = audio_cryptos.begin();
           crypto != audio_cryptos.end(); ++crypto) {
        audio->AddCrypto(*crypto);
      }

      if (secure() == SEC_REQUIRED) {
        if (audio->cryptos().empty()) {
          return NULL;  // Abort, crypto required but none found.
        }
        audio->set_crypto_required(true);
      }
    }

    offer->AddContent(CN_AUDIO, NS_JINGLE_RTP, audio.release());
  }

  // add video codecs, if this is a video call
  if (options.has_video) {
    scoped_ptr<VideoContentDescription> video(new VideoContentDescription());
    for (VideoCodecs::const_iterator codec = video_codecs_.begin();
         codec != video_codecs_.end(); ++codec) {
      video->AddCodec(*codec);
    }

    video->SortCodecs();
    if (!AddStreamParams(MEDIA_TYPE_VIDEO, options.streams, &current_params,
                         video.get())) {
      return NULL;  // Abort, something went seriously wrong.
    }

    if (options.streams.empty() && add_legacy_) {
      // TODO: Remove this legacy stream when all apps use StreamParams.
      video->AddLegacyStream(talk_base::CreateRandomNonZeroId());
    }
    video->set_multistream(options.is_muc);
    video->set_bandwidth(options.video_bandwidth);
    video->set_rtcp_mux(options.rtcp_mux_enabled);

    if (secure() != SEC_DISABLED) {
      CryptoParamsVec video_cryptos;
      if (current_description) {
        // Copy crypto parameters from the previous offer.
        const VideoContentDescription* desc =
            GetFirstVideoContentDescription(current_description);
        if (desc) {
          video_cryptos = desc->cryptos();
        }
      }
      if (video_cryptos.empty())
        GetSupportedVideoCryptos(&video_cryptos);  // Generate new crypto.
      for (CryptoParamsVec::const_iterator crypto = video_cryptos.begin();
           crypto != video_cryptos.end(); ++crypto) {
        video->AddCrypto(*crypto);
      }
      if (secure() == SEC_REQUIRED) {
        if (video->cryptos().empty()) {
          return NULL;  // Abort, crypto required but none found.
        }
        video->set_crypto_required(true);
      }
    }

    offer->AddContent(CN_VIDEO, NS_JINGLE_RTP, video.release());
  }

  return offer.release();
}

SessionDescription* MediaSessionDescriptionFactory::CreateAnswer(
    const SessionDescription* offer, const MediaSessionOptions& options,
    const SessionDescription* current_description) {
  // 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> accept(new SessionDescription());

  StreamParamsVec current_params;
  GetCurrentStreamParams(current_description, &current_params);

  const ContentInfo* audio_content = GetFirstAudioContent(offer);
  if (audio_content && options.has_audio) {
    const AudioContentDescription* audio_offer =
        static_cast<const AudioContentDescription*>(audio_content->description);
    scoped_ptr<AudioContentDescription> audio_accept(
        new AudioContentDescription());
    for (AudioCodecs::const_iterator ours = audio_codecs_.begin();
        ours != audio_codecs_.end(); ++ours) {
      for (AudioCodecs::const_iterator theirs = audio_offer->codecs().begin();
          theirs != audio_offer->codecs().end(); ++theirs) {
        if (ours->Matches(*theirs)) {
          AudioCodec negotiated(*ours);
          negotiated.id = theirs->id;
          audio_accept->AddCodec(negotiated);
        }
      }
    }

    audio_accept->SortCodecs();
    if (!AddStreamParams(MEDIA_TYPE_AUDIO, options.streams, &current_params,
                         audio_accept.get())) {
      return NULL;  // Abort, something went seriously wrong.
    }

    if (options.streams.empty() && add_legacy_) {
      // TODO: Remove this legacy stream when all apps use StreamParams.
      audio_accept->AddLegacyStream(talk_base::CreateRandomNonZeroId());
    }
    audio_accept->set_rtcp_mux(
        options.rtcp_mux_enabled && audio_offer->rtcp_mux());

    if (secure() != SEC_DISABLED) {
      CryptoParams crypto;

      if (SelectCrypto(audio_offer, &crypto)) {
        if (current_description) {
          // Check if this crypto already exist in the previous
          // session description. Use it in that case.
          const ContentInfo* info =
              GetFirstAudioContent(current_description);
          if (info) {
            const AudioContentDescription* desc =
                static_cast<const AudioContentDescription*>(info->description);
            const CryptoParamsVec& cryptos = desc->cryptos();
            for (CryptoParamsVec::const_iterator it = cryptos.begin();
                it != cryptos.end(); ++it) {
              if (crypto.Matches(*it)) {
                crypto = *it;
                break;
              }
            }
          }
        }
        audio_accept->AddCrypto(crypto);
      }
    }

    if (audio_accept->cryptos().empty() &&
        (audio_offer->crypto_required() || secure() == SEC_REQUIRED)) {
      return NULL;  // Fails the session setup.
    }
    accept->AddContent(audio_content->name, audio_content->type,
                       audio_accept.release());
  } else {
    LOG(LS_INFO) << "Audio is not supported in answer";
  }

  const ContentInfo* video_content = GetFirstVideoContent(offer);
  if (video_content && options.has_video) {
    const VideoContentDescription* video_offer =
        static_cast<const VideoContentDescription*>(video_content->description);
    scoped_ptr<VideoContentDescription> video_accept(
        new VideoContentDescription());
    for (VideoCodecs::const_iterator ours = video_codecs_.begin();
        ours != video_codecs_.end(); ++ours) {
      for (VideoCodecs::const_iterator theirs = video_offer->codecs().begin();
          theirs != video_offer->codecs().end(); ++theirs) {
        if (ours->Matches(*theirs)) {
          VideoCodec negotiated(*ours);
          negotiated.id = theirs->id;
          video_accept->AddCodec(negotiated);
        }
      }
    }
    if (!AddStreamParams(MEDIA_TYPE_VIDEO, options.streams, &current_params,
                         video_accept.get())) {
      return NULL;  // Abort, something went seriously wrong.
    }

    if (options.streams.empty() && add_legacy_) {
      // TODO: Remove this legacy stream when all apps use StreamParams.
      video_accept->AddLegacyStream(talk_base::CreateRandomNonZeroId());
    }
    video_accept->set_bandwidth(options.video_bandwidth);
    video_accept->set_rtcp_mux(
        options.rtcp_mux_enabled && video_offer->rtcp_mux());
    video_accept->SortCodecs();

    if (secure() != SEC_DISABLED) {
      CryptoParams crypto;

      if (SelectCrypto(video_offer, &crypto)) {
        if (current_description) {
          // Check if this crypto already exist in the previous
          // session description. Use it in that case.
          const VideoContentDescription* desc =
              GetFirstVideoContentDescription(current_description);
          if (desc) {
            const CryptoParamsVec& cryptos = desc->cryptos();
            for (CryptoParamsVec::const_iterator it = cryptos.begin();
                 it != cryptos.end(); ++it) {
              if (crypto.Matches(*it)) {
                crypto = *it;
                break;
              }
            }
          }
        }
        video_accept->AddCrypto(crypto);
      }
    }

    if (video_accept->cryptos().empty() &&
        (video_offer->crypto_required() || secure() == SEC_REQUIRED)) {
      return NULL;  // Fails the session setup.
    }
    accept->AddContent(video_content->name, video_content->type,
                       video_accept.release());
  } else {
    LOG(LS_INFO) << "Video is not supported in answer";
  }
  return accept.release();
}

static bool IsMediaContent(const ContentInfo* content, MediaType media_type) {
  if (content == NULL || content->type != NS_JINGLE_RTP) {
    return false;
  }

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

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

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

static const ContentInfo* GetFirstMediaContent(const ContentInfos& contents,
                                               MediaType media_type) {
  for (ContentInfos::const_iterator content = contents.begin();
       content != contents.end(); content++) {
    if (IsMediaContent(&*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);
}

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 AudioContentDescription* GetFirstAudioContentDescription(
    const SessionDescription* sdesc) {
  const ContentInfo* content = GetFirstAudioContent(sdesc);
  const ContentDescription* description = content ? content->description : NULL;
  return static_cast<const AudioContentDescription*>(description);
}

const VideoContentDescription* GetFirstVideoContentDescription(
    const SessionDescription* sdesc) {
  const ContentInfo* content = GetFirstVideoContent(sdesc);
  const ContentDescription* description = content ? content->description : NULL;
  return static_cast<const VideoContentDescription*>(description);
}

}  // namespace cricket
