/** @file
    WCCP (v2) support API.

    @section license License

    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#pragma once

#include <memory.h>

#include "tscore/TsBuffer.h"
#include "tscore/Errata.h"
#include "tscore/ink_defs.h"
#include "tscore/ink_memory.h"
// Nasty, defining this with no prefix. The value is still available
// in TS_VERSION_STRING.
#undef VERSION

// INADDR_ANY
#include <netinet/in.h>

#include <string_view>

/// WCCP Support.
namespace wccp
{
/// Forward declare implementation classes.
class Impl;
class CacheImpl;
class RouterImpl;

/// Namespace for implementation details.
namespace detail
{
  /// Cache implementation details.
  namespace cache
  {
    struct GroupData;
  }
  namespace router
  {
    struct GroupData;
  }
} // namespace detail

/// Basic time unit for WCCP in seconds
/// @note Sec 4.14: HERE_I_AM_T.
static time_t const TIME_UNIT   = 10;
static time_t const ASSIGN_WAIT = (3 * TIME_UNIT) / 2;
static time_t const RAPID_TIME  = TIME_UNIT / 10;

/// Service group related constants.
/// @internal In a struct so enum values can be imported to more than
/// one class.
struct ServiceConstants {
  /// Methods for forwarding intercepted packets to cache.
  /// @internal Enumerations values match protocol values.
  enum PacketStyle {
    NO_PACKET_STYLE = 0, ///< Undefined or invalid.
    GRE             = 1, ///< GRE tunnel only. [default]
    L2              = 2, ///< L2 rewrite only.
    GRE_OR_L2       = 3  ///< L2 rewrite or GRE tunnel.
  };

  /// Cache assignment supported methods.
  /// @internal Enumerations values match protocol values.
  enum CacheAssignmentStyle {
    NO_CACHE_ASSIGN_STYLE = 0, ///< Undefined or invalid.
    HASH_ONLY             = 1, ///< Use only hash assignment. [default]
    MASK_ONLY             = 2, ///< Use only mask assignment.
    HASH_OR_MASK          = 3  ///< Use hash or mask assignment.
  };
};

/** Service group definition.

    Also used as serialized layout internally by ServiceGroupElt. This is kept
    in serialized form because it is copied to and from message data far more
    often then it is accessed directly.
 */
class ServiceGroup : public ServiceConstants
{
public:
  typedef ServiceGroup self; ///< Self reference type.

  /// Type of service.
  enum Type : uint8_t {
    STANDARD = 0, ///< Well known service.
    DYNAMIC  = 1  ///< Dynamic (locally defined) service.
  };

  /// Result codes for service definition.
  enum Result {
    DEFINED  = 0, ///< Service group was created by the call.
    EXISTS   = 1, ///< Service group already existed.
    CONFLICT = 2  ///< Service group existed but didn't match new definition.
  };

  /// @name Well known (standard) services.
  //@{
  /// HTTP
  static uint8_t const HTTP = 0;
  //@}
  /// Service IDs of this value or less are reserved.
  static uint8_t const RESERVED = 50;

  /// Number of ports in component (defined by protocol).
  static size_t const N_PORTS = 8;

  /// @name Flag mask values.
  //@{
  /// Source IP address hash
  static uint32_t const SRC_IP_HASH = 1 << 0;
  /// Destination IP address hash
  static uint32_t const DST_IP_HASH = 1 << 1;
  /// Source port hash.
  static uint32_t const SRC_PORT_HASH = 1 << 2;
  /// Destination port hash
  static uint32_t const DST_PORT_HASH = 1 << 3;
  /// @a m_ports has port information.
  static uint32_t const PORTS_DEFINED = 1 << 4;
  /// @a m_ports has source ports (otherwise destination ports).
  static uint32_t const PORTS_SOURCE = 1 << 5;
  /// Alternate source IP address hash
  static uint32_t const SRC_IP_ALT_HASH = 1 << 8;
  /// Alternate destination IP address hash
  static uint32_t const DST_IP_ALT_HASH = 1 << 9;
  /// Alternate source port hash
  static uint32_t const SRC_PORT_ALT_HASH = 1 << 10;
  /// Alternate destination port hash
  static uint32_t const DST_PORT_ALT_HASH = 1 << 11;
  /// All hash related flags.
  static uint32_t const HASH_FLAGS = SRC_IP_HASH | DST_IP_HASH | SRC_PORT_HASH | DST_PORT_HASH | SRC_IP_ALT_HASH | DST_IP_ALT_HASH |
                                     SRC_PORT_ALT_HASH | DST_PORT_ALT_HASH;
  //@}

  /// Default constructor - no member initialization.
  ServiceGroup();
  /// Test for equivalent.
  bool operator==(self const &that) const;
  /// Test for not equivalent.
  bool operator!=(self const &that) const;

