/** @file
    WCCP (v2) support for Apache Traffic Server.

    @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 "wccp/Wccp.h"
#include "WccpUtil.h"
#include "ts/apidefs.h"
#include "tscore/Errata.h"
// Needed for template use of byte ordering functions.
#include <netinet/in.h>
#include <memory.h>
#include <map>
#include <string_view>

namespace YAML
{
class Node;
};

namespace wccp
{
// Forward declares
namespace detail
{
  class Assignment;
  namespace cache
  {
    struct RouterData;
  }
} // namespace detail

/// Default port used by the protocol.
static unsigned int const DEFAULT_PORT = 2048;
/// Number of buckets in WCCP hash allocation.
static unsigned int const N_BUCKETS = 256;
/// Unassigned bucket value (defined by protocol).
static uint8_t const UNASSIGNED_BUCKET = 0xFF;
/// Size of group password in octets.
static unsigned int const GROUP_PASSWORD_SIZE = 8;
/// Maximum # of caches
static uint32_t const MAX_CACHES = 32;
/// Maximum # of routers
static uint32_t const MAX_ROUTERS = 32;

/// Our version of the protocol.
static unsigned int const VERSION = 0x200;

/// @name Parse results.
/// @note Internal values are positive. System errors are reported as
/// the negative of errno.
//@{
/// Successful parse (message is well formatted)
static int const PARSE_SUCCESS = 0;
/// Component is the wrong type but looks like a valid type.
static int const PARSE_COMP_OTHER_TYPE = 1;
/// Component has a bogus type (cannot be valid).
static int const PARSE_COMP_TYPE_INVALID = 2;
/// Length in message is larger than actual message data.
static int const PARSE_MSG_TOO_BIG = 3;
/// Message header has invalid data.
static int const PARSE_MSG_INVALID = 5;
/// Component is malformed.
static int const PARSE_COMP_INVALID = 4;
/// Message is not the expected type.
static int const PARSE_MSG_WRONG_TYPE = 6;
/// Variable data for component can't fit in remaining data.
static int const PARSE_COMP_TOO_BIG = 7;
/// Fixed data for component can't fit in remaining data.
static int const PARSE_BUFFER_TOO_SMALL = 8;
/// Stored component size doesn't agree with locally computed size.
static int const PARSE_COMP_WRONG_SIZE = 9;
/// More data in message than can be accounted for.
static int const PARSE_DATA_OVERRUN = 10;
//@}

/** Buffer for serialized data.
    Takes the basic ATS buffer and adds a count field to track
    the amount of buffer in use.
*/
class MsgBuffer : protected ts::Buffer
{
public:
  typedef MsgBuffer self;   ///< Self reference type.
  typedef ts::Buffer super; ///< Parent type.

  MsgBuffer(); ///< Default construct empty buffer.
  /// Construct from ATS buffer.
  MsgBuffer(super const &that ///< Instance to copy.
  );
  /// Construct from pointer and size.
  MsgBuffer(void *ptr, ///< Pointer to buffer.
            size_t n   ///< Size of buffer.
  );
  /// Assign a buffer.
  MsgBuffer &set(void *ptr, ///< Pointer to buffer.
                 size_t n   ///< Size of buffer.
  );

  /// Get the buffer size.
  size_t getSize() const;
  /// Get the content size (use count).
  size_t getCount() const;
  /// Get address of first unused byte.
  char *getTail();
  /// Get address of first byte.
  char *getBase();
  /// Get address of first byte.
  const char *getBase() const;
  /// Get the remaining space in the buffer.
  size_t getSpace() const;
  /// Mark additional space in use.
  self &use(size_t n ///< Additional space to mark in use.
  );
  /// Mark all space as unused.
  self &reset();

  /// Reset and zero the buffer.
  self &zero();

  size_t _count; ///< Number of bytes in use.
};

/// Sect 4.4: Cache assignment method.
enum CacheAssignmentType {
  ASSIGNMENT_BY_HASH = 0,
  ASSIGNMENT_BY_MASK = 1,
};

/// Top level message types.
enum message_type_t {
  INVALID_MSG_TYPE = 0,
  HERE_I_AM        = 10,
  I_SEE_YOU        = 11,
  REDIRECT_ASSIGN  = 12,
  REMOVAL_QUERY    = 13,
};

/// Message component type.
/// See Sect 5.1 - 5.4
enum CompType {
  SECURITY_INFO       = 0,
  SERVICE_INFO        = 1,
  ROUTER_ID_INFO      = 2,
  CACHE_ID_INFO       = 3,
  RTR_VIEW_INFO       = 4,
  CACHE_VIEW_INFO     = 5,
  REDIRECT_ASSIGNMENT = 6,
  QUERY_INFO          = 7,
  CAPABILITY_INFO     = 8,
  ALT_ASSIGNMENT      = 13,
  ASSIGN_MAP          = 14,
  COMMAND_EXTENSION   = 15,
  COMP_TYPE_MIN       = SECURITY_INFO,
  COMP_TYPE_MAX       = COMMAND_EXTENSION
};

/// Router Identity.
/// Data is stored in host order. This structure is not used publicly.
struct RouterId {
  typedef RouterId self; ///< Self reference type.

  RouterId(); ///< Default constructor.
  /// Construct from address and sequence number.
  RouterId(uint32_t addr,   ///< Router address.
           uint32_t recv_id ///< Receive ID (sequence number).
  );

  uint32_t m_addr;    ///< Identifying router IP address.
  uint32_t m_recv_id; ///< Receive ID (sequence #).
};

/** Sect 5.7.1: Router Identity Element.

    This maps directly on to message content.

    @internal A @c RouterId with accessors to guarantee correct memory
    layout.
*/
class RouterIdElt : protected RouterId
{
protected:
  typedef RouterId super; ///< Parent type.
public:
  typedef RouterIdElt self; ///< Self reference type.

  /// Default constructor, members zero initialized.
  RouterIdElt();
  /// Construct from address and sequence number.
  RouterIdElt(uint32_t addr,   ///< Router address.
              uint32_t recv_id ///< Receive ID (sequence number).
  );

  /// @name Accessors
  //@{
  uint32_t getAddr() const;     ///< Get the address field.
  self &setAddr(uint32_t addr); ///< Set the address field to @a addr.
  uint32_t getRecvId() const;   ///< Get the receive ID field.
  self &setRecvId(uint32_t id); ///< Set the receive ID field to @a id.
  //@}

  /// Assign from non-serialized variant.
  self &operator=(super const &that);
};

/// Sect 5.7.3: Assignment Key Element
/// @note This maps directly on to message content.
/// @internal: At top level because it is used in more than one component.
class AssignmentKeyElt
{
public:
  typedef AssignmentKeyElt self; ///< Self reference type.

  AssignmentKeyElt(); ///< Default constructor. No member initialization.
  /// Construct from address and sequence number.
  AssignmentKeyElt(uint32_t addr,      ///< Key address.
                   uint32_t generation ///< Change number.
  );

  /// @name Accessors
  //@{
  uint32_t getAddr() const;          ///< Get the address field.
  self &setAddr(uint32_t addr);      ///< Set the address field to @a addr.
  uint32_t getChangeNumber() const;  ///< Get change number field.
  self &setChangeNumber(uint32_t n); ///< Set change number field to @a n.
  //@}
protected:
  uint32_t m_addr;          ///< Identifying router IP address.
  uint32_t m_change_number; ///< Change number (sequence #).
};

/// Sect 5.7.4: Router Assignment Element
/// @note This maps directly on to message content.
/// @internal: At top level because it is used in more than one component.
class RouterAssignElt : public RouterIdElt
{
public:
  typedef RouterAssignElt self; ///< Self reference type.
  typedef RouterIdElt super;    ///< Parent type.

  /// Default constructor, members zero initialized.
  RouterAssignElt();
  /// Construct from address and sequence number.
  RouterAssignElt(uint32_t addr,         ///< Router address.
                  uint32_t recv_id,      ///< Receive ID (sequence number).
                  uint32_t change_number ///< Change number (sequence number).
  );

  /// @name Accessors
  //@{
  uint32_t getChangeNumber() const;  ///< Get change number field.
  self &setChangeNumber(uint32_t n); ///< Set change number field to @a n.
  //@}
protected:
  uint32_t m_change_number; ///< Change number (sequence #).
};

/** List of @c RouterAssignElt
    @note Not explicitly part of the spec, but it shows up in multiple
    places.
 */
class RouterAssignListElt
{
public:
  typedef RouterAssignListElt self; ///< Self reference type.

  /// Default constructor - @b no initialization.
  RouterAssignListElt();
  /// Construct with @n elements.
  RouterAssignListElt(int n ///< Number of elements.
  );

  /// @name Accessors
  //@{
  /// Access element.
  RouterAssignElt &elt(int idx ///< Index of target element.
  );
  /// Access const element.
  RouterAssignElt const &elt(int idx ///< Index of target element.
  ) const;
  /// Get the number of elements.
  uint32_t getCount() const;
  //@}

  /// Update ID for a router.
  self &updateRouterId(uint32_t addr,  ///< Identifying IP address of router.
                       uint32_t rcvid, ///< New receive ID value.
                       uint32_t cno    ///< New change number.
  );

  /// Get size in bytes of this structure.
  size_t getSize() const;
  /// Get the size of the variable part only.
  /// This is useful for classes that put this element in their
  /// stub structure.
  size_t getVarSize() const;
  /// Calculate size in bytes for @a n elements.
  static size_t calcSize(int n ///< Number of elements.
  );
  /// Calculate size of variable data in bytes for @a n elements.
  static size_t calcVarSize(int n ///< Number of elements.
  );

protected:
  uint32_t m_count; ///< # of elements (network order).
};

/// Sect 5.7.5: Capability Element
/// @note This maps directly on to message content.
class CapabilityElt
{
public:
  typedef CapabilityElt self; ///< Self reference type.

  /// Capability types.
  enum Type : uint16_t {
    NO_METHOD               = 0, ///< Method not set.
    PACKET_FORWARD_METHOD   = 1, ///< Packet forwarding methods.
    CACHE_ASSIGNMENT_METHOD = 2, ///< Cache assignment methods.
    PACKET_RETURN_METHOD    = 3  ///< Packet return methods.
  };

  CapabilityElt(); ///< Default constructor.
  /// Construct from address and sequence number.
  CapabilityElt(Type type,    ///< Capability type.
                uint32_t data ///< Capability data.
  );

  /// @name Accessors
  //@{
  Type getCapType() const; ///< Get the capability type.
  /// Set capability type.
  self &setCapType(Type cap ///< Capability type.
  );
  uint32_t getCapData() const; ///< Get capability data.
  /// Set capability data.
  self &setCapData(uint32_t data ///< Data value.
  );
  //@}
protected:
  enum Type m_cap_type  = NO_METHOD; ///< Capability type.
  uint16_t m_cap_length = 0;         ///< Length of capability data.
  uint32_t m_cap_data   = 0;         ///< Capability data.
};

/// Sect 5.7.7: Mask element
class MaskElt
{
public:
  typedef MaskElt self; ///< Self reference type.

  /// Default constructor - @b no initialization.
  MaskElt();
  /// Construct with specific values.
  MaskElt(uint32_t srcAddr, ///< Mask for source address.
          uint32_t dstAddr, ///< Mask for destination address.
          uint16_t srcPort, ///< Mask for source port.
          uint16_t dstPort  ///< Mask for destination port.
  );

  /// @name Accessors
  //@{
  /// Get source address mask field.
  uint32_t getSrcAddr() const;
  /// Set source address mask field to @a mask.
  self &setSrcAddr(uint32_t mask);
  /// Get destination address field.
  uint32_t getDstAddr() const;
  /// Set destination address field to @a mask.
  self &setDstAddr(uint32_t mask);
  /// Get source port mask field.
  uint16_t getSrcPort() const;
  /// Set source port mask field to @a mask.
  self &setSrcPort(uint16_t mask);
  /// Get destination port mask field.
  uint16_t getDstPort() const;
  /// Set destination port mask field to @a mask.
  self &setDstPort(uint16_t mask);
  //@}

protected:
  uint32_t m_src_addr = INADDR_ANY; ///< Source address mask.
  uint32_t m_dst_addr = INADDR_ANY; ///< Destination address mask.
  uint16_t m_src_port = 0;          ///< Source port mask.
  uint16_t m_dst_port = 0;          ///< Destination port mask.
};

/// Sect 5.7.8: Value element.
class ValueElt
{
public:
  typedef ValueElt self; ///< Self reference type.

  /// Default constructor - @b no initialization.
  ValueElt();
  /// Construct a specific value.
  ValueElt(uint32_t cacheAddr, ///< Address of cache for this value.
           uint32_t srcAddr,   ///< Value for source address.
           uint32_t dstAddr,   ///< Value for destination address.
           uint16_t srcPort,   ///< Value for source port.
           uint16_t dstPort    ///< Value for destination port.
  );

  /// @name Accessors
  //@{
  uint32_t getf_src_addr() const;     ///< Get source address field.
  self &setf_src_addr(uint32_t addr); ///< Set source address field to @a addr.
  uint32_t getDstAddr() const;        ///< Get destination address field.
  self &setf_dst_addr(uint32_t addr); ///< Set destination address field to @a addr.
  uint16_t getf_src_port() const;     ///< Get source port field.
  self &setf_src_port(uint16_t port); ///< Set source port field to @a port.
  uint16_t getDstPort() const;        ///< Get destination port field.
  self &setf_dst_port(uint16_t port); ///< Set destination port field to @a port.
  uint32_t getCacheAddr() const;      ///< Get cache address field.
  self &setCacheAddr(uint32_t addr);  ///< Set cache address field to @a addr
  //@}

protected:
  uint32_t m_src_addr;   ///< Source address.
  uint32_t m_dst_addr;   ///< Destination address.
  uint16_t m_src_port;   ///< Source port.
  uint16_t m_dst_port;   ///< Destination port.
  uint32_t m_cache_addr; ///< Cache address.
};

