/*
 * 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) {
}

MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
    ChannelManager* channel_manager)
    : secure_(SEC_DISABLED) {
  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()) {
      // 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()) {
      // 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()) {
      // 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()) {
      // 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
