/** @file WCCP End Point class implementation.

    @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.
 */

#include "WccpLocal.h"
#include "WccpUtil.h"
#include "WccpMeta.h"
#include <errno.h>
#include "tscore/ink_string.h"
#include "tscore/ink_defs.h"
// ------------------------------------------------------
namespace wccp
{
#if defined IP_RECVDSTADDR
#define DSTADDR_SOCKOPT IP_RECVDSTADDR
#define DSTADDR_DATASIZE (CMSG_SPACE(sizeof(struct in_addr)))
#define dstaddr(x) (CMSG_DATA(x))
#elif defined IP_PKTINFO
#define DSTADDR_SOCKOPT IP_PKTINFO
#define DSTADDR_DATASIZE (CMSG_SPACE(sizeof(struct in_pktinfo)))
#define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
#else
#error "can't determine socket option"
#endif

// ------------------------------------------------------
Impl::GroupData &
Impl::GroupData::setKey(const char *key)
{
  if ((m_use_security_key = (key != nullptr))) {
    ink_strlcpy(m_security_key, key, SecurityComp::KEY_SIZE);
  }
  return *this;
}

Impl::GroupData &
Impl::GroupData::setSecurity(SecurityOption style)
{
  m_use_security_opt = true;
  m_security_opt     = style;
  return *this;
}

Impl::~Impl()
{
  this->close();
}

int
Impl::open(uint addr)
{
  struct sockaddr saddr;
  sockaddr_in &in_addr = reinterpret_cast<sockaddr_in &>(saddr);
  ats_scoped_fd fd;

  if (ts::NO_FD != m_fd) {
    log(LVL_INFO, "Attempted to open already open WCCP Endpoint");
    return -EALREADY;
  }

  if (ts::NO_FD == (fd = socket(PF_INET, SOCK_DGRAM, 0))) {
    log_errno(LVL_FATAL, "Failed to create socket");
    return -errno;
  }

  if (INADDR_ANY != addr)
    m_addr = addr; // overridden.
  memset(&saddr, 0, sizeof(saddr));
  in_addr.sin_family      = AF_INET;
  in_addr.sin_port        = htons(DEFAULT_PORT);
  in_addr.sin_addr.s_addr = m_addr;
  int zret                = bind(fd, &saddr, sizeof(saddr));
  if (-1 == zret) {
    log_errno(LVL_FATAL, "Failed to bind socket to port");
    this->close();
    return -errno;
  }
  logf(LVL_INFO, "Socket bound to %s:%d", ip_addr_to_str(m_addr), DEFAULT_PORT);

  // Now get the address. Usually the same but possibly different,
  // certainly if addr was INADDR_ANY.
  if (INADDR_ANY == m_addr && INADDR_ANY == (m_addr = Get_Local_Address(fd))) {
    log_errno(LVL_FATAL, "Failed to get local address for socket");
    this->close();
    return -errno;
  }

  // Enable retrieval of destination address on packets.
  int ip_pktinfo_flag = 1;
  if (-1 == setsockopt(fd, IPPROTO_IP, DSTADDR_SOCKOPT, &ip_pktinfo_flag, sizeof(ip_pktinfo_flag))) {
    log_errno(LVL_FATAL, "Failed to enable destination address retrieval");
    this->close();
    return -errno;
  }

#if defined IP_MTU_DISCOVER
  /// Disable PMTU on Linux because of a bug in IOS routers.
  /// WCCP packets are rejected as duplicates if the IP fragment
  /// identifier is 0, which is the value used when PMTU is enabled.
  int pmtu = IP_PMTUDISC_DONT;
  if (-1 == setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu))) {
    log_errno(LVL_FATAL, "Failed to disable PMTU on WCCP socket.");
    this->close();
    return -errno;
  }
#endif

  m_fd = fd.release();
  return 0;
}

void
Impl::close()
{
  if (ts::NO_FD != m_fd) {
    ::close(m_fd);
    m_fd = ts::NO_FD;
  }
}

void
Impl::useMD5Security(std::string_view const key)
{
  m_use_security_opt = true;
  m_security_opt     = SECURITY_MD5;
  m_use_security_key = true;
  memset(m_security_key, 0, SecurityComp::KEY_SIZE);
  // Great. Have to cast or we get a link error.
  memcpy(m_security_key, key.data(), std::min(key.size(), static_cast<size_t>(SecurityComp::KEY_SIZE)));
}

SecurityOption
Impl::setSecurity(BaseMsg &msg, GroupData const &group) const
{
  SecurityOption zret = SECURITY_NONE;
  if (group.m_use_security_opt)
    zret = group.m_security_opt;
  else if (m_use_security_opt)
    zret = m_security_opt;
  if (group.m_use_security_key)
    msg.m_security.setKey(group.m_security_key);
  else if (m_use_security_key)
    msg.m_security.setKey(m_security_key);
  return zret;
}

bool
Impl::validateSecurity(BaseMsg &msg, GroupData const &group)
{
  SecurityOption opt = msg.m_security.getOption();
  if (group.m_use_security_opt) {
    if (opt != group.m_security_opt)
      return false;
  } else if (m_use_security_opt) {
    if (opt != m_security_opt)
      return false;
  }
  if (opt == SECURITY_MD5) {
    if (group.m_use_security_key)
      msg.m_security.setKey(group.m_security_key);
    else if (m_use_security_key)
      msg.m_security.setKey(m_security_key);
    return msg.validateSecurity();
  }
  return true;
}

