]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
transaction_initiator ACL for detecting various unusual transactions
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Mon, 12 Jun 2017 20:26:41 +0000 (23:26 +0300)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Mon, 12 Jun 2017 20:26:41 +0000 (23:26 +0300)
This ACL is essential in several use cases, including:

* After fetching a missing intermediate certificate, Squid uses the
  regular cache (and regular caching rules) to store the response. Squid
  deployments that do not want to cache regular traffic need to cache
  fetched certificates and only them.

  acl fetched_certificate transaction_initiator certificate-fetching
  cache allow fetched_certificate
  cache deny all

* Many traffic policies and tools assume the existence of an HTTP client
  behind every transaction. Internal Squid requests violate that
  assumption. Identifying internal requests protects external ACLs, log
  analyzers, and other mechanisms from the transactions they mishandle.

  acl skip_logging transaction_initiator internal
  access_log ... !skip_logging

The new transaction_initiator ACL classifies transactions based on their
initiator. Currently supported initiators are esi, certificate-fetching,
cache-digest, internal, client, and all. In the future, the same ACL
will be able to identify HTTP/2 push transactions using the "server"
initiator. See src/cf.data.pre for details.

This is a Measurement Factory project.

43 files changed:
src/AclRegs.cc
src/Downloader.cc
src/Downloader.h
src/HttpRequest.cc
src/HttpRequest.h
src/Makefile.am
src/MasterXaction.h
src/PeerPoolMgr.cc
src/RequestFlags.h
src/XactionInitiator.cc [new file with mode: 0644]
src/XactionInitiator.h [new file with mode: 0644]
src/acl/Asn.cc
src/acl/Makefile.am
src/acl/TransactionInitiator.cc [new file with mode: 0644]
src/acl/TransactionInitiator.h [new file with mode: 0644]
src/adaptation/ecap/Host.cc
src/adaptation/ecap/XactionRep.cc
src/adaptation/icap/ModXact.cc
src/adaptation/icap/Xaction.cc
src/cf.data.pre
src/client_side.cc
src/client_side.h
src/client_side_reply.cc
src/client_side_request.cc
src/client_side_request.h
src/comm/TcpAcceptor.cc
src/esi/Include.cc
src/forward.h [new file with mode: 0644]
src/htcp.cc
src/icmp/net_db.cc
src/icp_v2.cc
src/mgr/Inquirer.cc
src/mime.cc
src/neighbors.cc
src/peer_digest.cc
src/security/PeerConnector.cc
src/servers/FtpServer.cc
src/servers/Http1Server.cc
src/servers/Server.h
src/store_digest.cc
src/tests/stub_HttpRequest.cc
src/tests/testHttpRequest.cc
src/urn.cc

index 48dd65c451dce1a598fc33ae32302b5a5a16c98c..73814e39639d1f7c52701e4c4af6a7153fc61d53 100644 (file)
@@ -87,6 +87,7 @@
 #include "acl/Tag.h"
 #include "acl/Time.h"
 #include "acl/TimeData.h"
+#include "acl/TransactionInitiator.h"
 #include "acl/Url.h"
 #include "acl/UrlLogin.h"
 #include "acl/UrlPath.h"
@@ -155,6 +156,7 @@ Acl::Init()
     RegisterMaker("annotate_client", [](TypeName name)->ACL* { return new ACLStrategised<NotePairs::Entry*>(new ACLAnnotationData, new ACLAnnotateClientStrategy, name); });
     RegisterMaker("annotate_transaction", [](TypeName name)->ACL* { return new ACLStrategised<NotePairs::Entry*>(new ACLAnnotationData, new ACLAnnotateTransactionStrategy, name); });
     RegisterMaker("has", [](TypeName name)->ACL* {return new ACLStrategised<ACLChecklist *>(new ACLHasComponentData, new ACLHasComponentStrategy, name); });
+    RegisterMaker("transaction_initiator", [](TypeName name)->ACL* {return new TransactionInitiator(name);});
 
 #if USE_OPENSSL
     RegisterMaker("ssl_error", [](TypeName name)->ACL* { return new ACLStrategised<const Security::CertErrors *>(new ACLSslErrorData, new ACLSslErrorStrategy, name); });
index 38904a75fca3c9f2cfc12a1cb1d7691ed5cde0fd..e153861d97589014791ef555347c8c8bd87586c8 100644 (file)
@@ -63,11 +63,12 @@ Downloader::CbDialer::print(std::ostream &os) const
     os << " Http Status:" << status << Raw("body data", object.rawContent(), 64).hex();
 }
 
-Downloader::Downloader(SBuf &url, AsyncCall::Pointer &aCallback, unsigned int level):
+Downloader::Downloader(SBuf &url, AsyncCall::Pointer &aCallback, const XactionInitiator initiator, unsigned int level):
     AsyncJob("Downloader"),
     url_(url),
     callback_(aCallback),
-    level_(level)
+    level_(level),
+    initiator_(initiator)
 {
 }
 
@@ -128,7 +129,8 @@ Downloader::buildRequest()
     const HttpRequestMethod method = Http::METHOD_GET;
 
     char *uri = xstrdup(url_.c_str());
-    HttpRequest *const request = HttpRequest::CreateFromUrl(uri, method);
+    const MasterXaction::Pointer mx = new MasterXaction(initiator_);
+    HttpRequest *const request = HttpRequest::FromUrl(uri, mx, method);
     if (!request) {
         debugs(33, 5, "Invalid URI: " << url_);
         xfree(uri);
@@ -137,7 +139,6 @@ Downloader::buildRequest()
     request->http_ver = Http::ProtocolVersion();
     request->header.putStr(Http::HdrType::HOST, request->url.host());
     request->header.putTime(Http::HdrType::DATE, squid_curtime);
-    request->flags.internalClient = true;
     request->client_addr.setNoAddr();
 #if FOLLOW_X_FORWARDED_FOR
     request->indirect_client_addr.setNoAddr();
index 7f8dca42e83c35cd86e4adeb9a75b5d401620051..5f8e24bd859c1db60be94f6e3d23c65af2eb6344 100644 (file)
@@ -14,6 +14,7 @@
 #include "http/forward.h"
 #include "http/StatusCode.h"
 #include "sbuf/SBuf.h"
+#include "XactionInitiator.h"
 
 class ClientHttpRequest;
 class StoreIOBuffer;
@@ -45,7 +46,7 @@ public:
         Http::StatusCode status;
     };
 
