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

/*
 * This plugin looks for range requests and then creates a new
 * cache key url so that each individual range requests is written
 * to the cache as a individual object so that subsequent range
 * requests are read across different disk drives reducing I/O
 * wait and load averages when there are large numbers of range
 * requests.
 */

#include "ts/ts.h"
#include "ts/remap.h"
#include "ts/remap_version.h"

#include <cinttypes>
#include <cstdio>
#include <cstring>
#include <getopt.h>
#include <string>
#include <string_view>

#define PLUGIN_NAME         "cache_range_requests"
#define DEBUG_LOG(fmt, ...) Dbg(dbg_ctl, fmt, ##__VA_ARGS__)
#define ERROR_LOG(fmt, ...) TSError("[%s:%d] %s(): " fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__)

// The following allows for scope based defer.
#ifndef defer
struct defer_dummy {
};
template <class F> struct deferrer {
  F f;
  ~deferrer() { f(); }
};
template <class F>
deferrer<F>
operator*(defer_dummy, F f)
{
  return {f};
}
#define DEFER_(LINE) zz_defer##LINE
#define DEFER(LINE)  DEFER_(LINE)
#define defer        auto DEFER(__LINE__) = defer_dummy{} *[&]()
#endif // defer

namespace
{
DbgCtl dbg_ctl{PLUGIN_NAME};

enum parent_select_mode_t {
  PS_DEFAULT,      // Default ATS parent selection mode
  PS_CACHEKEY_URL, // Set parent selection url to cache_key url
};

constexpr std::string_view DefaultIdentHeader = {"X-Crr-Ident"};
constexpr std::string_view SLICE_CRR_HEADER   = {"Slice-Crr-Status"};
constexpr std::string_view SLICE_CRR_VAL      = "1";
constexpr std::string_view SKIP_CRR_HDR_NAME  = {"X-Skip-Crr"};

std::string_view const Etag(TS_MIME_FIELD_ETAG, TS_MIME_LEN_ETAG);
std::string_view const LastModified(TS_MIME_FIELD_LAST_MODIFIED, TS_MIME_LEN_LAST_MODIFIED);
std::string_view const Stale{"Stale"};

struct pluginconfig {
  parent_select_mode_t ps_mode{PS_DEFAULT};
  bool                 consider_ident_header{false};
  bool                 modify_cache_key{true};
  bool                 verify_cacheability{false};
  bool                 cache_complete_responses{false};
  std::string          ident_header;
};

struct txndata {
  pluginconfig const *config{nullptr};
  std::string         range_value;
  TSHttpStatus        origin_status{TS_HTTP_STATUS_NONE};
  bool                ident_check{false};
  bool                verify_cacheability{false};
  bool                cache_complete_responses{false};
  bool                slice_response{false};
  bool                slice_request{false};
};

// pluginconfig struct (global plugin only)
pluginconfig *gPluginConfig = {nullptr};

int                  handle_read_request_header(TSCont, TSEvent, void *);
void                 range_header_check(TSHttpTxn, pluginconfig *const);
void                 handle_send_origin_request(TSCont, TSHttpTxn, txndata *const);
void                 handle_client_send_response(TSHttpTxn, txndata *const);
void                 handle_server_read_response(TSHttpTxn, txndata *const);
int                  remove_header(TSMBuffer, TSMLoc, const char *, int);
bool                 set_header(TSMBuffer, TSMLoc, const char *, int, const char *, int);
int                  transaction_handler(TSCont, TSEvent, void *);
struct pluginconfig *create_pluginconfig(int argc, char *const argv[]);
void                 delete_pluginconfig(pluginconfig *const);
static bool          has_skip_crr_header(TSHttpTxn);

/**
 * Creates pluginconfig data structure
 * Sets default parent url selection mode
 * Walk plugin argument list and updates config
 */
pluginconfig *
create_pluginconfig(int argc, char *const argv[])
{
  DEBUG_LOG("Number of arguments: %d", argc);
  for (int index = 0; index < argc; ++index) {
    DEBUG_LOG("args[%d] = %s", index, argv[index]);
  }

  pluginconfig *const pc = new pluginconfig;

  if (nullptr == pc) {
    ERROR_LOG("Can't allocate pluginconfig");
    return nullptr;
  }

  static const struct option longopts[] = {
    {const_cast<char *>("consider-ident"),           no_argument,       nullptr, 'd'},
    {const_cast<char *>("ident-header"),             required_argument, nullptr, 'j'},
    {const_cast<char *>("no-modify-cachekey"),       no_argument,       nullptr, 'n'},
    {const_cast<char *>("ps-cachekey"),              no_argument,       nullptr, 'p'},
    {const_cast<char *>("verify-cacheability"),      no_argument,       nullptr, 'v'},
    {const_cast<char *>("cache-complete-responses"), no_argument,       nullptr, 'r'},
    {nullptr,                                        0,                 nullptr, 0  },
  };

  // getopt assumes args start at '1'
  ++argc;
  --argv;

  for (;;) {
    int const opt = getopt_long(argc, argv, "j:", longopts, nullptr);
    if (-1 == opt) {
      break;
    }

    switch (opt) {
    case 'd': {
      DEBUG_LOG("Plugin considers the ident header");
      pc->consider_ident_header = true;
    } break;
    case 'j': {
      DEBUG_LOG("Plugin uses custom ident header: %s", optarg);
      pc->ident_header.assign(optarg);
      pc->consider_ident_header = true;
    } break;
    case 'n': {
      DEBUG_LOG("Plugin doesn't modify cache key");
      pc->modify_cache_key = false;
    } break;
    case 'p': {
      DEBUG_LOG("Plugin modifies parent selection key");
      pc->ps_mode = PS_CACHEKEY_URL;
    } break;
    case 'v': {
      DEBUG_LOG("Plugin verifies whether the object in the transaction is cacheable");
      pc->verify_cacheability = true;
    } break;
    case 'r': {
      DEBUG_LOG("Plugin allows complete responses (200 OK) to be cached");
      pc->cache_complete_responses = true;
    } break;
    default: {
    } break;
    }
  }

  // Backwards compatibility
  if (optind < argc && 0 == strcmp("ps_mode:cache_key_url", argv[optind])) {
    DEBUG_LOG("Plugin modifies parent selection key (deprecated)");
    pc->ps_mode = PS_CACHEKEY_URL;
  }

  if (pc->consider_ident_header && pc->ident_header.empty()) {
    pc->ident_header = DefaultIdentHeader;
    DEBUG_LOG("Plugin uses default ident header: %s", pc->ident_header.c_str());
  }

  return pc;
}

/**
 * Destroy pluginconfig data structure.
 */
void
delete_pluginconfig(pluginconfig *const pc)
{
  if (nullptr != pc) {
    DEBUG_LOG("Delete struct pluginconfig");
    delete pc;
  }
}

/**
 * Entry point when used as a global plugin.
 */
int
handle_read_request_header(TSCont /* txn_contp ATS_UNUSED */, TSEvent /* event ATS_UNUSED */, void *edata)
{
  TSHttpTxn txnp = static_cast<TSHttpTxn>(edata);

  if (!has_skip_crr_header(txnp)) {
    range_header_check(txnp, gPluginConfig);
  }

  TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
  return 0;
}

static bool
has_skip_crr_header(TSHttpTxn txnp)
{
  TSMBuffer hdr_buf = nullptr;
  TSMLoc    hdr_loc = TS_NULL_MLOC;
  bool      ret     = false;

  if (TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &hdr_buf, &hdr_loc)) {
    TSMLoc const skip_crr_loc = TSMimeHdrFieldFind(hdr_buf, hdr_loc, SKIP_CRR_HDR_NAME.data(), SKIP_CRR_HDR_NAME.length());
    if (TS_NULL_MLOC != skip_crr_loc) {
      TSHandleMLocRelease(hdr_buf, hdr_loc, skip_crr_loc);
      ret = true;
    }
    TSHandleMLocRelease(hdr_buf, TS_NULL_MLOC, hdr_loc);
  }
  return ret;
}