ts::Rv<int>
Impl::handleMessage()
{
  ts::Rv<int> zret;
  ssize_t n;                // recv byte count.
  struct sockaddr src_addr; // sender's address.
  msghdr recv_hdr;
  iovec recv_buffer;
  IpHeader ip_header;
  static ssize_t const BUFFER_SIZE = 65536;
  char buffer[BUFFER_SIZE];
  static size_t const ANC_BUFFER_SIZE = DSTADDR_DATASIZE;
  char anc_buffer[ANC_BUFFER_SIZE];

  if (ts::NO_FD == m_fd)
    return -ENOTCONN;

  recv_buffer.iov_base = buffer;
  recv_buffer.iov_len  = BUFFER_SIZE;

  recv_hdr.msg_name       = &src_addr;
  recv_hdr.msg_namelen    = sizeof(src_addr);
  recv_hdr.msg_iov        = &recv_buffer;
  recv_hdr.msg_iovlen     = 1;
  recv_hdr.msg_control    = anc_buffer;
  recv_hdr.msg_controllen = ANC_BUFFER_SIZE;
  recv_hdr.msg_flags      = 0; // output only, make Coverity shut up.

  // coverity[uninit_use_in_call]
  n = recvmsg(m_fd, &recv_hdr, MSG_TRUNC);
  if (n > BUFFER_SIZE)
    return -EMSGSIZE;
  else if (n < 0)
    return -errno;

  // Extract the original destination address.
  ip_header.m_src = access_field(&sockaddr_in::sin_addr, &src_addr).s_addr;
  for (cmsghdr *anc = CMSG_FIRSTHDR(&recv_hdr); anc; anc = CMSG_NXTHDR(&recv_hdr, anc)) {
    if (anc->cmsg_level == IPPROTO_IP && anc->cmsg_type == DSTADDR_SOCKOPT) {
      ip_header.m_dst = ((struct in_addr *)dstaddr(anc))->s_addr;
      break;
    }
  }

  // Check to see if there is a valid header.
  MsgHeaderComp header;
  MsgBuffer msg_buffer(buffer, n);
  if (PARSE_SUCCESS == header.parse(msg_buffer)) {
    message_type_t msg_type = header.getType();
    ts::Buffer chunk(buffer, n);

    switch (msg_type) {
    case HERE_I_AM:
      this->handleHereIAm(ip_header, chunk);
      break;
    case I_SEE_YOU:
      this->handleISeeYou(ip_header, chunk);
      break;
    case REDIRECT_ASSIGN:
      this->handleRedirectAssign(ip_header, chunk);
      break;
    case REMOVAL_QUERY:
      this->handleRemovalQuery(ip_header, chunk);
      break;
    default:
      fprintf(stderr, "Unknown message type %d ignored.\n", msg_type);
      break;
    };
  } else {
    fprintf(stderr, "Malformed message ignored.\n");
  }
  return zret;
}

ts::Errata
Impl::handleHereIAm(IpHeader const &, ts::Buffer const &)
{
  return log(LVL_INFO, "Unanticipated WCCP2_HERE_I_AM message ignored");
}
ts::Errata
Impl::handleISeeYou(IpHeader const &, ts::Buffer const & /* data ATS_UNUSED */)
{
  return log(LVL_INFO, "Unanticipated WCCP2_I_SEE_YOU message ignored.");
}
ts::Errata
Impl::handleRedirectAssign(IpHeader const &, ts::Buffer const & /* data ATS_UNUSED */)
{
  return log(LVL_INFO, "Unanticipated WCCP2_REDIRECT_ASSIGN message ignored.");
}
ts::Errata
Impl::handleRemovalQuery(IpHeader const &, ts::Buffer const & /* data ATS_UNUSED */)
{
  return log(LVL_INFO, "Unanticipated WCCP2_REMOVAL_QUERY message ignored.");
}
// ------------------------------------------------------
CacheImpl::GroupData::GroupData() : m_proc_name(NULL), m_assignment_pending(false) {}

CacheImpl::GroupData &
CacheImpl::GroupData::seedRouter(uint32_t addr)
{
  // Be nice and don't add it if it's already there.
  if (m_seed_routers.end() == find_by_member(m_seed_routers, &SeedRouter::m_addr, addr))
    m_seed_routers.push_back(SeedRouter(addr));
  return *this;
}

time_t
CacheImpl::GroupData::removeSeedRouter(uint32_t addr)
{
  time_t zret                             = 0;
  std::vector<SeedRouter>::iterator begin = m_seed_routers.begin();
  std::vector<SeedRouter>::iterator end   = m_seed_routers.end();
  std::vector<SeedRouter>::iterator spot  = std::find_if(begin, end, ts::predicate(&SeedRouter::m_addr, addr));

  if (end != spot) {
    zret = spot->m_xmit;
    m_seed_routers.erase(spot);
  }

  return zret;
}

CacheImpl::GroupData &
CacheImpl::GroupData::setKey(const char *key)
{
  return static_cast<self &>(this->super::setKey(key));
}

CacheImpl::GroupData &
CacheImpl::GroupData::setSecurity(SecurityOption style)
{
  return static_cast<self &>(this->super::setSecurity(style));
}

CacheImpl::CacheBag::iterator
CacheImpl::GroupData::findCache(uint32_t addr)
{
  return std::find_if(m_caches.begin(), m_caches.end(), ts::predicate(&CacheData::idAddr, addr));
}

CacheImpl::RouterBag::iterator
CacheImpl::GroupData::findRouter(uint32_t addr)
{
  return std::find_if(m_routers.begin(), m_routers.end(), ts::predicate(&RouterData::m_addr, addr));
}

void
CacheImpl::GroupData::resizeCacheSources()
{
  int count = m_routers.size();
  for (CacheBag::iterator spot = m_caches.begin(), limit = m_caches.end(); spot != limit; ++spot) {
    spot->m_src.resize(count);
  }
}

