/*
 * libjingle
 * Copyright 2012 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 <string>

#include "talk/media/base/constants.h"
#include "talk/media/base/fakenetworkinterface.h"
#include "talk/media/base/rtpdataengine.h"
#include "talk/media/base/rtputils.h"
#include "webrtc/base/buffer.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/ssladapter.h"
#include "webrtc/base/timing.h"

class FakeTiming : public rtc::Timing {
 public:
  FakeTiming() : now_(0.0) {}

  virtual double TimerNow() {
    return now_;
  }

  void set_now(double now) {
    now_ = now;
  }

 private:
  double now_;
};

class FakeDataReceiver : public sigslot::has_slots<> {
 public:
  FakeDataReceiver() : has_received_data_(false) {}

  void OnDataReceived(
      const cricket::ReceiveDataParams& params,
      const char* data, size_t len) {
    has_received_data_ = true;
    last_received_data_ = std::string(data, len);
    last_received_data_len_ = len;
    last_received_data_params_ = params;
  }

  bool has_received_data() const { return has_received_data_; }
  std::string last_received_data() const { return last_received_data_; }
  size_t last_received_data_len() const { return last_received_data_len_; }
  cricket::ReceiveDataParams last_received_data_params() const {
    return last_received_data_params_;
  }

 private:
  bool has_received_data_;
  std::string last_received_data_;
  size_t last_received_data_len_;
  cricket::ReceiveDataParams last_received_data_params_;
};

class RtpDataMediaChannelTest : public testing::Test {
 protected:
  virtual void SetUp() {
    // Seed needed for each test to satisfy expectations.
    iface_.reset(new cricket::FakeNetworkInterface());
    timing_ = new FakeTiming();
    dme_.reset(CreateEngine(timing_));
    receiver_.reset(new FakeDataReceiver());
  }

  void SetNow(double now) {
    timing_->set_now(now);
  }

  cricket::RtpDataEngine* CreateEngine(FakeTiming* timing) {
    cricket::RtpDataEngine* dme = new cricket::RtpDataEngine();
    dme->SetTiming(timing);
    return dme;
  }

  cricket::RtpDataMediaChannel* CreateChannel() {
    return CreateChannel(dme_.get());
  }

  cricket::RtpDataMediaChannel* CreateChannel(cricket::RtpDataEngine* dme) {
    cricket::RtpDataMediaChannel* channel =
        static_cast<cricket::RtpDataMediaChannel*>(dme->CreateChannel(
            cricket::DCT_RTP));
    channel->SetInterface(iface_.get());
    channel->SignalDataReceived.connect(
        receiver_.get(), &FakeDataReceiver::OnDataReceived);
    return channel;
  }

  FakeDataReceiver* receiver() {
    return receiver_.get();
  }

  bool HasReceivedData() {
    return receiver_->has_received_data();
  }

  std::string GetReceivedData() {
    return receiver_->last_received_data();
  }

  size_t GetReceivedDataLen() {
    return receiver_->last_received_data_len();
  }

  cricket::ReceiveDataParams GetReceivedDataParams() {
    return receiver_->last_received_data_params();
  }

  bool HasSentData(int count) {
    return (iface_->NumRtpPackets() > count);
  }

  std::string GetSentData(int index) {
    // Assume RTP header of length 12
    rtc::scoped_ptr<const rtc::Buffer> packet(
        iface_->GetRtpPacket(index));
    if (packet->size() > 12) {
      return std::string(packet->data<char>() + 12, packet->size() - 12);
    } else {
      return "";
    }
  }

  cricket::RtpHeader GetSentDataHeader(int index) {
    rtc::scoped_ptr<const rtc::Buffer> packet(
        iface_->GetRtpPacket(index));
    cricket::RtpHeader header;
    GetRtpHeader(packet->data(), packet->size(), &header);
    return header;
  }

 private:
  rtc::scoped_ptr<cricket::RtpDataEngine> dme_;
  // Timing passed into dme_.  Owned by dme_;
  FakeTiming* timing_;
  rtc::scoped_ptr<cricket::FakeNetworkInterface> iface_;
  rtc::scoped_ptr<FakeDataReceiver> receiver_;
};

TEST_F(RtpDataMediaChannelTest, SetUnknownCodecs) {
  rtc::scoped_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());

  cricket::DataCodec known_codec;
  known_codec.id = 103;
  known_codec.name = "google-data";
  cricket::DataCodec unknown_codec;
  unknown_codec.id = 104;
  unknown_codec.name = "unknown-data";

  cricket::DataSendParameters send_parameters_known;
  send_parameters_known.codecs.push_back(known_codec);
  cricket::DataRecvParameters recv_parameters_known;
  recv_parameters_known.codecs.push_back(known_codec);

  cricket::DataSendParameters send_parameters_unknown;
  send_parameters_unknown.codecs.push_back(unknown_codec);
  cricket::DataRecvParameters recv_parameters_unknown;
  recv_parameters_unknown.codecs.push_back(unknown_codec);

  cricket::DataSendParameters send_parameters_mixed;
  send_parameters_mixed.codecs.push_back(known_codec);
  send_parameters_mixed.codecs.push_back(unknown_codec);
  cricket::DataRecvParameters recv_parameters_mixed;
  recv_parameters_mixed.codecs.push_back(known_codec);
  recv_parameters_mixed.codecs.push_back(unknown_codec);

  EXPECT_TRUE(dmc->SetSendParameters(send_parameters_known));
  EXPECT_FALSE(dmc->SetSendParameters(send_parameters_unknown));
  EXPECT_TRUE(dmc->SetSendParameters(send_parameters_mixed));
  EXPECT_TRUE(dmc->SetRecvParameters(recv_parameters_known));
  EXPECT_FALSE(dmc->SetRecvParameters(recv_parameters_unknown));
  EXPECT_FALSE(dmc->SetRecvParameters(recv_parameters_mixed));
}

TEST_F(RtpDataMediaChannelTest, AddRemoveSendStream) {
  rtc::scoped_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());

  cricket::StreamParams stream1;
  stream1.add_ssrc(41);
  EXPECT_TRUE(dmc->AddSendStream(stream1));
  cricket::StreamParams stream2;
  stream2.add_ssrc(42);
  EXPECT_TRUE(dmc->AddSendStream(stream2));

  EXPECT_TRUE(dmc->RemoveSendStream(41));
  EXPECT_TRUE(dmc->RemoveSendStream(42));
  EXPECT_FALSE(dmc->RemoveSendStream(43));
}

TEST_F(RtpDataMediaChannelTest, AddRemoveRecvStream) {
  rtc::scoped_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());

  cricket::StreamParams stream1;
  stream1.add_ssrc(41);
  EXPECT_TRUE(dmc->AddRecvStream(stream1));
  cricket::StreamParams stream2;
  stream2.add_ssrc(42);
  EXPECT_TRUE(dmc->AddRecvStream(stream2));
  EXPECT_FALSE(dmc->AddRecvStream(stream2));

  EXPECT_TRUE(dmc->RemoveRecvStream(41));
  EXPECT_TRUE(dmc->RemoveRecvStream(42));
}

TEST_F(RtpDataMediaChannelTest, SendData) {
  rtc::scoped_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());

  cricket::SendDataParams params;
  params.ssrc = 42;
  unsigned char data[] = "food";
  rtc::Buffer payload(data, 4);
  unsigned char padded_data[] = {
    0x00, 0x00, 0x00, 0x00,
    'f', 'o', 'o', 'd',
  };
  cricket::SendDataResult result;

  // Not sending
  EXPECT_FALSE(dmc->SendData(params, payload, &result));
  EXPECT_EQ(cricket::SDR_ERROR, result);
  EXPECT_FALSE(HasSentData(0));
  ASSERT_TRUE(dmc->SetSend(true));

  // Unknown stream name.
  EXPECT_FALSE(dmc->SendData(params, payload, &result));
  EXPECT_EQ(cricket::SDR_ERROR, result);
  EXPECT_FALSE(HasSentData(0));

  cricket::StreamParams stream;
  stream.add_ssrc(42);
  ASSERT_TRUE(dmc->AddSendStream(stream));

  // Unknown codec;
  EXPECT_FALSE(dmc->SendData(params, payload, &result));
  EXPECT_EQ(cricket::SDR_ERROR, result);
  EXPECT_FALSE(HasSentData(0));

  cricket::DataCodec codec;
  codec.id = 103;
  codec.name = cricket::kGoogleRtpDataCodecName;
  cricket::DataSendParameters parameters;
  parameters.codecs.push_back(codec);
  ASSERT_TRUE(dmc->SetSendParameters(parameters));

  // Length too large;
  std::string x10000(10000, 'x');
  EXPECT_FALSE(dmc->SendData(
      params, rtc::Buffer(x10000.data(), x10000.length()), &result));
  EXPECT_EQ(cricket::SDR_ERROR, result);
  EXPECT_FALSE(HasSentData(0));

  // Finally works!
  EXPECT_TRUE(dmc->SendData(params, payload, &result));
  EXPECT_EQ(cricket::SDR_SUCCESS, result);
  ASSERT_TRUE(HasSentData(0));
  EXPECT_EQ(sizeof(padded_data), GetSentData(0).length());
  EXPECT_EQ(0, memcmp(
      padded_data, GetSentData(0).data(), sizeof(padded_data)));
  cricket::RtpHeader header0 = GetSentDataHeader(0);
  EXPECT_NE(0, header0.seq_num);
  EXPECT_NE(0U, header0.timestamp);
  EXPECT_EQ(header0.ssrc, 42U);
  EXPECT_EQ(header0.payload_type, 103);

  // Should bump timestamp by 180000 because the clock rate is 90khz.
  SetNow(2);

  EXPECT_TRUE(dmc->SendData(params, payload, &result));
  ASSERT_TRUE(HasSentData(1));
  EXPECT_EQ(sizeof(padded_data), GetSentData(1).length());
  EXPECT_EQ(0, memcmp(
      padded_data, GetSentData(1).data(), sizeof(padded_data)));
  cricket::RtpHeader header1 = GetSentDataHeader(1);
  EXPECT_EQ(header1.ssrc, 42U);
  EXPECT_EQ(header1.payload_type, 103);
  EXPECT_EQ(static_cast<uint16_t>(header0.seq_num + 1),
            static_cast<uint16_t>(header1.seq_num));
  EXPECT_EQ(header0.timestamp + 180000, header1.timestamp);
}

TEST_F(RtpDataMediaChannelTest, SendDataMultipleClocks) {
  // Timings owned by RtpDataEngines.
  FakeTiming* timing1 = new FakeTiming();
  rtc::scoped_ptr<cricket::RtpDataEngine> dme1(CreateEngine(timing1));
  rtc::scoped_ptr<cricket::RtpDataMediaChannel> dmc1(
      CreateChannel(dme1.get()));
  FakeTiming* timing2 = new FakeTiming();
  rtc::scoped_ptr<cricket::RtpDataEngine> dme2(CreateEngine(timing2));
  rtc::scoped_ptr<cricket::RtpDataMediaChannel> dmc2(
      CreateChannel(dme2.get()));

  ASSERT_TRUE(dmc1->SetSend(true));
  ASSERT_TRUE(dmc2->SetSend(true));

  cricket::StreamParams stream1;
  stream1.add_ssrc(41);
  ASSERT_TRUE(dmc1->AddSendStream(stream1));
  cricket::StreamParams stream2;
  stream2.add_ssrc(42);
  ASSERT_TRUE(dmc2->AddSendStream(stream2));

  cricket::DataCodec codec;
  codec.id = 103;
  codec.name = cricket::kGoogleRtpDataCodecName;
  cricket::DataSendParameters parameters;
  parameters.codecs.push_back(codec);
  ASSERT_TRUE(dmc1->SetSendParameters(parameters));
  ASSERT_TRUE(dmc2->SetSendParameters(parameters));

  cricket::SendDataParams params1;
  params1.ssrc = 41;
  cricket::SendDataParams params2;
  params2.ssrc = 42;

  unsigned char data[] = "foo";
  rtc::Buffer payload(data, 3);
  cricket::SendDataResult result;

  EXPECT_TRUE(dmc1->SendData(params1, payload, &result));
  EXPECT_TRUE(dmc2->SendData(params2, payload, &result));

  // Should bump timestamp by 90000 because the clock rate is 90khz.
  timing1->set_now(1);
  // Should bump timestamp by 180000 because the clock rate is 90khz.
  timing2->set_now(2);

  EXPECT_TRUE(dmc1->SendData(params1, payload, &result));
  EXPECT_TRUE(dmc2->SendData(params2, payload, &result));

  ASSERT_TRUE(HasSentData(3));
  cricket::RtpHeader header1a = GetSentDataHeader(0);
  cricket::RtpHeader header2a = GetSentDataHeader(1);
  cricket::RtpHeader header1b = GetSentDataHeader(2);
  cricket::RtpHeader header2b = GetSentDataHeader(3);

  EXPECT_EQ(static_cast<uint16_t>(header1a.seq_num + 1),
            static_cast<uint16_t>(header1b.seq_num));
  EXPECT_EQ(header1a.timestamp + 90000, header1b.timestamp);
  EXPECT_EQ(static_cast<uint16_t>(header2a.seq_num + 1),
            static_cast<uint16_t>(header2b.seq_num));
  EXPECT_EQ(header2a.timestamp + 180000, header2b.timestamp);
}

TEST_F(RtpDataMediaChannelTest, SendDataRate) {
  rtc::scoped_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());

  ASSERT_TRUE(dmc->SetSend(true));

  cricket::DataCodec codec;
  codec.id = 103;
  codec.name = cricket::kGoogleRtpDataCodecName;
  cricket::DataSendParameters parameters;
  parameters.codecs.push_back(codec);
  ASSERT_TRUE(dmc->SetSendParameters(parameters));

  cricket::StreamParams stream;
  stream.add_ssrc(42);
  ASSERT_TRUE(dmc->AddSendStream(stream));

  cricket::SendDataParams params;
  params.ssrc = 42;
  unsigned char data[] = "food";
  rtc::Buffer payload(data, 4);
  cricket::SendDataResult result;

  // With rtp overhead of 32 bytes, each one of our packets is 36
  // bytes, or 288 bits.  So, a limit of 872bps will allow 3 packets,
  // but not four.
  parameters.max_bandwidth_bps = 872;
  ASSERT_TRUE(dmc->SetSendParameters(parameters));

  EXPECT_TRUE(dmc->SendData(params, payload, &result));
  EXPECT_TRUE(dmc->SendData(params, payload, &result));
  EXPECT_TRUE(dmc->SendData(params, payload, &result));
  EXPECT_FALSE(dmc->SendData(params, payload, &result));
  EXPECT_FALSE(dmc->SendData(params, payload, &result));

  SetNow(0.9);
  EXPECT_FALSE(dmc->SendData(params, payload, &result));

  SetNow(1.1);
  EXPECT_TRUE(dmc->SendData(params, payload, &result));
  EXPECT_TRUE(dmc->SendData(params, payload, &result));
  SetNow(1.9);
  EXPECT_TRUE(dmc->SendData(params, payload, &result));

  SetNow(2.2);
  EXPECT_TRUE(dmc->SendData(params, payload, &result));
  EXPECT_TRUE(dmc->SendData(params, payload, &result));
  EXPECT_TRUE(dmc->SendData(params, payload, &result));
  EXPECT_FALSE(dmc->SendData(params, payload, &result));
}

TEST_F(RtpDataMediaChannelTest, ReceiveData) {
  // PT= 103, SN=2, TS=3, SSRC = 4, data = "abcde"
  unsigned char data[] = {
    0x80, 0x67, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2A,
    0x00, 0x00, 0x00, 0x00,
    'a', 'b', 'c', 'd', 'e'
  };
  rtc::Buffer packet(data, sizeof(data));

  rtc::scoped_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());

  // SetReceived not called.
  dmc->OnPacketReceived(&packet, rtc::PacketTime());
  EXPECT_FALSE(HasReceivedData());

  dmc->SetReceive(true);

  // Unknown payload id
  dmc->OnPacketReceived(&packet, rtc::PacketTime());
  EXPECT_FALSE(HasReceivedData());

  cricket::DataCodec codec;
  codec.id = 103;
  codec.name = cricket::kGoogleRtpDataCodecName;
  cricket::DataRecvParameters parameters;
  parameters.codecs.push_back(codec);
  ASSERT_TRUE(dmc->SetRecvParameters(parameters));

  // Unknown stream
  dmc->OnPacketReceived(&packet, rtc::PacketTime());
  EXPECT_FALSE(HasReceivedData());

  cricket::StreamParams stream;
  stream.add_ssrc(42);
  ASSERT_TRUE(dmc->AddRecvStream(stream));

  // Finally works!
  dmc->OnPacketReceived(&packet, rtc::PacketTime());
  EXPECT_TRUE(HasReceivedData());
  EXPECT_EQ("abcde", GetReceivedData());
  EXPECT_EQ(5U, GetReceivedDataLen());
}

TEST_F(RtpDataMediaChannelTest, InvalidRtpPackets) {
  unsigned char data[] = {
    0x80, 0x65, 0x00, 0x02
  };
  rtc::Buffer packet(data, sizeof(data));

  rtc::scoped_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());

  // Too short
  dmc->OnPacketReceived(&packet, rtc::PacketTime());
  EXPECT_FALSE(HasReceivedData());
}