  /// @name Accessors
  //@{
  ServiceGroup::Type getSvcType() const; ///< Get service type field.
                                         /** Set the service type.
                                             If @a svc is @c SERVICE_STANDARD then all fields except the
                                             component header and service id are set to zero as required
                                             by the protocol.
                                         */
  self &setSvcType(ServiceGroup::Type svc);

  uint8_t getSvcId() const;   ///< Get service ID field.
  self &setSvcId(uint8_t id); ///< Set service ID field to @a id.

  uint8_t getPriority() const;    ///< Get priority field.
  self &setPriority(uint8_t pri); ///< Set priority field to @a p.

  uint8_t getProtocol() const;  ///< Get protocol field.
  self &setProtocol(uint8_t p); ///< Set protocol field to @a p.

  uint32_t getFlags() const;  ///< Get flags field.
  self &setFlags(uint32_t f); ///< Set the flags flags in field to @a f.
  /// Set the flags in the flag field that are set in @a f.
  /// Other flags are unchanged.
  self &enableFlags(uint32_t f);
  /// Clear the flags in the flag field that are set in @a f.
  /// Other flags are unchanged.
  self &disableFlags(uint32_t f);

  /// Get a port value.
  uint16_t getPort(int idx ///< Index of target port.
  ) const;
  /// Set a port value.
  self &setPort(int idx,      ///< Index of port.
                uint16_t port ///< Value for port.
  );
  /// Zero (clear) all ports.
  self &clearPorts();
  //@}

protected:
  Type m_svc_type;           ///< @ref Type.
  uint8_t m_svc_id;          ///< ID for service type.
  uint8_t m_priority;        ///< Redirection priority ordering.
  uint8_t m_protocol;        ///< IP protocol for service.
  uint32_t m_flags;          ///< Flags.
  uint16_t m_ports[N_PORTS]; ///< Service ports.
};

/// Security component option (sub-type)
enum SecurityOption {
  SECURITY_NONE = 0, ///< No security @c WCCP2_NO_SECURITY
  SECURITY_MD5  = 1  ///< MD5 security @c WCCP2_MD5_SECURITY
};

class EndPoint
{
public:
  typedef EndPoint self; ///< Self reference type.
  typedef Impl ImplType; ///< Implementation type.

  /** Set the identifying IP address.
      This is also used as the address for the socket.
  */
  self &setAddr(uint32_t addr ///< IP address.
  );

  /** Check if this endpoint is ready to use.
      @return @c true if the address has been set and services
      have been added.
  */
  bool isConfigured() const;

  /** Open a socket for communications.

      If @a addr is @c INADDR_ANY then the identifying address is used.
      If that is not set this method will attempt to find an arbitrary
      local address and use that as the identifying address.

      Otherwise @a addr replaces any previously set address.

      @return 0 on success, -ERRNO on failure.
      @see setAddr
  */
  int open(uint32_t addr = INADDR_ANY ///< Local IP address for socket.
  );

  /// Get the internal socket.
  /// Useful primarily for socket options and using
  /// in @c select.
  int getSocket() const;

  /// Use MD5 based security with @a key.
  void useMD5Security(std::string_view const key ///< Shared hash key.
  );

  /// Perform house keeping, including sending outbound messages.
  int housekeeping();

  /// Receive and process a message on the socket.
  /// @return 0 for success, -ERRNO on system error.
  ts::Rv<int> handleMessage();

protected:
  /// Default constructor.
  EndPoint();
  /// Copy constructor.
  EndPoint(self const &that);
  /// Force virtual destructor
  virtual ~EndPoint();

  ts::IntrusivePtr<ImplType> m_ptr; ///< Implementation instance.

  /** Get a pointer to the implementation instance, creating it if needed.
      @internal This is paired with @c make so that the implementation check
      can be done non-virtually inline, while still allowing the actual
      implementation instantiation to be virtual so the correct type is
      created.
   */
  ImplType *instance();

  virtual ImplType *make() = 0; ///< Create a new implementation instance.
};

class Cache : public EndPoint
{
public:
  typedef Cache self;         ///< Self reference type.
  typedef EndPoint super;     ///< Parent type.
  typedef CacheImpl ImplType; ///< Implementation type.

  class Service;

  /// Default constructor.
  Cache();
  /// Destructor
  ~Cache() override;

  /// Define services from a configuration file.
  ts::Errata loadServicesFromFile(char const *path ///< Path to file.
  );

  /** Define a service group.

      Return a service reference object which references the group.

      If @a result is not @c NULL then its target is set to
      - @c ServiceGroup::DEFINED if the service was created.
      - @c ServiceGroup::EXISTS if the service matches the existing service.
      - @c ServiceGroup::CONFLICT if the service doesn't match the existing service.
   */
  Service defineServiceGroup(ServiceGroup const &svc, ///< Service group description.
                             ServiceGroup::Result *result = nullptr);