inline CacheImpl::RouterData::RouterData() : m_addr(0), m_generation(0), m_rapid(0), m_assign(false), m_send_caps(false) {}

inline CacheImpl::RouterData::RouterData(uint32_t addr)
  : m_addr(addr), m_generation(0), m_rapid(0), m_assign(false), m_send_caps(false)
{
}

time_t
CacheImpl::RouterData::pingTime(time_t now) const
{
  time_t tx = m_xmit.m_time + (m_rapid ? TIME_UNIT / 10 : TIME_UNIT);
  return tx < now ? 0 : tx - now;
}

time_t
CacheImpl::RouterData::waitTime(time_t now) const
{
  return m_assign ? 0 : this->pingTime(now);
}

inline uint32_t
detail::cache::CacheData::idAddr() const
{
  return m_id.getAddr();
}

CacheImpl::GroupData &
CacheImpl::defineServiceGroup(ServiceGroup const &svc, ServiceGroup::Result *result)
{
  uint8_t svc_id          = svc.getSvcId();
  GroupMap::iterator spot = m_groups.find(svc_id);
  GroupData *group; // service with target ID.
  ServiceGroup::Result zret;
  if (spot == m_groups.end()) { // not defined
    group        = &(m_groups[svc_id]);
    group->m_svc = svc;
    group->m_id.initDefaultHash(m_addr);
    zret = ServiceGroup::DEFINED;
  } else {
    group = &spot->second;
    zret  = group->m_svc == svc ? ServiceGroup::EXISTS : ServiceGroup::CONFLICT;
  }
  if (result)
    *result = zret;
  return *group;
}

time_t
CacheImpl::GroupData::waitTime(time_t now) const
{
  time_t zret = std::numeric_limits<time_t>::max();
  // Active routers.
  for (RouterBag::const_iterator router = m_routers.begin(), router_limit = m_routers.end(); router != router_limit && zret;
       ++router) {
    zret = std::min(zret, router->waitTime(now));
  }
  // Seed routers.
  for (std::vector<SeedRouter>::const_iterator router = m_seed_routers.begin(), router_limit = m_seed_routers.end();
       router != router_limit && zret; ++router) {
    time_t tx = router->m_xmit + TIME_UNIT;
    if (tx < now)
      zret = 0;
    else
      zret = std::min(tx - now, zret);
  }
  // Assignment
  if (m_assignment_pending) {
    time_t tx = m_generation_time + (3 * TIME_UNIT / 2);
    if (tx < now)
      zret = 0;
    else
      zret = std::min(tx - now, zret);
  }

  return zret;
}

bool
CacheImpl::GroupData::processUp()
{
  bool zret                 = false;
  const char *proc_pid_path = this->getProcName();
  if (proc_pid_path == NULL || proc_pid_path[0] == '\0') {
    zret = true; // No process to track, always chatter
  } else {
    // Look for the pid file
    ats_scoped_fd fd{open(proc_pid_path, O_RDONLY)};
    if (fd >= 0) {
      char buffer[256];
      ssize_t read_count = read(fd, buffer, sizeof(buffer) - 1);
      if (read_count > 0) {
        buffer[read_count] = '\0';
        int pid            = atoi(buffer);
        if (pid > 0) {
          // If the process is still running, it has an entry in the proc file system, (Linux only)
          sprintf(buffer, "/proc/%d/status", pid);
          ats_scoped_fd fd2{open(buffer, O_RDONLY)};
          if (fd2 >= 0) {
            zret = true;
          }
        }
      }
    }
  }
  return zret;
}

bool
CacheImpl::GroupData::cullRouters(time_t now)
{
  bool zret  = false;
  size_t idx = 0, n = m_routers.size();
  while (idx < n) {
    RouterData &router = m_routers[idx];
    if (router.m_recv.m_time + TIME_UNIT * 3 < now) {
      uint32_t addr = router.m_addr;
      // Clip the router by copying down and resizing.
      // Must do all caches as well.
      --n; // Decrement router counter first.
      if (idx < n)
        router = m_routers[n];
      m_routers.resize(n);
      for (CacheBag::iterator cache = m_caches.begin(), cache_limit = m_caches.end(); cache != cache_limit; ++cache) {
        if (idx < n)
          cache->m_src[idx] = cache->m_src[n];
        cache->m_src.resize(n);
      }
      // Put it back in the seeds.
      this->seedRouter(addr);
      zret = true; // Router was culled, report it to caller.
      logf(LVL_INFO, "Router " ATS_IP_PRINTF_CODE " timed out and was removed from the active list.", ATS_IP_OCTETS(addr));
    } else {
      ++idx; // move to next router.
    }
  }
  if (zret)
    this->viewChanged(now);
  return zret;
}

CacheImpl::GroupData &
CacheImpl::GroupData::viewChanged(time_t now)
{
  m_generation += 1;
  m_generation_time = now;
  m_assign_info.setActive(false); // invalidate current assignment.
  m_assignment_pending = m_routers.size() && m_caches.size();
  // Cancel any pending assignment transmissions.
  ts::for_each(m_routers, ts::assign_member(&RouterData::m_assign, false));
  logf(LVL_DEBUG, "Service group %d view change (%d)", m_svc.getSvcId(), m_generation);

  return *this;
}

Cache::Service &
Cache::Service::setKey(const char *key)
{
  m_group->setKey(key);
  return *this;
}

Cache::Service &
Cache::Service::setSecurity(SecurityOption opt)
{
  m_group->setSecurity(opt);
  return *this;
}

CacheImpl &
CacheImpl::seedRouter(uint8_t id, uint32_t addr)
{
  GroupMap::iterator spot = m_groups.find(id);
  if (spot != m_groups.end())
    spot->second.seedRouter(addr);
  return *this;
}

