/*
 *  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(),
                             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_->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