  /** Add a seed router to the service group.

      A seed router is one that is defined at start up and is where
      initial messages will be sent. Other routers will be added as
      discovered. The protocol cannot start successfully without at
      least one seed router.

      Seed routers are removed when a reply is received from that router.

  */
  self &addSeedRouter(uint8_t id,   ///< Service group ID.
                      uint32_t addr ///< IP address of router.
  );

  /// Number of seconds until next housekeeping activity is due.
  time_t waitTime() const;

protected:
  /// Get implementation instance, creating if needed.
  ImplType *instance();
  /// Get the current implementation instance cast to correct type.
  ImplType *impl();
  /// Get the current implementation instance cast to correct type.
  ImplType const *impl() const;
  /// Create a new implementation instance.
  super::ImplType *make() override;
};

/** Hold a reference to a service group in this end point.
    This is useful when multiple operations are to be done on the
    same group, rather than doing a lookup by id every time.
*/
class Cache::Service : public ServiceConstants
{
public:
  typedef Service self; ///< Self reference type.

  /// Default constructor (invalid reference).
  Service();

  /// Add an address for a seed router.
  self &addSeedRouter(uint32_t addr ///< Router IP address.
  );
  /// Set the security key.
  self &setKey(char const *key /// Shared key.
  );
  /// Set the service local security option.
  self &setSecurity(SecurityOption opt ///< Security style to use.
  );
  /// Set intercepted packet forwarding style.
  self &setForwarding(PacketStyle style ///< Type of forwarding supported.
  );
  /// Enable or disable packet return by layer 2 rewrite.
  self &setReturn(PacketStyle style ///< Type of return supported.
  );

  /// Set cache assignment style.
  self &setCacheAssignment(CacheAssignmentStyle style ///< Style to use.
  );

private:
  Service(Cache const &cache, detail::cache::GroupData &group);
  Cache m_cache;                               ///< Parent cache.
  detail::cache::GroupData *m_group = nullptr; ///< Service Group data.
  friend class Cache;
};

class Router : public EndPoint
{
public:
  typedef Router self;         ///< Self reference type.
  typedef EndPoint super;      ///< Parent type.
  typedef RouterImpl ImplType; ///< Implementation type.

  /// Default constructor
  Router();
  /// Destructor.
  ~Router() override;

  /// Transmit pending messages.
  int sendPendingMessages();

protected:
  /// Get implementation instance, creating if needed.
  ImplType *instance();
  /// Get the current implementation instance cast to correct type.
  ImplType *impl();
  /// Create a new implementation instance.
  super::ImplType *make() override;
};

// ------------------------------------------------------
inline bool
ServiceGroup::operator!=(self const &that) const
{
  return !(*this == that);
}

inline ServiceGroup::Type
ServiceGroup::getSvcType() const
{
  return static_cast<ServiceGroup::Type>(m_svc_type);
}
inline uint8_t
ServiceGroup::getSvcId() const
{
  return m_svc_id;
}

inline ServiceGroup &
ServiceGroup::setSvcId(uint8_t id)
{
  m_svc_id = id;
  return *this;
}

inline uint8_t
ServiceGroup::getPriority() const
{
  return m_priority;
}

inline ServiceGroup &
ServiceGroup::setPriority(uint8_t pri)
{
  m_priority = pri;
  return *this;
}

inline uint8_t
ServiceGroup::getProtocol() const
{
  return m_protocol;
}

inline ServiceGroup &
ServiceGroup::setProtocol(uint8_t proto)
{
  m_protocol = proto;
  return *this;
}

inline uint32_t
ServiceGroup::getFlags() const
{
  return ntohl(m_flags);
}

inline ServiceGroup &
ServiceGroup::setFlags(uint32_t flags)
{
  m_flags = htonl(flags);
  return *this;
}

inline ServiceGroup &
ServiceGroup::enableFlags(uint32_t flags)
{
  m_flags |= htonl(flags);
  return *this;
}

inline ServiceGroup &
ServiceGroup::disableFlags(uint32_t flags)
{
  m_flags &= ~htonl(flags);
  return *this;
}

inline uint16_t
ServiceGroup::getPort(int idx) const
{
  return ntohs(m_ports[idx]);
}

inline ServiceGroup &
ServiceGroup::setPort(int idx, uint16_t port)
{
  m_ports[idx] = htons(port);
  return *this;
}

inline ServiceGroup &
ServiceGroup::clearPorts()
{
  memset(m_ports, 0, sizeof(m_ports));
  return *this;
}

inline Cache::Service::Service() {}

inline Cache::Service::Service(Cache const &cache, detail::cache::GroupData &group) : m_cache(cache), m_group(&group) {}

// ------------------------------------------------------

} // namespace wccp