/**
 * Reads the client request header and if this is a range request:
 *
 * 1. creates a new cache key url using the range request information.
 * 2. Saves the range request information and then removes the range
 *    header so that the response retrieved from the origin will
 *    be written to cache.
 * 3. Schedules TS_HTTP_SEND_REQUEST_HDR_HOOK, TS_HTTP_SEND_RESPONSE_HDR_HOOK,
 *    and TS_HTTP_TXN_CLOSE_HOOK for further processing.
 */
void
range_header_check(TSHttpTxn txnp, pluginconfig *const pc)
{
  TSMBuffer hdr_buf = nullptr;
  TSMLoc    hdr_loc = TS_NULL_MLOC;

  if (TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &hdr_buf, &hdr_loc)) {
    defer
    {
      TSHandleMLocRelease(hdr_buf, TS_NULL_MLOC, hdr_loc);
    };
    TSMLoc const range_loc = TSMimeHdrFieldFind(hdr_buf, hdr_loc, TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE);
    if (TS_NULL_MLOC != range_loc) {
      defer
      {
        TSHandleMLocRelease(hdr_buf, hdr_loc, range_loc);
      };
      int               len       = 0;
      char const *const hdr_value = TSMimeHdrFieldValueStringGet(hdr_buf, hdr_loc, range_loc, 0, &len);

      if (!hdr_value || len <= 0) {
        DEBUG_LOG("Not a range request.");
      } else {
        txndata *const txn_state = new txndata;
        txn_state->range_value.assign(hdr_value, len);

        std::string const &rv = txn_state->range_value;
        DEBUG_LOG("txn_state->range_value: '%s'", rv.c_str());

        // Consider config options
        if (nullptr != pc) {
          txn_state->config         = pc;
          char cache_key_url[16384] = {0};
          int  cache_key_url_len    = 0;

          if (pc->modify_cache_key || PS_CACHEKEY_URL == pc->ps_mode) {
            int         url_len = 0;
            char *const req_url = TSHttpTxnEffectiveUrlStringGet(txnp, &url_len);
            cache_key_url_len   = snprintf(cache_key_url, sizeof(cache_key_url), "%s-%s", req_url, rv.c_str());
            DEBUG_LOG("Forming new cache URL for '%s': '%.*s'", req_url, cache_key_url_len, cache_key_url);
            if (req_url != nullptr) {
              TSfree(req_url);
            }
          }

          // Modify the cache_key
          if (pc->modify_cache_key) {
            DEBUG_LOG("Setting cache key to '%.*s'", cache_key_url_len, cache_key_url);
            if (TS_SUCCESS != TSCacheUrlSet(txnp, cache_key_url, cache_key_url_len)) {
              ERROR_LOG("Failed to change the cache url, disabling cache for this transaction to avoid cache poisoning.");
              TSHttpTxnCntlSet(txnp, TS_HTTP_CNTL_SERVER_NO_STORE, true);
              TSHttpTxnCntlSet(txnp, TS_HTTP_CNTL_RESPONSE_CACHEABLE, false);
              TSHttpTxnCntlSet(txnp, TS_HTTP_CNTL_REQUEST_CACHEABLE, false);
            }
          }

          // Set the parent_selection_url to the modified cache_key.
          if (PS_CACHEKEY_URL == pc->ps_mode) {
            TSMLoc      ps_loc = TS_NULL_MLOC;
            const char *start  = cache_key_url;
            const char *end    = cache_key_url + cache_key_url_len;
            if (TS_SUCCESS == TSUrlCreate(hdr_buf, &ps_loc)) {
              // This should always succeed.
              if (TS_PARSE_DONE == TSUrlParse(hdr_buf, ps_loc, &start, end) &&
                  TS_SUCCESS == TSHttpTxnParentSelectionUrlSet(txnp, hdr_buf, ps_loc)) {
                DEBUG_LOG("Setting Parent Selection URL to '%.*s'", cache_key_url_len, cache_key_url);
              }
              TSHandleMLocRelease(hdr_buf, TS_NULL_MLOC, ps_loc);
            }
          }

          // If not revalidating then consider the identity header
          if (pc->consider_ident_header) {
            TSMLoc const identloc = TSMimeHdrFieldFind(hdr_buf, hdr_loc, pc->ident_header.data(), pc->ident_header.size());
            if (TS_NULL_MLOC != identloc) {
              DEBUG_LOG("Servicing the '%s' header", pc->ident_header.c_str());
              txn_state->ident_check = true;
              TSHandleMLocRelease(hdr_buf, hdr_loc, identloc);
            };
          }

          txn_state->verify_cacheability      = pc->verify_cacheability;
          txn_state->cache_complete_responses = pc->cache_complete_responses;
        }

        // remove the range request header.
        if (remove_header(hdr_buf, hdr_loc, TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE) > 0) {
          DEBUG_LOG("Removed the Range: header from the request.");
        }

        // Set up the continuation
        TSCont const txn_contp = TSContCreate(transaction_handler, nullptr);
        TSContDataSet(txn_contp, txn_state);
        TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_REQUEST_HDR_HOOK, txn_contp);
        TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, txn_contp);
        TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, txn_contp);
        DEBUG_LOG("Added TS_HTTP_SEND_REQUEST_HDR_HOOK, TS_HTTP_SEND_RESPONSE_HDR_HOOK, and TS_HTTP_TXN_CLOSE_HOOK");

        if (txn_state->ident_check) {
          TSHttpTxnHookAdd(txnp, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, txn_contp);
          DEBUG_LOG("Also Added TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK");
        }

        // check if slice requests for cache lookup status
        TSMLoc const locfield(TSMimeHdrFieldFind(hdr_buf, hdr_loc, SLICE_CRR_HEADER.data(), SLICE_CRR_HEADER.size()));
        if (nullptr != locfield) {
          TSHandleMLocRelease(hdr_buf, hdr_loc, locfield);
          txn_state->slice_request = true;
        }
      }
    } else {
      DEBUG_LOG("No range request header.");
    }
  }
}