/** Sect 5.7.6: Mask/Value Set Element
    This is a variable sized element.
 */
class MaskValueSetElt
{
public:
  typedef MaskValueSetElt self; ///< Self reference type.

  MaskValueSetElt(); ///< Default constructor.
  /// Construct from address and sequence number.
  MaskValueSetElt(uint32_t n ///< Value count.
  );

  /// @name Accessors
  //@{
  /// Directly access contained mask element.
  MaskElt &maskElt();

  /// Get source address mask field.
  uint32_t getSrcAddrMask() const;
  /// Set source address mask field to @a mask.
  self &setSrcAddrMask(uint32_t mask);
  /// Get destination address field.
  uint32_t getDstAddrMask() const;
  /// Set destination address field to @a mask.
  self &setDstAddrMask(uint32_t mask);
  /// Get source port mask field.
  uint16_t getSrcPortMask() const;
  /// Set source port mask field to @a mask.
  self &setSrcPortMask(uint16_t mask);
  /// Get destination port mask field.
  uint16_t getDstPortMask() const;
  /// Set destination port mask field to @a mask.
  self &setDstPortMask(uint16_t mask);

  /// Append a value to this set.
  self &addValue(uint32_t cacheAddr, ///< Address of cache for this value.
                 uint32_t srcAddr,   ///< Value for source address.
                 uint32_t dstAddr,   ///< Value for destination address.
                 uint16_t srcPort,   ///< Value for source port.
                 uint16_t dstPort    ///< Value for destination port.
  );

  /// Get the value count.
  /// @note No corresponding @c set because this cannot be directly changed.
  uint32_t getCount() const;
  /// Access value element.
  ValueElt &operator[](int idx ///< Index of target element.
  );
  //@}
  /// Calculate the size of an element with @a n values.
  static size_t calcSize(uint32_t n ///< Number of values.
  );
  /// Get the size (length) of this element.
  size_t getSize() const;

protected:
  // All members are kept in network order.
  MaskElt m_mask;   ///< Base mask element.
  uint32_t m_count; ///< Number of value elements.

  /// Get base address of Value elements.
  ValueElt *values();
  /// Get base address of Value elements.
  ValueElt const *values() const;
};

/// Assignment of caches by hash.
/// Not in specification.
class HashAssignElt
{
public:
  typedef HashAssignElt self; ///< Self reference type.

  /// Hash assignment bucket.
  struct Bucket {
    unsigned int m_idx : 7; ///< Cache index.
    unsigned int m_alt : 1; ///<  Alternate hash flag.

    /// Test for unassigned value in bucket.
    bool is_unassigned() const;
  } __attribute__((aligned(1), packed));

  /// Default constructor - @b no initialization.
  HashAssignElt();
  /// Construct with @n elements.
  HashAssignElt(int n ///< Number of elements.
  );

  /// @name Accessors
  //@{
  /// Get the number of caches.
  uint32_t getCount() const;
  /// Get a cache address.
  uint32_t getAddr(int idx ///< Index of target address.
  ) const;
  /// Set a cache address.
  self &setAddr(int idx,      ///< Index of target address.
                uint32_t addr ///< Address value to set.
  );
  /// Access a bucket.
  Bucket &operator[](size_t idx ///< Bucket index (0..N_BUCKETS-1)
  );
  /// Access a const bucket.
  Bucket const &operator[](size_t idx ///< Bucket index (0..N_BUCKETS-1)
  ) const;
  //@}

  /** Do a round robin assignment.
      The buckets are assigned round robin, starting with 0, up to the
      index of the last cache.
      @return @c this.
  */
  self &round_robin_assign();

  /// Get size in bytes of this structure.
  size_t getSize() const;
  /// Calculate size in bytes for @a n caches.
  static size_t calcSize(int n ///< Number of caches.
  );

protected:
  uint32_t m_count; ///< # of caches (network order).

  Bucket *getBucketBase();
};

/** Assignment of caches by mask.
    @note Not in specification.

    @internal Because this is an element, it must correspond exactly
    to the serialized layout. Therefore we can't keep extra accounting
    data around to make manipulation easier. We need a helper class
    for that, which functions in a manner similar to an iterator.
 */

class MaskAssignElt
{
public:
  typedef MaskAssignElt self; ///< Self reference type.

  /** A minimalist insert iterator.
   */
  struct appender {
    typedef appender self; ///< Self reference type.
    /// Get pointer to current set.
    MaskValueSetElt *operator->();
    /// Append a new mask/value set.
    /// @return A pointer to the new set.
    MaskValueSetElt *mask(uint32_t srcAddr, ///< Mask for source address.
                          uint32_t dstAddr, ///< Mask for destination address.
                          uint16_t srcPort, ///< Mask for source port.
                          uint16_t dstPort  ///< Mask for destination port.
    );
    /// Initialize the current set to empty with specific mask values.
    /// @return A pointer to the new set.
    MaskValueSetElt *initSet(uint32_t srcAddr, ///< Mask for source address.
                             uint32_t dstAddr, ///< Mask for destination address.
                             uint16_t srcPort, ///< Mask for source port.
                             uint16_t dstPort  ///< Mask for destination port.
    );
    MaskValueSetElt *m_set; ///< Current set.
    MaskAssignElt *m_elt;   ///< Parent element.
  };

  /// @name Accessors
  //@{
  /// Get the number of mask/value sets.
  uint32_t getCount() const;
  //@}

  appender init(uint32_t srcAddr, ///< Mask for source address.
                uint32_t dstAddr, ///< Mask for destination address.
                uint16_t srcPort, ///< Mask for source port.
                uint16_t dstPort  ///< Mask for destination port.
  );

  /// Get size in bytes of this structure.
  /// @note This is not constant time. The mask/value sets must be traversed
  /// to get the total size.
  size_t getSize() const;
  /// Get the size in bytes of the variable part of this structure.
  /// @note This is not constant time. The mask/value sets must be traversed
  /// to get the total size.
  size_t getVarSize() const;

protected:
  uint32_t m_count = 0; ///< # of sets (network order).

  friend struct appender;
};

class CacheIdBox;

/** Sect 5.7.2: Web-Cache Identity Element
    According to the specification, this is a fixed structure with
    hash data. However, in practice there is an undocumented variant for
    mask assignment where it contains mask data instead of hash data.

    This class provides basic control. Two subclasses specialize for the
    two variants. Use @c isMask to detect which variant is present.

    @note Do not add virtual methods, as reasonable as that seems because
    this is a serialized object and the memory layout correspond to the
    protocol definition.

    @see CacheHashIdElt
    @see CacheMaskIdElt
*/
class CacheIdElt
{
  friend class CacheIdBox;

public:
  typedef CacheIdElt self; ///< Self reference type.

  /// Hash revision (protocol required).
  static uint16_t const HASH_REVISION = 0;

  /// @name Accessors
  //@{
  uint32_t getAddr() const;        ///< Get address field.
  self &setAddr(uint32_t addr);    ///< Set address field to @a addr.
  uint16_t getHashRev() const;     ///< Get hash revision field.
  self &setHashRev(uint16_t rev);  ///< Set hash revision field to @a rev.
  self &initHashRev();             ///< Set hash revision to default value.
  bool getUnassigned() const;      ///< Get unassigned field.
  self &setUnassigned(bool state); ///< Set unassigned field to @a state.
  bool isMask() const;             ///< @return @c true if this is a mask assignment.
                                   /** Set the maskiness of this structure.
                                       Be very careful with this, as different values change the
                                       memory layout of the object.
                                   */
  self &setMask(bool state         ///< @c true to be mask, @c false to be hash.
  );

  self &clearReserved(); ///< Set reserved bits to zero.
  //@}

protected:
  uint32_t m_addr;               ///< Identifying cache IP address.
  uint16_t m_hash_rev;           ///< Hash revision.
  unsigned int m_reserved_0 : 7; ///< Reserved bits.
                                 /** Cache not assigned.
                                     If set the cache does not have an assignment in the redirection
                                     hash table and the data in @a m_buckets is historical. This allows
                                     a cache that was removed to be added back in the same buckets.
                                 */
  unsigned int m_unassigned : 1;
  unsigned int m_reserved_1 : 1; ///< Reserved (unused).
  unsigned int m_is_mask : 1;    ///< Set -> mask, Clear -> hash.
  unsigned int m_reserved_2 : 6; ///< Reserved (unused).
                                 /** Trailing elements common to all cache ID variants.
                                     Unfortunately, although @c weight and @c status are common, they are
                                     after the variable data and so can't be put in the base class.
                                     Best we can do is declare a struct for them for later convenience.
                                 */
  struct Tail {
    uint16_t m_weight; ///< Weight of assignment.
    uint16_t m_status; ///< Cache status.
  };
};

/** Cache ID for Hash assignment.
 */
class CacheHashIdElt : public CacheIdElt
{
  friend class CacheIdBox;

public:
  typedef CacheHashIdElt self; ///< Self reference type.
  typedef CacheIdElt super;    ///< Parent type.
  /// Container for hash assignment.
  typedef uint8_t HashBuckets[N_BUCKETS >> 3];
  /// @name Accessors
  //@{
  bool getBucket(int idx) const; ///< Get bucket state at index @a idx.
  /// Set bucket at index @a idx to @a state.
  self &setBucket(int idx, bool state);
  self &setBuckets(bool state); ///< Set all buckets to @a state.
  uint16_t getWeight() const;   ///< Get weight field.
  self &setWeight(uint16_t w);  ///< Set weight field to @a w.
  uint16_t getStatus() const;   ///< Get status field.
  self &setStatus(uint16_t s);  ///< Set status field to @a s.
  //@}
  /// Get object size in bytes.
  size_t getSize() const;

protected:
  /// Bit vector of buckets assigned to this cache.
  HashBuckets m_buckets;
  Tail m_tail; /// Trailing values in element.

  /// Get the address of the tail elements.
  Tail *getTailPtr();
};

/** Cache ID for Mask assignment.
    Be a little careful with this object. Because it's an element and
    must copy the serialized data layout, almost all of the methods are
    not constant time but require walking internal data structures.

    @internal Experimentally,
    - A mask assign element count of zero does not work. It fails
    with the wrongly descriptive message "incompatible assignment data".
    - A single mask assign element with a mask set with one value seems to
    work.
 */
class CacheMaskIdElt : public CacheIdElt
{
  friend class CacheIdBox;

public:
  typedef CacheMaskIdElt self; ///< Self reference type.
  typedef CacheIdElt super;    ///< Parent type.
  /// @name Accessors
  //@{
  uint16_t getWeight() const;  ///< Get weight field.
  self &setWeight(uint16_t w); ///< Set weight field to @a w.
  uint16_t getStatus() const;  ///< Get status field.
  self &setStatus(uint16_t s); ///< Set status field to @a s.
  /// Get the number of mask/value sets.
  uint32_t getCount() const;
  //@}
  /// Get object size in bytes.
  size_t getSize() const;

protected:
  /// Mask assignment data.
  MaskAssignElt m_assign;
  /// Get a pointer to where the tail data is.
  /// Presumes the assignment is filled out.
  Tail *getTailPtr();
};

/** Holder for a @c CacheIdElt.
    This class is needed because of the restrictions on element classes and
    because a @c CacheIdElt is a variable sized element yet we need to store
    instances of it in other classes. This box both holds an instance and
    handles some of the memory allocation issues involved.
 */
class CacheIdBox
{
public:
  typedef CacheIdBox self; ///< Self reference type.

  /// Default constructor.
  CacheIdBox() = default;

  /// @name Accessors
  //@{
  /// Get the identifying cache address.
  uint32_t getAddr() const;
  /// Set the identifying cache address.
  self &setAddr(uint32_t ///< Identifying IP address.
  );
  uint16_t getHashRev() const;     ///< Get hash revision field.
  self &setHashRev(uint16_t rev);  ///< Set hash revision field to @a rev.
  self &initHashRev();             ///< Set hash revision to default value.
  bool getUnassigned() const;      ///< Get unassigned field.
  self &setUnassigned(bool state); ///< Set unassigned field to @a state.
  bool isMask() const;             ///< @return @c true if this is a mask assignment.
                                   /** Set the maskiness of this structure.
                                       Be very careful with this, as different values change the
                                       memory layout of the object.
                                   */
  self &setMask(bool state         ///< @c true to be mask, @c false to be hash.
  );

  self &clearReserved(); ///< Set reserved bits to zero.
  //@}
  /// Initialize to unassigned hash.
  /// The cache address is set to @a addr.
  self &initDefaultHash(uint32_t addr ///< Identifying cache address.
  );
  /// Initialize to unassigned mask
  /// The cache address is set to @a addr.
  self &initDefaultMask(uint32_t addr ///< Identifying cache address.
  );
  /** Fill in element from source copy.
      Internal memory is allocated and the @a src copied.
   */
  self &fill(self const &src ///< Original source element
  );
  /** Fill in element from source copy.
      This is used to write the element to memory that is allocated
      independently of the box.
      @note Caller is expected to have verified sufficient buffer space.
   */
  self &fill(void *base,     ///< Target buffer.
             self const &src ///< Original source element
  );
  /// Initialize box from an existing element in memory.
  int parse(MsgBuffer base ///< Source memory.
  );

  /// Get the size in bytes of the contained element.
  size_t getSize() const;

protected:
  /// Force buffer to be at least @a n bytes
  self &require(size_t n ///< Minimum buffer size required.
  );

  CacheIdElt *m_base       = nullptr; ///< Base address of memory for element.
  CacheIdElt::Tail *m_tail = nullptr; ///< Base address of trailing data elements.
  size_t m_size            = 0;       ///< Size of element (valid data in buffer);
  size_t m_cap             = 0;       ///< Size of allocated memory. Zero if external memory.
};