bool
CacheImpl::isConfigured() const
{
  return INADDR_ANY != m_addr && m_groups.size() > 0;
}

int
CacheImpl::open(uint32_t addr)
{
  int zret = this->super::open(addr);
  // If the socket was successfully opened, go through the
  // services and update the local service descriptor.
  if (0 <= zret) {
    for (GroupMap::iterator spot = m_groups.begin(), limit = m_groups.end(); spot != limit; ++spot) {
      spot->second.m_id.setAddr(m_addr);
    }
  }
  return zret;
}

time_t
CacheImpl::waitTime() const
{
  time_t now = time(0);
  return ts::minima(m_groups, &GroupData::waitTime, now);
}

void
CacheImpl::generateHereIAm(HereIAmMsg &msg, GroupData &group)
{
  msg.fill(group, group.m_id, this->setSecurity(msg, group));
  msg.finalize();
}

void
CacheImpl::generateHereIAm(HereIAmMsg &msg, GroupData &group, RouterData &router)
{
  SecurityOption sec_opt = this->setSecurity(msg, group);

  msg.fill(group, group.m_id, sec_opt);
  if (router.m_local_cache_id.getSize())
    msg.m_cache_id.setUnassigned(false);

  msg.fill_caps(router);
  msg.finalize();
}

void
CacheImpl::generateRedirectAssign(RedirectAssignMsg &msg, GroupData &group)
{
  msg.fill(group, this->setSecurity(msg, group));
  msg.finalize();
}

ts::Errata
CacheImpl::checkRouterAssignment(GroupData const &group, RouterViewComp const &comp) const
{
  detail::Assignment const &ainfo = group.m_assign_info;
  // If group doesn't have an active assignment, always match w/o checking.
  ts::Errata zret; // default is success.

  // if active assignment and data we can check, then check.
  if (ainfo.isActive() && !comp.isEmpty()) {
    // Validate the assignment key.
    if (ainfo.getKey().getAddr() != comp.getKeyAddr() || ainfo.getKey().getChangeNumber() != comp.getKeyChangeNumber()) {
      log(zret, LVL_INFO, "Router assignment key did not match.");
      ;
    } else if (ServiceGroup::HASH_ONLY == group.m_cache_assign) {
      // Still not sure how much checking we really want or should
      // do here. For now, we'll just leave the checks validating
      // the assignment key.
    } else if (ServiceGroup::MASK_ONLY == group.m_cache_assign) {
      // The data passed back is useless. In practice the interesting
      // data in the mask case is in the Assignment Map Component
      // which the router seems to send when using mask assignment.
    }
  }
  return zret;
}

int
CacheImpl::housekeeping()
{
  int zret = 0;
  sockaddr_in dst_addr;
  sockaddr *addr_ptr              = reinterpret_cast<sockaddr *>(&dst_addr);
  time_t now                      = time(0);
  static size_t const BUFFER_SIZE = 4096;
  MsgBuffer msg_buffer;
  char msg_data[BUFFER_SIZE];
  msg_buffer.set(msg_data, BUFFER_SIZE);

  // Set up everything except the IP address.
  memset(&dst_addr, 0, sizeof(dst_addr));
  dst_addr.sin_family = AF_INET;
  dst_addr.sin_port   = htons(DEFAULT_PORT);

  // Walk the service groups and do their housekeeping.
  for (GroupMap::iterator svc_spot = m_groups.begin(), svc_limit = m_groups.end(); svc_spot != svc_limit; ++svc_spot) {
    GroupData &group = svc_spot->second;

    // Check to see if it's time for an assignment.
    if (group.m_assignment_pending && group.m_generation_time + ASSIGN_WAIT <= now) {
      // Is a valid assignment possible?
      if (group.m_assign_info.fill(group, m_addr)) {
        group.m_assign_info.setActive(true);
        ts::for_each(group.m_routers, ts::assign_member(&RouterData::m_assign, true));
      }

      // Always clear because no point in sending an assign we can't generate.
      group.m_assignment_pending = false;
    }

    group.cullRouters(now); // TBD UPDATE VIEW!

    // Check to see if the related service is up
    if (group.processUp()) {
      // Check the active routers for scheduled packets.
      for (RouterBag::iterator rspot = group.m_routers.begin(), rend = group.m_routers.end(); rspot != rend; ++rspot) {
        dst_addr.sin_addr.s_addr = rspot->m_addr;
        if (0 == rspot->pingTime(now)) {
          HereIAmMsg here_i_am;
          here_i_am.setBuffer(msg_buffer);
          this->generateHereIAm(here_i_am, group, *rspot);
          zret = sendto(m_fd, msg_data, here_i_am.getCount(), 0, addr_ptr, sizeof(dst_addr));
          if (0 <= zret) {
            rspot->m_xmit.set(now, group.m_generation);
            rspot->m_send_caps = false;
            logf(LVL_DEBUG, "Sent HERE_I_AM for service group %d to router %s%s[#%d,%lu].", group.m_svc.getSvcId(),
                 ip_addr_to_str(rspot->m_addr), rspot->m_rapid ? " [rapid] " : " ", group.m_generation, now);
            if (rspot->m_rapid)
              --(rspot->m_rapid);
          } else {
            logf_errno(LVL_WARN, "Failed to send to router " ATS_IP_PRINTF_CODE " - ", ATS_IP_OCTETS(rspot->m_addr));
          }
        } else if (rspot->m_assign) {
          RedirectAssignMsg redirect_assign;
          redirect_assign.setBuffer(msg_buffer);
          this->generateRedirectAssign(redirect_assign, group);
          zret = sendto(m_fd, msg_data, redirect_assign.getCount(), 0, addr_ptr, sizeof(dst_addr));
          if (0 <= zret)
            rspot->m_assign = false;
        }
      }
    }

    // Seed routers.
    for (std::vector<SeedRouter>::iterator sspot = group.m_seed_routers.begin(), slimit = group.m_seed_routers.end();
         sspot != slimit; ++sspot) {
      // Check to see if the related service is up
      if (group.processUp()) {
        HereIAmMsg here_i_am;
        here_i_am.setBuffer(msg_buffer);
        // Is the router due for a ping?
        if (sspot->m_xmit + TIME_UNIT > now)
          continue; // no

        this->generateHereIAm(here_i_am, group);

        dst_addr.sin_addr.s_addr = sspot->m_addr;
        zret                     = sendto(m_fd, msg_data, here_i_am.getCount(), 0, addr_ptr, sizeof(dst_addr));
        if (0 <= zret) {
          logf(LVL_DEBUG, "Sent HERE_I_AM for SG %d to seed router %s [gen=#%d,t=%lu,n=%lu].", group.m_svc.getSvcId(),
               ip_addr_to_str(sspot->m_addr), group.m_generation, now, here_i_am.getCount());
          sspot->m_xmit = now;
          sspot->m_count += 1;
        } else
          logf(LVL_DEBUG, "Error [%d:%s] sending HERE_I_AM for SG %d to seed router %s [#%d,%lu].", zret, strerror(errno),
               group.m_svc.getSvcId(), ip_addr_to_str(sspot->m_addr), group.m_generation, now);
      }
    }
  }
  return zret;
}