/**
 * Restores the range request header if the request must be
 * satisfied from the origin and schedules the TS_READ_RESPONSE_HDR_HOOK.
 */
void
handle_send_origin_request(TSCont contp, TSHttpTxn txnp, txndata *const txn_state)
{
  TSMBuffer hdr_buf;
  TSMLoc    hdr_loc = TS_NULL_MLOC;

  std::string const &rv = txn_state->range_value;
  if (rv.empty()) {
    ERROR_LOG("txn_state->range_value unexpectedly empty!");
    return;
  }

  if (TS_SUCCESS == TSHttpTxnServerReqGet(txnp, &hdr_buf, &hdr_loc)) {
    defer
    {
      TSHandleMLocRelease(hdr_buf, TS_NULL_MLOC, hdr_loc);
    };
    if (!rv.empty() && set_header(hdr_buf, hdr_loc, TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE, rv.data(), rv.size())) {
      DEBUG_LOG("Added range header: %s", rv.c_str());
      TSHttpTxnHookAdd(txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, contp);
    }
  }
}

/**
 * Changes the response status back to a 206 before
 * replying to the client that requested a range.
 */
void
handle_client_send_response(TSHttpTxn txnp, txndata *const txn_state)
{
  bool partial_content_reason = false;

  // Detect header modified by this plugin (200 response)
  TSMBuffer resp_buf = nullptr;
  TSMLoc    resp_loc = TS_NULL_MLOC;
  if (TS_SUCCESS == TSHttpTxnClientRespGet(txnp, &resp_buf, &resp_loc)) {
    defer
    {
      TSHandleMLocRelease(resp_buf, TS_NULL_MLOC, resp_loc);
    };

    TSHttpStatus const status = TSHttpHdrStatusGet(resp_buf, resp_loc);
    // a cached status will be 200 with expected parent response status of 206
    if (TS_HTTP_STATUS_OK == status) {
      if (txn_state->origin_status == TS_HTTP_STATUS_NONE ||
          txn_state->origin_status == TS_HTTP_STATUS_NOT_MODIFIED) { // cache hit or revalidation
        // status is always TS_HTTP_STATUS_NONE on cache hit; its value is only set during handle_server_read_response()
        TSMLoc const content_range_loc =
          TSMimeHdrFieldFind(resp_buf, resp_loc, TS_MIME_FIELD_CONTENT_RANGE, TS_MIME_LEN_CONTENT_RANGE);

        if (TS_NULL_MLOC != content_range_loc) {
          DEBUG_LOG("Got TS_HTTP_STATUS_OK on cache hit or revalidation and Content-Range header present in response");
          partial_content_reason = true;
          TSHandleMLocRelease(resp_buf, resp_loc, content_range_loc);
        } else {
          DEBUG_LOG("Got TS_HTTP_STATUS_OK on cache hit and Content-Range header is NOT present in response");
        }
      } else if (txn_state->origin_status ==
                 TS_HTTP_STATUS_PARTIAL_CONTENT) { // only set on cache miss in handle_server_read_response()
        DEBUG_LOG("Got TS_HTTP_STATUS_OK with origin TS_HTTP_STATUS_PARTIAL_CONTENT");
        partial_content_reason = true;
      } else {
        DEBUG_LOG("Allowing TS_HTTP_STATUS_OK in response due to origin status code %d", txn_state->origin_status);
      }

      if (partial_content_reason) {
        DEBUG_LOG("Restoring response header to TS_HTTP_STATUS_PARTIAL_CONTENT.");
        TSHttpHdrStatusSet(resp_buf, resp_loc, TS_HTTP_STATUS_PARTIAL_CONTENT);
      }

      remove_header(resp_buf, resp_loc, SLICE_CRR_HEADER.data(), SLICE_CRR_HEADER.size());
      if (txn_state->slice_response) {
        set_header(resp_buf, resp_loc, SLICE_CRR_HEADER.data(), SLICE_CRR_HEADER.size(), SLICE_CRR_VAL.data(),
                   SLICE_CRR_VAL.size());
      }
    } else {
      DEBUG_LOG("Ignoring status code %d; txn_state->origin_status=%d", status, txn_state->origin_status);
    }
  }

  if (partial_content_reason) {
    DEBUG_LOG("Attempting to restore the Range header");
    std::string const &rv = txn_state->range_value;
    // Restore the range request header
    if (!rv.empty()) {
      TSMBuffer req_buf = nullptr;
      TSMLoc    req_loc = TS_NULL_MLOC;
      if (TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &req_buf, &req_loc)) {
        DEBUG_LOG("Adding range header: %s", rv.c_str());
        if (!set_header(req_buf, req_loc, TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE, rv.data(), rv.size())) {
          DEBUG_LOG("set_header() failed.");
        }
        TSHandleMLocRelease(req_buf, TS_NULL_MLOC, req_loc);
      }
    }
  }
}

