/*
- * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
#include "htcp.h"
#include "http.h"
#include "HttpRequest.h"
-#include "HttpStateFlags.h"
#include "icmp/net_db.h"
#include "ip/tools.h"
#include "md5.h"
+#include "mem/forward.h"
#include "MemBuf.h"
#include "refresh.h"
#include "SquidConfig.h"
#include "tools.h"
#include "URL.h"
-/** htcpDetail uses explicit alloc()/freeOne()
- * XXX: convert to MEMPROXY_CLASS() API
- */
-#include "mem/Pool.h"
-
typedef struct _Countstr Countstr;
typedef struct _htcpHeader htcpHeader;
typedef struct _htcpAuthHeader htcpAuthHeader;
-typedef struct _htcpDetail htcpDetail;
-
struct _Countstr {
uint16_t length;
char *text;
uint16_t length;
#if WORDS_BIGENDIAN
-uint8_t opcode:
- 4;
-uint8_t response:
- 4;
+ uint8_t opcode:4;
+ uint8_t response:4;
#else
-uint8_t response:
- 4;
-uint8_t opcode:
- 4;
+ uint8_t response:4;
+ uint8_t opcode:4;
#endif
#if WORDS_BIGENDIAN
-uint8_t reserved:
- 6;
-uint8_t F1:
- 1;
-uint8_t RR:
- 1;
+ uint8_t reserved:6;
+ uint8_t F1:1;
+ uint8_t RR:1;
#else
-uint8_t RR:
- 1;
-uint8_t F1:
- 1;
-uint8_t reserved:
- 6;
+ uint8_t RR:1;
+ uint8_t F1:1;
+ uint8_t reserved:6;
#endif
uint32_t msg_id;
Countstr signature;
};
-class htcpSpecifier : public StoreClient
+class htcpSpecifier : public RefCountable, public StoreClient
{
MEMPROXY_CLASS(htcpSpecifier);
public:
- htcpSpecifier() :
- method(NULL),
- uri(NULL),
- version(NULL),
- req_hdrs(NULL),
- reqHdrsSz(0),
- request(NULL),
- checkHitRequest(NULL),
- dhdr(NULL)
- {}
- // XXX: destructor?
-
- void created (StoreEntry *newEntry);
+ typedef RefCount<htcpSpecifier> Pointer;
+
void checkHit();
- void checkedHit(StoreEntry *e);
+ void checkedHit(StoreEntry *);
- void setFrom(Ip::Address &from);
- void setDataHeader(htcpDataHeader *);
- const char *method;
- char *uri;
- char *version;
- char *req_hdrs;
- size_t reqHdrsSz; ///< size of the req_hdrs content
- HttpRequest *request;
+ void setFrom(Ip::Address &anIp) { from = anIp; }
+ void setDataHeader(htcpDataHeader *aDataHeader) {
+ dhdr = aDataHeader;
+ }
+
+ /* StoreClient API */
+ void created(StoreEntry *);
+
+public:
+ const char *method = nullptr;
+ char *uri = nullptr;
+ char *version = nullptr;
+ char *req_hdrs = nullptr;
+ size_t reqHdrsSz = 0; ///< size of the req_hdrs content
+ HttpRequest::Pointer request;
private:
- HttpRequest *checkHitRequest;
+ HttpRequest::Pointer checkHitRequest;
- Ip::Address from; // was a ptr. return to such IFF needed. otherwise copy should do.
- htcpDataHeader *dhdr;
+ Ip::Address from;
+ htcpDataHeader *dhdr = nullptr;
};
-struct _htcpDetail {
+class htcpDetail {
+ MEMPROXY_CLASS(htcpDetail);
+public:
+ htcpDetail() : resp_hdrs(nullptr), respHdrsSz(0), entity_hdrs(nullptr), entityHdrsSz(0), cache_hdrs(nullptr), cacheHdrsSz(0) {}
char *resp_hdrs;
size_t respHdrsSz;
static cache_key queried_keys[N_QUERIED_KEYS][SQUID_MD5_DIGEST_LENGTH];
static Ip::Address queried_addr[N_QUERIED_KEYS];
-static MemAllocator *htcpDetailPool = NULL;
static int old_squid_format = 0;
static ssize_t htcpBuildPacket(char *buf, size_t buflen, htcpStuff * stuff);
-static htcpSpecifier *htcpUnpackSpecifier(char *buf, int sz);
static htcpDetail *htcpUnpackDetail(char *buf, int sz);
static ssize_t htcpBuildAuth(char *buf, size_t buflen);
static ssize_t htcpBuildCountstr(char *buf, size_t buflen, const char *s, size_t len);
static ssize_t htcpBuildOpData(char *buf, size_t buflen, htcpStuff * stuff);
static ssize_t htcpBuildSpecifier(char *buf, size_t buflen, htcpStuff * stuff);
static ssize_t htcpBuildTstOpData(char *buf, size_t buflen, htcpStuff * stuff);
-static void htcpFreeSpecifier(htcpSpecifier * s);
-static void htcpFreeDetail(htcpDetail * s);
static void htcpHandleMsg(char *buf, int sz, Ip::Address &from);
ssize_t off = 0;
ssize_t op_data_sz;
size_t hdr_sz = sizeof(htcpDataHeader);
- htcpDataHeader hdr;
if (buflen < hdr_sz)
return -1;
debugs(31, 3, "htcpBuildData: hdr.length = " << off);
- hdr.length = (uint16_t) off;
-
- hdr.opcode = stuff->op;
-
- hdr.response = stuff->response;
-
- hdr.RR = stuff->rr;
-
- hdr.F1 = stuff->f1;
-
- hdr.msg_id = stuff->msg_id;
-
- /* convert multi-byte fields */
- hdr.length = htons(hdr.length);
-
- hdr.msg_id = htonl(hdr.msg_id);
-
if (!old_squid_format) {
+ htcpDataHeader hdr;
+ memset(&hdr, 0, sizeof(hdr));
+ /* convert multi-byte fields */
+ hdr.msg_id = htonl(stuff->msg_id);
+ hdr.length = htons(static_cast<uint16_t>(off));
+ hdr.opcode = stuff->op;
+ hdr.response = stuff->response;
+ hdr.RR = stuff->rr;
+ hdr.F1 = stuff->f1;
memcpy(buf, &hdr, hdr_sz);
} else {
htcpDataHeaderSquid hdrSquid;
memset(&hdrSquid, 0, sizeof(hdrSquid));
- hdrSquid.length = hdr.length;
- hdrSquid.opcode = hdr.opcode;
- hdrSquid.response = hdr.response;
- hdrSquid.F1 = hdr.F1;
- hdrSquid.RR = hdr.RR;
+ hdrSquid.length = htons(static_cast<uint16_t>(off));
+ hdrSquid.opcode = stuff->op;
+ hdrSquid.response = stuff->response;
+ hdrSquid.F1 = stuff->f1;
+ hdrSquid.RR = stuff->rr;
memcpy(buf, &hdrSquid, hdr_sz);
}
static void
htcpSend(const char *buf, int len, Ip::Address &to)
{
- debugs(31, 3, HERE << to);
+ debugs(31, 3, to);
htcpHexdump("htcpSend", buf, len);
- if (comm_udp_sendto(htcpOutgoingConn->fd, to, buf, len) < 0)
- debugs(31, 3, HERE << htcpOutgoingConn << " sendto: " << xstrerror());
- else
+ if (comm_udp_sendto(htcpOutgoingConn->fd, to, buf, len) < 0) {
+ int xerrno = errno;
+ debugs(31, 3, htcpOutgoingConn << " sendto: " << xstrerr(xerrno));
+ } else
++statCounter.htcp.pkts_sent;
}
-/*
- * STUFF FOR RECEIVING HTCP MESSAGES
- */
-
-void
-htcpSpecifier::setFrom(Ip::Address &aSocket)
-{
- from = aSocket;
-}
-
-void
-htcpSpecifier::setDataHeader(htcpDataHeader *aDataHeader)
-{
- dhdr = aDataHeader;
-}
-
-static void
-htcpFreeSpecifier(htcpSpecifier * s)
-{
- HTTPMSGUNLOCK(s->request);
-
- delete s;
-}
-
-static void
-htcpFreeDetail(htcpDetail * d)
-{
- htcpDetailPool->freeOne(d);
-}
-
/*
* Unpack an HTCP SPECIFIER in place
* This will overwrite any following AUTH block
*/
// XXX: this needs to be turned into an Htcp1::Parser inheriting from Http1::RequestParser
// but with different first-line and block unpacking logic.
-static htcpSpecifier *
+static htcpSpecifier::Pointer
htcpUnpackSpecifier(char *buf, int sz)
{
- htcpSpecifier *s = new htcpSpecifier;
+ static const htcpSpecifier::Pointer nil;
+ htcpSpecifier::Pointer s(new htcpSpecifier);
HttpRequestMethod method;
/* Find length of METHOD */
if (l > sz) {
debugs(31, 3, "htcpUnpackSpecifier: failed to unpack METHOD");
- htcpFreeSpecifier(s);
- return NULL;
+ return nil;
}
/* Set METHOD */
if (l > sz) {
debugs(31, 3, "htcpUnpackSpecifier: failed to unpack URI");
- htcpFreeSpecifier(s);
- return NULL;
+ return nil;
}
/* Add terminating null to METHOD */
if (l > sz) {
debugs(31, 3, "htcpUnpackSpecifier: failed to unpack VERSION");
- htcpFreeSpecifier(s);
- return NULL;
+ return nil;
}
/* Add terminating null to URI */
if (l > sz) {
debugs(31, 3, "htcpUnpackSpecifier: failed to unpack REQ-HDRS");
- htcpFreeSpecifier(s);
- return NULL;
+ return nil;
}
/* Add terminating null to URI */
// Parse the request
method.HttpRequestMethodXXX(s->method);
- s->request = HttpRequest::CreateFromUrlAndMethod(s->uri, method == Http::METHOD_NONE ? HttpRequestMethod(Http::METHOD_GET) : method);
-
- if (s->request)
- HTTPMSGLOCK(s->request);
-
+ const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initHtcp);
+ s->request = HttpRequest::FromUrl(s->uri, mx, method == Http::METHOD_NONE ? HttpRequestMethod(Http::METHOD_GET) : method);
return s;
}
static htcpDetail *
htcpUnpackDetail(char *buf, int sz)
{
- htcpDetail *d = static_cast<htcpDetail *>(htcpDetailPool->alloc());
+ htcpDetail *d = new htcpDetail;
/* Find length of RESP-HDRS */
uint16_t l = ntohs(*(uint16_t *) buf);
if (l > sz) {
debugs(31, 3, "htcpUnpackDetail: failed to unpack RESP_HDRS");
- htcpFreeDetail(d);
+ delete d;
return NULL;
}
if (l > sz) {
debugs(31, 3, "htcpUnpackDetail: failed to unpack ENTITY_HDRS");
- htcpFreeDetail(d);
+ delete d;
return NULL;
}
if (l > sz) {
debugs(31, 3, "htcpUnpackDetail: failed to unpack CACHE_HDRS");
- htcpFreeDetail(d);
+ delete d;
return NULL;
}
}
static bool
-htcpAccessAllowed(acl_access * acl, htcpSpecifier * s, Ip::Address &from)
+htcpAccessAllowed(acl_access * acl, const htcpSpecifier::Pointer &s, Ip::Address &from)
{
/* default deny if no access list present */
if (!acl)
return false;
- ACLFilledChecklist checklist(acl, s->request, NULL);
+ ACLFilledChecklist checklist(acl, s->request.getRaw(), nullptr);
checklist.src_addr = from;
checklist.my_addr.setNoAddr();
return (checklist.fastCheck() == ACCESS_ALLOWED);
stuff.S.req_hdrs = spec->req_hdrs;
stuff.S.reqHdrsSz = spec->reqHdrsSz;
if (e)
- hdr.putInt(HDR_AGE, (e->timestamp <= squid_curtime ? (squid_curtime - e->timestamp) : 0) );
+ hdr.putInt(Http::HdrType::AGE, (e->timestamp <= squid_curtime ? (squid_curtime - e->timestamp) : 0) );
else
- hdr.putInt(HDR_AGE, 0);
+ hdr.putInt(Http::HdrType::AGE, 0);
MemBuf mb;
mb.init();
hdr.packInto(&mb);
stuff.D.respHdrsSz = mb.contentSize();
debugs(31, 3, "htcpTstReply: resp_hdrs = {" << stuff.D.resp_hdrs << "}");
mb.reset();
- hdr.reset();
+ hdr.clean();
if (e && e->expires > -1)
- hdr.putTime(HDR_EXPIRES, e->expires);
+ hdr.putTime(Http::HdrType::EXPIRES, e->expires);
- if (e && e->lastmod > -1)
- hdr.putTime(HDR_LAST_MODIFIED, e->lastmod);
+ if (e && e->lastModified() > -1)
+ hdr.putTime(Http::HdrType::LAST_MODIFIED, e->lastModified());
hdr.packInto(&mb);
debugs(31, 3, "htcpTstReply: entity_hdrs = {" << stuff.D.entity_hdrs << "}");
mb.reset();
-
- hdr.reset();
+ hdr.clean();
#if USE_ICMP
if (char *host = urlHostname(spec->uri)) {
{
checkHitRequest = request;
- if (NULL == checkHitRequest) {
+ if (!checkHitRequest) {
debugs(31, 3, "htcpCheckHit: NO; failed to parse URL");
checkedHit(NullStoreEntry::getInstance());
return;
if (!checkHitRequest->header.parse(req_hdrs, reqHdrsSz)) {
debugs(31, 3, "htcpCheckHit: NO; failed to parse request headers");
- delete checkHitRequest;
- checkHitRequest = NULL;
+ checkHitRequest = nullptr;
checkedHit(NullStoreEntry::getInstance());
return;
}
- StoreEntry::getPublicByRequest(this, checkHitRequest);
+ StoreEntry::getPublicByRequest(this, checkHitRequest.getRaw());
}
void
-htcpSpecifier::created (StoreEntry *e)
+htcpSpecifier::created(StoreEntry *e)
{
- StoreEntry *hit=NULL;
- assert (e);
+ StoreEntry *hit = nullptr;
- if (e->isNull()) {
+ if (!e || e->isNull()) {
debugs(31, 3, "htcpCheckHit: NO; public object not found");
} else if (!e->validToSend()) {
debugs(31, 3, "htcpCheckHit: NO; entry not valid to send" );
- } else if (refreshCheckHTCP(e, checkHitRequest)) {
+ } else if (refreshCheckHTCP(e, checkHitRequest.getRaw())) {
debugs(31, 3, "htcpCheckHit: NO; cached response is stale");
} else {
debugs(31, 3, "htcpCheckHit: YES!?");
hit = e;
}
- checkedHit (hit);
+ checkedHit(hit);
}
static void
}
static int
-htcpClrStore(const htcpSpecifier * s)
+htcpClrStore(const htcpSpecifier::Pointer &s)
{
- HttpRequest *request = s->request;
- StoreEntry *e = NULL;
- int released = 0;
-
- if (request == NULL) {
+ HttpRequestPointer request(s->request);
+ if (!request) {
debugs(31, 3, "htcpClrStore: failed to parse URL");
return -1;
}
return -1;
}
+ StoreEntry *e = nullptr;
+ int released = 0;
/* Lookup matching entries. This matches both GET and HEAD */
- while ((e = storeGetPublicByRequest(request)) != NULL) {
- if (e != NULL) {
- htcpClrStoreEntry(e);
- ++released;
- }
+ while ((e = storeGetPublicByRequest(request.getRaw()))) {
+ htcpClrStoreEntry(e);
+ ++released;
}
if (released) {
neighborsHtcpReply(key, &htcpReply, from);
htcpReply.hdr.clean();
- if (d)
- htcpFreeDetail(d);
+ delete d;
}
static void
htcpHandleTstRequest(htcpDataHeader * dhdr, char *buf, int sz, Ip::Address &from)
{
- /* buf should be a SPECIFIER */
- htcpSpecifier *s;
-
if (sz == 0) {
debugs(31, 3, "htcpHandleTst: nothing to do");
return;
if (dhdr->F1 == 0)
return;
- /* s is a new object */
- s = htcpUnpackSpecifier(buf, sz);
+ /* buf should be a SPECIFIER */
+ htcpSpecifier::Pointer s(htcpUnpackSpecifier(buf, sz));
- if (s == NULL) {
+ if (!s) {
debugs(31, 3, "htcpHandleTstRequest: htcpUnpackSpecifier failed");
htcpLogHtcp(from, dhdr->opcode, LOG_UDP_INVALID, dash_str);
return;
if (!s->request) {
debugs(31, 3, "htcpHandleTstRequest: failed to parse request");
htcpLogHtcp(from, dhdr->opcode, LOG_UDP_INVALID, dash_str);
- htcpFreeSpecifier(s);
return;
}
if (!htcpAccessAllowed(Config.accessList.htcp, s, from)) {
debugs(31, 3, "htcpHandleTstRequest: Access denied");
htcpLogHtcp(from, dhdr->opcode, LOG_UDP_DENIED, s->uri);
- htcpFreeSpecifier(s);
return;
}
htcpTstReply(dhdr, NULL, NULL, from); /* cache miss */
htcpLogHtcp(from, dhdr->opcode, LOG_UDP_MISS, uri);
}
-
- htcpFreeSpecifier(this);
}
static void
htcpHandleClr(htcpDataHeader * hdr, char *buf, int sz, Ip::Address &from)
{
- htcpSpecifier *s;
/* buf[0/1] is reserved and reason */
int reason = buf[1] << 4;
debugs(31, 2, "HTCP CLR reason: " << reason);
return;
}
- s = htcpUnpackSpecifier(buf, sz);
+ htcpSpecifier::Pointer s(htcpUnpackSpecifier(buf, sz));
- if (NULL == s) {
+ if (!s) {
debugs(31, 3, "htcpHandleClr: htcpUnpackSpecifier failed");
htcpLogHtcp(from, hdr->opcode, LOG_UDP_INVALID, dash_str);
return;
if (!s->request) {
debugs(31, 3, "htcpHandleTstRequest: failed to parse request");
htcpLogHtcp(from, hdr->opcode, LOG_UDP_INVALID, dash_str);
- htcpFreeSpecifier(s);
return;
}
if (!htcpAccessAllowed(Config.accessList.htcp_clr, s, from)) {
debugs(31, 3, "htcpHandleClr: Access denied");
htcpLogHtcp(from, hdr->opcode, LOG_UDP_DENIED, s->uri);
- htcpFreeSpecifier(s);
return;
}
default:
break;
}
-
- htcpFreeSpecifier(s);
}
/*
debugs(31, DBG_IMPORTANT, "Sending HTCP messages from " << htcpOutgoingConn->local);
}
- if (!htcpDetailPool) {
- htcpDetailPool = memPoolCreate("htcpDetail", sizeof(htcpDetail));
- }
}
static void
ssize_t pktlen;
char vbuf[32];
HttpHeader hdr(hoRequest);
- HttpStateFlags flags;
+ Http::StateFlags flags;
if (!Comm::IsConnOpen(htcpIncomingConn))
return 0;
char vbuf[32];
HttpHeader hdr(hoRequest);
MemBuf mb;
- HttpStateFlags flags;
+ Http::StateFlags flags;
if (!Comm::IsConnOpen(htcpIncomingConn))
return;
htcpLogHtcp(Ip::Address &caddr, int opcode, LogTags logcode, const char *url)
{
AccessLogEntry::Pointer al = new AccessLogEntry;
- if (LOG_TAG_NONE == logcode)
+ if (LOG_TAG_NONE == logcode.oldType)
return;
if (!Config.onoff.log_udp)
return;