ts::Errata
CacheImpl::handleISeeYou(IpHeader const & /* ip_hdr ATS_UNUSED */, ts::Buffer const &chunk)
{
  ts::Errata zret;
  ISeeYouMsg msg;
  // Set if our view of the group changes enough to bump the
  // generation number.
  bool view_changed = false;
  time_t now        = time(0); // don't call this over and over.
  int parse         = msg.parse(chunk);

  if (PARSE_SUCCESS != parse)
    return logf(LVL_INFO, "Ignored malformed [%d] WCCP2_I_SEE_YOU message.", parse);

  ServiceGroup svc(msg.m_service);
  GroupMap::iterator spot = m_groups.find(svc.getSvcId());
  if (spot == m_groups.end())
    return logf(LVL_INFO, "WCCP2_I_SEE_YOU ignored - service group %d not found.", svc.getSvcId());

  GroupData &group = spot->second;

  if (!this->validateSecurity(msg, group))
    return log(LVL_INFO, "Ignored WCCP2_I_SEE_YOU with invalid security.\n");

  if (svc != group.m_svc)
    return logf(LVL_INFO, "WCCP2_I_SEE_YOU ignored - service group definition %d does not match.\n", svc.getSvcId());

  if (-1 == msg.m_router_id.findFromAddr(m_addr))
    return logf(LVL_INFO, "WCCP2_I_SEE_YOU ignored -- cache not in from list.\n");

  logf(LVL_DEBUG, "Received WCCP2_I_SEE_YOU for group %d.", group.m_svc.getSvcId());

  // Preferred address for router.
  uint32_t router_addr = msg.m_router_id.idElt().getAddr();
  // Where we sent our packet.
  uint32_t to_addr = msg.m_router_id.getToAddr();
  uint32_t recv_id = msg.m_router_id.idElt().getRecvId();
  RouterBag::iterator ar_spot; // active router
  int router_idx;              // index in active routers.

  CapComp &caps = msg.m_capabilities;
  // Handle the router that sent us this.
  ar_spot = find_by_member(group.m_routers, &RouterData::m_addr, router_addr);
  if (ar_spot == group.m_routers.end()) {
    // This is a new router that's replied to one of our pings.
    // Need to do various setup and reply things to get the connection
    // established.

    // Remove this from the seed routers and copy the last packet
    // sent time.
    RouterData r(router_addr); // accumulate state before we commit it.
    r.m_xmit.m_time = group.removeSeedRouter(to_addr);

    // Validate capabilities.
    ServiceGroup::PacketStyle ps;
    ServiceGroup::CacheAssignmentStyle as;
    const char *caps_tag = caps.isEmpty() ? "default" : "router";

    // No caps -> use GRE forwarding.
    ps = caps.isEmpty() ? ServiceGroup::GRE : caps.getPacketForwardStyle();
    if (ServiceGroup::GRE & ps & group.m_packet_forward)
      r.m_packet_forward = ServiceGroup::GRE;
    else if (ServiceGroup::L2 & ps & group.m_packet_forward)
      r.m_packet_forward = ServiceGroup::L2;
    else
      logf(zret, LVL_WARN, "Packet forwarding (config=%d, %s=%d) did not match.", group.m_packet_forward, caps_tag, ps);

    // No caps -> use GRE return.
    ps = caps.isEmpty() ? ServiceGroup::GRE : caps.getPacketReturnStyle();
    if (ServiceGroup::GRE & ps & group.m_packet_return)
      r.m_packet_return = ServiceGroup::GRE;
    else if (ServiceGroup::L2 & ps & group.m_packet_return)
      r.m_packet_return = ServiceGroup::L2;
    else
      logf(zret, LVL_WARN, "Packet return (local=%d, %s=%d) did not match.", group.m_packet_return, caps_tag, ps);

    // No caps -> use HASH assignment.
    as = caps.isEmpty() ? ServiceGroup::HASH_ONLY : caps.getCacheAssignmentStyle();
    if (ServiceGroup::HASH_ONLY & as & group.m_cache_assign)
      r.m_cache_assign = ServiceGroup::HASH_ONLY;
    else if (ServiceGroup::MASK_ONLY & as & group.m_cache_assign) {
      r.m_cache_assign = ServiceGroup::MASK_ONLY;
      group.m_id.initDefaultMask(m_addr); // switch to MASK style ID.
    } else
      logf(zret, LVL_WARN, "Cache assignment (local=%d, %s=%d) did not match.", group.m_cache_assign, caps_tag, as);

    if (!zret) {
      // cancel out, can't use this packet because we reject the router.
      return logf(zret, LVL_WARN, "Router %s rejected because of capabilities mismatch.", ip_addr_to_str(router_addr));
    }

    group.m_routers.push_back(r);
    ar_spot      = group.m_routers.end() - 1;
    view_changed = true;
    logf(LVL_INFO, "Added source router %s to view %d", ip_addr_to_str(router_addr), group.m_svc.getSvcId());
  } else {
    // Existing router. Update the receive ID in the assignment object.
    group.m_assign_info.updateRouterId(router_addr, recv_id, msg.m_router_view.getChangeNumber());
    // Check the assignment to see if we need to send it again.
    ts::Errata status = this->checkRouterAssignment(group, msg.m_router_view);
    if (status.size()) {
      ar_spot->m_assign = true; // schedule an assignment message.
      logf(status, LVL_INFO,
           "Router assignment reported from " ATS_IP_PRINTF_CODE " did not match local assignment. Resending assignment.\n ",
           ATS_IP_OCTETS(router_addr));
    }
  }
  time_t then = ar_spot->m_recv.m_time; // used for comparisons later.
  ar_spot->m_recv.set(now, recv_id);
  ar_spot->m_generation = msg.m_router_view.getChangeNumber();
  router_idx            = ar_spot - group.m_routers.begin();
  // Reply with our own capability options iff the router sent one to us.
  // This is a violation of the spec but it's what we have to do in practice
  // for mask assignment.
  ar_spot->m_send_caps = !caps.isEmpty();

  // For all the other listed routers, seed them if they're not
  // already active.
  uint32_t nr = msg.m_router_view.getRouterCount();
  for (uint32_t idx = 0; idx < nr; ++idx) {
    uint32_t addr = msg.m_router_view.getRouterAddr(idx);
    if (group.m_routers.end() == find_by_member(group.m_routers, &RouterData::m_addr, addr))
      group.seedRouter(addr);
  }

  // Update/Install the caches.
  // TBD: Must bump view if a router fails to report a cache it reported
  // in its last packet.
  group.resizeCacheSources();
  uint32_t nc = msg.m_router_view.getCacheCount();
  for (uint32_t idx = 0; idx < nc; ++idx) {
    CacheIdBox &cache          = msg.m_router_view.cacheId(idx);
    CacheBag::iterator ac_spot = group.findCache(cache.getAddr());
    if (group.m_caches.end() == ac_spot) {
      group.m_caches.push_back(CacheData());
      ac_spot = group.m_caches.end() - 1;
      ac_spot->m_src.resize(group.m_routers.size());
      logf(LVL_INFO, "Added cache %s to view %d", ip_addr_to_str(cache.getAddr()), group.m_svc.getSvcId());
      view_changed = true;
    } else {
      // Check if the cache wasn't reported last time but was reported
      // this time. In that case we need to bump the view to trigger
      // assignment generation.
      if (ac_spot->m_src[router_idx].m_time != then)
        view_changed = true;
    }
    ac_spot->m_id.fill(cache);
    // If cache is this cache, update data in router record.
    if (cache.getAddr() == m_addr)
      ar_spot->m_local_cache_id.fill(cache);
    ac_spot->m_src[router_idx].set(now, recv_id);
  }

  if (view_changed)
    group.viewChanged(now);

  return zret;
}