/**
 * After receiving a range request response from the origin, change
 * the response status from a 206 to a 200 so that
 * the response will be written to cache.
 */
void
handle_server_read_response(TSHttpTxn txnp, txndata *const txn_state)
{
  TSMBuffer resp_buf = nullptr;
  TSMLoc    resp_loc = TS_NULL_MLOC;
  int       cache_lookup;

  if (TS_SUCCESS != TSHttpTxnServerRespGet(txnp, &resp_buf, &resp_loc)) {
    return;
  }

  defer
  {
    TSHandleMLocRelease(resp_buf, TS_NULL_MLOC, resp_loc);
  };

  TSHttpStatus const status = TSHttpHdrStatusGet(resp_buf, resp_loc);
  txn_state->origin_status  = status;
  if (TS_HTTP_STATUS_PARTIAL_CONTENT == status) {
    DEBUG_LOG("Got TS_HTTP_STATUS_PARTIAL_CONTENT.");
    // changing the status code from 206 to 200 forces the object into cache
    TSHttpHdrStatusSet(resp_buf, resp_loc, TS_HTTP_STATUS_OK);
    DEBUG_LOG("Set response header to TS_HTTP_STATUS_OK.");

    if (txn_state->verify_cacheability && !TSHttpTxnIsCacheable(txnp, nullptr, resp_buf)) {
      DEBUG_LOG("transaction is not cacheable; resetting status code to 206");
      TSHttpHdrStatusSet(resp_buf, resp_loc, TS_HTTP_STATUS_PARTIAL_CONTENT);
    }
  } else if (TS_HTTP_STATUS_OK == status) {
    bool cacheable = txn_state->cache_complete_responses;

    if (cacheable && txn_state->verify_cacheability) {
      DEBUG_LOG("Received a cacheable complete response from the origin; verifying cacheability");
      cacheable = TSHttpTxnIsCacheable(txnp, nullptr, resp_buf);
    }

    // 200s are cached by default; only cache if configured to do so
    if (!cacheable && TS_SUCCESS == TSHttpTxnCntlSet(txnp, TS_HTTP_CNTL_SERVER_NO_STORE, true)) {
      DEBUG_LOG("Cache write has been disabled for this transaction.");
    } else {
      DEBUG_LOG("Allowing object to be cached.");
    }
  }

  // slice requesting cache lookup status and cacheability (only on miss or validation)
  if ((txn_state->origin_status == TS_HTTP_STATUS_PARTIAL_CONTENT || txn_state->origin_status == TS_HTTP_STATUS_NOT_MODIFIED) &&
      txn_state->slice_request && TSHttpTxnIsCacheable(txnp, nullptr, resp_buf) &&
      TSHttpTxnCacheLookupStatusGet(txnp, &cache_lookup) == TS_SUCCESS &&
      (cache_lookup == TS_CACHE_LOOKUP_MISS || cache_lookup == TS_CACHE_LOOKUP_HIT_STALE)) {
    txn_state->slice_response = true;
  }
}

