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

#ifndef QUICHE_QUIC_QBONE_BONNET_ICMP_REACHABLE_H_
#define QUICHE_QUIC_QBONE_BONNET_ICMP_REACHABLE_H_

#include <netinet/icmp6.h>

#include <memory>

#include "absl/strings/string_view.h"
#include "quiche/quic/core/io/quic_event_loop.h"
#include "quiche/quic/core/quic_alarm.h"
#include "quiche/quic/core/quic_alarm_factory.h"
#include "quiche/quic/core/quic_clock.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/platform/api/quic_ip_address.h"
#include "quiche/quic/platform/api/quic_mutex.h"
#include "quiche/quic/qbone/bonnet/icmp_reachable_interface.h"
#include "quiche/quic/qbone/platform/kernel_interface.h"

namespace quic {

extern const char kUnknownSource[];
extern const char kNoSource[];

// IcmpReachable schedules itself with an EpollServer, periodically sending
// ICMPv6 Echo Requests to the given |destination| on the interface that the
// given |source| is bound to. Echo Requests are sent once every |timeout|.
// On Echo Replies, timeouts, and I/O errors, the given |stats| object will
// be called back with details of the event.
class IcmpReachable : public IcmpReachableInterface {
 public:
  enum Status { REACHABLE, UNREACHABLE };

  struct ReachableEvent {
    Status status;
    QuicTime::Delta response_time;
    std::string source;
  };

  class StatsInterface {
   public:
    StatsInterface() = default;

    StatsInterface(const StatsInterface&) = delete;
    StatsInterface& operator=(const StatsInterface&) = delete;

    StatsInterface(StatsInterface&&) = delete;
    StatsInterface& operator=(StatsInterface&&) = delete;

    virtual ~StatsInterface() = default;

    virtual void OnEvent(ReachableEvent event) = 0;

    virtual void OnReadError(int error) = 0;

    virtual void OnWriteError(int error) = 0;
  };

  // |source| is the IPv6 address bound to the interface that IcmpReachable will
  //          send Echo Requests on.
  // |destination| is the IPv6 address of the destination of the Echo Requests.
  // |timeout| is the duration IcmpReachable will wait between Echo Requests.
  //           If no Echo Response is received by the next Echo Request, it will
  //           be considered a timeout.
  // |kernel| is not owned, but should outlive this instance.
  // |epoll_server| is not owned, but should outlive this instance.
  //                IcmpReachable's Init() must be called from within the Epoll
  //                Server's thread.
  // |stats| is not owned, but should outlive this instance. It will be called
  //         back on Echo Replies, timeouts, and I/O errors.
  IcmpReachable(QuicIpAddress source, QuicIpAddress destination,
                QuicTime::Delta timeout, KernelInterface* kernel,
                QuicEventLoop* event_loop, StatsInterface* stats);

  ~IcmpReachable() override;

  // Initializes this reachability probe. Must be called from within the
  // |epoll_server|'s thread.
  bool Init() QUIC_LOCKS_EXCLUDED(header_lock_) override;

  void OnAlarm() QUIC_LOCKS_EXCLUDED(header_lock_);

  static absl::string_view StatusName(Status status);

 private:
  class EpollCallback : public QuicSocketEventListener {
   public:
    explicit EpollCallback(IcmpReachable* reachable) : reachable_(reachable) {}

    EpollCallback(const EpollCallback&) = delete;
    EpollCallback& operator=(const EpollCallback&) = delete;

    EpollCallback(EpollCallback&&) = delete;
    EpollCallback& operator=(EpollCallback&&) = delete;

    void OnSocketEvent(QuicEventLoop* event_loop, QuicUdpSocketFd fd,
                       QuicSocketEventMask events) override;

   private:
    IcmpReachable* reachable_;
  };

  class AlarmCallback : public QuicAlarm::DelegateWithoutContext {
   public:
    explicit AlarmCallback(IcmpReachable* reachable) : reachable_(reachable) {}

    void OnAlarm() override { reachable_->OnAlarm(); }

   private:
    IcmpReachable* reachable_;
  };

  bool OnEvent(int fd) QUIC_LOCKS_EXCLUDED(header_lock_);

  const QuicTime::Delta timeout_;

  QuicEventLoop* event_loop_;
  const QuicClock* clock_;
  std::unique_ptr<QuicAlarmFactory> alarm_factory_;

  EpollCallback cb_;
  std::unique_ptr<QuicAlarm> alarm_;

  sockaddr_in6 src_{};
  sockaddr_in6 dst_{};

  KernelInterface* kernel_;

  StatsInterface* stats_;

  int send_fd_;
  int recv_fd_;

  QuicMutex header_lock_;
  icmp6_hdr icmp_header_ QUIC_GUARDED_BY(header_lock_){};

  QuicTime start_ = QuicTime::Zero();
  QuicTime end_ = QuicTime::Zero();
};

}  // namespace quic

#endif  // QUICHE_QUIC_QBONE_BONNET_ICMP_REACHABLE_H_
