// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This fuzzer tests the hypothesis that the packet nub protocol allows
// eventual connectivity even in the face of packet loss.

#include "src/connectivity/overnet/lib/environment/trace_cout.h"
#include "src/connectivity/overnet/lib/links/packet_nub.h"
#include "src/connectivity/overnet/lib/testing/test_timer.h"

using namespace overnet;

///////////////////////////////////////////////////////////////////////////////
// Simulation

class Fuzzer;

class Nub final : public PacketNub<int, 256> {
 public:
  Nub(Fuzzer* fuzzer, uint8_t index);

  void SendTo(int dest, Slice slice) override;
  Router* GetRouter() override;
  void Publish(LinkPtr<> link) override {
    router_.RegisterLink(std::move(link));
  }

 private:
  Fuzzer* const fuzzer_;
  const uint8_t index_;
  Router router_;
};

class Fuzzer {
 public:
  Fuzzer();

  Timer* timer() { return &timer_; }
  bool IsDone() {
    return nub1_.GetRouter()->HasRouteTo(NodeId(2)) &&
           nub2_.GetRouter()->HasRouteTo(NodeId(1));
  }
  bool StepTime() { return timer_.StepUntilNextEvent(); }
  bool StepTime(uint64_t us) { return timer_.Step(us); }
  void QueueSend(int src, int dest, Slice slice);
  bool FlushPackets();
  void AllowPacket(uint64_t packet);
  void DropPacket(uint64_t packet);
  void Initiate1();
  void Initiate2();

 private:
  TestTimer timer_;
  TraceCout cout_{&timer_};
  // ScopedRenderer renderer_{&cout_};
  Nub nub1_{this, 1};
  Nub nub2_{this, 2};

  enum class PacketState : uint8_t {
    QUEUED,
    SENT,
    DROPPED,
  };
  struct Packet {
    int src;
    int dest;
    PacketState state;
    Slice payload;
  };
  std::vector<Packet> packets_;
};

Nub::Nub(Fuzzer* fuzzer, uint8_t index)
    : PacketNub(fuzzer->timer(), NodeId(index)),
      fuzzer_(fuzzer),
      index_(index),
      router_(fuzzer->timer(), NodeId(index), false) {}

void Nub::SendTo(int dest, Slice slice) {
  fuzzer_->QueueSend(index_, dest, std::move(slice));
}

Router* Nub::GetRouter() { return &router_; }

Fuzzer::Fuzzer() = default;

void Fuzzer::Initiate1() { nub1_.Initiate({2}, NodeId(2)); }
void Fuzzer::Initiate2() { nub2_.Initiate({1}, NodeId(1)); }

void Fuzzer::QueueSend(int src, int dest, Slice slice) {
  packets_.emplace_back(
      Packet{src, dest, PacketState::QUEUED, std::move(slice)});
}

bool Fuzzer::FlushPackets() {
  bool flushed_any = false;
  for (size_t i = 0; i < packets_.size(); i++) {
    if (packets_[i].state == PacketState::QUEUED) {
      AllowPacket(i);
      assert(packets_[i].state != PacketState::QUEUED);
      flushed_any = true;
    }
  }
  return flushed_any;
}

void Fuzzer::AllowPacket(uint64_t packet) {
  if (packet >= packets_.size()) {
    return;
  }
  auto& p = packets_[packet];
  if (p.state == PacketState::DROPPED) {
    return;
  }
  p.state = PacketState::SENT;
  const auto now = timer_.Now();
  switch (p.dest) {
    case 1:
      nub1_.Process(now, p.src, p.payload);
      break;
    case 2:
      nub2_.Process(now, p.src, p.payload);
      break;
  }
}

void Fuzzer::DropPacket(uint64_t packet) {
  if (packet >= packets_.size()) {
    return;
  }
  auto& p = packets_[packet];
  p.state = PacketState::DROPPED;
}

///////////////////////////////////////////////////////////////////////////////
// Input

class InputStream {
 public:
  InputStream(const uint8_t* data, size_t size)
      : cur_(data), end_(data + size) {}

  uint64_t Next64() {
    uint64_t out;
    if (!varint::Read(&cur_, end_, &out))
      out = 0;
    return out;
  }

  uint8_t NextByte() {
    if (cur_ == end_)
      return 0;
    return *cur_++;
  }

  bool IsEof() const { return cur_ == end_; }

 private:
  const uint8_t* cur_;
  const uint8_t* end_;
};

///////////////////////////////////////////////////////////////////////////////
// Main loop

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  InputStream input(data, size);
  Fuzzer fuzzer;
  const uint8_t end_behavior = input.NextByte();
  while (!fuzzer.IsDone()) {
    switch (input.NextByte()) {
      case 0:
        OVERNET_TRACE(INFO) << "Fuzzer: Flush";
        do {
          if (input.IsEof()) {
            if (end_behavior & 1) {
              OVERNET_TRACE(INFO) << "Fuzzer: Initiate from 1 -> 2";
              fuzzer.Initiate1();
            } else {
              OVERNET_TRACE(INFO) << "Fuzzer: Initiate from 2 -> 1";
              fuzzer.Initiate2();
            }
          }
        } while (fuzzer.FlushPackets() || fuzzer.StepTime());
        if (input.IsEof() && !fuzzer.IsDone()) {
          std::cerr << "Failed to connect\n";
          abort();
        }
        break;
      case 1: {
        auto dt = TimeDelta::FromMicroseconds(input.Next64());
        dt = std::min(dt, TimeDelta::FromHours(1));
        dt = std::max(dt, TimeDelta::FromMicroseconds(1));
        OVERNET_TRACE(INFO) << "Fuzzer: Step " << dt;
        fuzzer.StepTime(dt.as_us());
      } break;
      case 2: {
        auto idx = input.Next64();
        OVERNET_TRACE(INFO) << "Fuzzer: Allow packet " << idx;
        fuzzer.AllowPacket(idx);
      } break;
      case 3: {
        auto idx = input.Next64();
        OVERNET_TRACE(INFO) << "Fuzzer: Drop packet " << idx;
        fuzzer.DropPacket(idx);
      } break;
      case 4: {
        OVERNET_TRACE(INFO) << "Fuzzer: Initiate from 1 -> 2";
        fuzzer.Initiate1();
      } break;
      case 5: {
        OVERNET_TRACE(INFO) << "Fuzzer: Initiate from 2 -> 1";
        fuzzer.Initiate2();
      } break;
      default: {
        return 0;
      }
    }
  }
  return 0;
}