/** Base class for all components.

    Each component is a fixed sized object that represents a
    component in the WCCP message. The component instance points at
    its corresponding data in the message. Values in the message are
    accessed through accessor methods which have the form @c
    getNAME and @c setNAME for "get field" and "set field". The
    @c set methods return a reference to the component so that
    they can be chained.

    Most components will have an internal typedef @c raw_t which is a
    structure with the exact memory layout of the
    component. Components without this typedef cannot be directed
    represented by a C++ structure (which is why we need this
    indirection in the first place).
*/
class ComponentBase
{
public:
  typedef ComponentBase self; ///< Self reference type.
  /// Default constructor.
  ComponentBase() = default;
  /// Check for not present.
  bool isEmpty() const;

protected:
  /// Base of component in message data.
  /// If this is @c NULL then the component is not in the message.
  char *m_base = nullptr;
};

/// Synthetic component to represent the overall message header.
class MsgHeaderComp : public ComponentBase
{
public:
  typedef MsgHeaderComp self;  ///< Self reference type.
  typedef ComponentBase super; ///< Parent type.

  /// Sect 5.5:  Message Header
  /// Serialized layout of message header.
  struct raw_t {
    uint32_t m_type;    ///< @c message_type_t
    uint16_t m_version; ///< Implementation version of sender
    uint16_t m_length;  ///< Message body length (excluding header)
  };

  /// Default constructor.
  MsgHeaderComp() {}
  /// @name Accessors
  //@{
  message_type_t getType();           ///< Get message type field.
  uint16_t getVersion();              ///< Get message version field.
  uint16_t getLength();               ///< Get message length field.
  self &setType(message_type_t type); ///< Set message type field to @a type.
  self &setVersion(uint16_t version); ///< Set version field to @a version.
  self &setLength(uint16_t length);   ///< Set length field to @a length.
  //@}

  /// Write initial values to message data.
  /// @a base is updated to account for this component.
  self &fill(MsgBuffer &base, ///< [in,out] Buffer for component storage.
             message_type_t t ///< Message type.
  );

  /// Validate component for existing data.
  /// @a base is updated to account for this component.
  int parse(MsgBuffer &base ///< [in,out] Base address for component data.
  );

  /// Compute size of a component of this type.
  static size_t calcSize();

  /// Convert to a top level message type.
  /// @return The converted type if valid, @c INVALID_MSG_TYPE if not.
  static message_type_t toMsgType(int t);
};

/** Intermediate base class for components with the standard component header.

    @note That's all of them except the message header itself.

    @internal This saves some work getting around C++ co-variance issues
    with return values.
*/
template <typename T ///< Child class (CRT pattern)
          >
struct CompWithHeader : public ComponentBase {
  /** Serialized layout of per component header.
      All components except the message header start with this structure.
      Provided for ease of use by child classes, which should
      subclass this for their own @c raw_t.
  */
  struct raw_t {
    uint16_t m_type;   ///< Serialized @ref CompType.
    uint16_t m_length; ///< length of rest of component (not including header).
  };
  /** Size of header.
      This is needed by all subclasses because the value in the length field
      excludes this structure.
  */
  static size_t const HEADER_SIZE = sizeof(raw_t);

  /// @name Accessors
  //@{
  CompType getType() const;      ///< Get component type field.
  uint16_t getLength() const;    ///< Get component length field.
  T &setType(CompType type);     ///< Set component type field to @a type.
  T &setLength(uint16_t length); ///< Set length field to @a length.
                                 //@}

  /** Check the component header for type and length sanity.
      This requires the (subclass) client to
      - Do a size check to verify enough space for the component header.
      - Set @a m_base

      This method
      - Checks the component type against the expected type (@a ect)
      - Checks stored component length against the buffer size.

      @return A parse result.
  */
  int checkHeader(MsgBuffer const &buffer, ///< Message buffer.
                  CompType t               ///< Expected component type.
  );
};

/** Sect 5.6.1: Security Info Component
    This is used for both security options. Clients should check
    the @c m_option to see if the @a m_impl member is valid.
*/
class SecurityComp : public CompWithHeader<SecurityComp>
{
public:
  typedef SecurityComp self;          ///< Self reference type.
  typedef CompWithHeader<self> super; ///< Parent type.
  /// Specify the type for this component.
  static CompType const COMP_TYPE = SECURITY_INFO;

  /// Import security option type.
  typedef SecurityOption Option;

  static size_t const KEY_SIZE = 8;
  typedef char Key[KEY_SIZE];

  /// Raw memory layout, no security.
  struct RawNone : public super::raw_t {
    uint32_t m_option; ///< @c Option
  };

  /// Raw memory layout, with MD5.
  struct RawMD5 : public RawNone {
    /// Size of MD5 hash (in bytes).
    static size_t const HASH_SIZE = 16;
    /// Storage for MD5 hash.
    typedef uint8_t HashData[HASH_SIZE];
    /// MD5 hash value.
    HashData m_data;
  };

  /// Default constructor.
  SecurityComp();

  /// @name Accessors
  //@{
  Option getOption() const;    ///< Get security option field.
  self &setOption(Option opt); ///< Set security option field to @a opt.
  //@}

  /// Write default values to the serialization buffer.
  self &fill(MsgBuffer &buffer, Option opt = m_default_opt);
  /// Validate an existing structure.
  int parse(MsgBuffer &buffer);

  /// Compute the memory size of the component.
  static size_t calcSize(Option opt);

  /// Set the global / default security key.
  /// This is used for the security hash unless the local key is set.
  /// @a key is copied to a global buffer and clipped to @c KEY_SIZE bytes.
  static void setDefaultKey(const char *key ///< Shared key.
  );
  static void setDefaultOption(Option opt ///< Type of security.
  );

  /// Set message local security key.
  self &setKey(const char *key ///< Shared key.
  );

  /// Compute and set the security data.
  /// @a msg must be a buffer that covers exactly the entire message.
  self &secure(MsgBuffer const &msg ///< Message data.
  );

  bool validate(MsgBuffer const &msg ///< Message data.
  ) const;

protected:
  /// Local to this message shared key / password.
  Key m_key;
  /// Use local key.
  bool m_local_key;
  /// Global (static) shared key / password.
  static Key m_default_key;
  /// Default security option.
  static Option m_default_opt;
};

/// Sect 5.6.2: Service Info Component
class ServiceComp : public CompWithHeader<ServiceComp>
{
public:
  typedef ServiceComp self;           ///< Self reference type.
  typedef CompWithHeader<self> super; ///< Parent type.

  /// Specify the type for this component.
  static CompType const COMP_TYPE = SERVICE_INFO;

  /// Serialized format for component.
  struct raw_t : public super::raw_t, public ServiceGroup {
  };

  ServiceComp(); ///< Default constructor, no member initialization.

  /// @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();
  /** Add a port to the service.
      The first port which has not been set is set to @a port. It is an error
      to add more than @c N_PORTS ports.
   */
  self &addPort(uint16_t port ///< Port value.
  );
  //@}

  /// Raw access to ServiceGroup.
  operator ServiceGroup const &() const;

  /** Fill from a service group definition.
   */
  self &fill(MsgBuffer &base,        ///< Target storage.
             ServiceGroup const &svc ///< Service group definition.
  );

  /// Validate an existing structure.
  /// @return Parse result.
  int parse(MsgBuffer &buffer);

  /// Compute the memory size of the component.
  static size_t calcSize();

protected:
  int m_port_count; ///< Number of ports in use.

  /// Cast raw internal pointer to data type.
  raw_t *access();
  /// Cast raw internal pointer to data type.
  raw_t const *access() const;
};

/// Sect 5.6.3: RouterIdentity Info Component
/// @note An instance of this struct is followed by @a m_count
/// IP addresses.
class RouterIdComp : public CompWithHeader<RouterIdComp>
{
public:
  typedef RouterIdComp self;          ///< Self reference type.
  typedef CompWithHeader<self> super; ///< Parent type.

  /// Specify the type for this component.
  static CompType const COMP_TYPE = ROUTER_ID_INFO;

  /// Stub of serialized layout.
  struct raw_t : public super::raw_t {
    RouterIdElt m_id; ///< Router ID element.
    /// Source address.
    /// For response messages, this is the address to which the
    /// original message was sent.
    uint32_t m_to_addr;
    /// # of target cache addresses.
    uint32_t m_from_count;
    // Addresses follow here.
  };

  /// @name Accessors
  //@{
  /// Directly access router ID element.
  RouterIdElt &idElt();
  /// Directly access router ID element.
  RouterIdElt const &idElt() const;
  /// Set the fields in the router ID element.
  self &setIdElt(uint32_t addr,   ///< Identifying IP address for router.
                 uint32_t recv_id ///< Receive count for router to target cache.
  );
  uint32_t getAddr() const;     ///< Get the address field in the ID element.
  self &setAddr(uint32_t addr); ///< Set the address field in the ID element.
  uint32_t getRecvId() const;   ///< Get the receive ID field in the ID element.
  self &setRecvId(uint32_t id); ///< Set the receive ID field in the ID element.

  /// Get the sent to address.
  uint32_t getToAddr() const;
  /// Set the sent to address.
  self &setToAddr(uint32_t addr ///< Address value.
  );
  /// Get router count field.
  /// @note No @c setf method because this cannot be changed independently.
  /// @see fill
  uint32_t getFromCount() const;
  /// Get received from address.
  uint32_t getFromAddr(int idx ///< Index of address.
  ) const;
  /// Set received from address.
  self &setFromAddr(int idx,      ///< Index of address.
                    uint32_t addr ///< Address value.
  );
  //@}
  /// Find an address in the from list.
  /// @return The index of the address, or -1 if not found.
  int findFromAddr(uint32_t addr ///< Search value.
  );

  /** Write serialization data for single cache target.
      This completely fills the component.
  */
  self &fillSingleton(MsgBuffer &base,     ///< Target storage.
                      uint32_t addr,       ///< Identifying IP address.
                      uint32_t recv_count, ///< Receive count for target cache.
                      uint32_t to_addr,    ///< Destination address in initial packet.
                      uint32_t from_addr   ///< Identifying IP address of target cache.
  );

  /** Write basic message structure.
      The router and cache data must be filled in separately.
  */
  self &fill(MsgBuffer &base, ///< Target storage.
             size_t n_caches  ///< Number of caches (fromAddr).
  );

  /// Validate an existing structure.
  /// @return Parse result.
  int parse(MsgBuffer &buffer);

  /// Compute the memory size of the component.
  static size_t calcSize(int n ///< Receive address count
  );
};

/** Sect 5.6.4: Web-Cache Identity Info Component
 */
class CacheIdComp : public CompWithHeader<CacheIdComp>
{
public:
  typedef CacheIdComp self;           ///< Self reference type.
  typedef CompWithHeader<self> super; ///< Parent type.

  /// Component type ID for this component.
  static CompType const COMP_TYPE = CACHE_ID_INFO;

  /// Serialized format.
  struct raw_t : public super::raw_t {
    CacheIdElt m_id; ///< Identity element stub.
  };

  /// @name Accessors
  //@{
  /// Direct access to the cache ID element.
  CacheIdBox &cacheId();
  CacheIdBox const &cacheId() const;

  // Only forward the common ones.
  uint32_t getAddr() const;        ///< Get address field.
  self &setAddr(uint32_t addr);    ///< Set address field to @a addr.
  uint16_t getHashRev() const;     ///< Get hash revision field.
  self &setHashRev(uint16_t rev);  ///< Set hash revision field to @a rev.
  bool getUnassigned() const;      ///< Get unassigned field.
  self &setUnassigned(bool state); ///< Set unassigned field to @a state.
  uint16_t getWeight() const;      ///< Get weight field.
  self &setWeight(uint16_t w);     ///< Set weight field to @a w.
  uint16_t getStatus() const;      ///< Get status field.
  self &setStatus(uint16_t s);     ///< Set status field to @a s.
                                   //@}

  /** Write serialization data.
      - Sets required header fields for the component.
      - Copies the data from @a src.
  */
  self &fill(MsgBuffer &base,      ///< Target storage.
             CacheIdBox const &src ///< Cache descriptor
  );

  /// Validate an existing structure.
  /// @return Parse result.
  int parse(MsgBuffer &buffer);

  /// Compute the memory size of the component.
  /// Cannot be reliably computed statically.
  size_t getSize();

protected:
  CacheIdBox m_box; ///< Wrapper for cache id element.
};

/** Sect 5.6.5: Router View Info Component
 */
class RouterViewComp : public CompWithHeader<RouterViewComp>
{
public:
  typedef RouterViewComp self;        ///< Self reference type.
  typedef CompWithHeader<self> super; ///< Parent type.

  /// Component type ID for this component.
  static CompType const COMP_TYPE = RTR_VIEW_INFO;

  /// Stub of the serialized data.
  /// There is more variable sized data that must be handled specially.
  struct raw_t : public super::raw_t {
    uint32_t m_change_number; ///< Sequence number.
    AssignmentKeyElt m_key;   ///< Assignment data.
    uint32_t m_router_count;  ///< # of router elements.
  };

  RouterViewComp();

  /// @name Accessors
  //@{
  /// Directly access assignment key.
  AssignmentKeyElt &keyElt();
  /// Directly access assignment key.
  AssignmentKeyElt const &keyElt() const;
  /// Get address in assignment key.
  uint32_t getKeyAddr() const;
  /// Set address in assignment key.
  self &setKeyAddr(uint32_t addr);
  /// Get change number in assignment key.
  uint32_t getKeyChangeNumber() const;
  /// Set change number in assignment key.
  self &setKeyChangeNumber(uint32_t n);

  uint32_t getChangeNumber() const;  ///< Get change number field.
  self &setChangeNumber(uint32_t n); ///< Set change number field to @a n