/**
 * Remove a header (fully) from an TSMLoc / TSMBuffer. Return the number
 * of fields (header values) we removed.
 *
 * From background_fetch.cc
 */
int
remove_header(TSMBuffer buf, TSMLoc hdr_loc, const char *header, int len)
{
  TSMLoc field = TSMimeHdrFieldFind(buf, hdr_loc, header, len);
  int    cnt   = 0;

  while (TS_NULL_MLOC != field) {
    TSMLoc const tmp = TSMimeHdrFieldNextDup(buf, hdr_loc, field);
    ++cnt;
    TSMimeHdrFieldDestroy(buf, hdr_loc, field);
    TSHandleMLocRelease(buf, hdr_loc, field);
    field = tmp;
  }

  return cnt;
}

/**
 * Set a header to a specific value. This will avoid going to through a
 * remove / add sequence in case of an existing header.
 * but clean.
 *
 * From background_fetch.cc
 */
bool
set_header(TSMBuffer buf, TSMLoc hdr_loc, const char *header, int len, const char *val, int val_len)
{
  if (nullptr == buf || TS_NULL_MLOC == hdr_loc || nullptr == header || len <= 0 || nullptr == val || val_len <= 0) {
    return false;
  }

  DEBUG_LOG("header: %s, len: %d, val: %s, val_len: %d", header, len, val, val_len);
  bool   ret       = false;
  TSMLoc field_loc = TSMimeHdrFieldFind(buf, hdr_loc, header, len);

  if (TS_NULL_MLOC == field_loc) {
    // No existing header, so create one
    if (TS_SUCCESS == TSMimeHdrFieldCreateNamed(buf, hdr_loc, header, len, &field_loc)) {
      if (TS_SUCCESS == TSMimeHdrFieldValueStringSet(buf, hdr_loc, field_loc, -1, val, val_len)) {
        TSMimeHdrFieldAppend(buf, hdr_loc, field_loc);
        ret = true;
      }
      TSHandleMLocRelease(buf, hdr_loc, field_loc);
    }
  } else {
    bool first = true;

    while (TS_NULL_MLOC != field_loc) {
      TSMLoc const tmp = TSMimeHdrFieldNextDup(buf, hdr_loc, field_loc);
      if (first) {
        first = false;
        if (TS_SUCCESS == TSMimeHdrFieldValueStringSet(buf, hdr_loc, field_loc, -1, val, val_len)) {
          ret = true;
        }
      } else {
        TSMimeHdrFieldDestroy(buf, hdr_loc, field_loc);
      }
      TSHandleMLocRelease(buf, hdr_loc, field_loc);
      field_loc = tmp;
    }
  }

  return ret;
}

