/*
 *  Copyright 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/api/quicdatatransport.h"

#include <memory>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>

#include "webrtc/api/quicdatachannel.h"
#include "webrtc/base/bytebuffer.h"
#include "webrtc/base/gunit.h"
#include "webrtc/p2p/base/faketransportcontroller.h"
#include "webrtc/p2p/quic/quictransportchannel.h"
#include "webrtc/p2p/quic/reliablequicstream.h"

using webrtc::DataBuffer;
using webrtc::DataChannelInit;
using webrtc::DataChannelInterface;
using webrtc::DataChannelObserver;
using webrtc::QuicDataChannel;
using webrtc::QuicDataTransport;
using cricket::FakeTransportChannel;
using cricket::QuicTransportChannel;
using cricket::ReliableQuicStream;

namespace {

// Timeout for asynchronous operations.
static const int kTimeoutMs = 1000;  // milliseconds

// FakeObserver receives messages from the data channel.
class FakeObserver : public DataChannelObserver {
 public:
  FakeObserver() {}

  void OnStateChange() override {}

  void OnBufferedAmountChange(uint64_t previous_amount) override {}

  void OnMessage(const webrtc::DataBuffer& buffer) override {
    messages_.push_back(std::string(buffer.data.data<char>(), buffer.size()));
  }

  const std::vector<std::string>& messages() const { return messages_; }

  size_t messages_received() const { return messages_.size(); }

 private:
  std::vector<std::string> messages_;
};

// A peer who uses a QUIC transport channel and fake ICE transport channel to
// send or receive data.
class QuicDataTransportPeer {
 public:
  QuicDataTransportPeer()
      : quic_data_transport_(rtc::Thread::Current(), rtc::Thread::Current()),
        ice_transport_channel_(new FakeTransportChannel("data", 0)),
        quic_transport_channel_(ice_transport_channel_) {
    ice_transport_channel_->SetAsync(true);
  }

  void GenerateCertificateAndFingerprint() {
    rtc::scoped_refptr<rtc::RTCCertificate> local_cert =
        rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
            rtc::SSLIdentity::Generate("cert_name", rtc::KT_DEFAULT)));
    quic_transport_channel_.SetLocalCertificate(local_cert);
    local_fingerprint_.reset(CreateFingerprint(local_cert.get()));
  }

  // Connects |ice_transport_channel_| to that of the other peer.
  void Connect(QuicDataTransportPeer* other_peer) {
    ice_transport_channel_->Connect();
    other_peer->ice_transport_channel_->Connect();
    ice_transport_channel_->SetDestination(other_peer->ice_transport_channel_);
  }

  std::unique_ptr<rtc::SSLFingerprint>& local_fingerprint() {
    return local_fingerprint_;
  }

  QuicTransportChannel* quic_transport_channel() {
    return &quic_transport_channel_;
  }

  // Write a messge directly to the ReliableQuicStream.
  void WriteMessage(int data_channel_id,
                    uint64_t message_id,
                    const std::string& message) {
    ReliableQuicStream* stream = quic_transport_channel_.CreateQuicStream();
    rtc::CopyOnWriteBuffer payload;
    webrtc::WriteQuicDataChannelMessageHeader(data_channel_id, message_id,
                                              &payload);
    stream->Write(payload.data<char>(), payload.size(), false);
    stream->Write(message.data(), message.size(), true);
  }

  rtc::scoped_refptr<DataChannelInterface> CreateDataChannel(
      const DataChannelInit* config) {
    return quic_data_transport_.CreateDataChannel("testing", config);
  }

  QuicDataTransport* quic_data_transport() { return &quic_data_transport_; }

 private:
  // Creates a fingerprint from a certificate.
  rtc::SSLFingerprint* CreateFingerprint(rtc::RTCCertificate* cert) {
    std::string digest_algorithm;
    cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm);
    std::unique_ptr<rtc::SSLFingerprint> fingerprint(
        rtc::SSLFingerprint::Create(digest_algorithm, cert->identity()));
    return fingerprint.release();
  }

  QuicDataTransport quic_data_transport_;
  FakeTransportChannel* ice_transport_channel_;
  QuicTransportChannel quic_transport_channel_;
  std::unique_ptr<rtc::SSLFingerprint> local_fingerprint_;
};

class QuicDataTransportTest : public testing::Test {
 public:
  QuicDataTransportTest() {}

  void ConnectTransportChannels() {
    SetCryptoParameters();
    peer1_.Connect(&peer2_);
    ASSERT_TRUE_WAIT(peer1_.quic_transport_channel()->writable() &&
                         peer2_.quic_transport_channel()->writable(),
                     kTimeoutMs);
  }

  void SetTransportChannels() {
    ASSERT_TRUE(peer1_.quic_data_transport()->SetTransportChannel(
        peer1_.quic_transport_channel()));
    ASSERT_TRUE(peer2_.quic_data_transport()->SetTransportChannel(
        peer2_.quic_transport_channel()));
  }

  // Sets crypto parameters required for the QUIC handshake.
  void SetCryptoParameters() {
    peer1_.GenerateCertificateAndFingerprint();
    peer2_.GenerateCertificateAndFingerprint();

    peer1_.quic_transport_channel()->SetSslRole(rtc::SSL_CLIENT);
    peer2_.quic_transport_channel()->SetSslRole(rtc::SSL_SERVER);

    std::unique_ptr<rtc::SSLFingerprint>& peer1_fingerprint =
        peer1_.local_fingerprint();
    std::unique_ptr<rtc::SSLFingerprint>& peer2_fingerprint =
        peer2_.local_fingerprint();

    peer1_.quic_transport_channel()->SetRemoteFingerprint(
        peer2_fingerprint->algorithm,
        reinterpret_cast<const uint8_t*>(peer2_fingerprint->digest.data()),
        peer2_fingerprint->digest.size());
    peer2_.quic_transport_channel()->SetRemoteFingerprint(
        peer1_fingerprint->algorithm,
        reinterpret_cast<const uint8_t*>(peer1_fingerprint->digest.data()),
        peer1_fingerprint->digest.size());
  }

 protected:
  QuicDataTransportPeer peer1_;
  QuicDataTransportPeer peer2_;
};

// Tests creation and destruction of data channels.
TEST_F(QuicDataTransportTest, CreateAndDestroyDataChannels) {
  QuicDataTransport* quic_data_transport = peer2_.quic_data_transport();
  EXPECT_FALSE(quic_data_transport->HasDataChannels());
  for (int data_channel_id = 0; data_channel_id < 5; ++data_channel_id) {
    EXPECT_FALSE(quic_data_transport->HasDataChannel(data_channel_id));
    webrtc::DataChannelInit config;
    config.id = data_channel_id;
    rtc::scoped_refptr<DataChannelInterface> data_channel =
        peer2_.CreateDataChannel(&config);
    EXPECT_NE(nullptr, data_channel);
    EXPECT_EQ(data_channel_id, data_channel->id());
    EXPECT_TRUE(quic_data_transport->HasDataChannel(data_channel_id));
  }
  EXPECT_TRUE(quic_data_transport->HasDataChannels());
  for (int data_channel_id = 0; data_channel_id < 5; ++data_channel_id) {
    quic_data_transport->DestroyDataChannel(data_channel_id);
    EXPECT_FALSE(quic_data_transport->HasDataChannel(data_channel_id));
  }
  EXPECT_FALSE(quic_data_transport->HasDataChannels());
}

// Tests that the QuicDataTransport does not allow creating multiple
// QuicDataChannels with the same id.
TEST_F(QuicDataTransportTest, CannotCreateDataChannelsWithSameId) {
  webrtc::DataChannelInit config;
  config.id = 2;
  EXPECT_NE(nullptr, peer2_.CreateDataChannel(&config));
  EXPECT_EQ(nullptr, peer2_.CreateDataChannel(&config));
}

// Tests that any data channels created by the QuicDataTransport are in state
// kConnecting before the QuicTransportChannel is set, then transiton to state
// kOpen when the transport channel becomes writable.
TEST_F(QuicDataTransportTest, DataChannelsOpenWhenTransportChannelWritable) {
  webrtc::DataChannelInit config1;
  config1.id = 7;
  rtc::scoped_refptr<DataChannelInterface> data_channel1 =
      peer2_.CreateDataChannel(&config1);
  EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, data_channel1->state());
  SetTransportChannels();
  EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, data_channel1->state());
  webrtc::DataChannelInit config2;
  config2.id = 14;
  rtc::scoped_refptr<DataChannelInterface> data_channel2 =
      peer2_.CreateDataChannel(&config2);
  EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, data_channel2->state());
  // Existing data channels should open once the transport channel is writable.
  ConnectTransportChannels();
  EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, data_channel1->state(),
                 kTimeoutMs);
  EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, data_channel2->state(),
                 kTimeoutMs);
  // Any data channels created afterwards should start in state kOpen.
  webrtc::DataChannelInit config3;
  config3.id = 21;
  rtc::scoped_refptr<DataChannelInterface> data_channel3 =
      peer2_.CreateDataChannel(&config3);
  EXPECT_EQ(webrtc::DataChannelInterface::kOpen, data_channel3->state());
}

// Tests that the QuicTransport dispatches messages for one QuicDataChannel.
TEST_F(QuicDataTransportTest, ReceiveMessagesForSingleDataChannel) {
  ConnectTransportChannels();
  SetTransportChannels();

  int data_channel_id = 1337;
  webrtc::DataChannelInit config;
  config.id = data_channel_id;
  rtc::scoped_refptr<DataChannelInterface> peer2_data_channel =
      peer2_.CreateDataChannel(&config);
  FakeObserver observer;
  peer2_data_channel->RegisterObserver(&observer);

  uint64_t message1_id = 26u;
  peer1_.WriteMessage(data_channel_id, message1_id, "Testing");
  ASSERT_EQ_WAIT(1, observer.messages_received(), kTimeoutMs);
  EXPECT_EQ("Testing", observer.messages()[0]);

  uint64_t message2_id = 402u;
  peer1_.WriteMessage(data_channel_id, message2_id, "Hello, World!");
  ASSERT_EQ_WAIT(2, observer.messages_received(), kTimeoutMs);
  EXPECT_EQ("Hello, World!", observer.messages()[1]);

  uint64_t message3_id = 100260415u;
  peer1_.WriteMessage(data_channel_id, message3_id, "Third message");
  ASSERT_EQ_WAIT(3, observer.messages_received(), kTimeoutMs);
  EXPECT_EQ("Third message", observer.messages()[2]);
}

// Tests that the QuicTransport dispatches messages to the correct data channel
// when multiple are in use.
TEST_F(QuicDataTransportTest, ReceiveMessagesForMultipleDataChannels) {
  ConnectTransportChannels();
  SetTransportChannels();

  std::vector<rtc::scoped_refptr<DataChannelInterface>> data_channels;
  for (int data_channel_id = 0; data_channel_id < 5; ++data_channel_id) {
    webrtc::DataChannelInit config;
    config.id = data_channel_id;
    data_channels.push_back(peer2_.CreateDataChannel(&config));
  }

  for (int data_channel_id = 0; data_channel_id < 5; ++data_channel_id) {
    uint64_t message1_id = 48023u;
    FakeObserver observer;
    DataChannelInterface* peer2_data_channel =
        data_channels[data_channel_id].get();
    peer2_data_channel->RegisterObserver(&observer);
    peer1_.WriteMessage(data_channel_id, message1_id, "Testing");
    ASSERT_EQ_WAIT(1, observer.messages_received(), kTimeoutMs);
    EXPECT_EQ("Testing", observer.messages()[0]);

    uint64_t message2_id = 1372643095u;
    peer1_.WriteMessage(data_channel_id, message2_id, "Hello, World!");
    ASSERT_EQ_WAIT(2, observer.messages_received(), kTimeoutMs);
    EXPECT_EQ("Hello, World!", observer.messages()[1]);
  }
}

// Tests end-to-end that both peers can use multiple QuicDataChannels to
// send/receive messages using a QuicDataTransport.
TEST_F(QuicDataTransportTest, EndToEndSendReceiveMessages) {
  ConnectTransportChannels();
  SetTransportChannels();

  std::vector<rtc::scoped_refptr<DataChannelInterface>> peer1_data_channels;
  std::vector<rtc::scoped_refptr<DataChannelInterface>> peer2_data_channels;

  for (int data_channel_id = 0; data_channel_id < 5; ++data_channel_id) {
    webrtc::DataChannelInit config;
    config.id = data_channel_id;
    peer1_data_channels.push_back(peer1_.CreateDataChannel(&config));
    peer2_data_channels.push_back(peer2_.CreateDataChannel(&config));
  }

  for (int data_channel_id = 0; data_channel_id < 5; ++data_channel_id) {
    DataChannelInterface* peer1_data_channel =
        peer1_data_channels[data_channel_id].get();
    FakeObserver observer1;
    peer1_data_channel->RegisterObserver(&observer1);
    DataChannelInterface* peer2_data_channel =
        peer2_data_channels[data_channel_id].get();
    FakeObserver observer2;
    peer2_data_channel->RegisterObserver(&observer2);

    peer1_data_channel->Send(webrtc::DataBuffer("Peer 1 message 1"));
    ASSERT_EQ_WAIT(1, observer2.messages_received(), kTimeoutMs);
    EXPECT_EQ("Peer 1 message 1", observer2.messages()[0]);

    peer1_data_channel->Send(webrtc::DataBuffer("Peer 1 message 2"));
    ASSERT_EQ_WAIT(2, observer2.messages_received(), kTimeoutMs);
    EXPECT_EQ("Peer 1 message 2", observer2.messages()[1]);

    peer2_data_channel->Send(webrtc::DataBuffer("Peer 2 message 1"));
    ASSERT_EQ_WAIT(1, observer1.messages_received(), kTimeoutMs);
    EXPECT_EQ("Peer 2 message 1", observer1.messages()[0]);

    peer2_data_channel->Send(webrtc::DataBuffer("Peer 2 message 2"));
    ASSERT_EQ_WAIT(2, observer1.messages_received(), kTimeoutMs);
    EXPECT_EQ("Peer 2 message 2", observer1.messages()[1]);
  }
}

// Tests that SetTransportChannel returns false when setting a NULL transport
// channel or a transport channel that is not equivalent to the one already set.
TEST_F(QuicDataTransportTest, SetTransportChannelReturnValue) {
  QuicDataTransport* quic_data_transport = peer1_.quic_data_transport();
  EXPECT_FALSE(quic_data_transport->SetTransportChannel(nullptr));
  QuicTransportChannel* transport_channel = peer1_.quic_transport_channel();
  EXPECT_TRUE(quic_data_transport->SetTransportChannel(transport_channel));
  EXPECT_TRUE(quic_data_transport->SetTransportChannel(transport_channel));
  QuicTransportChannel* other_transport_channel =
      peer2_.quic_transport_channel();
  EXPECT_FALSE(
      quic_data_transport->SetTransportChannel(other_transport_channel));
}

}  // namespace