  /// Get cache count field.
  /// @note No @c setf method because this cannot be changed independently.
  /// @see fill
  uint32_t getCacheCount() const;
  /// Access cache element.
  CacheIdBox &cacheId(int idx ///< Index of target element.
  );
  /// Access cache element.
  CacheIdBox const &cacheId(int idx ///< Index of target element.
  ) const;
  /// Get router count field.
  /// @note No @c setf method because this cannot be changed independently.
  /// @see fill
  uint32_t getRouterCount() const;
  /// Get router address.
  uint32_t getRouterAddr(int idx ///< Index of router.
  ) const;
  /// Set router address.
  self &setRouterAddr(int idx,      ///< Index of router.
                      uint32_t addr ///< Address value.
  );
  //@}

  /** Write serialization data.

      A client @b must call this method before writing any fields directly.
      After invocation the client must fill in the router and cache elements.
  */
  self &fill(MsgBuffer &base, ///< Target storage.
             int n_routers,   ///< Number of routers in view.
             int n_caches     ///< Number of caches in view.
  );

  /// Validate an existing structure.
  /// @return Parse result.
  int parse(MsgBuffer &buffer);

protected:
  /// Serialized count of cache addresses.
  /// The actual addresses start immediate after this.
  uint32_t *m_cache_count;
  /// Wrappers for cache identity elements.
  /// These are variably sized in the general case.
  CacheIdBox m_cache_ids[MAX_CACHES];

  /// Compute the address of the cache count field.
  /// Assumes the router count field is set.
  uint32_t *calc_cache_count_ptr();
};

/** Sect 5.6.6: Web-Cache View Info Component
 */
class CacheViewComp : public CompWithHeader<CacheViewComp>
{
public:
  typedef CacheViewComp self;         ///< Self reference type.
  typedef CompWithHeader<self> super; ///< Parent type.

  /// Component type ID for this component.
  static CompType const COMP_TYPE = CACHE_VIEW_INFO;

  /// Stub of the serialized data.
  /// There is more variable sized data that must be handled specially.
  struct raw_t : public super::raw_t {
    uint32_t m_change_number; ///< Sequence number.
    uint32_t m_router_count;  ///< # of router ID elements.
  };

  /// @name Accessors
  //@{
  uint32_t getChangeNumber() const;  ///< Get change number field.
  self &setChangeNumber(uint32_t n); ///< Set change number field to @a n

  /// Get router count field.
  /// @note No @c setf method because this cannot be changed independently.
  /// @see fill
  uint32_t getRouterCount() const;
  /// Access a router ID element.
  RouterIdElt &routerElt(int idx ///< Index of target element.
  );
  /** Find a router element by router IP address.
      @return A pointer to the router element or @c NULL
      if no router is identified by @a addr.
  */
  RouterIdElt *findf_router_elt(uint32_t addr ///< Router IP address.
  );
  /// Get cache count field.
  /// @note No @c setf method because this cannot be changed independently.
  /// @see fill
  uint32_t getCacheCount() const;
  /// Get a cache address.
  uint32_t getCacheAddr(int idx ///< Index of target address.
  ) const;
  /// Set a cache address.
  self &setCacheAddr(int idx,      ///< Index of target address.
                     uint32_t addr ///< Address value to set.
  );
  //@}

  /** Write serialization data.

      A client @b must call this method before writing any fields directly.
      After invocation the client must fill in the router and cache elements.
  */
  self &fill(MsgBuffer &buffer,                    ///< Target storage.
             detail::cache::GroupData const &group ///< Service group information.
  );

  /// Validate an existing structure.
  /// @return Parse result.
  int parse(MsgBuffer &buffer);

  /// Compute the total size of the component.
  static size_t calcSize(int n_routers, ///< Number of routers in view.
                         int n_caches   ///< Number of caches in view.
  );

protected:
  /// Get router element array.
  /// @return A pointer to the first router element.
  RouterIdElt *atf_router_array();
  /// Serialized count of cache addresses.
  /// The actual addresses start immediate after this.
  uint32_t *m_cache_count;
};

/** Sect 5.6.7: Assignment Info Component
 */
class AssignInfoComp : public CompWithHeader<AssignInfoComp>
{
public:
  typedef AssignInfoComp self;        ///< Self reference type.
  typedef CompWithHeader<self> super; ///< Parent type.

  /// Component type ID for this component.
  static CompType const COMP_TYPE = REDIRECT_ASSIGNMENT;

  /// Stub of the serialized data.
  /// There is more variable sized data that must be handled specially.
  struct raw_t : public super::raw_t {
    AssignmentKeyElt m_key;        ///< Assignment key data.
    RouterAssignListElt m_routers; ///< Routers.
  };
  typedef HashAssignElt::Bucket Bucket; ///< Import type.

  /// @name Accessors
  //@{
  /// Directly access assignment key.
  AssignmentKeyElt &keyElt();
  /// Directly access assignment key.
  AssignmentKeyElt const &keyElt() const;
  /// Get address in assignment key.
  uint32_t getKeyAddr() const;
  /// Set address in assignment key.
  self &setKeyAddr(uint32_t addr);
  /// Get change number in assignment key.
  uint32_t getKeyChangeNumber() const;
  /// Set change number in assignment key.
  self &setKeyChangeNumber(uint32_t n);

  /// Get router count field.
  /// @note No @c setf method because this cannot be changed independently.
  /// @see fill
  uint32_t getRouterCount() const;
  /// Access a router assignment element.
  RouterAssignElt &routerElt(int idx ///< Index of target element.
  );
  /// Get cache count field.
  /// @note No @c setf method because this cannot be changed independently.
  /// @see fill
  uint32_t getCacheCount() const;
  /// Get a cache address.
  uint32_t getCacheAddr(int idx ///< Index of target address.
  ) const;
  /// Set a cache address.
  self &setCacheAddr(int idx,      ///< Index of target address.
                     uint32_t addr ///< Address value to set.
  );
  /// Access a bucket.
  Bucket &bucket(int idx ///< Index of target bucket.
  );
  /// Access a bucket.
  Bucket const &bucket(int idx ///< Index of target bucket.
  ) const;
  //@}

  /// Fill out the component from an @c Assignment.
  self &fill(MsgBuffer &buffer,               ///< Target storage.
             detail::Assignment const &assign ///< Assignment data.
  );

  /// Validate an existing structure.
  /// @return Parse result.
  int parse(MsgBuffer &buffer);

  /// Compute the total size of the component.
  static size_t calcSize(int n_routers, ///< Number of routers in view.
                         int n_caches   ///< Number of caches in view.
  );

protected:
  /// Serialized count of cache addresses.
  /// The actual addresses start immediate after this.
  uint32_t *m_cache_count;
  /// Serialized bucket data.
  Bucket *m_buckets;
  /// Calculate the address of the cache count.
  uint32_t *calcCacheCountPtr();
  /// Calculate the address of the bucket array.
  Bucket *calcBucketPtr();
};

/** Sect 5.6.9: Capabilities Info Component
 */
class CapComp : public CompWithHeader<CapComp>
{
public:
  typedef CapComp self;               ///< Self reference type.
  typedef CompWithHeader<self> super; ///< Parent type.

  /// Component type ID for this component.
  static CompType const COMP_TYPE = CAPABILITY_INFO;

  // Not even a stub for this component, just an array of elements.

  /// Default constructor.
  CapComp();

  /// @name Accessors.
  //@{
  /// Directly access mask value element.
  CapabilityElt &elt(int idx ///< Index of target element.
  );
  CapabilityElt const &elt(int idx ///< Index of target element.
  ) const;
  /// Get the element count.
  /// @note No corresponding @c setf_ because that cannot be changed once set.
  /// @see fill
  uint32_t getEltCount() const;
  //@}

  /** Write serialization data.

      The capability elements must be filled @b after invoking this method.
      And, of course, do not fill more than @a n of them.
  */
  self &fill(MsgBuffer &buffer, ///< Target storage.
             int n              ///< Number of capabilities.
  );

  /// Validate an existing structure.
  /// @return Parse result.
  int parse(MsgBuffer &buffer);

  /// Compute the total size of the component.
  static size_t calcSize(int n ///< Number of capabilities.
  );

  /// Find value for Cache Assignment.
  ServiceGroup::CacheAssignmentStyle getCacheAssignmentStyle() const;
  /// Find value for packet forwarding.
  ServiceGroup::PacketStyle getPacketForwardStyle() const;
  /// Find value for packet return.
  ServiceGroup::PacketStyle getPacketReturnStyle() const;
  /// Invalidate cached values.
  /// Needed after modifying elements via the @c elt method.
  self &invalidate();

protected:
  /// Fill the cached values.
  void cache() const;

  int m_count = 0; ///< # of elements.
                   /** Whether the style values are valid.
                       We load all the values on the first request because we have to walk
                       all the capabilities anyway, and cache them.
                   */
  mutable bool m_cached = false;
  /// Style used to forward packets to cache.
  mutable ServiceGroup::PacketStyle m_packet_forward = ServiceGroup::PacketStyle::NO_PACKET_STYLE;
  /// Style used to return packets to the router.
  mutable ServiceGroup::PacketStyle m_packet_return = ServiceGroup::PacketStyle::NO_PACKET_STYLE;
  /// Style used to make cache assignments.
  mutable ServiceGroup::CacheAssignmentStyle m_cache_assign = ServiceGroup::CacheAssignmentStyle::NO_CACHE_ASSIGN_STYLE;
};

/** Sect 5.6.10: Alternate Assignment Component
    This is an abstract base class. It is specialized for each alternate.
 */
class AltAssignComp : public CompWithHeader<AltAssignComp>
{
public:
  typedef AltAssignComp self;         ///< Self reference type.
  typedef CompWithHeader<self> super; ///< Parent type.

  /// Component type ID for this component.
  static CompType const COMP_TYPE = ALT_ASSIGNMENT;
  /// Alternate is hash.
  static uint16_t const ALT_HASH_ASSIGNMENT = 0;
  /// Alternate is mask.
  static uint16_t const ALT_MASK_ASSIGNMENT = 1;

  /// Component secondary header.
  /// @internal Split out because we need to compute its size.
  struct local_header_t {
    uint16_t m_assign_type;   ///< Assignment body type.
    uint16_t m_assign_length; ///< Assignment body length.
  };
  /// Stub of the serialized data.
  /// There is more variable sized data that must be handled specially.
  struct raw_t : public super::raw_t, public local_header_t {
    // These are the same in all current subclasses.
    AssignmentKeyElt m_key;        ///< Assignment key data.
    RouterAssignListElt m_routers; ///< Routers.
  };

  /// Force virtual destructor.
  virtual ~AltAssignComp() {}
  /// @name Accessors
  //@{
  /// Get the assignment type.
  uint16_t getAssignType() const;
  /// Set the assignment type.
  self &setAssignType(uint16_t t ///< Assignment type.
  );
  /// Get the assignment length.
  uint16_t getAssignLength() const;
  /// Set the assignment length.
  self &setAssignLength(uint16_t length ///< Length in bytes.
  );
  /// Get router count field.
  /// @note No @c setf method because this cannot be changed independently.
  /// @see fill
  uint32_t getRouterCount() const;
  /// Directly access assignment key.
  AssignmentKeyElt &keyElt();
  /// Directly access assignment key.
  AssignmentKeyElt const &keyElt() const;
  //@}

  /// Fill out the component from an @c Assignment.
  virtual self &fill(MsgBuffer &buffer,               ///< Target storage.
                     detail::Assignment const &assign ///< Assignment data.
                     ) = 0;

  /// Validate an existing structure.
  /// @return Parse result.
  virtual int parse(MsgBuffer &buffer) = 0;

protected:
  /// Calculate the first byte past the end of the variable data.
  void *calcVarPtr();
};

/** Sect 5.6.10: Alternate Assignment Component
    This is the hash based version.
 */
class AltHashAssignComp : public AltAssignComp
{
public:
  typedef AltHashAssignComp self; ///< Self reference type.
  typedef AltAssignComp super;    ///< Parent type.

  /// @name Accessors
  //@{
  /// Get cache count field.
  /// @note No @c setf method because this cannot be changed independently.
  /// @see fill
  uint32_t getCacheCount() const;
  //@}

  /// Force virtual destructor.
  virtual ~AltHashAssignComp() {}
  /// Fill out the component from an @c Assignment.
  virtual self &fill(MsgBuffer &buffer,               ///< Target storage.
                     detail::Assignment const &assign ///< Assignment data.
  );

  /// Validate an existing structure.
  /// @return Parse result.
  virtual int parse(MsgBuffer &buffer);

  /// Compute the total size of the component.
  static size_t calcSize(int n_routers, ///< Number of routers in view.
                         int n_caches   ///< Number of caches in view.
  );

protected:
  /// Serialized count of cache addresses.
  /// The actual addresses start immediate after this.
  uint32_t *m_cache_count;
  /// Calculate the address of the cache count.
  uint32_t *calcCacheCountPtr();
};

/** Sect 5.6.10: Alternate Assignment Component
    This is the mask based version.
 */
class AltMaskAssignComp : public AltAssignComp
{
public:
  typedef AltMaskAssignComp self; ///< Self reference type.
  typedef AltAssignComp super;    ///< Parent type.

  /// Force virtual destructor.
  virtual ~AltMaskAssignComp() {}
  /// Fill out the component from an @c Assignment.
  virtual self &fill(MsgBuffer &buffer,               ///< Target storage.
                     detail::Assignment const &assign ///< Assignment data.
  );

  /// Validate an existing structure.
  /// @return Parse result.
  virtual int parse(MsgBuffer &buffer);

protected:
  MaskAssignElt *m_mask_elt; ///< Address of the mask assign element.
};

/** Sect 5.6.12: Command Info Component
 */
class CmdComp : public CompWithHeader<CmdComp>
{
public:
  typedef CmdComp self;               ///< Self reference type.
  typedef CompWithHeader<self> super; ///< Parent type.