void
debugTxnUrl(TSHttpTxn const txnp, std::string_view const desc, std::string const &rangeval)
{
  int         url_len = 0;
  char *const req_url = TSHttpTxnEffectiveUrlStringGet(txnp, &url_len);
  if (nullptr != req_url) {
    DEBUG_LOG("%.*s: %.*s-%s", (int)desc.length(), desc.data(), url_len, req_url, rangeval.c_str());
    TSfree(req_url);
  }
}

/**
 * Handle the identity/validator check.
 * Based on RFC7232 and HttpTransactCache::match_response_to_request_conditionals
 * Compare ETAG if provided.
 * else Compare Last-Modified if provided.
 */
void
handle_cache_lookup_complete(TSHttpTxn txnp, txndata *const txn_state)
{
  TSAssert(txn_state->ident_check);
  int cachestat;
  if (TS_SUCCESS == TSHttpTxnCacheLookupStatusGet(txnp, &cachestat)) {
    if (TS_CACHE_LOOKUP_HIT_FRESH != cachestat && TS_CACHE_LOOKUP_HIT_STALE != cachestat) {
      return;
    }

    // ensure the cached response is a 200
    TSMBuffer cbuf  = nullptr;
    TSMLoc    chloc = TS_NULL_MLOC;
    if (TSHttpTxnCachedRespGet(txnp, &cbuf, &chloc) != TS_SUCCESS) {
      return;
    }

    defer
    {
      TSHandleMLocRelease(cbuf, TS_NULL_MLOC, chloc);
    };

    if (TS_HTTP_STATUS_OK != TSHttpHdrStatusGet(cbuf, chloc)) {
      return;
    }

    pluginconfig const *const pc = txn_state->config;

    // request identifier/validator
    TSMBuffer rbuf  = nullptr;
    TSMLoc    rhloc = TS_NULL_MLOC;
    if (TS_SUCCESS != TSHttpTxnClientReqGet(txnp, &rbuf, &rhloc)) {
      return;
    }

    defer
    {
      TSHandleMLocRelease(rbuf, TS_NULL_MLOC, rhloc);
    };

    // No directive found (should not happen)
    TSMLoc const riloc = TSMimeHdrFieldFind(rbuf, rhloc, pc->ident_header.data(), pc->ident_header.size());
    if (TS_NULL_MLOC == riloc) {
      return;
    }
    defer
    {
      TSHandleMLocRelease(rbuf, rhloc, riloc);
    };

    int               rilen = 0;
    char const *const ristr = TSMimeHdrFieldValueStringGet(rbuf, rhloc, riloc, -1, &rilen);
    if (0 == rilen) {
      return;
    }

    // pull the identifier from the request header
    std::string_view rident(ristr, rilen);
    std::string_view rtag;
    if (rident.substr(0, Etag.length()) == Etag) {
      DEBUG_LOG("Etag identifier provided in '%.*s'", rilen, ristr);
      rtag   = Etag;
      rident = rident.substr(Etag.length() + 1);
    } else if (rident.substr(0, LastModified.length()) == LastModified) {
      DEBUG_LOG("Last-Modified indentifier provided in '%.*s'", rilen, ristr);
      rtag   = LastModified;
      rident = rident.substr(LastModified.length() + 1);
    } else if (rident.substr(0, Stale.length()) == Stale) {
      // note tag isn't set here
      if (TS_CACHE_LOOKUP_HIT_FRESH == cachestat) {
        TSHttpTxnCacheLookupStatusSet(txnp, TS_CACHE_LOOKUP_HIT_STALE);
        if (dbg_ctl.on()) {
          debugTxnUrl(txnp, "force to stale", txn_state->range_value);
        }
      }
      return;
    } else {
      DEBUG_LOG("Unknown indentifier provided in '%.*s'", rilen, ristr);
      return;
    }

    // pull the identifier from the cached response
    // first priority is etag
    std::string_view ctag  = Etag;
    TSMLoc           ciloc = TSMimeHdrFieldFind(cbuf, chloc, ctag.data(), ctag.length());
    if (TS_NULL_MLOC == ciloc) {
      ctag  = LastModified;
      ciloc = TSMimeHdrFieldFind(cbuf, chloc, ctag.data(), ctag.length());
      if (TS_NULL_MLOC == ciloc) {
        return;
      }
    }

    defer
    {
      TSHandleMLocRelease(cbuf, chloc, ciloc);
    };

    int               cilen = 0;
    char const *const cistr = TSMimeHdrFieldValueStringGet(cbuf, chloc, ciloc, -1, &cilen);
    if (0 == cilen) {
      return;
    }
    std::string_view cident(cistr, cilen);

    // fresh to stale with ident mismatch
    if (TS_CACHE_LOOKUP_HIT_FRESH == cachestat) {
      if (rtag != ctag || rident != cident) {
        TSHttpTxnCacheLookupStatusSet(txnp, TS_CACHE_LOOKUP_HIT_STALE);
        if (dbg_ctl.on()) {
          debugTxnUrl(txnp, "flip to stale", txn_state->range_value);
        }
      }
      // stale to fresh with ident match
    } else if (TS_CACHE_LOOKUP_HIT_STALE == cachestat) {
      if (rtag == ctag && rident == cident) {
        TSHttpTxnCacheLookupStatusSet(txnp, TS_CACHE_LOOKUP_HIT_FRESH);
        if (dbg_ctl.on()) {
          debugTxnUrl(txnp, "flip to fresh", txn_state->range_value);
        }
      }
    }
  }
}