ts::Errata
CacheImpl::handleRemovalQuery(IpHeader const & /* ip_hdr ATS_UNUSED */, ts::Buffer const &chunk)
{
  ts::Errata zret;
  RemovalQueryMsg msg;
  time_t now = time(0);
  int parse  = msg.parse(chunk);

  if (PARSE_SUCCESS != parse)
    return log(LVL_INFO, "Ignored malformed WCCP2_REMOVAL_QUERY message.");

  ServiceGroup svc(msg.m_service);
  GroupMap::iterator spot = m_groups.find(svc.getSvcId());
  if (spot == m_groups.end())
    return logf(LVL_INFO, "WCCP2_REMOVAL_QUERY ignored - service group %d not found.", svc.getSvcId());

  GroupData &group = spot->second;

  if (!this->validateSecurity(msg, group))
    return log(LVL_INFO, "Ignored WCCP2_REMOVAL_QUERY with invalid security.\n");

  if (svc != group.m_svc)
    return logf(LVL_INFO, "WCCP2_REMOVAL_QUERY ignored - service group definition %d does not match.\n", svc.getSvcId());

  uint32_t target_addr = msg.m_query.getCacheAddr(); // intended cache
  if (m_addr == target_addr) {
    uint32_t raddr             = msg.m_query.getRouterAddr();
    RouterBag::iterator router = group.findRouter(raddr);
    if (group.m_routers.end() != router) {
      router->m_rapid = true; // do rapid responses.
      router->m_recv.set(now, msg.m_query.getRecvId());
      logf(LVL_INFO, "WCCP2_REMOVAL_QUERY from router " ATS_IP_PRINTF_CODE ".\n", ATS_IP_OCTETS(raddr));
    } else {
      logf(LVL_INFO, "WCCP2_REMOVAL_QUERY from unknown router " ATS_IP_PRINTF_CODE ".\n", ATS_IP_OCTETS(raddr));
    }
  } else {
    // Not an error in the multi-cast case, so just log under debug.
    logf(LVL_DEBUG,
         "WCCP2_REMOVAL_QUERY ignored -- target cache address " ATS_IP_PRINTF_CODE
         " did not match local address " ATS_IP_PRINTF_CODE "\n.",
         ATS_IP_OCTETS(target_addr), ATS_IP_OCTETS(m_addr));
  }

  logf(LVL_DEBUG, "Received WCCP2_REMOVAL_QUERY for group %d.", group.m_svc.getSvcId());

  return zret;
}
// ------------------------------------------------------
inline uint32_t
detail::router::CacheData::idAddr() const
{
  return m_id.getAddr();
}