  /// Component type ID for this component.
  static CompType const COMP_TYPE = COMMAND_EXTENSION;

  /// Command types.
  enum cmd_t {
    SHUTDOWN          = 1, ///< Cache is shutting down.
    SHUTDOWN_RESPONSE = 2  ///< SHUTDOWN ack.
  };

  /// Serialized data layout.
  /// @internal Technically the command data is variable, but all currently
  /// defined commands have the same 32 bit data element.
  struct raw_t : public super::raw_t {
    uint16_t m_cmd;        ///< Command type / code.
    uint16_t m_cmd_length; ///< Length of command data.
    uint32_t m_cmd_data;   ///< Command data.
  };

  /// @name Accessors.
  //@{
  /// Directly access mask value element.
  cmd_t getCmd() const;            ///< Get command type.
  self &setCmd(cmd_t cmd);         ///< Set command type.
  uint32_t getCmdData() const;     ///< Get command data.
  self &setCmdData(uint32_t data); ///< Set command @a data.
  //@}

  /// Write basic serialization data.
  /// Elements must be filled in separately and after invoking this method.
  self &fill(MsgBuffer &buffer, ///< Component storage.
             cmd_t cmd,         ///< Command type.
             uint32_t data      ///< Command data.
  );

  /// Validate an existing structure.
  /// @return Parse result.
  int parse(MsgBuffer &buffer);

  /// Compute the total size of the component.
  static size_t calcSize();
};

/// Sect 5.6.11: Assignment Map Component
class AssignMapComp : public CompWithHeader<AssignMapComp>
{
public:
  typedef AssignMapComp self;         ///< Self reference type.
  typedef CompWithHeader<self> super; ///< Parent type.

  /// Component type ID for this component.
  static CompType const COMP_TYPE = ASSIGN_MAP;

  /// Serialized layout structure.
  /// Not complete, only a stub.
  struct raw_t : public super::raw_t {
    MaskAssignElt m_assign;
  };

  /// Default constructor.
  AssignMapComp();

  /// @name Accessors.
  //@{
  /// Get the element count.
  uint32_t getCount() const;
  //@}

  /// Fill from assignment data.
  self &fill(MsgBuffer &buffer,               ///< Component storage.
             detail::Assignment const &assign ///< Assignment data.
  );

  /// Validate an existing structure.
  /// @return Parse result.
  int parse(MsgBuffer &buffer);
};

/// Sect 5.6.8: Router Query Info Component.
class QueryComp : public CompWithHeader<QueryComp>
{
public:
  typedef QueryComp self;             ///< Self reference type.
  typedef CompWithHeader<self> super; ///< Parent type.

  /// Component type ID for this component.
  static CompType const COMP_TYPE = QUERY_INFO;

  /// Internal layout.
  struct raw_t : public super::raw_t {
    uint32_t m_router_addr; ///< Identifying router address.
    uint32_t m_recv_id;     ///< Receive ID router expects in reply.
    uint32_t m_to_addr;     ///< Destination address of query.
    uint32_t m_cache_addr;  ///< Identifying address of cache.
  };

  /// @name Accessors.
  //@{
  /// Directly access mask value element.
  uint32_t getRouterAddr() const;     ///< Get identifying router address.
  self &setRouterAddr(uint32_t addr); ///< Set identifying router address.
  uint32_t getToAddr() const;         ///< Get target address.
  self &setToAddr(uint32_t addr);     ///< Set target address.
  uint32_t getCacheAddr() const;      ///< Get identifying cache address.
  self &setCacheAddr(uint32_t addr);  ///< Set identifying cache address.
  uint32_t getRecvId() const;         ///< Get receive ID.
  self &setRecvId(uint32_t data);     ///< Set receive ID.
  //@}

  /// Write serialization data.
  /// This fills in all fields.
  self &fill(MsgBuffer &buffer,   ///< Component storage.
             uint32_t routerAddr, ///< Router identifying address.
             uint32_t toAddr,     ///< Destination address.
             uint32_t cacheAddr,  ///< Cache identifying address.
             uint32_t recvId      ///< Receive ID.
  );

  /// Validate an existing structure.
  /// @return Parse result.
  int parse(MsgBuffer &buffer);

  /// Compute the total size of the component.
  static size_t calcSize();
};

/// Cache assignment hash function.
inline uint8_t
assignment_hash(uint32_t key ///< Key to hash.
)
{
  key ^= key >> 16;
  key ^= key >> 8;
  return key & 0xFF;
}

/// IP header information for a receive message.
struct IpHeader {
  uint32_t m_src; ///< Source address.
  uint32_t m_dst; ///< Destination address.
};

// Various static values.
const char *const BUFFER_TOO_SMALL_FOR_COMP_TEXT = "Unable to write component -- buffer too small";

// ------------------------------------------------------
namespace detail
{
  /** Local storage for cache assignment data.
      The maintenance of this data is sufficiently complex that it is better
      to have a standard class to hold it, rather than updating a serialized
      form.
  */
  class Assignment
  {
  public:
    typedef Assignment self;      ///< Self reference type.
    typedef AssignmentKeyElt Key; ///< Import assignment key type.
    /// Import assignment bucket definition.
    /// @internal Just one byte, no serialization issues.
    typedef AssignInfoComp::Bucket Bucket;

    /// Default constructor. Initialization to empty state.
    Assignment();

    /** Check for active assignment.

        An assignment is active if it is is current. This means either it
        was successfully generated on the cache side, or a valid assignment
        was received on the router side and has not expired.

        @return The current active state.
    */
    bool isActive() const;
    /// Control active flag.
    self &setActive(bool state ///< New active state.
    );

    /** Fill the assignment from cache service group data.
        Caches that are obsolete are purged from the data.
        @return @c true if a valid assignment was generated,
        @c false otherwise.
    */
    bool fill(cache::GroupData &group, ///< Service group data.
              uint32_t addr            ///< Identifying IP address of designated cache.
    );
    /// Update the receive ID for a router.
    self &updateRouterId(uint32_t addr,  ///< Identifying IP address of router.
                         uint32_t rcvid, ///< New receive ID.
                         uint32_t cno    ///< New change number.
    );

    /// Get the assignment key.
    AssignmentKeyElt const &getKey() const;
    /// Get the router assignment list.
    RouterAssignListElt const &getRouterList() const;
    /// Get the hash assignment.
    HashAssignElt const &getHash() const;
    /// Get the mask assignment.
    MaskAssignElt const &getMask() const;

  protected:
    Key m_key;     ///< Assignment key.
    bool m_active; ///< Active state.

    // These store the serialized assignment chunks which are assembled
    // in to the components as needed. Each points in to the serialization
    // buffer, or is @c NULL if that assignment data isn't valid.
    /// Router assignments.
    RouterAssignListElt *m_router_list;
    /// Hash assignment.
    HashAssignElt *m_hash_assign;
    /// Mask assignment.
    MaskAssignElt *m_mask_assign;

    /// Buffer for serialization.
    MsgBuffer m_buffer;
  };

  namespace endpoint
  {
    /// Common service group data.
    struct GroupData {
      typedef GroupData self; ///< Self reference type.

      ServiceGroup m_svc;           ///< The service definition.
      uint32_t m_generation    = 0; ///< Generation value (change number).
      time_t m_generation_time = 0; ///< Time of last view change.

      bool m_use_security_opt             = false;         ///< Use group local security.
      SecurityComp::Option m_security_opt = SECURITY_NONE; ///< Type of security.
      bool m_use_security_key             = false;         ///< Use group local key.
      SecurityComp::Key m_security_key;                    ///< MD5 key.

      /** Group assignment data.
          This is used as a place to generate an assignment or
          store one received from an extern source.
      */
      detail::Assignment m_assign_info;

      /// Default constructor.
      GroupData() = default;
      /// Use @a key instead of global default.
      self &setKey(const char *key ///< Shared key.
      );
      /// Use security @a style instead of global default.
      self &setSecurity(SecurityOption style ///< Security style to use.
      );
    };
  } // namespace endpoint
} // namespace detail
// ------------------------------------------------------
/** Base class for all messages.
 */
class BaseMsg
{
public:
  /// Default constructor.
  BaseMsg();
  /// Destructor.
  virtual ~BaseMsg() {}
  /// Set the message @a buffer.
  void setBuffer(MsgBuffer const &buffer ///< Storage for message.
  );
  /// Get the current buffer.
  MsgBuffer const &buffer() const;
  /// Invoke once all components have been filled.
  /// Sets the length and updates security data if needed.
  virtual void finalize();
  /// Get available buffer space.
  size_t getSpace() const;
  /// Get the message size.
  size_t getCount() const;

  /// Validate security option.
  /// @note This presumes a subclass has already successfully parsed.
  bool validateSecurity() const;

  // Common starting components for all messages.
  MsgHeaderComp m_header;  ///< Message header.
  SecurityComp m_security; ///< Security component.
  ServiceComp m_service;   ///< Service provided.

protected:
  MsgBuffer m_buffer; ///< Raw storage for message data.
};

/// Sect 5.1: Layout and control for @c WCCP2_HERE_I_AM
class HereIAmMsg : public BaseMsg
{
public:
  typedef HereIAmMsg self; ///< Self reference type.

  /** Fill in the basic message structure.
      This expects @c setBuffer to have already been called
      with an appropriate buffer.
      The actual router and cache data must be filled in
      after this call, which will allocate the appropriate spaces
      in the message layou.
  */
  void fill(detail::cache::GroupData const &group, ///< Service group for message.
            CacheIdBox const &cache_id,            ///< ID to use for this cache.
            SecurityOption sec_opt                 ///< Security option to use.
  );
  /** Fill in optional capabilities.
      The capabilities component is added only if the @a router
      is set to send them.
  */
  void fill_caps(detail::cache::RouterData const &router ///< Target router.
  );
  /// Parse message data, presumed to be of this type.
  int parse(ts::Buffer const &buffer ///< Raw message data.
  );

  CacheIdComp m_cache_id;     ///< Web cache identity info.
  CacheViewComp m_cache_view; ///< Web cache view.
  CapComp m_capabilities;     ///< Capabilities data.
  CmdComp m_command;          ///< Command extension.
};

/// Sect 5.2: 'I See You' Message
class ISeeYouMsg : public BaseMsg
{
public:
  typedef ISeeYouMsg self; ///< Self reference type.

  /// Fill out message structure.
  /// Router ID and view data must be filled in separately.
  void fill(detail::router::GroupData const &group, ///< Service groupc context.
            SecurityOption sec_opt,                 ///< Security option.
            detail::Assignment &assign,             ///< Cache assignment data.
            size_t to_caches,                       ///< # of target caches for message.
            size_t n_routers,                       ///< Routers in view.
            size_t n_caches,                        ///< Caches in view.
            bool send_capabilities = false          ///< Send capabilities.
  );

  /// Parse message data, presumed to be of this type.
  int parse(ts::Buffer const &buffer ///< Raw message data.
  );

  RouterIdComp m_router_id;     ///< Router ID.
  RouterViewComp m_router_view; ///< Router view data.
  // The rest of these are optional. The spec says we should get
  // an assignment or map, but in practice that doesn't happen with
  // actual Cisco routers in the hash case. Perhaps it happens with
  // a map.
  AssignInfoComp m_assignment; ///< Assignment data.
  AssignMapComp m_map;         ///< Assignment map.
  CapComp m_capabilities;      ///< Capabilities data.
  CmdComp m_command;           ///< Command extension.
};

/// Sect 5.1: Layout and control for @c WCCP2_REDIRECT_ASSIGN
class RedirectAssignMsg : public BaseMsg
{
public:
  typedef RedirectAssignMsg self; ///< Self reference type.

  /** Fill in the basic message structure.
      This expects @c setBuffer to have already been called
      with an appropriate buffer.
      The actual router and cache data must be filled in
      after this call, which will allocate the appropriate spaces
      in the message layou.
  */
  void fill(detail::cache::GroupData const &group, ///< Service group for message.
            SecurityOption sec_opt                 ///< Security option to use.
  );

  /// Parse message data, presumed to be of this type.
  int parse(ts::Buffer const &buffer ///< Raw message data.
  );

  // Only one of these should be present in an instance.
  AssignInfoComp m_hash_assign;        ///< Primary (hash) assignment.
  AltHashAssignComp m_alt_hash_assign; ///< Alternate (hash) assignment.
  AltMaskAssignComp m_alt_mask_assign; ///< Alternate (mask) assignment.
};

/// Sect 5.4: @c WCCP_REMOVAL_QUERY
class RemovalQueryMsg : public BaseMsg
{
public:
  typedef RemovalQueryMsg self; ///< Self reference type.

  /** Fill in the basic message structure.
      This expects @c setBuffer to have already been called
      with an appropriate buffer.
      The actual router and cache data must be filled in
      after this call, which will allocate the appropriate spaces
      in the message layou.
  */
  void fill(detail::cache::GroupData const &group, ///< Service group for message.
            SecurityOption sec_opt,                ///< Security option to use.
            AssignmentKeyElt const &key,           ///< Assignment key.
            int n_routers,                         ///< Number of routers expected.
            int n_caches                           ///< Number of caches expected.
  );

  /// Parse message data, presumed to be of this type.
  int parse(ts::Buffer const &buffer ///< Raw message data.
  );

  QueryComp m_query; ///< Router Removal Query component.
};

// ------------------------------------------------------
/// Last packet information.
struct PacketStamp {
  typedef PacketStamp self; ///< Self reference type.

  PacketStamp(); ///< Default constructor (zero elements).
  /// Set the @a time and @a generation.
  self &set(time_t time, uint32_t generation);

  time_t m_time; ///< Time when packet was sent/received.
  uint32_t m_sn; ///< Sequence # of packet.
};