-    Downloader(SBuf &url, AsyncCall::Pointer &aCallback, unsigned int level = 0);
+    Downloader(SBuf &url, AsyncCall::Pointer &aCallback, const XactionInitiator initiator, unsigned int level = 0);
     virtual ~Downloader();
     virtual void swanSong();
 
@@ -75,6 +76,8 @@ private:
     AsyncCall::Pointer callback_; ///< callback to call when download finishes
     SBuf object_; ///< the object body data
     const unsigned int level_; ///< holds the nested downloads level
+    /// The initiator of the download request.
+    XactionInitiator initiator_;
 
     /// Pointer to an object that stores the clientStream required info
     DownloaderContextPointer context_;
index 8ca441555dd124267f52795ed8a035332ac7c444..9b75838d1921e2b6d5a35206f3e2a1df3d1a7de1 100644 (file)
 #include "adaptation/icap/icap_log.h"
 #endif
 
-HttpRequest::HttpRequest() :
-    Http::Message(hoRequest)
+HttpRequest::HttpRequest(const MasterXaction::Pointer &mx) :
+    Http::Message(hoRequest),
+    masterXaction(mx)
 {
+    assert(mx);
     init();
 }
 
-HttpRequest::HttpRequest(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aSchemeImg, const char *aUrlpath) :
-    Http::Message(hoRequest)
+HttpRequest::HttpRequest(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aSchemeImg, const char *aUrlpath, const MasterXaction::Pointer &mx) :
+    Http::Message(hoRequest),
+    masterXaction(mx)
 {
+    assert(mx);
     static unsigned int id = 1;
     debugs(93,7, HERE << "constructed, this=" << this << " id=" << ++id);
     init();
@@ -170,7 +174,7 @@ HttpRequest::reset()
 HttpRequest *
 HttpRequest::clone() const
 {
-    HttpRequest *copy = new HttpRequest();
+    HttpRequest *copy = new HttpRequest(masterXaction);
     copy->method = method;
     // TODO: move common cloning clone to Msg::copyTo() or copy ctor
     copy->header.append(&header);
@@ -515,9 +519,9 @@ HttpRequest::expectingBody(const HttpRequestMethod &, int64_t &theSize) const
  * If the request cannot be created cleanly, NULL is returned
  */
 HttpRequest *
-HttpRequest::CreateFromUrl(char * url, const HttpRequestMethod& method)
+HttpRequest::FromUrl(char * url, const MasterXaction::Pointer &mx, const HttpRequestMethod& method)
 {
-    std::unique_ptr<HttpRequest> req(new HttpRequest());
+    std::unique_ptr<HttpRequest> req(new HttpRequest(mx));
     if (urlParse(method, url, *req))
         return req.release();
     return nullptr;
index 5c097042cd36593a9168eb1c9f6df1af3a031067..ef13d19af77e7c22f196b14926f011030239884d 100644 (file)
@@ -12,6 +12,7 @@
 #include "base/CbcPointer.h"
 #include "dns/forward.h"
 #include "err_type.h"
+#include "forward.h"
 #include "HierarchyLogEntry.h"
 #include "http/Message.h"
 #include "http/RequestMethod.h"
@@ -48,8 +49,8 @@ class HttpRequest: public Http::Message
 public:
     typedef RefCount<HttpRequest> Pointer;
 
-    HttpRequest();
-    HttpRequest(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *schemeImage, const char *aUrlpath);
+    HttpRequest(const MasterXactionPointer &);
+    HttpRequest(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *schemeImage, const char *aUrlpath, const MasterXactionPointer &);
     ~HttpRequest();
     virtual void reset();
 
@@ -193,7 +194,7 @@ public:
 
     static void httpRequestPack(void *obj, Packable *p);
 
-    static HttpRequest * CreateFromUrl(char * url, const HttpRequestMethod &method = Http::METHOD_GET);
+    static HttpRequest * FromUrl(char * url, const MasterXactionPointer &, const HttpRequestMethod &method = Http::METHOD_GET);
 
     ConnStateData *pinnedConnection();
 
@@ -214,6 +215,9 @@ public:
     /// The Downloader object which initiated the HTTP request if any
     CbcPointer<Downloader> downloader;
 
+    /// the master transaction this request belongs to. Never nil.
+    MasterXactionPointer masterXaction;
+
     /// forgets about the cached Range header (for a reason)
     void ignoreRange(const char *reason);
     int64_t getRangeOffsetLimit(); /* the result of this function gets cached in rangeOffsetLimit */
index 323653c9ad44db5b92fc46f7f191acfbe7139ef4..c93d6f4c283fb045a9189f9bf281fb8e71bf07f3 100644 (file)
@@ -486,6 +486,8 @@ squid_SOURCES = \
        whois.cc \
        wordlist.h \
        wordlist.cc \
+       XactionInitiator.h \
+       XactionInitiator.cc \
        $(WIN32_SOURCE) \
        $(WINSVC_SOURCE)
 
index 5554861d02c73681df98d4167b31043a021343b7..5aa8822a7fad484b64eb4566b9341b67353bcd42 100644 (file)
 #define SQUID_SRC_MASTERXACTION_H
 
 #include "anyp/forward.h"
+#include "anyp/PortCfg.h"
 #include "base/InstanceId.h"
 #include "base/Lock.h"
+#include "base/RefCount.h"
 #include "comm/forward.h"
+#include "XactionInitiator.h"
 
 /** Master transaction details.
  *
@@ -38,6 +41,8 @@ class MasterXaction : public RefCountable
 public:
     typedef RefCount<MasterXaction> Pointer;
 
+    explicit MasterXaction(const XactionInitiator anInitiator) : initiator(anInitiator) {};
+
     /// transaction ID.
     InstanceId<MasterXaction> id;
 
@@ -47,6 +52,9 @@ public:
     /// the client TCP connection which originated this transaction
     Comm::ConnectionPointer tcpClient;
 
+    /// the initiator of this transaction
+    XactionInitiator initiator;
+
     // TODO: add state from other Jobs in the transaction
 };
 
index a422a06ec8734b1b26fe465bc1e54ca639cc0b3c..5329ff0a919a76f9f40b623f4909c1342f7be527 100644 (file)
@@ -18,6 +18,7 @@
 #include "FwdState.h"
 #include "globals.h"
 #include "HttpRequest.h"
+#include "MasterXaction.h"
 #include "neighbors.h"
 #include "pconn.h"
 #include "PeerPoolMgr.h"
@@ -59,9 +60,10 @@ PeerPoolMgr::start()
 {
     AsyncJob::start();
 
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initPeerPool);
     // ErrorState, getOutgoingAddress(), and other APIs may require a request.
     // We fake one. TODO: Optionally send this request to peers?
-    request = new HttpRequest(Http::METHOD_OPTIONS, AnyP::PROTO_HTTP, "http", "*");
+    request = new HttpRequest(Http::METHOD_OPTIONS, AnyP::PROTO_HTTP, "http", "*", mx);
     request->url.host(peer->host);
 
     checkpoint("peer initialized");
index 9ef3af70669d37146518c72639a9e31eb24797be..353186d01cefa60758f3e67ce7d62125563e6597 100644 (file)
@@ -72,9 +72,6 @@ public:
     bool spoofClientIp = false;
     /** set if the request is internal (\see ClientHttpRequest::flags.internal)*/
     bool internal = false;
-    //XXX this is set in in clientBeginRequest, but never tested.
-    /** set for internally-generated requests */
-    bool internalClient = false;
     /** if set, request to try very hard to keep the connection alive */
     bool mustKeepalive = false;
     /** set if the rquest wants connection oriented auth */
diff --git a/src/XactionInitiator.cc b/src/XactionInitiator.cc
new file mode 100644 (file)
index 0000000..31e4cc4
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#include "squid.h"
+#include "cache_cf.h"
+#include "Debug.h"
+#include "XactionInitiator.h"
+
+XactionInitiator::Initiators
+XactionInitiator::ParseInitiators(const char *name)
+{
+    typedef std::map<std::string, XactionInitiator::Initiators> InitiatorsMap;
+    static InitiatorsMap SupportedInitiators = {
+        {"client", initClient},
+        {"peer-pool", initPeerPool},
+        {"certificate-fetching", initCertFetcher},
+        {"esi", initEsi},
+        {"cache-digest", initCacheDigest},
+        {"server", initServer},
+        {"htcp", initHtcp},
+        {"icp", initIcp},
+        {"icmp", initIcmp},
+        {"asn", initAsn},
+        {"ipc", initIpc},
+        {"adaptation", initAdaptation},
+        {"icon", initIcon},
+        {"peer-mcast", initPeerMcast},
+        {"internal", InternalInitiators()},
+        {"all", AllInitiators()}
+    };
+    const auto it = SupportedInitiators.find(name);
+    if (it != SupportedInitiators.cend())
+        return it->second;
+
+    debugs(28, DBG_CRITICAL, "FATAL: Invalid transaction_initiator value near " << name);
+    self_destruct();
+    return 0;
+}
diff --git a/src/XactionInitiator.h b/src/XactionInitiator.h
new file mode 100644 (file)
index 0000000..985b85f
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_SRC_XACTION_INITIATOR_H
+#define SQUID_SRC_XACTION_INITIATOR_H
+
+/// identifies a protocol agent or Squid feature initiating transactions
+class XactionInitiator {
+public:
+    /// transaction triggers
+    enum Initiator {
+        initUnknown = 0,
+        initClient = 1 << 0, ///< HTTP or FTP client
+        initPeerPool = 1 << 1, ///< PeerPool manager
+        initCertFetcher = 1 << 2, ///< Missing intermediate certificates fetching code
+        initEsi = 1 << 3, ///< ESI processing code
+        initCacheDigest = 1 << 4, ///< Cache Digest fetching code
+        initHtcp = 1<< 5, ///< HTCP client
+        initIcp = 1 << 6, ///< the ICP/neighbors subsystem
+        initIcmp = 1 << 7, ///< the ICMP RTT database (NetDB) neighbors exchange subsystem
+        initAsn = 1 << 8, ///< the ASN db subsystem
+        initIpc = 1 << 9, ///< the IPC subsystem
+        initAdaptation = 1 << 10,  ///< ICAP/ECAP requests generated by Squid
+        initIcon = 1 << 11, ///< internal icons
+        initPeerMcast = 1 << 12, ///< neighbor multicast
+        initServer = 1 << 13, ///< HTTP/2 push request (not yet supported by Squid)
+
+        initAdaptationOrphan_ = 1 << 31 ///< eCAP-created HTTP message w/o an associated HTTP transaction (not ACL-detectable)
+    };
+
+    typedef uint32_t Initiators; ///< Initiator set
+
+    // this class is a just a trivial wrapper so we allow explicit conversions
+    XactionInitiator(Initiator i) : initiator(i) {}
+
+    /// whether this initiator belongs to the given set
+    bool in(Initiators setOfInitiators) const {return (initiator & setOfInitiators) != 0;}
+
+    /// whether the transaction was initiated by an internal subsystem
+    bool internalClient() const {
+        return (initiator & InternalInitiators()) != 0;
+    }
+
+    /// internally generated requests
+    static Initiators InternalInitiators() {
+        return initPeerPool | initCertFetcher | initEsi | initCacheDigest | initIcp | initIcmp | initIpc | initAdaptation | initIcon | initPeerMcast;
+    }
+
+    /// all initiators
+    static Initiators AllInitiators() {
+        return 0xFFFFFFFF;
+    }
+
+    static Initiators ParseInitiators(const char *name);
+
+private:
+    XactionInitiator() {}
+
+    Initiator initiator;
+};
+
+#endif // SQUID_SRC_XACTION_INITIATOR_H
index 5707ea1ac8f0a548b6c51ae6e258caed29b34d86..c152f29bf3d2f4974476745b432c77aec14bf1d4 100644 (file)
@@ -20,6 +20,7 @@
 #include "HttpReply.h"
 #include "HttpRequest.h"
 #include "ipcache.h"
+#include "MasterXaction.h"
 #include "mgr/Registration.h"
 #include "radix.h"
 #include "RequestFlags.h"
@@ -240,7 +241,8 @@ asnCacheStart(int as)
     debugs(53, 3, "AS " << as);
     snprintf(asres, 4096, "whois://%s/!gAS%d", Config.as_whois_server, as);
     asState->as_number = as;
-    asState->request = HttpRequest::CreateFromUrl(asres);
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initAsn);
+    asState->request = HttpRequest::FromUrl(asres, mx);
     assert(asState->request != NULL);
 
     if ((e = storeGetPublic(asres, Http::METHOD_GET)) == NULL) {
index 98804b9e449054c2033e07734931a081dccf97d5..d59dd769d1dfa3298513b857815d3dbc304bdb23 100644 (file)
@@ -133,6 +133,8 @@ libacls_la_SOURCES = \
        SquidErrorData.h \
        Tag.cc \
        Tag.h \
+       TransactionInitiator.cc \
+       TransactionInitiator.h \
        Url.cc \
        Url.h \
        UrlLogin.cc \
diff --git a/src/acl/TransactionInitiator.cc b/src/acl/TransactionInitiator.cc
new file mode 100644 (file)
index 0000000..0225984
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/* DEBUG: section 28    Access Control */
+
+#include "squid.h"
+#include "acl/TransactionInitiator.h"
+#include "acl/FilledChecklist.h"
+#include "cache_cf.h"
+#include "Debug.h"
+#include "HttpRequest.h"
+#include "MasterXaction.h"
+#include "SquidConfig.h"
+
+ACL *
+Acl::TransactionInitiator::clone() const
+{
+    return new Acl::TransactionInitiator(*this);
+}
+
+Acl::TransactionInitiator::TransactionInitiator (const char *aClass) : class_ (aClass), initiators_(0)
+{}
+
+char const *
+Acl::TransactionInitiator::typeString() const
+{
+    return class_;
+}
+
+bool
+Acl::TransactionInitiator::empty () const
+{
+    return false;
+}
+
+void
+Acl::TransactionInitiator::parse()
+{
+    while (const char *s = ConfigParser::strtokFile()) {
+        initiators_ |= XactionInitiator::ParseInitiators(s);
+        cfgWords.push_back(SBuf(s));
+    }
+}
+
+int
+Acl::TransactionInitiator::match(ACLChecklist *checklist)
+{
+    ACLFilledChecklist *filled = Filled((ACLChecklist*)checklist);
+    assert(filled->request);
+    assert(filled->request->masterXaction);
+    const XactionInitiator requestInitiator = filled->request->masterXaction->initiator;
+    return requestInitiator.in(initiators_) ? 1 : 0;
+}
+
+SBufList
+Acl::TransactionInitiator::dump() const
+{
+    return cfgWords;
+}
+
diff --git a/src/acl/TransactionInitiator.h b/src/acl/TransactionInitiator.h
new file mode 100644 (file)
index 0000000..ff8ff0b
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_ACL_TRANSACTION_INITIATOR_H
+#define SQUID_ACL_TRANSACTION_INITIATOR_H
+
+#include "acl/Acl.h"
+#include "acl/Checklist.h"
+#include "XactionInitiator.h"
+
+namespace Acl
+{
+
+/// transaction_initiator ACL
+class TransactionInitiator : public ACL
+{
+    MEMPROXY_CLASS(TransactionInitiator);
+
+public:
+    TransactionInitiator(char const *);
+
+    virtual ACL *clone()const;
+    virtual char const *typeString() const;
+    virtual void parse();
+    virtual int match(ACLChecklist *checklist);
+    virtual bool requiresRequest() const { return true; }
+    virtual SBufList dump() const;
+    virtual bool empty () const;
+
+protected:
+    char const *class_;
+    XactionInitiator::Initiators initiators_;
+    SBufList cfgWords; /// initiator names in the configured order
+};
+
+} // namespace Acl
+
+#endif /* SQUID_ACL_TRANSACTION_INITIATOR_H */
+
index 705651f08fa569777e952fc2d8f0f4983d192d77..3f906c0d2836ed2fe8436b6fc2268b40f6f022d9 100644 (file)
@@ -18,6 +18,7 @@
 #include "base/TextException.h"
 #include "HttpReply.h"
 #include "HttpRequest.h"
+#include "MasterXaction.h"
 
 const libecap::Name Adaptation::Ecap::protocolInternal("internal", libecap::Name::NextId());
 const libecap::Name Adaptation::Ecap::protocolCacheObj("cache_object", libecap::Name::NextId());
@@ -162,7 +163,8 @@ Adaptation::Ecap::Host::closeDebug(std::ostream *debug)
 Adaptation::Ecap::Host::MessagePtr
 Adaptation::Ecap::Host::newRequest() const
 {
-    return MessagePtr(new Adaptation::Ecap::MessageRep(new HttpRequest));
+    static const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initAdaptationOrphan_);
+    return MessagePtr(new Adaptation::Ecap::MessageRep(new HttpRequest(mx)));
 }
 
 Adaptation::Ecap::Host::MessagePtr
index 0645a71e8bb7b44eedbbe9fef89ebced1f1aa27d..660eea5c405d8bf294881cca22c2183a869f7d4e 100644 (file)
@@ -23,6 +23,7 @@
 #include "format/Format.h"
 #include "HttpReply.h"
 #include "HttpRequest.h"
+#include "MasterXaction.h"
 #include "SquidTime.h"
 
 CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Ecap::XactionRep, XactionRep);
@@ -737,5 +738,13 @@ void
 Adaptation::Ecap::XactionRep::updateSources(Http::Message *adapted)
 {
     adapted->sources |= service().cfg().connectionEncryption ? Http::Message::srcEcaps : Http::Message::srcEcap;
+
+    // Update masterXaction object for adapted HTTP requests.
+    if (HttpRequest *adaptedReq = dynamic_cast<HttpRequest*>(adapted)) {
+        HttpRequest *request = dynamic_cast<HttpRequest*> (theCauseRep ?
+                               theCauseRep->raw().header : theVirginRep.raw().header);
+        Must(request);
+        adaptedReq->masterXaction = request->masterXaction;
+    }
 }
 
index acb271b545949b0814bcecf6280856a120c4fac0..54e25cd946f0341952ece03803d351b9c90603ee 100644 (file)
@@ -28,6 +28,7 @@
 #include "http/one/TeChunkedParser.h"
 #include "HttpHeaderTools.h"
 #include "HttpReply.h"
+#include "MasterXaction.h"
 #include "SquidTime.h"
 #include "URL.h"
 
@@ -736,7 +737,7 @@ void Adaptation::Icap::ModXact::maybeAllocateHttpMsg()
         setOutcome(service().cfg().method == ICAP::methodReqmod ?
                    xoSatisfied : xoModified);
     } else if (gotEncapsulated("req-hdr")) {
-        adapted.setHeader(new HttpRequest);
+        adapted.setHeader(new HttpRequest(virginRequest().masterXaction));
         setOutcome(xoModified);
     } else
         throw TexcHere("Neither res-hdr nor req-hdr in maybeAllocateHttpMsg()");