RouterImpl::GroupData::GroupData() {}

RouterImpl::CacheBag::iterator
RouterImpl::GroupData::findCache(uint32_t addr)
{
  return std::find_if(m_caches.begin(), m_caches.end(), ts::predicate(&CacheData::idAddr, addr));
}

RouterImpl::GroupData &
RouterImpl::defineServiceGroup(ServiceGroup const &svc, ServiceGroup::Result *result)
{
  uint8_t svc_id          = svc.getSvcId();
  GroupMap::iterator spot = m_groups.find(svc_id);
  GroupData *group; // service with target ID.
  ServiceGroup::Result zret;
  if (spot == m_groups.end()) { // not defined
    group        = &(m_groups[svc_id]);
    group->m_svc = svc;
    zret         = ServiceGroup::DEFINED;
  } else {
    group = &spot->second;
    zret  = group->m_svc == svc ? ServiceGroup::EXISTS : ServiceGroup::CONFLICT;
  }
  if (result)
    *result = zret;
  return *group;
}

void
RouterImpl::GroupData::resizeRouterSources()
{
  ts::for_each(m_routers, &RouterData::resize, m_caches.size());
}

ts::Errata
RouterImpl::handleHereIAm(IpHeader const &ip_hdr, ts::Buffer const &chunk)
{
  ts::Errata zret;
  HereIAmMsg msg;
  static GroupData nil_group; // scratch until I clean up the security.
  // Set if our view of the group changes enough to bump the
  // generation number.
  bool view_changed = false;
  int i;                // scratch index var.
  time_t now = time(0); // don't call this over and over.
  int parse  = msg.parse(chunk);

  if (PARSE_SUCCESS != parse)
    return log(LVL_INFO, "Ignored malformed WCCP2_HERE_I_AM message.\n");

  if (!this->validateSecurity(msg, nil_group))
    return log(LVL_INFO, "Ignored WCCP2_HERE_I_AM with invalid security.\n");

  ServiceGroup svc(msg.m_service);
  ServiceGroup::Result r;
  GroupData &group = this->defineServiceGroup(svc, &r);
  if (ServiceGroup::CONFLICT == r)
    return logf(LVL_INFO, "WCCP2_HERE_I_AM ignored - service group %d definition does not match.\n", svc.getSvcId());
  else if (ServiceGroup::DEFINED == r)
    return logf(LVL_INFO, "Service group %d defined by WCCP2_HERE_I_AM.\n", svc.getSvcId());

  // Check if this cache is already known.
  uint32_t cache_addr = msg.m_cache_id.getAddr();
  int cache_idx;
  uint32_t cache_gen;
  CacheBag::iterator cache = group.findCache(cache_addr);
  if (cache == group.m_caches.end()) { // not known
    group.m_caches.push_back(CacheData());
    // Vector modified, need clean end value.
    cache               = group.m_caches.end() - 1;
    cache->m_recv_count = 0;
    group.resizeRouterSources();
    view_changed = true;
  } else {
    // Did the cache mention us specifically?
    // If so, make sure the sequence # is correct.
    RouterIdElt *me = msg.m_cache_view.findf_router_elt(m_addr);
    if (me && me->getRecvId() != cache->m_recv_count)
      return logf(LVL_INFO, "Discarded out of date (recv=%d, local=%ld) WCCP2_HERE_I_AM.\n", me->getRecvId(), cache->m_recv_count);
  }

  cache_gen = msg.m_cache_view.getChangeNumber();

  cache_idx = cache - group.m_caches.begin();
  cache->m_id.fill(msg.m_cache_id.cacheId());
  cache->m_recv.set(now, cache_gen);
  cache->m_pending = true;
  cache->m_to_addr = ip_hdr.m_dst;

  // Add any new routers
  i = msg.m_cache_view.getRouterCount();
  while (i-- > 0) {
    uint32_t addr            = msg.m_cache_view.routerElt(i).getAddr();
    RouterBag::iterator spot = find_by_member(group.m_routers, &RouterData::m_addr, addr);
    if (spot == group.m_routers.end()) {
      group.m_routers.push_back(RouterData());
      // Can't count on previous end value, modified container.
      spot         = group.m_routers.end() - 1;
      spot->m_addr = addr;
      spot->m_src.resize(group.m_caches.size());
      view_changed = true;
    }
    spot->m_src[cache_idx].set(now, cache_gen);
  }

  if (view_changed)
    ++(group.m_generation);
  return zret;
}

void
RouterImpl::generateISeeYou(ISeeYouMsg &msg, GroupData &group, CacheData &cache)
{
  int i;
  size_t n_routers = group.m_routers.size();
  size_t n_caches  = group.m_caches.size();

  // Not handling multi-cast so target caches is hardwired to 1.
  msg.fill(group, this->setSecurity(msg, group), group.m_assign_info, 1, n_routers, n_caches);

  // Fill in ID data not done by fill.
  msg.m_router_id.setIdElt(m_addr, cache.m_recv_count + 1).setToAddr(cache.m_to_addr).setFromAddr(0, cache.idAddr());
  ;

  // Fill view routers.
  i = 0;
  for (RouterBag::iterator router = group.m_routers.begin(), router_limit = group.m_routers.end(); router != router_limit;
       ++router, ++i) {
    msg.m_router_view.setRouterAddr(i, router->m_addr);
  }

  // Fill view caches.
  i = 0;
  for (CacheBag::iterator spot = group.m_caches.begin(), limit = group.m_caches.end(); spot != limit; ++spot, ++i) {
    // TBD: This needs to track memory because cache ID elements
    // turn out to be variable sized.
    //    msg.m_router_view.cacheId(i) = spot->m_id;
  }

  msg.finalize();
}