/** Implementation class for EndPoint.
    All of the WCCP structures are defined in this class.

    A note on the component classes - these are designed to reside in
    a side buffer which then points in to the actual message
    buffer. This is done because the WCCP designers were not too
    bright. Rather than packing the fixed sized elements in front and
    using offsets to point at variables sized data, it's intermixed,
    so it's not possible to declare C++ structures that map on to the
    actual message data in all cases. And because mixed styles are
    worse than a consistent mediocre style, we go with the latter and
    put all the message structures on the side. This also means having
    to use accessor methods.
 */
class Impl : public ts::IntrusivePtrCounter
{
  friend class EndPoint;

public:
  typedef Impl self; ///< Self reference type.

  /// Import detail struct.
  typedef detail::endpoint::GroupData GroupData;

  /// Default constructor.
  Impl() = default;
  /** Set the local address used for this endpoint.
      If not set, an arbitrary local address will be
      @note This can only be called once, and must be called before
      @c open.
  */
  /// Force virtual destructor.
  virtual ~Impl();

  /// Open a socket for communications.
  /// @return 0 on success, -ERRNO on failure.
  virtual int open(uint32_t addr ///< Local IP address.
  );

  /// Use MD5 security.
  void useMD5Security(std::string_view const key ///< Shared key.
  );

  /// Perform all scheduled housekeeping functions.
  /// @return 0 for success, -errno on error.
  virtual int housekeeping() = 0;

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

  /// Check if endpoint is configured.
  /// @return @c true if ready to operate, @c false otherwise.
  virtual bool isConfigured() const = 0;

  /* These handlers simply generate an error message and return.  The
     base @c handleMessage will read the data from the socket and
     validate the message header. It then calls the appropriate one of
     these specialized message handlers.  Subclasses should override
     to process relevant messages.
  */
  /// Process HERE_I_AM message.
  virtual ts::Errata handleHereIAm(IpHeader const &header, ///< IP packet data.
                                   ts::Buffer const &data  ///< Buffer with message data.
  );
  /// Process I_SEE_YOU message.
  virtual ts::Errata handleISeeYou(IpHeader const &header, ///< IP packet data.
                                   ts::Buffer const &data  ///< Buffer with message data.
  );
  /// Process REDIRECT_ASSIGN message.
  virtual ts::Errata handleRedirectAssign(IpHeader const &header, ///< IP packet data.
                                          ts::Buffer const &data  ///< Buffer with message data.
  );
  /// Process REMOVAL_QUERY message.
  virtual ts::Errata handleRemovalQuery(IpHeader const &header, ///< IP packet data.
                                        ts::Buffer const &data  ///< Buffer with message data.
  );

protected:
  /** Local address for this end point.
      This is set only when the socket is open.
   */
  uint32_t m_addr = INADDR_ANY;
  int m_fd        = ts::NO_FD; ///< Our socket.

  bool m_use_security_opt             = false;         ///< Use group local security.
  SecurityComp::Option m_security_opt = SECURITY_NONE; ///< Type of security.
  bool m_use_security_key             = false;         ///< Use group local key.
  SecurityComp::Key m_security_key;                    ///< MD5 key.

  /// Close the socket.
  void close();
  /// Set security options in a message.
  /// @return Security option to use during message fill.
  SecurityOption setSecurity(BaseMsg &msg,          ///< Message.
                             GroupData const &group ///< Group data used to control fill.
  ) const;
  /// Validate a security component.
  bool validateSecurity(BaseMsg &msg,          ///< Message data (including security component).
                        GroupData const &group ///< Group data for message.
  );
};
// ------------------------------------------------------
namespace detail
{
  namespace cache
  {
    /// Caches's view of caches.
    struct CacheData {
      /// Get the identifying IP address for this cache.
      uint32_t idAddr() const;
      /// Cache identity data.
      CacheIdBox m_id;
      /// Last time this cache was mentioned by the routers.
      /// Indexed in parallel to the routers.
      std::vector<PacketStamp> m_src;
    };

    /// Cache's view of routers.
    struct RouterData {
      /// Default constructor, no member initialization.
      RouterData();
      /// Construct with address.
      RouterData(uint32_t addr ///< Router identifying address.
      );

      /// Time until next packet.
      /// @return Seconds until a packet should be sent.
      time_t waitTime(time_t now ///< Current time.
      ) const;
      /// Time till next ping.
      /// @return Seconds until a HERE_I_AM should be sent.
      time_t pingTime(time_t now ///< Current time.
      ) const;

      uint32_t m_addr;       ///< Router identifying IP address.
      uint32_t m_generation; ///< Router's view change number.
                             /** Most recent packet received from router.
                              *  The sequence number @a m_sn is the receive ID of the router.
                              */
      PacketStamp m_recv;
      /** Most recent packet sent to router.
       *  The sequence number @a m_sn is the view generation of this cache.
       */
      PacketStamp m_xmit;
      /// Cache ID of this cache as reflected by this router.
      CacheIdBox m_local_cache_id;
      int m_rapid;      ///< Rapid replies to send.
      bool m_assign;    ///< Send a REDIRECT_ASSIGN.
      bool m_send_caps; ///< Send capabilities.
      /// Packet forwarding method selected.
      ServiceGroup::PacketStyle m_packet_forward = ServiceConstants::NO_PACKET_STYLE;
      /// Packet return method selected.
      ServiceGroup::PacketStyle m_packet_return = ServiceConstants::NO_PACKET_STYLE;
      /// Cache assignment method selected.
      ServiceGroup::CacheAssignmentStyle m_cache_assign = ServiceConstants::NO_CACHE_ASSIGN_STYLE;
    };

    /// Data for a seeded router.
    struct SeedRouter {
      SeedRouter(); ///< Default constructor, no member initialization.
      /// Construct with address @a addr.
      /// Other members are zero initialized.
      SeedRouter(uint32_t addr);
      uint32_t m_addr;  ///< Address of router.
      uint32_t m_count; ///< # of packets sent w/o response.
      time_t m_xmit;    ///< Time of last packet sent.
    };

    /// Storage type for known caches.
    typedef std::vector<CacheData> CacheBag;
    /// Storage type for known routers.
    typedef std::vector<RouterData> RouterBag;

    /** Cache's view of a service group.
        This stores the internal accounting information, it is not the
        serialized form.
    */
    struct GroupData : public endpoint::GroupData {
      typedef GroupData self;            ///< Self reference type.
      typedef endpoint::GroupData super; ///< Parent type.

      /// Cache identity of this cache.
      CacheIdBox m_id;

      /// Packet forwarding methods supported.
      ServiceGroup::PacketStyle m_packet_forward = ServiceConstants::NO_PACKET_STYLE;
      /// Packet return methods supported.
      ServiceGroup::PacketStyle m_packet_return = ServiceConstants::NO_PACKET_STYLE;
      /// Cache assignment methods supported.
      ServiceGroup::CacheAssignmentStyle m_cache_assign = ServiceConstants::NO_CACHE_ASSIGN_STYLE;

      /// Known caches.
      CacheBag m_caches;
      /// Known routers.
      RouterBag m_routers;
      char *m_proc_name;

      /// Set if there an assignment should be computed and sent.
      /// This is before checking for being a designated cache
      /// (that check is part of the assignment generation).
      bool m_assignment_pending;

      /// Seed routers.
      std::vector<SeedRouter> m_seed_routers;

      GroupData(); ///< Default constructor.

      void setProcName(const std::string_view name);
      const char *getProcName();

      /// Find a router by IP @a addr.
      /// @return A pointer to the router, or @c NULL if not found.
      RouterBag::iterator findRouter(uint32_t addr ///< IP address of cache.
      );

      /// Set an initial router for a service group.
      self &seedRouter(uint32_t addr ///< IP address for router.
      );
      /// Remove a seed router.
      /// @return The last time a packet was sent to the router.
      time_t removeSeedRouter(uint32_t addr ///< Identifying router address.
      );

      /// Find a cache by IP @a addr.
      /// @return An iterator to the cache, or @c NULL if not found.
      CacheBag::iterator findCache(uint32_t addr ///< IP address of cache.
      );
      /// Adjust packet stamp vectors to track routers.
      void resizeCacheSources();

      /// Time until next event.
      /// @return The number of seconds until the next event of interest.
      time_t waitTime(time_t now ///< Current time.
      ) const;

      /** Cull routers.
          Routers that have not replied recently are moved from the
          active router list to the seed router list.

          @return @c true if any routers were culled, @c false otherwise.
      */
      bool cullRouters(time_t now ///< Current time.
      );

      /** Check to see if the process associated with service is up
       */
      bool processUp();

      /// Update state to reflect a view change.
      self &viewChanged(time_t now);

      /// Use @a key instead of global default.
      self &setKey(const char *key ///< Shared key.
      );
      /// Use security @a style instead of global default.
      self &setSecurity(SecurityOption style ///< Security style to use.
      );
    };
    inline const char *
    GroupData::getProcName()
    {
      return m_proc_name;
    }
    inline void
    GroupData::setProcName(const std::string_view name)
    {
      m_proc_name = ats_strndup(name.data(), name.size());
    }
  } // namespace cache
} // namespace detail

/** Implementation class for Cache Endpoint.
 */
class CacheImpl : public Impl
{
public:
  typedef CacheImpl self; ///< Self reference type.
  typedef Impl super;     ///< Parent type.

  // Import details
  typedef detail::cache::SeedRouter SeedRouter;
  typedef detail::cache::CacheData CacheData;
  typedef detail::cache::RouterData RouterData;
  typedef detail::cache::GroupData GroupData;
  typedef detail::cache::CacheBag CacheBag;
  typedef detail::cache::RouterBag RouterBag;

  /** Define a service group.
      If no service is defined for the ID in @a svc, it is created.
      If @a result is not @c NULL then it 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.

      @return The data for the service group.
  */
  virtual GroupData &defineServiceGroup(ServiceGroup const &svc,         ///< [in] Service to define.
                                        ServiceGroup::Result *result = 0 ///< [out] Result for service creation.
  );

  /** Set an initial router for a service group.
      This is needed to bootstrap the protocol.
      If the router is already seeded, this call is silently ignored.
  */
  self &seedRouter(uint8_t id,   ///< Service group ID.
                   uint32_t addr ///< IP address for router.
  );

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

  /// Override.
  int open(uint32_t addr);

  /// Time until next scheduled event.
  time_t waitTime() const;

  /// Check for configuration.
  bool isConfigured() const;

  /// Perform all scheduled housekeeping functions.
  /// @return 0 for success, -errno on error.
  virtual int housekeeping();

  /** Check cache assignment reported by a router against internal assign.
      @return @c true if they are the same, @c false otherwise.
  */
  virtual ts::Errata checkRouterAssignment(GroupData const &group,    ///< Group with assignment.
                                           RouterViewComp const &comp ///< Assignment reported by router.
  ) const;

protected:
  /// Generate contents in HERE_I_AM @a msg for seed router.
  void generateHereIAm(HereIAmMsg &msg, ///< Message with allocated buffer.
                       GroupData &group ///< Group with data for message.
  );
  /// Generate contents in HERE_I_AM @a msg for active @a router.
  void generateHereIAm(HereIAmMsg &msg,   ///< Message with allocated buffer.
                       GroupData &group,  ///< Group with data for message.
                       RouterData &router ///< Target router.
  );
  /// Generate contents in REDIRECT_ASSIGN @a msg for a service @a group.
  void generateRedirectAssign(RedirectAssignMsg &msg, ///< Message with allocated buffer.
                              GroupData &group        ///< Group with data for message.
  );
  /// Process HERE_I_AM message.
  virtual ts::Errata handleISeeYou(IpHeader const &header, ///< IP packet data.
                                   ts::Buffer const &data  ///< Buffer with message data.
  );
  /// Process REMOVAL_QUERY message.
  virtual ts::Errata handleRemovalQuery(IpHeader const &header, ///< IP packet data.
                                        ts::Buffer const &data  ///< Message data.
  );

  /// Map Service Group ID to Service Group Data.
  typedef std::map<uint8_t, GroupData> GroupMap;
  /// Active service groups.
  GroupMap m_groups;

private:
  ts::Errata loader(const YAML::Node &node);
};

// ------------------------------------------------------
namespace detail
{
  namespace router
  {
    /** Router's view of a cache.
        @a m_count tracks the number of packets received from this particular
        cache. The RFC is unclear but it looks like this should be tracked
        independently for each target address (which can be different than
        caches if multicasting). A response is pending if @a m_count is
        different than @ m_xmit.m_gen which is the received count last time
        this router sent this cache a response.
    */
    struct CacheData {
      /// Get the identifying IP address for this cache.
      uint32_t idAddr() const;

      /// Received count for this cache.
      uint32_t m_recv_count;
      /// Change number of last received message.
      uint32_t m_generation;
      /// Need to send a response to this cache.
      bool m_pending;
      /// Address used by cache to send to this router.
      uint32_t m_to_addr;
      /// Stamp for last pack transmitted to this cache.
      PacketStamp m_xmit;
      //// Stamp for last packet received from this cache.
      PacketStamp m_recv;

      CacheIdBox m_id;        ///< Transmitted cache descriptor.
      uint32_t m_target_addr; ///< Target address of last packet.
    };

    /// Router's view of other routers.
    struct RouterData {
      typedef RouterData self; ///< Self reference type.

      /// Identifying IP address of router.
      uint32_t m_addr;
      /** Stamp for last mention of this router from a cache.
          Indexed in parallel with the Caches.
          The sequence number @a m_sn is the cache's change #.
      */
      std::vector<PacketStamp> m_src;
      /// Resize the packet stamp vector.
      self &resize(size_t);
    };

    /// Storage type for known caches.
    typedef std::vector<CacheData> CacheBag;
    /// Storage type for known routers.
    typedef std::vector<RouterData> RouterBag;

    /** A router's view of a service group.

        This stores the internal accounting information, it is not the
        serialized form.
    */
    struct GroupData : public detail::endpoint::GroupData {
      typedef GroupData self;                    ///< Self reference type.
      typedef detail::endpoint::GroupData super; ///< Parent type.