@@ -970,8 +971,8 @@ void Adaptation::Icap::ModXact::prepEchoing()
     Must(!adapted.header);
     {
         Http::MessagePointer newHead;
-        if (dynamic_cast<const HttpRequest*>(oldHead)) {
-            newHead = new HttpRequest;
+        if (const HttpRequest *r = dynamic_cast<const HttpRequest*>(oldHead)) {
+            newHead = new HttpRequest(r->masterXaction);
         } else if (dynamic_cast<const HttpReply*>(oldHead)) {
             newHead = new HttpReply;
         }
@@ -1594,7 +1595,7 @@ Adaptation::Icap::ModXact::encapsulateHead(MemBuf &icapBuf, const char *section,
     Http::MessagePointer headClone;
 
     if (const HttpRequest* old_request = dynamic_cast<const HttpRequest*>(head)) {
-        HttpRequest::Pointer new_request(new HttpRequest);
+        HttpRequest::Pointer new_request(new HttpRequest(old_request->masterXaction));
         // copy the request-line details
         new_request->method = old_request->method;
         new_request->url = old_request->url;
index cb154869986ef016c59c0d43e912a69a687450db..8cee03ff085e1ba59e27e96ede3d1f1b26173a48 100644 (file)
@@ -97,7 +97,8 @@ Adaptation::Icap::Xaction::Xaction(const char *aTypeName, Adaptation::Icap::Serv
 {
     debugs(93,3, typeName << " constructed, this=" << this <<
            " [icapx" << id << ']'); // we should not call virtual status() here
-    icapRequest = new HttpRequest;
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initAdaptation);
+    icapRequest = new HttpRequest(mx);
     HTTPMSGLOCK(icapRequest);
     icap_tr_start = current_time;
     memset(&icap_tio_start, 0, sizeof(icap_tio_start));
index 8a05095f8d0e13adcc24a36e978711dc712b42cd..600f59590abed5da6d635b409f63d17e1db15dd2 100644 (file)
@@ -1299,6 +1299,28 @@ DOC_START
          # adaptation_meta because it starts matching immediately after
          # the service has been selected for adaptation.
 
+       acl aclname transaction_initiator initiator ...
+         # Matches transaction's initiator [fast]
+         #
+         # Supported initiators are:
+         #  esi: matches transactions fetching ESI resources
+         #  certificate-fetching: matches transactions fetching
+         #     a missing intermediate TLS certificate
+         #  cache-digest: matches transactions fetching Cache Digests
+         #     from a cache_peer
+         #  htcp: matches HTCP requests from peers
+         #  icp: matches ICP requests to peers
+         #  icmp: matches ICMP RTT database (NetDB) requests to peers
+         #  asn: matches asns db requests
+         #  internal: matches any of the above
+         #  client: matches transactions containing an HTTP or FTP
+         #     client request received at a Squid *_port
+         #  all: matches any transaction, including internal transactions
+         #     without a configurable initiator and hopefully rare
+         #     transactions without a known-to-Squid initiator
+         #
+         # Multiple initiators are ORed.
+
        acl aclname has component
          # matches a transaction "component" [fast]
          #
index c89a9257b607488392d724864daad58efc18bd27..d8a5af00b1b04ff9ba197480647a983e8876e11f 100644 (file)
@@ -2794,9 +2794,11 @@ ConnStateData::postHttpsAccept()
             return;
         }
 
+        MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
+        mx->tcpClient = clientConnection;
         // Create a fake HTTP request for ssl_bump ACL check,
         // using tproxy/intercept provided destination IP and port.
-        HttpRequest *request = new HttpRequest();
+        HttpRequest *request = new HttpRequest(mx);
         static char ip[MAX_IPSTRLEN];
         assert(clientConnection->flags & (COMM_TRANSPARENT | COMM_INTERCEPTION));
         request->url.host(clientConnection->local.toStr(ip, sizeof(ip)));
@@ -3436,9 +3438,11 @@ ConnStateData::buildFakeRequest(Http::MethodType const method, SBuf &useHost, un
 
     stream->registerWithConn();
 
+    MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
+    mx->tcpClient = clientConnection;
     // Setup Http::Request object. Maybe should be replaced by a call to (modified)
     // clientProcessRequest
-    HttpRequest::Pointer request = new HttpRequest();
+    HttpRequest::Pointer request = new HttpRequest(mx);
     AnyP::ProtocolType proto = (method == Http::METHOD_NONE) ? AnyP::PROTO_AUTHORITY_FORM : AnyP::PROTO_HTTP;
     request->url.setScheme(proto, nullptr);
     request->method = method;
index fbb33225d65e69fba7df5fd74ccc56f7e7a46a79..8c774f2cbfaa10305f04b6e8d5264f91a5f84ba3 100644 (file)
@@ -14,6 +14,7 @@
 #include "base/RunnersRegistry.h"
 #include "clientStreamForward.h"
 #include "comm.h"
+#include "forward.h"
 #include "helper/forward.h"
 #include "http/forward.h"
 #include "HttpControlMsg.h"
@@ -69,7 +70,7 @@ class ConnStateData : public Server, public HttpControlMsgSink, private Independ
 {
 
 public:
-    explicit ConnStateData(const MasterXaction::Pointer &xact);
+    explicit ConnStateData(const MasterXactionPointer &xact);
     virtual ~ConnStateData();
 
     /* ::Server API */
index 767a43ac2530f628bf82b822765eb59b812e0266..359cf496c9f832c67e7535e73c176a32ea704b33 100644 (file)
@@ -2280,7 +2280,8 @@ clientReplyContext::createStoreEntry(const HttpRequestMethod& m, RequestFlags re
      */
 
     if (http->request == NULL) {
-        http->request = new HttpRequest(m, AnyP::PROTO_NONE, "http", null_string);
+        const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
+        http->request = new HttpRequest(m, AnyP::PROTO_NONE, "http", null_string, mx);
         HTTPMSGLOCK(http->request);
     }
 
index 3a8f0254f433c80ac777586f4a7ba38db71a2e0c..d4628cbcc2f09cd4bc914b3a79ae1098498f827e 100644 (file)
@@ -320,7 +320,7 @@ ClientHttpRequest::~ClientHttpRequest()
 int
 clientBeginRequest(const HttpRequestMethod& method, char const *url, CSCB * streamcallback,
                    CSD * streamdetach, ClientStreamData streamdata, HttpHeader const *header,
-                   char *tailbuf, size_t taillen)
+                   char *tailbuf, size_t taillen, const MasterXaction::Pointer &mx)
 {
     size_t url_sz;
     ClientHttpRequest *http = new ClientHttpRequest(NULL);
@@ -346,7 +346,7 @@ clientBeginRequest(const HttpRequestMethod& method, char const *url, CSCB * stre
     http->uri = (char *)xcalloc(url_sz, 1);
     strcpy(http->uri, url);
 
-    if ((request = HttpRequest::CreateFromUrl(http->uri, method)) == NULL) {
+    if ((request = HttpRequest::FromUrl(http->uri, mx, method)) == NULL) {
         debugs(85, 5, "Invalid URL: " << http->uri);
         return -1;
     }
@@ -368,8 +368,6 @@ clientBeginRequest(const HttpRequestMethod& method, char const *url, CSCB * stre
      */
     request->flags.accelerated = http->flags.accel;
 
-    request->flags.internalClient = true;
-
     /* this is an internally created
      * request, not subject to acceleration
      * target overrides */
index c515ca7c3f09e4b94929b2930318512850a768f5..40c270c5b49e36d6f792651150ec7f0fa6a46bf9 100644 (file)
@@ -13,6 +13,7 @@
 #include "acl/forward.h"
 #include "client_side.h"
 #include "clientStream.h"
+#include "forward.h"
 #include "http/forward.h"
 #include "HttpHeaderRange.h"
 #include "LogTags.h"
@@ -28,7 +29,7 @@ class ConnStateData;
 class MemObject;
 
 /* client_side_request.c - client side request related routines (pure logic) */
-int clientBeginRequest(const HttpRequestMethod&, char const *, CSCB *, CSD *, ClientStreamData, HttpHeader const *, char *, size_t);
+int clientBeginRequest(const HttpRequestMethod&, char const *, CSCB *, CSD *, ClientStreamData, HttpHeader const *, char *, size_t, const MasterXactionPointer &);
 
 class ClientHttpRequest
 #if USE_ADAPTATION
index ba77cb6191f2088b51b98559d784092325a3752b..890d13f654af0df035c119cd293f25595b4b4a2c 100644 (file)
@@ -328,7 +328,7 @@ Comm::TcpAcceptor::notify(const Comm::Flag flag, const Comm::ConnectionPointer &
     if (theCallSub != NULL) {
         AsyncCall::Pointer call = theCallSub->callback();
         CommAcceptCbParams &params = GetCommParams<CommAcceptCbParams>(call);
-        params.xaction = new MasterXaction;
+        params.xaction = new MasterXaction(XactionInitiator::initClient);
         params.xaction->squidPort = listenPort_;
         params.fd = conn->fd;
         params.conn = params.xaction->tcpClient = newConnDetails;
index e92eeb717a525332b4a2bc87a39a7fc252083fcc..1c2b732f0a91aa38e5fefd039497d3f3ab10a590 100644 (file)
@@ -299,8 +299,8 @@ ESIInclude::Start (ESIStreamContext::Pointer stream, char const *url, ESIVarStat
     char const *tempUrl = vars->extractChar ();
 
     debugs(86, 5, "ESIIncludeStart: Starting subrequest with url '" << tempUrl << "'");
-
-    if (clientBeginRequest(Http::METHOD_GET, tempUrl, esiBufferRecipient, esiBufferDetach, stream.getRaw(), &tempheaders, stream->localbuffer->buf, HTTP_REQBUF_SZ)) {
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initEsi);
+    if (clientBeginRequest(Http::METHOD_GET, tempUrl, esiBufferRecipient, esiBufferDetach, stream.getRaw(), &tempheaders, stream->localbuffer->buf, HTTP_REQBUF_SZ, mx)) {
         debugs(86, DBG_CRITICAL, "starting new ESI subrequest failed");
     }
 
diff --git a/src/forward.h b/src/forward.h
new file mode 100644 (file)
index 0000000..750a9ea
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * 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.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_SRC_FORWARD_H
+#define SQUID_SRC_FORWARD_H
+
+class MasterXaction;
+template <class C> class RefCount;
+typedef RefCount<MasterXaction> MasterXactionPointer;
+
+#endif
index b4c3b19d85e993bc5b267e0e2cdfe8aa12f37139..7ebc44fcaf5942fdf6e0af7c1ed184bb74b1cc38 100644 (file)
@@ -678,7 +678,8 @@ htcpUnpackSpecifier(char *buf, int sz)
     // Parse the request
     method.HttpRequestMethodXXX(s->method);
 
-    s->request = HttpRequest::CreateFromUrl(s->uri, method == Http::METHOD_NONE ? HttpRequestMethod(Http::METHOD_GET) : method);
+    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;
 }
 
index 73aad008faa799f697af9cf5ace61e8cbd39cf28..c8cf5bfac4abf5908f4772b0a5947092059161ce 100644 (file)
@@ -1274,7 +1274,8 @@ netdbExchangeStart(void *data)
     char *uri = internalRemoteUri(p->host, p->http_port, "/squid-internal-dynamic/", netDB);
     debugs(38, 3, "netdbExchangeStart: Requesting '" << uri << "'");
     assert(NULL != uri);
-    HttpRequestPointer req(HttpRequest::CreateFromUrl(uri));
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initIcmp);
+    HttpRequestPointer req(HttpRequest::FromUrl(uri, mx));
 
     if (!req) {
         debugs(38, DBG_IMPORTANT, "netdbExchangeStart: Bad URI " << uri);
index bc64d65deea971c1c3da4f2f6de3b856b3d13783..d9ed9f0df27647d3571ca62e84d8fe7af1bffdac 100644 (file)
@@ -439,8 +439,8 @@ icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from)
     }
 
     HttpRequest *result;
-
-    if ((result = HttpRequest::CreateFromUrl(url)) == NULL)
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initIcp);
+    if ((result = HttpRequest::FromUrl(url, mx)) == NULL)
         icpCreateAndSend(ICP_ERR, 0, url, reqnum, 0, fd, from);
 
     return result;
index 85212b11f9aecfb5d71d33250af311415871b8ff..fc662d8bf58b5e44339194f52529fbdce849c002 100644 (file)
@@ -76,7 +76,8 @@ Mgr::Inquirer::start()
     if (strands.empty()) {
         LOCAL_ARRAY(char, url, MAX_URL);
         snprintf(url, MAX_URL, "%s", aggrAction->command().params.httpUri.termedBuf());
-        HttpRequest *req = HttpRequest::CreateFromUrl(url);
+        const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initIpc);
+        HttpRequest *req = HttpRequest::FromUrl(url, mx);
         ErrorState err(ERR_INVALID_URL, Http::scNotFound, req);
         std::unique_ptr<HttpReply> reply(err.BuildHttpReply());
         replyBuf.reset(reply->pack());
index cc0208f34f9e58c39ba5de66ef94d6cc0dceaafe..063513dcbae89af4cf5be5b66ba74a3c667567dc 100644 (file)
@@ -403,7 +403,8 @@ MimeIcon::created(StoreEntry *newEntry)
     e->setPublicKey();
     e->buffer();
 
-    HttpRequestPointer r(HttpRequest::CreateFromUrl(url_));
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initIcon);
+    HttpRequestPointer r(HttpRequest::FromUrl(url_, mx));
     if (!r)
         fatalf("mimeLoadIcon: cannot parse internal URL: %s", url_);
 
index b16994d639325892dacf3032f6c6dd6cbdd96f09..2087b688c18dcc78d3c65a117332f9b96ddb59d0 100644 (file)
@@ -1384,7 +1384,8 @@ peerCountMcastPeersStart(void *data)
     p->in_addr.toUrl(url+7, MAX_URL -8 );
     strcat(url, "/");
     fake = storeCreateEntry(url, url, RequestFlags(), Http::METHOD_GET);
-    HttpRequest *req = HttpRequest::CreateFromUrl(url);
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initPeerMcast);
+    HttpRequest *req = HttpRequest::FromUrl(url, mx);
     psstate = new ps_state(nullptr);
     psstate->request = req;
     HTTPMSGLOCK(psstate->request);
index 3306a2dd917ef3e3d09e6b8e79dd910d6748b58c..f288328bf4188afb6740d30f1742ab0bd759bb35 100644 (file)
@@ -319,7 +319,8 @@ peerDigestRequest(PeerDigest * pd)
     else
         url = xstrdup(internalRemoteUri(p->host, p->http_port, "/squid-internal-periodic/", SBuf(StoreDigestFileName)));
 
-    req = HttpRequest::CreateFromUrl(url);
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initCacheDigest);
+    req = HttpRequest::FromUrl(url, mx);
 
     assert(req);
 
index 3d6a37af7e1c3654ece7d4862b4d4912d2e3ba77..4b3b6ceaca519989246bc765f35cdba232174a62 100644 (file)
@@ -629,7 +629,7 @@ Security::PeerConnector::startCertDownloading(SBuf &url)
                                       PeerConnectorCertDownloaderDialer(&Security::PeerConnector::certDownloadingDone, this));
 
     const Downloader *csd = (request ? dynamic_cast<const Downloader*>(request->downloader.valid()) : nullptr);
-    Downloader *dl = new Downloader(url, certCallback, csd ? csd->nestedLevel() + 1 : 1);
+    Downloader *dl = new Downloader(url, certCallback, XactionInitiator::initCertFetcher, csd ? csd->nestedLevel() + 1 : 1);
     AsyncJob::Start(dl);
 }
 
index 8a7d64ecd6651e753b177114ab03d9d75f4ce09b..ca9f71d6153ef467da7e7cd048d0b9cfec142076 100644 (file)
@@ -728,7 +728,9 @@ Ftp::Server::parseOneRequest()
                        &params : NULL;
     calcUri(path);
     char *newUri = xstrdup(uri.c_str());
-    HttpRequest *const request = HttpRequest::CreateFromUrl(newUri, method);
+    MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
+    mx->tcpClient = clientConnection;
+    HttpRequest *const request = HttpRequest::FromUrl(newUri, mx, method);
     if (!request) {
         debugs(33, 5, "Invalid FTP URL: " << uri);
         uri.clear();
index 4eba62af9dde104d3e81e8ce6c47c7ebbf4bcb3b..2cbfbe0f498a7acdd1403772367d11e564eb473d 100644 (file)
@@ -132,7 +132,9 @@ Http::One::Server::buildHttpRequest(Http::StreamPointer &context)
         return false;
     }
 
-    if ((request = HttpRequest::CreateFromUrl(http->uri, parser_->method())) == NULL) {
+    MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
+    mx->tcpClient = clientConnection;
+    if ((request = HttpRequest::FromUrl(http->uri, mx, parser_->method())) == NULL) {
         debugs(33, 5, "Invalid URL: " << http->uri);
         // setLogUri should called before repContext->setReplyToError
         setLogUri(http, http->uri, true);
index 0a3e1090863e0357305754925b89893d481c9b2f..40d1ba3e790cb63c97082626ff105a81cc2e309e 100644 (file)
@@ -17,6 +17,7 @@
 #include "BodyPipe.h"
 #include "comm/Write.h"
 #include "CommCalls.h"
+#include "forward.h"
 #include "Pipeline.h"
 #include "sbuf/SBuf.h"
 
@@ -27,7 +28,7 @@
 class Server : virtual public AsyncJob, public BodyProducer
 {
 public:
-    Server(const MasterXaction::Pointer &xact);
+    Server(const MasterXactionPointer &xact);
     virtual ~Server() {}
 
     /* AsyncJob API */
index 95a428cb05e04d6ddd6a0b7b791940b01f3b5d49..549b8a241ecf30518f3b167e9ad032a219857a35 100644 (file)
@@ -421,7 +421,8 @@ storeDigestRewriteStart(void *datanotused)
     assert(e);
     sd_state.rewrite_lock = e;
     debugs(71, 3, "storeDigestRewrite: url: " << url << " key: " << e->getMD5Text());
-    e->mem_obj->request = HttpRequest::CreateFromUrl(url);
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initCacheDigest);
+    e->mem_obj->request = HttpRequest::FromUrl(url, mx);
     /* wait for rebuild (if any) to finish */
 
     if (sd_state.rebuild_lock) {
index 44ab6cc553bf368137fdcac81761d68a1d92d185..620cb6f0ebdd3236fc648c889ca614f3083ee502 100644 (file)
@@ -9,14 +9,15 @@
 #include "squid.h"
 #include "AccessLogEntry.h"
 #include "HttpRequest.h"
+#include "MasterXaction.h"
 
 #define STUB_API "HttpRequest.cc"
 #include "tests/STUB.h"
 
 // void httpRequestPack(void *obj, Packable *p);
 
-HttpRequest::HttpRequest() : Http::Message(hoRequest) {STUB}
-HttpRequest::HttpRequest(const HttpRequestMethod &, AnyP::ProtocolType, const char *, const char *) : Http::Message(hoRequest) {STUB}
+HttpRequest::HttpRequest(const MasterXactionPointer&) : Http::Message(hoRequest) {STUB}
+HttpRequest::HttpRequest(const HttpRequestMethod &, AnyP::ProtocolType, const char *, const char *, const MasterXactionPointer &) : Http::Message(hoRequest) {STUB}
 HttpRequest::~HttpRequest() STUB
 void HttpRequest::reset() STUB
 void HttpRequest::initHTTP(const HttpRequestMethod &, AnyP::ProtocolType, const char *, const char *) STUB
@@ -47,7 +48,7 @@ int HttpRequest::prefixLen() const STUB_RETVAL(0)
 void HttpRequest::swapOut(StoreEntry *) STUB
 void HttpRequest::pack(Packable *) const STUB
 void HttpRequest::httpRequestPack(void *, Packable *) STUB
-HttpRequest * HttpRequest::CreateFromUrl(char *, const HttpRequestMethod &) STUB_RETVAL(NULL)
+HttpRequest * HttpRequest::FromUrl(char *, const MasterXaction::Pointer &, const HttpRequestMethod &) STUB_RETVAL(NULL)
 ConnStateData *HttpRequest::pinnedConnection() STUB_RETVAL(NULL)
 const SBuf HttpRequest::storeId() STUB_RETVAL(SBuf("."))
 void HttpRequest::ignoreRange(const char *) STUB
index 35d9d99b68dfe964d467ddbbdeba8633e5f5841b..2f30ddd8b1252318a62551c715500aa918be0a90 100644 (file)
@@ -13,6 +13,7 @@
 #include "HttpHeader.h"
 #include "HttpRequest.h"
 #include "mime_header.h"
+#include "MasterXaction.h"
 #include "testHttpRequest.h"
 #include "unitTestMain.h"
 
@@ -22,6 +23,7 @@ CPPUNIT_TEST_SUITE_REGISTRATION( testHttpRequest );
 class PrivateHttpRequest : public HttpRequest
 {
 public:
+    PrivateHttpRequest(const MasterXactionPointer &mx) : HttpRequest(mx) {}
     bool doSanityCheckStartLine(const char *b, const size_t h, Http::StatusCode *e) { return sanityCheckStartLine(b,h,e); };
 };
 
@@ -44,7 +46,8 @@ testHttpRequest::testCreateFromUrl()
     /* vanilla url, implict method */
     unsigned short expected_port;
     char * url = xstrdup("http://foo:90/bar");
-    HttpRequest *aRequest = HttpRequest::CreateFromUrl(url);
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
+    HttpRequest *aRequest = HttpRequest::FromUrl(url, mx);
     expected_port = 90;
     CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
     CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
@@ -56,7 +59,7 @@ testHttpRequest::testCreateFromUrl()
 
     /* vanilla url */
     url = xstrdup("http://foo:90/bar");
-    aRequest = HttpRequest::CreateFromUrl(url, Http::METHOD_GET);
+    aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
     expected_port = 90;
     CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
     CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
@@ -68,7 +71,7 @@ testHttpRequest::testCreateFromUrl()
 
     /* vanilla url, different method */
     url = xstrdup("http://foo/bar");
-    aRequest = HttpRequest::CreateFromUrl(url, Http::METHOD_PUT);
+    aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_PUT);
     expected_port = 80;
     CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
     CPPUNIT_ASSERT(aRequest->method == Http::METHOD_PUT);
@@ -81,13 +84,13 @@ testHttpRequest::testCreateFromUrl()
     /* a connect url with non-CONNECT data */
     HttpRequest *nullRequest = nullptr;
     url = xstrdup(":foo/bar");
-    aRequest = HttpRequest::CreateFromUrl(url, Http::METHOD_CONNECT);
+    aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_CONNECT);
     xfree(url);
     CPPUNIT_ASSERT_EQUAL(nullRequest, aRequest);
 
     /* a CONNECT url with CONNECT data */
     url = xstrdup("foo:45");
-    aRequest = HttpRequest::CreateFromUrl(url, Http::METHOD_CONNECT);
+    aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_CONNECT);
     expected_port = 45;
     CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
     CPPUNIT_ASSERT(aRequest->method == Http::METHOD_CONNECT);
@@ -112,7 +115,8 @@ testHttpRequest::testIPv6HostColonBug()
 
     /* valid IPv6 address without port */
     url = xstrdup("http://[2000:800::45]/foo");
-    aRequest = HttpRequest::CreateFromUrl(url, Http::METHOD_GET);
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
+    aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
     expected_port = 80;
     CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
     CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
@@ -124,7 +128,7 @@ testHttpRequest::testIPv6HostColonBug()
 
     /* valid IPv6 address with port */
     url = xstrdup("http://[2000:800::45]:90/foo");
-    aRequest = HttpRequest::CreateFromUrl(url, Http::METHOD_GET);
+    aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
     expected_port = 90;
     CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
     CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
@@ -136,7 +140,7 @@ testHttpRequest::testIPv6HostColonBug()
 
     /* IPv6 address as invalid (bug trigger) */
     url = xstrdup("http://2000:800::45/foo");
-    aRequest = HttpRequest::CreateFromUrl(url, Http::METHOD_GET);
+    aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
     expected_port = 80;
     CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
     CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
@@ -151,7 +155,8 @@ void
 testHttpRequest::testSanityCheckStartLine()
 {
     MemBuf input;
-    PrivateHttpRequest engine;
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
+    PrivateHttpRequest engine(mx);
     Http::StatusCode error = Http::scNone;
     size_t hdr_len;
     input.init();
index 896231e3d13663772157c7c2d5e9be88ee229ba5..71605325d455bafabe99ceacbab3a0b4a84cbca5 100644 (file)
@@ -151,7 +151,7 @@ UrnState::setUriResFromRequest(HttpRequest *r)
     safe_free(host);
     safe_free(urlres);
     urlres = xstrdup(local_urlres);
-    urlres_r = HttpRequest::CreateFromUrl(urlres);
+    urlres_r = HttpRequest::FromUrl(urlres, r->masterXaction);
 
     if (urlres_r == NULL) {
         debugs(52, 3, "urnStart: Bad uri-res URL " << urlres);