// Copyright (c) 2012 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_TOOLS_QUIC_CLIENT_DEFAULT_NETWORK_HELPER_H_
#define QUICHE_QUIC_TOOLS_QUIC_CLIENT_DEFAULT_NETWORK_HELPER_H_

#include <cstdint>
#include <memory>
#include <string>

#include "absl/types/optional.h"
#include "quiche/quic/core/io/quic_event_loop.h"
#include "quiche/quic/core/quic_packet_reader.h"
#include "quiche/quic/core/quic_udp_socket.h"
#include "quiche/quic/tools/quic_client_base.h"
#include "quiche/common/quiche_linked_hash_map.h"

namespace quic {

namespace test {
class QuicClientPeer;
}  // namespace test

// An implementation of the QuicClientBase::NetworkHelper interface that is
// based on the QuicEventLoop API.
class QuicClientDefaultNetworkHelper : public QuicClientBase::NetworkHelper,
                                       public QuicSocketEventListener,
                                       public ProcessPacketInterface {
 public:
  QuicClientDefaultNetworkHelper(QuicEventLoop* event_loop,
                                 QuicClientBase* client);
  QuicClientDefaultNetworkHelper(const QuicClientDefaultNetworkHelper&) =
      delete;
  QuicClientDefaultNetworkHelper& operator=(
      const QuicClientDefaultNetworkHelper&) = delete;

  ~QuicClientDefaultNetworkHelper() override;

  // From QuicSocketEventListener.
  void OnSocketEvent(QuicEventLoop* event_loop, QuicUdpSocketFd fd,
                     QuicSocketEventMask events) override;

  // From ProcessPacketInterface. This will be called for each received
  // packet.
  void ProcessPacket(const QuicSocketAddress& self_address,
                     const QuicSocketAddress& peer_address,
                     const QuicReceivedPacket& packet) override;

  // From NetworkHelper.
  void RunEventLoop() override;
  bool CreateUDPSocketAndBind(QuicSocketAddress server_address,
                              QuicIpAddress bind_to_address,
                              int bind_to_port) override;
  void CleanUpAllUDPSockets() override;
  QuicSocketAddress GetLatestClientAddress() const override;
  QuicPacketWriter* CreateQuicPacketWriter() override;

  // Accessors provided for convenience, not part of any interface.
  QuicEventLoop* event_loop() { return event_loop_; }
  const quiche::QuicheLinkedHashMap<int, QuicSocketAddress>& fd_address_map()
      const {
    return fd_address_map_;
  }

  // If the client has at least one UDP socket, return the latest created one.
  // Otherwise, return -1.
  int GetLatestFD() const;

  // Create socket for connection to |server_address| with default socket
  // options.
  // Return fd index.
  virtual int CreateUDPSocket(QuicSocketAddress server_address,
                              bool* overflow_supported);

  QuicClientBase* client() { return client_; }

  void set_max_reads_per_event_loop(int num_reads) {
    max_reads_per_event_loop_ = num_reads;
  }
  // If |fd| is an open UDP socket, unregister and close it. Otherwise, do
  // nothing.
  void CleanUpUDPSocket(int fd);

  // Used for testing.
  void SetClientPort(int port);

  // Indicates that some of the FDs owned by the network helper may be
  // unregistered by the external code by manually calling
  // event_loop()->UnregisterSocket() (this is useful for certain scenarios
  // where an external event loop is used).
  void AllowFdsToBeUnregisteredExternally() {
    fds_unregistered_externally_ = true;
  }

  // Bind a socket to a specific network interface.
  bool BindInterfaceNameIfNeeded(int fd);

 private:
  // Actually clean up |fd|.
  void CleanUpUDPSocketImpl(int fd);

  // Listens for events on the client socket.
  QuicEventLoop* event_loop_;

  // Map mapping created UDP sockets to their addresses. By using linked hash
  // map, the order of socket creation can be recorded.
  quiche::QuicheLinkedHashMap<int, QuicSocketAddress> fd_address_map_;

  // If overflow_supported_ is true, this will be the number of packets dropped
  // during the lifetime of the server.
  QuicPacketCount packets_dropped_;

  // True if the kernel supports SO_RXQ_OVFL, the number of packets dropped
  // because the socket would otherwise overflow.
  bool overflow_supported_;

  // Point to a QuicPacketReader object on the heap. The reader allocates more
  // space than allowed on the stack.
  std::unique_ptr<QuicPacketReader> packet_reader_;

  QuicClientBase* client_;

  int max_reads_per_event_loop_;

  // If true, some of the FDs owned by the network helper may be unregistered by
  // the external code.
  bool fds_unregistered_externally_ = false;
};

}  // namespace quic

#endif  // QUICHE_QUIC_TOOLS_QUIC_CLIENT_DEFAULT_NETWORK_HELPER_H_