int
RouterImpl::xmitISeeYou()
{
  int zret = 0;
  ISeeYouMsg msg;
  MsgBuffer buffer;
  sockaddr_in dst_addr;
  time_t now                      = time(0);
  static size_t const BUFFER_SIZE = 4096;
  char *data                      = static_cast<char *>(alloca(BUFFER_SIZE));

  memset(&dst_addr, 0, sizeof(dst_addr));
  dst_addr.sin_family = AF_INET;
  dst_addr.sin_port   = htons(DEFAULT_PORT);
  buffer.set(data, BUFFER_SIZE);

  // Send out messages for each service group.
  for (GroupMap::iterator svc_spot = m_groups.begin(), svc_limit = m_groups.end(); svc_spot != svc_limit; ++svc_spot) {
    GroupData &group = svc_spot->second;

    // Check each active cache in the group.
    for (CacheBag::iterator cache = group.m_caches.begin(), cache_limit = group.m_caches.end(); cache != cache_limit; ++cache) {
      if (!cache->m_pending)
        continue;

      msg.setBuffer(buffer);
      this->generateISeeYou(msg, group, *cache);
      dst_addr.sin_addr.s_addr = cache->m_id.getAddr();
      zret                     = sendto(m_fd, data, msg.getCount(), 0, reinterpret_cast<sockaddr *>(&dst_addr), sizeof(dst_addr));
      if (0 <= zret) {
        cache->m_xmit.set(now, group.m_generation);
        cache->m_pending    = false;
        cache->m_recv_count = msg.m_router_id.getRecvId();
        logf(LVL_DEBUG, "I_SEE_YOU -> %s\n", ip_addr_to_str(cache->m_id.getAddr()));
      } else {
        log_errno(LVL_WARN, "Router transmit failed -");
        return zret;
      }
    }
  }
  return zret;
}

int
RouterImpl::housekeeping()
{
  return this->xmitISeeYou();
}

bool
RouterImpl::isConfigured() const
{
  return false;
}
// ------------------------------------------------------
EndPoint::EndPoint() {}

EndPoint::~EndPoint() {}

EndPoint::EndPoint(self const &that) : m_ptr(that.m_ptr) {}

inline EndPoint::ImplType *
EndPoint::instance()
{
  return m_ptr ? m_ptr.get() : this->make();
}

EndPoint &
EndPoint::setAddr(uint32_t addr)
{
  this->instance()->m_addr = addr;
  logf(LVL_DEBUG, "Endpoint address set to %s\n", ip_addr_to_str(addr));
  return *this;
}

bool
EndPoint::isConfigured() const
{
  return m_ptr && m_ptr->isConfigured();
}

int
EndPoint::open(uint32_t addr)
{
  return this->instance()->open(addr);
}

void
EndPoint::useMD5Security(std::string_view const key)
{
  this->instance()->useMD5Security(key);
}

int
EndPoint::getSocket() const
{
  return m_ptr ? m_ptr->m_fd : ts::NO_FD;
}

int
EndPoint::housekeeping()
{
  // Don't force an instance because if there isn't one,
  // there's no socket either.
  return m_ptr && ts::NO_FD != m_ptr->m_fd ? m_ptr->housekeeping() : -ENOTCONN;
}

ts::Rv<int>
EndPoint::handleMessage()
{
  return m_ptr ? m_ptr->handleMessage() :
                 ts::Rv<int>(-ENOTCONN, log(LVL_INFO, "EndPoint::handleMessage called on unconnected instance"));
}
// ------------------------------------------------------
Cache::Cache() {}

Cache::~Cache() {}

EndPoint::ImplType *
Cache::make()
{
  m_ptr.reset(new ImplType);
  return m_ptr.get();
}

inline Cache::ImplType *
Cache::instance()
{
  return static_cast<ImplType *>(this->super::instance());
}

inline Cache::ImplType *
Cache::impl()
{
  return static_cast<ImplType *>(m_ptr.get());
}

inline Cache::ImplType const *
Cache::impl() const
{
  return static_cast<ImplType *>(m_ptr.get());
}

Cache::Service
Cache::defineServiceGroup(ServiceGroup const &svc, ServiceGroup::Result *result)
{
  return Service(*this, this->instance()->defineServiceGroup(svc, result));
}

time_t
Cache::waitTime() const
{
  return m_ptr ? this->impl()->waitTime() : std::numeric_limits<time_t>::max();
}

Cache &
Cache::addSeedRouter(uint8_t id, uint32_t addr)
{
  this->instance()->seedRouter(id, addr);
  return *this;
}

ts::Errata
Cache::loadServicesFromFile(const char *path)
{
  return this->instance()->loadServicesFromFile(path);
}
// ------------------------------------------------------
Router::Router() {}

Router::~Router() {}

EndPoint::ImplType *
Router::make()
{
  m_ptr.reset(new ImplType);
  return m_ptr.get();
}

inline Router::ImplType *
Router::instance()
{
  return static_cast<ImplType *>(this->super::instance());
}

inline Router::ImplType *
Router::impl()
{
  return static_cast<ImplType *>(m_ptr.get());
}
// ------------------------------------------------------
} // namespace wccp