/**
 * Transaction event handler.
 */
int
transaction_handler(TSCont contp, TSEvent event, void *edata)
{
  TSHttpTxn      txnp      = static_cast<TSHttpTxn>(edata);
  txndata *const txn_state = static_cast<txndata *>(TSContDataGet(contp));

  switch (event) {
  case TS_EVENT_HTTP_READ_RESPONSE_HDR:
    handle_server_read_response(txnp, txn_state);
    break;
  case TS_EVENT_HTTP_SEND_REQUEST_HDR:
    handle_send_origin_request(contp, txnp, txn_state);
    break;
  case TS_EVENT_HTTP_SEND_RESPONSE_HDR:
    handle_client_send_response(txnp, txn_state);
    break;
  case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE:
    handle_cache_lookup_complete(txnp, txn_state);
    break;
  case TS_EVENT_HTTP_TXN_CLOSE:
    if (txn_state != nullptr) {
      TSContDataSet(contp, nullptr);
      delete txn_state;
    }
    TSContDestroy(contp);
    break;
  default:
    TSAssert(!"Unexpected event");
    break;
  }
  TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
  return 0;
}

} // namespace

/**
 * Remap initialization.
 */
TSReturnCode
TSRemapInit(TSRemapInterface *api_info, char *errbuf, int errbuf_size)
{
  CHECK_REMAP_API_COMPATIBILITY(api_info, errbuf, errbuf_size);
  DEBUG_LOG("cache_range_requests remap is successfully initialized.");
  return TS_SUCCESS;
}

