33#include "mem/forward.h"
151 const char *
uri =
nullptr;
244#define N_QUERIED_KEYS 8192
255static ssize_t
htcpBuildCountstr(
char *buf,
size_t buflen,
const char *s,
size_t len);
267static void htcpRecv(
int fd,
void *data);
297 debugs(31, 3,
"htcpHexdump " << tag);
298 memset(hex,
'\0',
sizeof(hex));
300 for (
int i = 0; i < sz; ++i) {
302 snprintf(&hex[k * 3], 4,
" %02x", (
int) *(s + i));
304 if (k < 15 && i < (sz - 1))
307 debugs(31, 3,
"\t" << hex);
309 memset(hex,
'\0',
sizeof(hex));
319parseUint16(
const char *
const buf,
const int sz, uint16_t &out,
const char *
const field)
322 debugs(31, 3,
"too short for " << field);
326 memcpy(&out, buf, 2);
340 assert(2 ==
sizeof(uint16_t));
343 if (buflen < copy_sz)
345 memcpy(buf, &auth, copy_sz);
354 if (buflen -
off < 2)
357 debugs(31, 3,
"htcpBuildCountstr: LENGTH = " << len);
359 debugs(31, 3,
"htcpBuildCountstr: TEXT = {" << (s ? s :
"<NULL>") <<
"}");
361 uint16_t length = htons((uint16_t) len);
363 memcpy(buf +
off, &length, 2);
367 if (buflen -
off < len)
371 memcpy(buf +
off, s, len);
411 debugs(31, 3,
"htcpBuildSpecifier: size " <<
off);
451 debugs(31, 3,
"htcpBuildTstOpData: RR_REQUEST");
455 debugs(31, 3,
"htcpBuildTstOpData: RR_RESPONSE");
456 debugs(31, 3,
"htcpBuildTstOpData: F1 = " << stuff->
f1);
464 fatal_dump(
"htcpBuildTstOpData: bad RR value");
473 unsigned short reason;
477 debugs(31, 3,
"htcpBuildClrOpData: RR_REQUEST");
478 reason = htons((
unsigned short)stuff->
reason);
481 memcpy(buf, &reason, 2);
491 fatal_dump(
"htcpBuildClrOpData: bad RR value");
540 debugs(31, 3,
"htcpBuildData: hdr.length = " <<
off);
544 memset(&hdr, 0,
sizeof(hdr));
547 hdr.
length = htons(
static_cast<uint16_t
>(
off));
552 memcpy(buf, &hdr, hdr_sz);
555 memset(&hdrSquid, 0,
sizeof(hdrSquid));
556 hdrSquid.
length = htons(
static_cast<uint16_t
>(
off));
559 hdrSquid.
F1 = stuff->
f1;
560 hdrSquid.
RR = stuff->
rr;
561 memcpy(buf, &hdrSquid, hdr_sz);
564 debugs(31, 3,
"htcpBuildData: size " <<
off);
582 if (buflen < hdr_sz) {
609 memcpy(buf, &hdr, hdr_sz);
611 debugs(31, 3,
"htcpBuildPacket: size " <<
off);
651 debugs(31, 3,
"htcpUnpackSpecifier: failed to unpack METHOD");
659 debugs(31, 6,
"htcpUnpackSpecifier: METHOD (" << l <<
"/" << sz <<
") '" << s->method <<
"'");
668 debugs(31, 3,
"htcpUnpackSpecifier: failed to unpack URI");
680 debugs(31, 6,
"htcpUnpackSpecifier: URI (" << l <<
"/" << sz <<
") '" << s->uri <<
"'");
689 debugs(31, 3,
"htcpUnpackSpecifier: failed to unpack VERSION");
701 debugs(31, 6,
"htcpUnpackSpecifier: VERSION (" << l <<
"/" << sz <<
") '" << s->version <<
"'");
710 debugs(31, 3,
"htcpUnpackSpecifier: failed to unpack REQ-HDRS");
723 debugs(31, 6,
"htcpUnpackSpecifier: REQ-HDRS (" << l <<
"/" << sz <<
") '" << s->req_hdrs <<
"'");
725 debugs(31, 3,
"htcpUnpackSpecifier: " << sz <<
" bytes left");
737 const auto mx = MasterXaction::MakePortless<XactionInitiator::initHtcp>();
740 debugs(31, 3,
"failed to create request. Invalid URI?");
754 auto d = std::make_unique<htcpDetail>();
765 debugs(31, 3,
"htcpUnpackDetail: failed to unpack RESP_HDRS");
776 if (!
parseUint16(buf, sz, l,
"ENTITY-HDRS length"))
782 debugs(31, 3,
"htcpUnpackDetail: failed to unpack ENTITY_HDRS");
792 d->entity_hdrs = buf;
804 debugs(31, 3,
"htcpUnpackDetail: failed to unpack CACHE_HDRS");
819 debugs(31, 3,
"htcpUnpackDetail: " << sz <<
" bytes left");
847 static char pkt[8192];
900 snprintf(cto_buf,
sizeof(cto_buf),
"%s %d %f %d",
901 host, samp, 0.001 * rtt, hops);
902 hdr.
putExt(
"Cache-to-Origin", cto_buf);
925 debugs(31, 3,
"htcpTstReply: htcpBuildPacket() failed");
936 static char pkt[8192];
946 stuff.
response = purgeSucceeded ? 0 : 2;
953 debugs(31, 3,
"htcpClrReply: htcpBuildPacket() failed");
971 return mx->id.detach();
985 return os <<
Debug::Extra <<
"current master transaction: " << mx->id;
998 debugs(31, 3,
"htcpCheckHit: NO; failed to parse URL");
1004 debugs(31, 3,
"htcpCheckHit: NO; failed to parse request headers");
1014 debugs(31, 3,
"NO; public object not found");
1015 }
else if (!e->validToSend()) {
1016 debugs(31, 3,
"NO; entry not valid to send" );
1018 debugs(31, 3,
"NO; prohibited CF hit: " << *e);
1020 debugs(31, 3,
"NO; cached response is stale");
1053 debugs(31, 4,
"htcpClrStoreEntry: Clearing store for entry: " << e->
url() );
1062 debugs(31, 3,
"htcpClrStore: failed to parse URL");
1067 if (!request->
parseHeader(s->req_hdrs, s->reqHdrsSz)) {
1068 debugs(31, 2,
"htcpClrStore: failed to parse request headers");
1081 debugs(31, 4,
"htcpClrStore: Cleared " << released <<
" matching entries");
1084 debugs(31, 4,
"htcpClrStore: No matching entry found");
1093 debugs(31, 3,
"htcpHandleTst: sz = " << sz);
1104 memset(&
cto, 0,
sizeof(
cto));
1127 debugs(31, 2,
"htcpHandleTstResponse: No matching query id '" <<
1128 hdr->
msg_id <<
"' (expected " <<
1138 debugs(31, 3,
"htcpHandleTstResponse: No query key for response id '" << hdr->
msg_id <<
"' from '" << from <<
"'");
1144 if ( *peer != from || peer->
port() != from.
port() ) {
1145 debugs(31, 3,
"htcpHandleTstResponse: Unexpected response source " << from );
1150 debugs(31, 2,
"htcpHandleTstResponse: error condition, F1/MO == 1");
1155 debugs(31, 3,
"htcpHandleTstResponse: msg_id = " << htcpReply.
msg_id);
1159 debugs(31, 3,
"htcpHandleTstResponse: MISS");
1161 debugs(31, 3,
"htcpHandleTstResponse: HIT");
1165 debugs(31, 3,
"htcpHandleTstResponse: bad DETAIL");
1190 debugs(31, 3,
"htcpHandleTst: nothing to do");
1201 debugs(31, 3,
"htcpHandleTstRequest: htcpUnpackSpecifier failed");
1206 s->setDataHeader(dhdr);
1210 debugs(31, 3,
"htcpHandleTstRequest: failed to parse request");
1216 debugs(31, 3,
"htcpHandleTstRequest: Access denied");
1221 debugs(31, 2,
"HTCP TST request: " << s->method <<
" " << s->uri <<
" " << s->version);
1222 debugs(31, 2,
"HTCP TST headers: " << s->req_hdrs);
1243 debugs(31, 4,
"too short for reserved+reason fields (sz=" << sz <<
")");
1247 int reason =
static_cast<unsigned char>(buf[1]) << 4;
1248 debugs(31, 2,
"HTCP CLR reason: " << reason);
1250 const auto specifierStart = buf + 2;
1251 const auto specifierSize = sz - 2;
1254 debugs(31, 4,
"nothing to do");
1262 debugs(31, 3,
"htcpUnpackSpecifier failed");
1267 s->setDataHeader(hdr);
1271 debugs(31, 3,
"failed to parse request");
1277 debugs(31, 3,
"Access denied");
1282 debugs(31, 2,
"HTCP CLR request: " << s->method <<
" " << s->uri <<
" " << s->version);
1283 debugs(31, 2,
"HTCP CLR headers: " << s->req_hdrs);
1309 if (!p->options.htcp) {
1312 if (!p->options.htcp_forward_clr) {
1338 if (sz < 0 || (
size_t)sz <
sizeof(
htcpHeader)) {
1340 debugs(31, 2,
"htcpHandle: msg size less than htcpHeader size from " << from);
1348 if (htcpHdr.
minor == 0)
1353 debugs(31, 3,
"htcpHandle: htcpHdr.length = " << htcpHdr.
length);
1354 debugs(31, 3,
"htcpHandle: htcpHdr.major = " << htcpHdr.
major);
1355 debugs(31, 3,
"htcpHandle: htcpHdr.minor = " << htcpHdr.
minor);
1357 if (sz != htcpHdr.
length) {
1358 debugs(31, 3,
"htcpHandle: sz/" << sz <<
" != htcpHdr.length/" <<
1359 htcpHdr.
length <<
" from " << from );
1364 if (htcpHdr.
major != 0) {
1365 debugs(31, 3,
"htcpHandle: Unknown major version " << htcpHdr.
major <<
" from " << from );
1374 debugs(31, 3,
"htcpHandleData: msg size less than htcpDataHeader size");
1379 memcpy(&hdr, hbuf,
sizeof(hdr));
1384 memset(&hdrSquid, 0,
sizeof(hdrSquid));
1395 hdr.
F1 = hdrSquid.
F1;
1396 hdr.
RR = hdrSquid.
RR;
1403 debugs(31, 3,
"htcpHandleData: hsz = " << hsz);
1404 debugs(31, 3,
"htcpHandleData: length = " << hdr.
length);
1407 debugs(31, 3,
"htcpHandleData: client " << from <<
", opcode " << hdr.
opcode <<
" out of range");
1413 debugs(31, 3,
"htcpHandleData: F1 = " << hdr.
F1);
1414 debugs(31, 3,
"htcpHandleData: RR = " << hdr.
RR);
1415 debugs(31, 3,
"htcpHandleData: msg_id = " << hdr.
msg_id);
1424 debugs(31, 3,
"htcpHandleData: sz < hdr.length");
1435 debugs(31, 3,
"htcpHandleData: hsz = " << hsz);
1441 debugs(31, 3,
"HTCP NOP not implemented");
1447 debugs(31, 3,
"HTCP MON not implemented");
1450 debugs(31, 3,
"HTCP SET not implemented");
1463 static char buf[8192];
1471 debugs(31, 3,
"htcpRecv: FD " << fd <<
", " << len <<
" bytes from " << from );
1498 fatal(
"HTCP port cannot be opened.");
1518 fatal(
"HTCP port cannot be opened.");
1530 fatal(
"Cannot open Outgoing HTCP Socket");
1542 const auto &conn = answer.
conn;
1545 fatal(
"Cannot open HTCP Socket");
1561 static char pkt[8192];
1571 snprintf(vbuf,
sizeof(vbuf),
"%d/%d",
1577 stuff.
S.
uri = (
char *) e->
url();
1588 debugs(31, 3,
"htcpQuery: htcpBuildPacket() failed");
1609 static char pkt[8192];
1620 snprintf(vbuf,
sizeof(vbuf),
"%d/%d",
1647 debugs(31, 3,
"htcpClear: htcpBuildPacket() failed");
void accessLogLog(const AccessLogEntryPointer &, ACLChecklist *)
#define asyncCallbackFun(dbgSection, dbgLevel, function)
AsyncCall for calling back a function.
const CachePeers & CurrentCachePeers()
#define DefineRunnerRegistrator(ClassName)
Acl::Answer const & fastCheck()
void setRequest(HttpRequest *)
configure client request-related fields for the first time
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
struct timeval start_time
The time the master transaction started.
struct timeval trTime
The response time.
class AccessLogEntry::CacheDetails cache
class AccessLogEntry::HtcpDetails htcp
void setVirginUrlForMissingRequest(const SBuf &vu)
Remember Client URI (or equivalent) when there is no HttpRequest.
ScopedId codeContextGist() const override
std::ostream & detailCodeContext(std::ostream &os) const override
appends human-friendly context description line(s) to a cache.log record
unsigned int major
major version number
unsigned int minor
minor version number
void host(const char *src)
struct CachePeer::@20 options
static std::ostream & Extra(std::ostream &)
struct HtcpReplyData::cto_t cto
bool parseHeader(const char *buffer, const size_t size)
parses request header from the buffer
void useConfig() override
void startReconfigure() override
void syncConfig() override
void startShutdown() override
void HttpRequestMethodXXX(char const *)
const SBuf & image() const
MasterXaction::Pointer masterXaction
the master transaction this request belongs to. Never nil.
static HttpRequest * FromUrlXXX(const char *url, const MasterXaction::Pointer &, const HttpRequestMethod &method=Http::METHOD_GET)
bool parseHeader(Http1::Parser &hp)
AnyP::Uri url
the request URI
const SBuf & effectiveRequestUri() const
RFC 7230 section 5.5 - Effective Request URI.
static void httpBuildRequestHeader(HttpRequest *request, StoreEntry *entry, const AccessLogEntryPointer &al, HttpHeader *hdr_out, const CachePeer *peer, const Http::StateFlags &flags)
AnyP::ProtocolVersion http_ver
unsigned short port() const
Comm::ConnectionPointer conn
opened listening socket
void init(mb_size_t szInit, mb_size_t szMax)
mb_size_t contentSize() const
available data size
struct SquidConfig::@85 Addrs
struct SquidConfig::@90 onoff
struct SquidConfig::@91 accessList
struct SquidConfig::@78 Port
struct StatCounters::@107 htcp
a storeGetPublic*() caller
bool didCollapse
whether startCollapsingOn() was called and returned true
bool startCollapsingOn(const StoreEntry &, const bool doingRevalidation) const
void lastModified(const time_t when)
void releaseRequest(const bool shareable=false)
MEMPROXY_CLASS(htcpDetail)
MEMPROXY_CLASS(htcpSpecifier)
void setDataHeader(htcpDataHeader *aDataHeader)
HttpRequest::Pointer checkHitRequest
void checkedHit(StoreEntry *)
ScopedId codeContextGist() const override
std::ostream & detailCodeContext(std::ostream &os) const override
appends human-friendly context description line(s) to a cache.log record
AccessLogEntryPointer al
optimization: nil until needed
void setFrom(Ip::Address &anIp)
RefCount< htcpSpecifier > Pointer
size_t reqHdrsSz
size of the req_hdrs content
LogTags * loggingTags() const override
HttpRequest::Pointer request
void fillChecklist(ACLFilledChecklist &) const override
configure the given checklist (to reflect the current transaction state)
htcpStuff(uint32_t id, int o, int r, int f)
int comm_udp_sendto(int fd, const Ip::Address &to_addr, const void *buf, int len)
void comm_open_listener(int sock_type, int proto, Comm::ConnectionPointer &conn, const char *note)
int comm_udp_recvfrom(int fd, void *buf, size_t len, int flags, Ip::Address &from)
#define debugs(SECTION, LEVEL, CONTENT)
void fatal(const char *message)
void fatal_dump(const char *message)
static void htcpSyncAle(AccessLogEntryPointer &al, const Ip::Address &caddr, const int opcode, const char *url)
static Ip::Address queried_addr[N_QUERIED_KEYS]
static ssize_t htcpBuildCountstr(char *buf, size_t buflen, const char *s, size_t len)
static void htcpTstReply(htcpDataHeader *, StoreEntry *, htcpSpecifier *, Ip::Address &)
@ MAJOR_VERSION_UNSUPPORTED
@ MINOR_VERSION_UNSUPPORTED
static void htcpSocketShutdown()
static void htcpSend(const char *buf, int len, Ip::Address &to)
static void htcpHandleTst(htcpDataHeader *, char *buf, int sz, Ip::Address &from)
static void htcpHandleMsg(char *buf, int sz, Ip::Address &from)
static uint32_t queried_id[N_QUERIED_KEYS]
static void htcpClrStoreEntry(StoreEntry *e)
static void htcpRecv(int fd, void *data)
static ssize_t htcpBuildOpData(char *buf, size_t buflen, htcpStuff *stuff)
int htcpQuery(StoreEntry *e, HttpRequest *req, CachePeer *p)
static void htcpHandleTstResponse(htcpDataHeader *, char *, int, Ip::Address &)
static int htcpClrStore(const htcpSpecifier::Pointer &s)
static cache_key queried_keys[N_QUERIED_KEYS][SQUID_MD5_DIGEST_LENGTH]
static ssize_t htcpBuildClrOpData(char *buf, size_t buflen, htcpStuff *stuff)
static int old_squid_format
static Comm::ConnectionPointer htcpOutgoingConn
static ssize_t htcpBuildSpecifier(char *buf, size_t buflen, htcpStuff *stuff)
static void htcpClosePorts()
static void htcpClrReply(htcpDataHeader *dhdr, int purgeSucceeded, Ip::Address &from)
static Comm::ConnectionPointer htcpIncomingConn
static bool htcpAccessAllowed(acl_access *acl, const htcpSpecifier::Pointer &s, Ip::Address &from)
static const char *const htcpOpcodeStr[]
static bool parseUint16(const char *const buf, const int sz, uint16_t &out, const char *const field)
struct _htcpHeader htcpHeader
void htcpClear(StoreEntry *e, HttpRequest *req, const HttpRequestMethod &, CachePeer *p, htcp_clr_reason reason)
static void htcpHandleClr(htcpDataHeader *const hdr, char *const buf, const int sz, Ip::Address &from)
static ssize_t htcpBuildDetail(char *buf, size_t buflen, htcpStuff *stuff)
static ssize_t htcpBuildTstOpData(char *buf, size_t buflen, htcpStuff *stuff)
static ssize_t htcpBuildPacket(char *buf, size_t buflen, htcpStuff *stuff)
struct _htcpDataHeader htcpDataHeader
static void htcpLogHtcp(Ip::Address &, const int, const LogTags_ot, const char *, AccessLogEntryPointer)
static htcpDetail * htcpUnpackDetail(char *buf, int sz)
static void htcpIncomingConnectionOpened(Ipc::StartListeningAnswer &)
static void htcpOpenPorts()
static ssize_t htcpBuildAuth(char *buf, size_t buflen)
static void htcpHandleTstRequest(htcpDataHeader *, char *buf, int sz, Ip::Address &from)
static void htcpHexdump(const char *tag, const char *s, int sz)
static uint32_t msg_id_counter
static htcpSpecifier::Pointer htcpUnpackSpecifier(char *buf, int sz)
static ssize_t htcpBuildData(char *buf, size_t buflen, htcpStuff *stuff)
void neighborsHtcpReply(const cache_key *, HtcpReplyData *, const Ip::Address &)
#define SQUID_MD5_DIGEST_LENGTH
bool IsConnOpen(const Comm::ConnectionPointer &conn)
void SetSelect(int, unsigned int, PF *, void *, time_t)
Mark an FD to be watched for its IO status.
void StartListening(int sock_type, int proto, const Comm::ConnectionPointer &listenConn, FdNoteId, StartListeningCallback &)
void netdbHostData(const char *host, int *samp, int *rtt, int *hops)
int refreshCheckHTCP(const StoreEntry *entry, HttpRequest *request)
unsigned char cache_key
Store key.
StoreEntry * storeGetPublicByRequest(HttpRequest *req, const KeyScope keyScope)
cache_key * storeKeyCopy(cache_key *dst, const cache_key *src)
const char * storeKeyText(const cache_key *key)
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
const char * xstrerr(int error)