      GroupData(); ///< Default constructor.

      /// Known caches.
      CacheBag m_caches;
      /// Known (other) routers.
      RouterBag m_routers;

      /// Find a cache by IP @a addr.
      /// @return An iterator to the cache, or @c NULL if not found.
      CacheBag::iterator findCache(uint32_t addr ///< IP address of cache.
      );
      /// Adjust packet stamp vectors to track caches.
      void resizeRouterSources();
    };
  } // namespace router
} // namespace detail

/** Implementation class for Router Endpoint.
 */
class RouterImpl : public Impl
{
public:
  typedef RouterImpl self; ///< Self reference type.
  typedef Impl super;      ///< Parent type.
  // Import details
  typedef detail::router::CacheData CacheData;
  typedef detail::router::RouterData RouterData;
  typedef detail::router::GroupData GroupData;
  typedef detail::router::CacheBag CacheBag;
  typedef detail::router::RouterBag RouterBag;

  /// Process HERE_I_AM message.
  virtual ts::Errata handleHereIAm(IpHeader const &header, ///< IP packet data.
                                   ts::Buffer const &data  ///< Buffer with message data.
  );
  /// Perform all scheduled housekeeping functions.
  int housekeeping();
  /// Send pending I_SEE_YOU messages.
  int xmitISeeYou();
  /// Check for configuration.
  bool isConfigured() const;

protected:
  /** Find or create a service group record.
      If no service is defined for the ID, it is created.
      If @a result is not @c NULL then it 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.

      @return The data for the service group.
  */
  GroupData &defineServiceGroup(ServiceGroup const &svc, ServiceGroup::Result *result);
  /// Fill out message data.
  void generateISeeYou(ISeeYouMsg &msg,  ///< Message structure to fill.
                       GroupData &group, ///< Group data for message.
                       CacheData &cache  ///< Target cache.
  );

  /// Map Service Group ID to Service Group Data.
  typedef std::map<uint8_t, GroupData> GroupMap;
  /// Active service groups.
  GroupMap m_groups;
};
// ------------------------------------------------------
inline RouterId::RouterId() : m_addr(0), m_recv_id(0) {}
inline RouterId::RouterId(uint32_t addr, uint32_t recv_id) : m_addr(addr), m_recv_id(recv_id) {}

inline RouterIdElt::RouterIdElt(uint32_t addr, uint32_t recv_id) : super(addr, htonl(recv_id)) {}
inline uint32_t
RouterIdElt::getAddr() const
{
  return m_addr;
}
inline RouterIdElt &
RouterIdElt::setAddr(uint32_t addr)
{
  m_addr = addr;
  return *this;
}
inline uint32_t
RouterIdElt::getRecvId() const
{
  return ntohl(m_recv_id);
}
inline RouterIdElt &
RouterIdElt::setRecvId(uint32_t recv_id)
{
  m_recv_id = htonl(recv_id);
  return *this;
}
inline RouterIdElt &
RouterIdElt::operator=(super const &that)
{
  return this->setAddr(that.m_addr).setRecvId(that.m_recv_id);
}

inline MaskElt::MaskElt() {}

inline MaskElt::MaskElt(uint32_t srcAddr, uint32_t dstAddr, uint16_t srcPort, uint16_t dstPort)
  : m_src_addr(srcAddr), m_dst_addr(dstAddr), m_src_port(srcPort), m_dst_port(dstPort)
{
}

inline uint32_t
MaskElt::getSrcAddr() const
{
  return ntohl(m_src_addr);
}
inline MaskElt &
MaskElt::setSrcAddr(uint32_t mask)
{
  m_src_addr = htonl(mask);
  return *this;
}
inline uint32_t
MaskElt::getDstAddr() const
{
  return ntohl(m_dst_addr);
}
inline MaskElt &
MaskElt::setDstAddr(uint32_t mask)
{
  m_dst_addr = htonl(mask);
  return *this;
}
inline uint16_t
MaskElt::getSrcPort() const
{
  return ntohs(m_src_port);
}
inline MaskElt &
MaskElt::setSrcPort(uint16_t mask)
{
  m_src_port = htons(mask);
  return *this;
}
inline uint16_t
MaskElt::getDstPort() const
{
  return ntohs(m_dst_port);
}
inline MaskElt &
MaskElt::setDstPort(uint16_t mask)
{
  m_dst_port = htons(mask);
  return *this;
}

inline ValueElt::ValueElt() {}

inline ValueElt::ValueElt(uint32_t cacheAddr, uint32_t srcAddr, uint32_t dstAddr, uint16_t srcPort, uint16_t dstPort)
  : m_src_addr(srcAddr), m_dst_addr(dstAddr), m_src_port(srcPort), m_dst_port(dstPort), m_cache_addr(cacheAddr)
{
}

inline MaskValueSetElt::MaskValueSetElt() {}
inline MaskValueSetElt::MaskValueSetElt(uint32_t count) : m_count(count) {}
inline MaskElt &
MaskValueSetElt::maskElt()
{
  return m_mask;
}
inline uint32_t
MaskValueSetElt::getCount() const
{
  return ntohl(m_count);
}

inline uint32_t
MaskValueSetElt::getSrcAddrMask() const
{
  return m_mask.getSrcAddr();
}
inline MaskValueSetElt &
MaskValueSetElt::setSrcAddrMask(uint32_t mask)
{
  m_mask.setSrcAddr(mask);
  return *this;
}
inline uint32_t
MaskValueSetElt::getDstAddrMask() const
{
  return m_mask.getDstAddr();
}
inline MaskValueSetElt &
MaskValueSetElt::setDstAddrMask(uint32_t mask)
{
  m_mask.setDstAddr(mask);
  return *this;
}
inline uint16_t
MaskValueSetElt::getSrcPortMask() const
{
  return m_mask.getSrcPort();
}
inline MaskValueSetElt &
MaskValueSetElt::setSrcPortMask(uint16_t mask)
{
  m_mask.setSrcPort(mask);
  return *this;
}
inline uint16_t
MaskValueSetElt::getDstPortMask() const
{
  return m_mask.getDstPort();
}
inline MaskValueSetElt &
MaskValueSetElt::setDstPortMask(uint16_t mask)
{
  m_mask.setDstPort(mask);
  return *this;
}
inline ValueElt *
MaskValueSetElt::values()
{
  return reinterpret_cast<ValueElt *>(this + 1);
}
inline ValueElt const *
MaskValueSetElt::values() const
{
  return const_cast<self *>(this)->values();
}
inline size_t
MaskValueSetElt::calcSize(uint32_t n)
{
  return sizeof(self) + n * sizeof(ValueElt);
}
inline size_t
MaskValueSetElt::getSize() const
{
  return self::calcSize(ntohl(m_count));
}

inline size_t
MaskAssignElt::getSize() const
{
  return sizeof(self) + this->getVarSize();
}

inline uint32_t
CacheIdElt::getAddr() const
{
  return m_addr;
}
inline CacheIdElt &
CacheIdElt::setAddr(uint32_t addr)
{
  m_addr = addr;
  return *this;
}
inline uint16_t
CacheIdElt::getHashRev() const
{
  return ntohs(m_hash_rev);
}
inline CacheIdElt &
CacheIdElt::setHashRev(uint16_t addr)
{
  m_hash_rev = htons(addr);
  return *this;
}
inline CacheIdElt &
CacheIdElt::initHashRev()
{
  this->setHashRev(HASH_REVISION);
  return *this;
}
inline bool
CacheIdElt::getUnassigned() const
{
  return 1 == m_unassigned;
}
inline CacheIdElt &
CacheIdElt::setUnassigned(bool state)
{
  m_unassigned = state ? 1 : 0;
  return *this;
}
inline CacheIdElt &
CacheIdElt::clearReserved()
{
  m_reserved_0 = 0;
  m_reserved_1 = 0;
  m_reserved_2 = 0;
  return *this;
}
inline bool
CacheIdElt::isMask() const
{
  return 1 == m_is_mask;
}
inline CacheIdElt &
CacheIdElt::setMask(bool state)
{
  m_is_mask = state ? 1 : 0;
  return *this;
}

inline CacheIdElt::Tail *
CacheHashIdElt::getTailPtr()
{
  return &m_tail;
}

inline uint32_t
CacheMaskIdElt::getCount() const
{
  return m_assign.getCount();
}

inline size_t
CacheMaskIdElt::getSize() const
{
  return sizeof(self) + sizeof(Tail) + m_assign.getVarSize();
}

inline CacheIdElt::Tail *
CacheMaskIdElt::getTailPtr()
{
  return reinterpret_cast<Tail *>(reinterpret_cast<char *>(this) + sizeof(self) + m_assign.getVarSize());
}

inline uint32_t
CacheIdBox::getAddr() const
{
  return m_base->getAddr();
}

inline CacheIdBox &
CacheIdBox::setAddr(uint32_t addr)
{
  m_base->setAddr(addr);
  return *this;
}

inline CacheIdBox &
CacheIdBox::setUnassigned(bool state)
{
  m_base->setUnassigned(state);
  return *this;
}

inline AssignmentKeyElt::AssignmentKeyElt(uint32_t addr, uint32_t n) : m_addr(addr), m_change_number(htonl(n)) {}
inline uint32_t
AssignmentKeyElt::getAddr() const
{
  return m_addr;
}
inline AssignmentKeyElt &
AssignmentKeyElt::setAddr(uint32_t addr)
{
  m_addr = addr;
  return *this;
}
inline uint32_t
AssignmentKeyElt::getChangeNumber() const
{
  return ntohl(m_change_number);
}
inline AssignmentKeyElt &
AssignmentKeyElt::setChangeNumber(uint32_t n)
{
  m_change_number = htonl(n);
  return *this;
}

inline RouterAssignElt::RouterAssignElt(uint32_t addr, uint32_t recv_id, uint32_t change_number)
  : super(addr, recv_id), m_change_number(htonl(change_number))
{
}
inline uint32_t
RouterAssignElt::getChangeNumber() const
{
  return ntohl(m_change_number);
}
inline RouterAssignElt &
RouterAssignElt::setChangeNumber(uint32_t n)
{
  m_change_number = htonl(n);
  return *this;
}

inline SecurityComp::SecurityComp() : m_local_key(false) {}
inline void
SecurityComp::setDefaultOption(Option opt)
{
  m_default_opt = opt;
}
inline size_t
SecurityComp::calcSize(Option opt)
{
  return SECURITY_NONE == opt ? sizeof(RawNone) : sizeof(RawMD5);
}

inline ServiceComp::ServiceComp() : m_port_count(0) {}
inline ServiceComp::raw_t *
ServiceComp::access()
{
  return reinterpret_cast<raw_t *>(m_base);
}
inline ServiceComp::raw_t const *
ServiceComp::access() const
{
  return reinterpret_cast<raw_t const *>(m_base);
}
inline ServiceGroup::Type
ServiceComp::getSvcType() const
{
  return this->access()->getSvcType();
}
inline ServiceComp &
ServiceComp::setSvcType(ServiceGroup::Type t)
{
  this->access()->setSvcType(t);
  return *this;
}
inline uint8_t
ServiceComp::getSvcId() const
{
  return this->access()->getSvcId();
}
inline ServiceComp &
ServiceComp::setSvcId(uint8_t id)
{
  this->access()->setSvcId(id);
  return *this;
}
inline uint8_t
ServiceComp::getPriority() const
{
  return this->access()->getPriority();
}
inline ServiceComp &
ServiceComp::setPriority(uint8_t pri)
{
  this->access()->setPriority(pri);
  return *this;
}
inline uint8_t
ServiceComp::getProtocol() const
{
  return this->access()->getProtocol();
}
inline ServiceComp &
ServiceComp::setProtocol(uint8_t proto)
{
  this->access()->setProtocol(proto);
  return *this;
}
inline uint32_t
ServiceComp::getFlags() const
{
  return this->access()->getFlags();
}
inline ServiceComp &
ServiceComp::setFlags(uint32_t flags)
{
  this->access()->setFlags(flags);
  return *this;
}
inline ServiceComp &
ServiceComp::enableFlags(uint32_t flags)
{
  this->access()->enableFlags(flags);
  return *this;
}
inline ServiceComp &
ServiceComp::disableFlags(uint32_t flags)
{
  this->access()->disableFlags(flags);
  return *this;
}
inline uint16_t
ServiceComp::getPort(int idx) const
{
  return this->access()->getPort(idx);
}
inline size_t
ServiceComp::calcSize()
{
  return sizeof(raw_t);
}
inline ServiceComp::operator ServiceGroup const &() const
{
  return *static_cast<ServiceGroup const *>(this->access());
}

inline size_t
RouterIdComp::calcSize(int n)
{
  return sizeof(raw_t) + n * sizeof(uint32_t);
}

inline uint32_t
RouterViewComp::getKeyAddr() const
{
  return this->keyElt().getAddr();
}
inline RouterViewComp &
RouterViewComp::setKeyAddr(uint32_t addr)
{
  this->keyElt().setAddr(addr);
  return *this;
}
inline uint32_t
RouterViewComp::getKeyChangeNumber() const
{
  return this->keyElt().getChangeNumber();
}
inline RouterViewComp &
RouterViewComp::setKeyChangeNumber(uint32_t change_number)
{
  this->keyElt().setChangeNumber(change_number);
  return *this;
}
inline CacheIdBox const &
RouterViewComp::cacheId(int idx) const
{
  return const_cast<self *>(this)->cacheId(idx);
}