/**
 * New Remap instance
 */
TSReturnCode
TSRemapNewInstance(int argc, char *argv[], void **ih, char * /*errbuf */, int /* errbuf_size */)
{
  if (argc < 2) {
    ERROR_LOG("Remap argument list should contain at least 2 params"); // Should never happen..
    return TS_ERROR;
  }

  // Skip over the Remap params
  char *const *plugin_argv = const_cast<char *const *>(argv);

  // Parse the argument list.
  *ih = static_cast<void *>(create_pluginconfig(argc - 2, plugin_argv + 2));

  if (*ih == nullptr) {
    ERROR_LOG("Can't create pluginconfig");
  }

  return TS_SUCCESS;
}

/**
 * Delete Remap instance
 */
void
TSRemapDeleteInstance(void *ih)
{
  pluginconfig *const pc = static_cast<pluginconfig *>(ih);

  if (nullptr != pc) {
    delete_pluginconfig(pc);
  }
}

/**
 * Remap entry point.
 */
TSRemapStatus
TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo * /* rri */)
{
  pluginconfig *const pc = static_cast<pluginconfig *>(ih);

  if (!has_skip_crr_header(txnp)) {
    range_header_check(txnp, pc);
  }

  return TSREMAP_NO_REMAP;
}

/**
 * Global plugin initialization.
 */
void
TSPluginInit(int argc, const char *argv[])
{
  TSPluginRegistrationInfo info;
  TSCont                   txnp_cont;

  info.plugin_name   = (char *)PLUGIN_NAME;
  info.vendor_name   = (char *)"Comcast";
  info.support_email = (char *)"John_Rushford@cable.comcast.com";

  if (TSPluginRegister(&info) != TS_SUCCESS) {
    ERROR_LOG("Plugin registration failed.\n");
    ERROR_LOG("Unable to initialize plugin (disabled).");
    return;
  }

  if (nullptr == gPluginConfig) {
    if (1 < argc) {
      char *const *plugin_argv = const_cast<char *const *>(argv);
      gPluginConfig            = create_pluginconfig(argc - 1, plugin_argv + 1);
    }
  }

  if (nullptr == (txnp_cont = TSContCreate(static_cast<TSEventFunc>(handle_read_request_header), nullptr))) {
    ERROR_LOG("failed to create the transaction continuation handler.");
    return;
  } else {
    TSHttpHookAdd(TS_HTTP_POST_REMAP_HOOK, txnp_cont);
  }
}