inline CacheIdBox &
CacheIdComp::cacheId()
{
  return m_box;
}
inline CacheIdBox const &
CacheIdComp::cacheId() const
{
  return m_box;
}
inline uint32_t
CacheIdComp::getAddr() const
{
  return this->cacheId().getAddr();
}
inline CacheIdComp &
CacheIdComp::setAddr(uint32_t addr)
{
  this->cacheId().setAddr(addr);
  return *this;
}
inline uint16_t
CacheIdComp::getHashRev() const
{
  return this->cacheId().getHashRev();
}
inline CacheIdComp &
CacheIdComp::setHashRev(uint16_t rev)
{
  this->cacheId().setHashRev(rev);
  return *this;
}
inline bool
CacheIdComp::getUnassigned() const
{
  return this->cacheId().getUnassigned();
}
inline CacheIdComp &
CacheIdComp::setUnassigned(bool state)
{
  this->cacheId().setUnassigned(state);
  return *this;
}

inline bool
detail::Assignment::isActive() const
{
  return m_active;
}
inline detail::Assignment &
detail::Assignment::setActive(bool state)
{
  m_active = state;
  return *this;
}
inline detail::Assignment &
detail::Assignment::updateRouterId(uint32_t addr, uint32_t rcvid, uint32_t cno)
{
  if (m_router_list)
    m_router_list->updateRouterId(addr, rcvid, cno);
  return *this;
}
inline AssignmentKeyElt::AssignmentKeyElt() {}
inline AssignmentKeyElt const &
detail::Assignment::getKey() const
{
  return m_key;
}
inline RouterAssignListElt const &
detail::Assignment::getRouterList() const
{
  assert(m_router_list);
  return *m_router_list;
}
inline HashAssignElt const &
detail::Assignment::getHash() const
{
  assert(m_hash_assign);
  return *m_hash_assign;
}
inline MaskAssignElt const &
detail::Assignment::getMask() const
{
  assert(m_mask_assign);
  return *m_mask_assign;
}

inline MsgBuffer::MsgBuffer() : super(), _count(0) {}
inline MsgBuffer::MsgBuffer(super const &that) : super(that), _count(0) {}
inline MsgBuffer::MsgBuffer(void *p, size_t n) : super(static_cast<char *>(p), n), _count(0) {}

inline size_t
MsgBuffer::getSize() const
{
  return _size;
}
inline size_t
MsgBuffer::getCount() const
{
  return _count;
}
inline char *
MsgBuffer::getBase()
{
  return _ptr;
}
inline const char *
MsgBuffer::getBase() const
{
  return _ptr;
}
inline char *
MsgBuffer::getTail()
{
  return _ptr + _count;
}
inline size_t
MsgBuffer::getSpace() const
{
  return _size - _count;
}
inline MsgBuffer &
MsgBuffer::reset()
{
  _count = 0;
  return *this;
}

inline MsgBuffer &
MsgBuffer::set(void *ptr, size_t n)
{
  _ptr   = static_cast<char *>(ptr);
  _size  = n;
  _count = 0;
  return *this;
}

inline MsgBuffer &
MsgBuffer::use(size_t n)
{
  _count += std::min(n, this->getSpace());
  return *this;
}

inline MsgBuffer &
MsgBuffer::zero()
{
  memset(_ptr, 0, _size);
  _count = 0;
  return *this;
}

inline PacketStamp::PacketStamp() : m_time(0), m_sn(0) {}

inline PacketStamp &
PacketStamp::set(time_t time, uint32_t sn)
{
  m_time = time;
  m_sn   = sn;
  return *this;
}

inline ServiceGroup::ServiceGroup() : m_svc_type(STANDARD), m_svc_id(0), m_priority(0), m_protocol(0), m_flags(0) {}

inline RouterIdElt::RouterIdElt() {}
inline RouterAssignElt::RouterAssignElt() : m_change_number(0) {}

inline RouterAssignListElt::RouterAssignListElt() {}
inline RouterAssignListElt::RouterAssignListElt(int n) : m_count(htonl(n)) {}
inline RouterAssignElt &
RouterAssignListElt::elt(int n)
{
  return access_array<RouterAssignElt>(this + 1)[n];
}
inline RouterAssignElt const &
RouterAssignListElt::elt(int n) const
{
  return const_cast<self *>(this)->elt(n);
}
inline size_t
RouterAssignListElt::calcVarSize(int n)
{
  return n * sizeof(RouterAssignElt);
}
inline size_t
RouterAssignListElt::calcSize(int n)
{
  return sizeof(self) + self::calcVarSize(n);
}
inline size_t
RouterAssignListElt::getSize() const
{
  return this->calcSize(this->getCount());
}
inline size_t
RouterAssignListElt::getVarSize() const
{
  return this->getSize() - sizeof(self);
}
// This is untainted because an overall size check is done when the packet is read. If any of the
// counts are bogus, that size check will fail.
// coverity[ -tainted_data_return]
inline uint32_t
RouterAssignListElt::getCount() const
{
  return ntohl(m_count);
}

inline HashAssignElt::HashAssignElt() {}
inline HashAssignElt::HashAssignElt(int n) : m_count(htonl(n)) {}
// This is untainted because an overall size check is done when the packet is read. If any of the
// counts are bogus, that size check will fail.
// coverity[ -tainted_data_return]
inline uint32_t
HashAssignElt::getCount() const
{
  return ntohl(m_count);
}
inline size_t
HashAssignElt::calcSize(int n)
{
  return sizeof(self) + n * sizeof(uint32_t) + sizeof(Bucket) * N_BUCKETS;
}
inline size_t
HashAssignElt::getSize() const
{
  return self::calcSize(this->getCount());
}
inline uint32_t
HashAssignElt::getAddr(int idx) const
{
  // coverity[ptr_arith]
  return (&m_count)[idx + 1];
}
inline HashAssignElt &
HashAssignElt::setAddr(int idx, uint32_t addr)
{
  // coverity[ptr_arith]
  (&m_count)[idx + 1] = addr;
  return *this;
}
inline HashAssignElt::Bucket *
HashAssignElt::getBucketBase()
{
  // coverity[ptr_arith]
  return reinterpret_cast<Bucket *>((&m_count + 1 + this->getCount()));
}
inline HashAssignElt::Bucket &
HashAssignElt::operator[](size_t idx)
{
  return this->getBucketBase()[idx];
}
inline HashAssignElt::Bucket const &
HashAssignElt::operator[](size_t idx) const
{
  return (*(const_cast<self *>(this)))[idx];
}

// This is untainted because an overall size check is done when the packet is read. If any of the
// counts are bogus, that size check will fail.
// coverity[ -tainted_data_return]
inline uint32_t
MaskAssignElt::getCount() const
{
  return ntohl(m_count);
}
inline MaskValueSetElt *
MaskAssignElt::appender::operator->()
{
  return m_set;
}
inline MaskValueSetElt *
MaskAssignElt::appender::initSet(uint32_t srcAddr, uint32_t dstAddr, uint16_t srcPort, uint16_t dstPort)
{
  (*(new (m_set) MaskValueSetElt(0)))
    .setSrcAddrMask(srcAddr)
    .setDstAddrMask(dstAddr)
    .setSrcPortMask(srcPort)
    .setDstPortMask(dstPort);
  return m_set;
}
inline MaskValueSetElt *
MaskAssignElt::appender::mask(uint32_t srcAddr, uint32_t dstAddr, uint16_t srcPort, uint16_t dstPort)
{
  m_set          = reinterpret_cast<MaskValueSetElt *>(reinterpret_cast<char *>(m_set) + m_set->getSize());
  m_elt->m_count = htonl(1 + m_elt->getCount()); // bump set count.
  this->initSet(srcAddr, dstAddr, srcPort, dstPort);
  return m_set;
}
inline MaskAssignElt::appender
MaskAssignElt::init(uint32_t srcAddr, uint32_t dstAddr, uint16_t srcPort, uint16_t dstPort)
{
  appender zret;
  m_count    = htonl(1);
  zret.m_set = reinterpret_cast<MaskValueSetElt *>(this + 1);
  zret.m_elt = this;
  zret.initSet(srcAddr, dstAddr, srcPort, dstPort);
  return zret;
}

inline bool
ComponentBase::isEmpty() const
{
  return 0 == m_base;
}

inline message_type_t
MsgHeaderComp::toMsgType(int t)
{
  return HERE_I_AM != t && I_SEE_YOU != t && REDIRECT_ASSIGN != t && REMOVAL_QUERY != t ? INVALID_MSG_TYPE :
                                                                                          static_cast<message_type_t>(t);
}

template <typename T>
CompType
CompWithHeader<T>::getType() const
{
  return static_cast<CompType>(ntohs(reinterpret_cast<raw_t const *>(m_base)->m_type));
}

template <typename T>
T &
CompWithHeader<T>::setType(CompType t)
{
  reinterpret_cast<raw_t *>(m_base)->m_type = htons(t);
  return static_cast<T &>(*this);
}

template <typename T>
uint16_t
CompWithHeader<T>::getLength() const
{
  return ntohs(reinterpret_cast<raw_t const *>(m_base)->m_length);
}

template <typename T>
T &
CompWithHeader<T>::setLength(uint16_t length)
{
  reinterpret_cast<raw_t *>(m_base)->m_length = htons(length);
  return static_cast<T &>(*this);
}

template <typename T>
int
CompWithHeader<T>::checkHeader(MsgBuffer const &buffer, CompType ect)
{
  CompType act = this->getType();
  if (act != ect)
    return (act < COMP_TYPE_MIN || COMP_TYPE_MAX < act) ? PARSE_COMP_TYPE_INVALID : PARSE_COMP_OTHER_TYPE;
  if (this->getLength() + sizeof(raw_t) > buffer.getSpace())
    return PARSE_COMP_TOO_BIG;
  return PARSE_SUCCESS;
}

inline AssignInfoComp::Bucket &
AssignInfoComp::bucket(int idx)
{
  return m_buckets[idx];
}
inline AssignInfoComp::Bucket const &
AssignInfoComp::bucket(int idx) const
{
  return m_buckets[idx];
}
inline RouterViewComp::RouterViewComp() : m_cache_count(0)
{
  ink_zero(m_cache_ids);
}

inline CapComp::CapComp() {}
inline CapComp &
CapComp::invalidate()
{
  m_cached = false;
  return *this;
}
inline uint32_t
CapComp::getEltCount() const
{
  return this->m_count;
}
inline size_t
CapComp::calcSize(int n)
{
  return sizeof(super::raw_t) + n * sizeof(CapabilityElt);
}
inline ServiceGroup::PacketStyle
CapComp::getPacketForwardStyle() const
{
  if (!m_cached)
    this->cache();
  return m_packet_forward;
}
inline ServiceGroup::PacketStyle
CapComp::getPacketReturnStyle() const
{
  if (!m_cached)
    this->cache();
  return m_packet_return;
}
inline ServiceGroup::CacheAssignmentStyle
CapComp::getCacheAssignmentStyle() const
{
  if (!m_cached)
    this->cache();
  return m_cache_assign;
}

inline AssignMapComp::AssignMapComp() {}

/*  Implementation note: Due to a bug in gcc, we have to be
    careful with these fields. If we use the field access templates
    directly, we get bad results because the pointer to member matching
    is done incorrectly (it uses a super type, not @c raw_t). We work
    around this by putting the pointer to member in a static variable.
*/
inline uint16_t
AltAssignComp::getAssignType() const
{
  static uint16_t raw_t::*mptr = &raw_t::m_assign_type;
  return get_field(mptr, m_base);
}
inline AltAssignComp &
AltAssignComp::setAssignType(uint16_t t)
{
  static uint16_t raw_t::*mptr = &raw_t::m_assign_type;
  set_field(mptr, m_base, t);
  return *this;
}
inline uint16_t
AltAssignComp::getAssignLength() const
{
  static uint16_t raw_t::*mptr = &raw_t::m_assign_length;
  return get_field(mptr, m_base);
}
inline AltAssignComp &
AltAssignComp::setAssignLength(uint16_t length)
{
  static uint16_t raw_t::*mptr = &raw_t::m_assign_length;
  set_field(mptr, m_base, length);
  return *this;
}

inline uint32_t
QueryComp::getRouterAddr() const
{
  return access_field(&raw_t::m_router_addr, m_base);
}
inline QueryComp &
QueryComp::setRouterAddr(uint32_t addr)
{
  access_field(&raw_t::m_router_addr, m_base) = addr;
  return *this;
}
inline uint32_t
QueryComp::getToAddr() const
{
  return access_field(&raw_t::m_to_addr, m_base);
}
inline QueryComp &
QueryComp::setToAddr(uint32_t addr)
{
  access_field(&raw_t::m_to_addr, m_base) = addr;
  return *this;
}
inline uint32_t
QueryComp::getCacheAddr() const
{
  return access_field(&raw_t::m_cache_addr, m_base);
}
inline QueryComp &
QueryComp::setCacheAddr(uint32_t addr)
{
  access_field(&raw_t::m_cache_addr, m_base) = addr;
  return *this;
}
inline uint32_t
QueryComp::getRecvId() const
{
  return get_field(&raw_t::m_recv_id, m_base);
}
inline QueryComp &
QueryComp::setRecvId(uint32_t data)
{
  set_field(&raw_t::m_recv_id, m_base, data);
  return *this;
}
inline size_t
QueryComp::calcSize()
{
  return sizeof(raw_t);
}

inline detail::cache::SeedRouter::SeedRouter() {}

inline detail::cache::SeedRouter::SeedRouter(uint32_t addr) : m_addr(addr), m_count(0), m_xmit(0) {}

inline BaseMsg::BaseMsg() : m_buffer(0, 0) {}
inline MsgBuffer const &
BaseMsg::buffer() const
{
  return m_buffer;
}
inline size_t
BaseMsg::getSpace() const
{
  return m_buffer.getSpace();
}
inline size_t
BaseMsg::getCount() const
{
  return m_buffer.getCount();
}

inline RouterImpl::RouterData &
RouterImpl::RouterData::resize(size_t n)
{
  m_src.resize(n);
  return *this;
}
// ------------------------------------------------------

} // namespace wccp
