[squid-dev] [PATCH] Http::ProtocolVersion update

Amos Jeffries squid3 at treenet.co.nz
Sun Dec 7 06:56:22 UTC 2014


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

As mentioned by Alex in the FTP server addition the
Http::ProtocolVersion(*) does not work sufficiently well as a class
hierarchy and should be re-implemented as global functions.

This patch does that re-implementation.

Convert Http::ProtocolVersion to two functions:

* Http::ProtocolVersion() providing the default Squid HTTP version
level, and

* Http::ProtocolVersion(unsigned, unsigned) providing the HTTP version
details for the given level.

NP: using two overloaded functions instead of one with default
parameter values because with HTTP/0.x and HTTP/2.x we cannot safely
default just the minor value. ie. using two functions prevents
mistakenly using HTTP/2.1, HTTP/0.1 or HTTP/1.0 if the second
parameter is omitted.

All variables must now be of type AnyP::ProtocolVersion, and should be
constructed from an appropriate Foo::ProtocolVersion() function.

Amos
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (MingW32)

iQEcBAEBAgAGBQJUg/oWAAoJELJo5wb/XPRjWkIIALNtUpyqnQohpye5vzZvTdaK
Vib1f0kas2YBURCrtYvLmwt5KIRVsKiwcyofIL0M2l2OEr2ptJhq5Gw2oHAcNZTb
WSN9CmZ+WVR+NBLcSKbKN+tppFTlN9VAgMlRiz1qcFjG4y+mHSBsZiXj9obmp4BJ
avffJHy/5H9tU78c2jTEe487rsIY+jVUcO6yk5FmhjIQ9oi3nEb4SgHs6gTYdTT5
dsQTqaBaMr6wmWGF1FVWiOAvJktEtOyUqFjaVRq3V0Y++XfZH9eWJedpGxtMNvUQ
gOrw5FwcGSTPKTGJlb9hXl2YqmnrXNNlBHcsbD5vC2bnB7xnZ7M7Hm5oeU9Kg/o=
=J2dr
-----END PGP SIGNATURE-----
-------------- next part --------------
=== modified file 'src/AccessLogEntry.h'
--- src/AccessLogEntry.h	2014-11-20 08:57:14 +0000
+++ src/AccessLogEntry.h	2014-12-06 16:46:01 +0000
@@ -55,41 +55,41 @@
     // TCP/IP level details about the server or peer connection
     // are stored in hier.tcpServer
 
     /** \brief This subclass holds log info for HTTP protocol
      * \todo Inner class declarations should be moved outside
      * \todo details of HTTP held in the parent class need moving into here.
      */
     class HttpDetails
     {
 
     public:
         HttpDetails() : method(Http::METHOD_NONE), code(0), content_type(NULL),
                 timedout(false),
                 aborted(false),
                 clientRequestSz(),
                 clientReplySz() {}
 
         HttpRequestMethod method;
         int code;
         const char *content_type;
-        Http::ProtocolVersion version;
+        AnyP::ProtocolVersion version;
         bool timedout; ///< terminated due to a lifetime or I/O timeout
         bool aborted; ///< other abnormal termination (e.g., I/O error)
 
         /// compute suffix for the status access.log field
         const char *statusSfx() const {
             return timedout ? "_TIMEDOUT" : (aborted ? "_ABORTED" : "");
         }
 
         /// counters for the original request received from client
         // TODO calculate header and payload better (by parser)
         // XXX payload encoding overheads not calculated at all yet.
         MessageSizes clientRequestSz;
 
         /// counters for the response sent to client
         // TODO calculate header and payload better (by parser)
         // XXX payload encoding overheads not calculated at all yet.
         MessageSizes clientReplySz;
 
     } http;
 

=== modified file 'src/HttpMsg.cc'
--- src/HttpMsg.cc	2014-09-14 12:43:00 +0000
+++ src/HttpMsg.cc	2014-12-06 18:24:23 +0000
@@ -283,41 +283,41 @@
 
 /* handy: resets and returns -1 */
 int
 HttpMsg::httpMsgParseError()
 {
     reset();
     return -1;
 }
 
 void
 HttpMsg::setContentLength(int64_t clen)
 {
     header.delById(HDR_CONTENT_LENGTH); // if any
     header.putInt64(HDR_CONTENT_LENGTH, clen);
     content_length = clen;
 }
 
 bool
 HttpMsg::persistent() const
 {
-    if (http_ver > Http::ProtocolVersion(1, 0)) {
+    if (http_ver > Http::ProtocolVersion(1,0)) {
         /*
          * for modern versions of HTTP: persistent unless there is
          * a "Connection: close" header.
          */
         return !httpHeaderHasConnDir(&header, "close");
     } else {
         /* for old versions of HTTP: persistent if has "keep-alive" */
         return httpHeaderHasConnDir(&header, "keep-alive");
     }
 }
 
 void HttpMsg::packInto(Packer *p, bool full_uri) const
 {
     packFirstLineInto(p, full_uri);
     header.packInto(p);
     packerAppend(p, "\r\n", 2);
 }
 
 void HttpMsg::hdrCacheInit()
 {

=== modified file 'src/HttpMsg.h'
--- src/HttpMsg.h	2014-09-14 12:43:00 +0000
+++ src/HttpMsg.h	2014-12-06 16:48:11 +0000
@@ -30,41 +30,41 @@
 
     void packInto(Packer * p, bool full_uri) const;
 
     ///< produce a message copy, except for a few connection-specific settings
     virtual HttpMsg *clone() const = 0; ///< \todo rename: not a true copy?
 
     /// [re]sets Content-Length header and cached value
     void setContentLength(int64_t clen);
 
     /**
      * \retval true  the message sender asks to keep the connection open.
      * \retval false the message sender will close the connection.
      *
      * Factors other than the headers may result in connection closure.
      */
     bool persistent() const;
 
 public:
     /// HTTP-Version field in the first line of the message.
     /// see RFC 7230 section 3.1
-    Http::ProtocolVersion http_ver;
+    AnyP::ProtocolVersion http_ver;
 
     HttpHeader header;
 
     HttpHdrCc *cache_control;
 
     /* Unsupported, writable, may disappear/change in the future
      * For replies, sums _stored_ status-line, headers, and <CRLF>.
      * Also used to report parsed header size if parse() is successful */
     int hdr_sz;
 
     int64_t content_length;
 
     HttpMsgParseState pstate;   /* the current parsing state */
 
     BodyPipe::Pointer body_pipe; // optional pipeline to receive message body
 
     // returns true and sets hdr_sz on success
     // returns false and sets *error to zero when needs more data
     // returns false and sets *error to a positive Http::StatusCode on error
     bool parse(MemBuf *buf, bool eol, Http::StatusCode *error);

=== modified file 'src/HttpReply.cc'
--- src/HttpReply.cc	2014-09-13 13:59:43 +0000
+++ src/HttpReply.cc	2014-12-06 18:20:56 +0000
@@ -136,102 +136,102 @@
     return mb;
 }
 
 HttpReply *
 HttpReply::make304() const
 {
     static const http_hdr_type ImsEntries[] = {HDR_DATE, HDR_CONTENT_TYPE, HDR_EXPIRES, HDR_LAST_MODIFIED, /* eof */ HDR_OTHER};
 
     HttpReply *rv = new HttpReply;
     int t;
     HttpHeaderEntry *e;
 
     /* rv->content_length; */
     rv->date = date;
     rv->last_modified = last_modified;
     rv->expires = expires;
     rv->content_type = content_type;
     /* rv->cache_control */
     /* rv->content_range */
     /* rv->keep_alive */
-    rv->sline.set(Http::ProtocolVersion(1,1), Http::scNotModified, NULL);
+    rv->sline.set(Http::ProtocolVersion(), Http::scNotModified, NULL);
 
     for (t = 0; ImsEntries[t] != HDR_OTHER; ++t)
         if ((e = header.findEntry(ImsEntries[t])))
             rv->header.addEntry(e->clone());
 
     /* rv->body */
     return rv;
 }
 
 MemBuf *
 HttpReply::packed304Reply()
 {
     /* Not as efficient as skipping the header duplication,
      * but easier to maintain
      */
     HttpReply *temp = make304();
     MemBuf *rv = temp->pack();
     delete temp;
     return rv;
 }
 
 void
 HttpReply::setHeaders(Http::StatusCode status, const char *reason,
                       const char *ctype, int64_t clen, time_t lmt, time_t expiresTime)
 {
     HttpHeader *hdr;
-    sline.set(Http::ProtocolVersion(1,1), status, reason);
+    sline.set(Http::ProtocolVersion(), status, reason);
     hdr = &header;
     hdr->putStr(HDR_SERVER, visible_appname_string);
     hdr->putStr(HDR_MIME_VERSION, "1.0");
     hdr->putTime(HDR_DATE, squid_curtime);
 
     if (ctype) {
         hdr->putStr(HDR_CONTENT_TYPE, ctype);
         content_type = ctype;
     } else
         content_type = String();
 
     if (clen >= 0)
         hdr->putInt64(HDR_CONTENT_LENGTH, clen);
 
     if (expiresTime >= 0)
         hdr->putTime(HDR_EXPIRES, expiresTime);
 
     if (lmt > 0)		/* this used to be lmt != 0 @?@ */
         hdr->putTime(HDR_LAST_MODIFIED, lmt);
 
     date = squid_curtime;
 
     content_length = clen;
 
     expires = expiresTime;
 
     last_modified = lmt;
 }
 
 void
 HttpReply::redirect(Http::StatusCode status, const char *loc)
 {
     HttpHeader *hdr;
-    sline.set(Http::ProtocolVersion(1,1), status, NULL);
+    sline.set(Http::ProtocolVersion(), status, NULL);
     hdr = &header;
     hdr->putStr(HDR_SERVER, APP_FULLNAME);
     hdr->putTime(HDR_DATE, squid_curtime);
     hdr->putInt64(HDR_CONTENT_LENGTH, 0);
     hdr->putStr(HDR_LOCATION, loc);
     date = squid_curtime;
     content_length = 0;
 }
 
 /* compare the validators of two replies.
  * 1 = they match
  * 0 = they do not match
  */
 int
 HttpReply::validatorsMatch(HttpReply const * otherRep) const
 {
     String one,two;
     assert (otherRep);
     /* Numbers first - easiest to check */
     /* Content-Length */
@@ -460,41 +460,41 @@
         debugs(58, 3, "HttpReply::sanityCheckStartLine: missing or invalid status number in '" << buf->content() << "'");
         *error = Http::scInvalidHeader;
         return false;
     }
 
     return true;
 }
 
 bool
 HttpReply::parseFirstLine(const char *blk_start, const char *blk_end)
 {
     return sline.parse(protoPrefix, blk_start, blk_end);
 }
 
 /* handy: resets and returns -1 */
 int
 HttpReply::httpMsgParseError()
 {
     int result(HttpMsg::httpMsgParseError());
     /* indicate an error in the status line */
-    sline.set(Http::ProtocolVersion(1,1), Http::scInvalidHeader);
+    sline.set(Http::ProtocolVersion(), Http::scInvalidHeader);
     return result;
 }
 
 /*
  * Indicate whether or not we would usually expect an entity-body
  * along with this response
  */
 bool
 HttpReply::expectingBody(const HttpRequestMethod& req_method, int64_t& theSize) const
 {
     bool expectBody = true;
 
     if (req_method == Http::METHOD_HEAD)
         expectBody = false;
     else if (sline.status() == Http::scNoContent)
         expectBody = false;
     else if (sline.status() == Http::scNotModified)
         expectBody = false;
     else if (sline.status() < Http::scOkay)
         expectBody = false;

=== modified file 'src/client_side_reply.cc'
--- src/client_side_reply.cc	2014-09-13 13:59:43 +0000
+++ src/client_side_reply.cc	2014-12-06 18:21:46 +0000
@@ -1452,41 +1452,41 @@
          */
         authenticateFixHeader(reply, request->auth_user_request, request, 0, 1);
     } else if (request->auth_user_request != NULL)
         authenticateFixHeader(reply, request->auth_user_request, request, http->flags.accel, 0);
 #endif
 
     /* Append X-Cache */
     httpHeaderPutStrf(hdr, HDR_X_CACHE, "%s from %s",
                       is_hit ? "HIT" : "MISS", getMyHostname());
 
 #if USE_CACHE_DIGESTS
     /* Append X-Cache-Lookup: -- temporary hack, to be removed @?@ @?@ */
     httpHeaderPutStrf(hdr, HDR_X_CACHE_LOOKUP, "%s from %s:%d",
                       lookup_type ? lookup_type : "NONE",
                       getMyHostname(), getMyPort());
 
 #endif
 
     const bool maySendChunkedReply = !request->multipartRangeRequest() &&
                                      reply->sline.protocol == AnyP::PROTO_HTTP && // response is HTTP
-                                     (request->http_ver >= Http::ProtocolVersion(1, 1));
+                                     (request->http_ver >= Http::ProtocolVersion(1,1));
 
     /* Check whether we should send keep-alive */
     if (!Config.onoff.error_pconns && reply->sline.status() >= 400 && !request->flags.mustKeepalive) {
         debugs(33, 3, "clientBuildReplyHeader: Error, don't keep-alive");
         request->flags.proxyKeepalive = false;
     } else if (!Config.onoff.client_pconns && !request->flags.mustKeepalive) {
         debugs(33, 2, "clientBuildReplyHeader: Connection Keep-Alive not requested by admin or client");
         request->flags.proxyKeepalive = false;
     } else if (request->flags.proxyKeepalive && shutting_down) {
         debugs(88, 3, "clientBuildReplyHeader: Shutting down, don't keep-alive.");
         request->flags.proxyKeepalive = false;
     } else if (request->flags.connectionAuth && !reply->keep_alive) {
         debugs(33, 2, "clientBuildReplyHeader: Connection oriented auth but server side non-persistent");
         request->flags.proxyKeepalive = false;
     } else if (reply->bodySize(request->method) < 0 && !maySendChunkedReply) {
         debugs(88, 3, "clientBuildReplyHeader: can't keep-alive, unknown body size" );
         request->flags.proxyKeepalive = false;
     } else if (fdUsageHigh()&& !request->flags.mustKeepalive) {
         debugs(88, 3, "clientBuildReplyHeader: Not many unused FDs, can't keep-alive");
         request->flags.proxyKeepalive = false;
@@ -1544,42 +1544,42 @@
     /* Surrogate-Control requires Surrogate-Capability from upstream to pass on */
     if ( hdr->has(HDR_SURROGATE_CONTROL) ) {
         if (!request->header.has(HDR_SURROGATE_CAPABILITY)) {
             hdr->delById(HDR_SURROGATE_CONTROL);
         }
         /* TODO: else case: drop any controls intended specifically for our surrogate ID */
     }
 
     httpHdrMangleList(hdr, request, ROR_REPLY);
 }
 
 void
 clientReplyContext::cloneReply()
 {
     assert(reply == NULL);
 
     reply = http->storeEntry()->getReply()->clone();
     HTTPMSGLOCK(reply);
 
     if (reply->sline.protocol == AnyP::PROTO_HTTP) {
-        /* RFC 2616 requires us to advertise our 1.1 version (but only on real HTTP traffic) */
-        reply->sline.version = Http::ProtocolVersion(1,1);
+        /* RFC 2616 requires us to advertise our version (but only on real HTTP traffic) */
+        reply->sline.version = Http::ProtocolVersion();
     }
 
     /* do header conversions */
     buildReplyHeader();
 }
 
 /// Safely disposes of an entry pointing to a cache hit that we do not want.
 /// We cannot just ignore the entry because it may be locking or otherwise
 /// holding an associated cache resource of some sort.
 void
 clientReplyContext::forgetHit()
 {
     StoreEntry *e = http->storeEntry();
     assert(e); // or we are not dealing with a hit
     // We probably have not locked the entry earlier, unfortunately. We lock it
     // now so that we can unlock two lines later (and trigger cleanup).
     // Ideally, ClientHttpRequest::storeEntry() should lock/unlock, but it is
     // used so inconsistently that simply adding locking there leads to bugs.
     e->lock("clientReplyContext::forgetHit");
     http->storeEntry(NULL);

=== modified file 'src/client_side_request.cc'
--- src/client_side_request.cc	2014-12-04 16:01:10 +0000
+++ src/client_side_request.cc	2014-12-06 18:23:29 +0000
@@ -349,42 +349,41 @@
      * request, not subject to acceleration
      * target overrides */
     /*
      * FIXME? Do we want to detect and handle internal requests of internal
      * objects ?
      */
 
     /* Internally created requests cannot have bodies today */
     request->content_length = 0;
 
     request->client_addr.setNoAddr();
 
 #if FOLLOW_X_FORWARDED_FOR
     request->indirect_client_addr.setNoAddr();
 #endif /* FOLLOW_X_FORWARDED_FOR */
 
     request->my_addr.setNoAddr();	/* undefined for internal requests */
 
     request->my_addr.port(0);
 
-    /* Our version is HTTP/1.1 */
-    request->http_ver = Http::ProtocolVersion(1,1);
+    request->http_ver = Http::ProtocolVersion();
 
     http->request = request;
     HTTPMSGLOCK(http->request);
 
     /* optional - skip the access check ? */
     http->calloutContext = new ClientRequestContext(http);
 
     http->calloutContext->http_access_done = false;
 
     http->calloutContext->redirect_done = true;
 
     http->calloutContext->no_cache_done = true;
 
     http->doCallouts();
 
     return 0;
 }
 
 bool
 ClientRequestContext::httpStateIsValid()

=== modified file 'src/ftp/Elements.cc'
--- src/ftp/Elements.cc	2014-09-13 13:59:43 +0000
+++ src/ftp/Elements.cc	2014-12-06 16:51:25 +0000
@@ -14,41 +14,41 @@
 #include "HttpReply.h"
 #include "SBuf.h"
 
 // FTP does not have a notion of a "protocol version" but we need something for
 // compatibility with the current HttpMsg wrapping layer. We use version 1.1:
 // * some ICAP services probably expect /1.0 or /1.1 when parsing HTTP headers;
 // * FTP commands are sent on a "persistent by default" connection, just like
 //   HTTP/1.1. Using 1.1 leads to fewer exceptions in current code shared by
 //   HTTP and FTP.
 AnyP::ProtocolVersion
 Ftp::ProtocolVersion()
 {
     return AnyP::ProtocolVersion(AnyP::PROTO_FTP, 1, 1);
 }
 
 HttpReply *
 Ftp::HttpReplyWrapper(const int ftpStatus, const char *ftpReason, const Http::StatusCode httpStatus, const int64_t clen)
 {
     HttpReply *const reply = new HttpReply;
 
-    Http::ProtocolVersion httpVersion = Http::ProtocolVersion(
+    AnyP::ProtocolVersion httpVersion = Http::ProtocolVersion(
                                             Ftp::ProtocolVersion().major, Ftp::ProtocolVersion().minor);
     reply->sline.set(httpVersion, httpStatus);
 
     HttpHeader &header = reply->header;
     header.putTime(HDR_DATE, squid_curtime);
     {
         HttpHdrCc cc;
         cc.Private(String());
         header.putCc(&cc);
     }
     if (ftpStatus > 0)
         header.putInt(HDR_FTP_STATUS, ftpStatus);
     if (ftpReason)
         header.putStr(HDR_FTP_REASON, ftpReason);
     if (clen >= 0)
         header.putInt64(HDR_CONTENT_LENGTH, clen);
     reply->hdrCacheInit();
     return reply;
 }
 

=== modified file 'src/http.cc'
--- src/http.cc	2014-12-03 15:13:08 +0000
+++ src/http.cc	2014-12-06 18:20:14 +0000
@@ -705,41 +705,41 @@
     Http::StatusCode error = Http::scNone;
 
     HttpReply *newrep = new HttpReply;
     const bool parsed = newrep->parse(readBuf, eof, &error);
 
     if (!parsed && readBuf->contentSize() > 5 && strncmp(readBuf->content(), "HTTP/", 5) != 0 && strncmp(readBuf->content(), "ICY", 3) != 0) {
         MemBuf *mb;
         HttpReply *tmprep = new HttpReply;
         tmprep->setHeaders(Http::scOkay, "Gatewaying", NULL, -1, -1, -1);
         tmprep->header.putExt("X-Transformed-From", "HTTP/0.9");
         mb = tmprep->pack();
         newrep->parse(mb, eof, &error);
         delete mb;
         delete tmprep;
     } else {
         if (!parsed && error > 0) { // unrecoverable parsing error
             debugs(11, 3, "processReplyHeader: Non-HTTP-compliant header: '" <<  readBuf->content() << "'");
             flags.headers_parsed = true;
             // XXX: when sanityCheck is gone and Http::StatusLine is used to parse,
             //   the sline should be already set the appropriate values during that parser stage
-            newrep->sline.set(Http::ProtocolVersion(1,1), error);
+            newrep->sline.set(Http::ProtocolVersion(), error);
             HttpReply *vrep = setVirginReply(newrep);
             entry->replaceHttpReply(vrep);
             ctx_exit(ctx);
             return;
         }
 
         if (!parsed) { // need more data
             assert(!error);
             assert(!eof);
             delete newrep;
             ctx_exit(ctx);
             return;
         }
 
         debugs(11, 2, "HTTP Server " << serverConnection);
         debugs(11, 2, "HTTP Server REPLY:\n---------\n" << readBuf->content() << "\n----------");
 
         header_bytes_read = headersEnd(readBuf->content(), readBuf->contentSize());
         readBuf->consume(header_bytes_read);
     }
@@ -1244,41 +1244,41 @@
     }
 
     if (!flags.headers_parsed && !eof) {
         debugs(11, 9, HERE << "needs more at " << readBuf->contentSize());
         flags.do_next_read = true;
         /** \retval false If we have not finished parsing the headers and may get more data.
          *                Schedules more reads to retrieve the missing data.
          */
         maybeReadVirginBody(); // schedules all kinds of reads; TODO: rename
         return false;
     }
 
     /** If we are done with parsing, check for errors */
 
     err_type error = ERR_NONE;
 
     if (flags.headers_parsed) { // parsed headers, possibly with errors
         // check for header parsing errors
         if (HttpReply *vrep = virginReply()) {
             const Http::StatusCode s = vrep->sline.status();
-            const Http::ProtocolVersion &v = vrep->sline.version;
+            const AnyP::ProtocolVersion &v = vrep->sline.version;
             if (s == Http::scInvalidHeader && v != Http::ProtocolVersion(0,9)) {
                 debugs(11, DBG_IMPORTANT, "WARNING: HTTP: Invalid Response: Bad header encountered from " << entry->url() << " AKA " << request->GetHost() << request->urlpath.termedBuf() );
                 error = ERR_INVALID_RESP;
             } else if (s == Http::scHeaderTooLarge) {
                 fwd->dontRetry(true);
                 error = ERR_TOO_BIG;
             } else {
                 return true; // done parsing, got reply, and no error
             }
         } else {
             // parsed headers but got no reply
             debugs(11, DBG_IMPORTANT, "WARNING: HTTP: Invalid Response: No reply at all for " << entry->url() << " AKA " << request->GetHost() << request->urlpath.termedBuf() );
             error = ERR_INVALID_RESP;
         }
     } else {
         assert(eof);
         if (readBuf->hasContent()) {
             error = ERR_INVALID_RESP;
             debugs(11, DBG_IMPORTANT, "WARNING: HTTP: Invalid Response: Headers did not parse at all for " << entry->url() << " AKA " << request->GetHost() << request->urlpath.termedBuf() );
         } else {
@@ -2065,47 +2065,47 @@
 
     int64_t roffLimit = request->getRangeOffsetLimit();
 
     if (NULL == request->range || !request->flags.cachable
             || request->range->offsetLimitExceeded(roffLimit) || request->flags.connectionAuth)
         result = false;
 
     debugs(11, 8, "decideIfWeDoRanges: range specs: " <<
            request->range << ", cachable: " <<
            request->flags.cachable << "; we_do_ranges: " << result);
 
     return result;
 }
 
 /* build request prefix and append it to a given MemBuf;
  * return the length of the prefix */
 mb_size_t
 HttpStateData::buildRequestPrefix(MemBuf * mb)
 {
     const int offset = mb->size;
-    /* Uses a local httpver variable to print the HTTP/1.1 label
+    /* Uses a local httpver variable to print the HTTP label
      * since the HttpRequest may have an older version label.
      * XXX: This could create protocol bugs as the headers sent and
      * flow control should all be based on the HttpRequest version
      * not the one we are sending. Needs checking.
      */
-    Http::ProtocolVersion httpver(1,1);
+    const AnyP::ProtocolVersion httpver = Http::ProtocolVersion();
     const char * url;
     if (_peer && !_peer->options.originserver)
         url = urlCanonical(request);
     else
         url = request->urlpath.termedBuf();
     mb->Printf(SQUIDSBUFPH " %s %s/%d.%d\r\n",
                SQUIDSBUFPRINT(request->method.image()),
                url && *url ? url : "/",
                AnyP::ProtocolType_str[httpver.protocol],
                httpver.major,httpver.minor);
     /* build and pack headers */
     {
         HttpHeader hdr(hoRequest);
         Packer p;
         httpBuildRequestHeader(request, entry, fwd->al, &hdr, flags);
 
         if (request->flags.pinned && request->flags.connectionAuth)
             request->flags.authSent = true;
         else if (hdr.has(HDR_AUTHORIZATION))
             request->flags.authSent = true;

=== modified file 'src/http/ProtocolVersion.h'
--- src/http/ProtocolVersion.h	2014-09-13 13:59:43 +0000
+++ src/http/ProtocolVersion.h	2014-12-06 16:44:42 +0000
@@ -1,34 +1,39 @@
 /*
  * Copyright (C) 1996-2014 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_HTTP_PROTOCOLVERSION_H
 #define SQUID_HTTP_PROTOCOLVERSION_H
 
 #include "anyp/ProtocolVersion.h"
 
 namespace Http
 {
 
+/// HTTP version label information
+inline AnyP::ProtocolVersion
+ProtocolVersion(unsigned int aMajor, unsigned int aMinor)
+{
+    return AnyP::ProtocolVersion(AnyP::PROTO_HTTP,aMajor,aMinor);
+}
+
 /**
- * Stores HTTP version label information.
+ * HTTP version label information.
  *
  * Squid being conditionally compliant with RFC 2616
  * on both client and server connections the default
  * value is HTTP/1.1.
  */
-class ProtocolVersion : public AnyP::ProtocolVersion
+inline AnyP::ProtocolVersion
+ProtocolVersion()
 {
-public:
-    ProtocolVersion() : AnyP::ProtocolVersion(AnyP::PROTO_HTTP,1,1) {}
-
-    ProtocolVersion(unsigned int aMajor, unsigned int aMinor) : AnyP::ProtocolVersion(AnyP::PROTO_HTTP,aMajor,aMinor) {}
-};
+  return AnyP::ProtocolVersion(AnyP::PROTO_HTTP,1,1);
+}
 
 }; // namespace Http
 
 #endif /* SQUID_HTTP_PROTOCOLVERSION_H */

=== modified file 'src/http/StatusLine.cc'
--- src/http/StatusLine.cc	2014-09-13 13:59:43 +0000
+++ src/http/StatusLine.cc	2014-12-06 18:07:58 +0000
@@ -10,41 +10,41 @@
 
 #include "squid.h"
 #include "Debug.h"
 #include "http/StatusLine.h"
 #include "Packer.h"
 
 void
 Http::StatusLine::init()
 {
     set(Http::ProtocolVersion(), Http::scNone, NULL);
 }
 
 void
 Http::StatusLine::clean()
 {
     set(Http::ProtocolVersion(), Http::scInternalServerError, NULL);
 }
 
 /* set values */
 void
-Http::StatusLine::set(const Http::ProtocolVersion &newVersion, const Http::StatusCode newStatus, const char *newReason)
+Http::StatusLine::set(const AnyP::ProtocolVersion &newVersion, const Http::StatusCode newStatus, const char *newReason)
 {
     protocol = AnyP::PROTO_HTTP;
     version = newVersion;
     status_ = newStatus;
     /* Note: no xstrdup for 'reason', assumes constant 'reasons' */
     reason_ = newReason;
 }
 
 const char *
 Http::StatusLine::reason() const
 {
     return reason_ ? reason_ : Http::StatusCodeString(status());
 }
 
 void
 Http::StatusLine::packInto(Packer * p) const
 {
     assert(p);
 
     /* local constants */

=== modified file 'src/http/StatusLine.h'
--- src/http/StatusLine.h	2014-09-13 13:59:43 +0000
+++ src/http/StatusLine.h	2014-12-06 16:47:44 +0000
@@ -18,61 +18,61 @@
 
 namespace Http
 {
 
 /**
  * Holds the values parsed from an HTTP reply status line.
  *
  * For example: HTTP/1.1 200 OK
  */
 class StatusLine
 {
 public:
     /// reset this status-line back to empty state
     void init();
 
     /// reset this status-line back to Internal Server Error state
     void clean();
 
     /// set this status-line to the given values
     /// when reason is NULL the default message text for this StatusCode will be used
-    void set(const Http::ProtocolVersion &newVersion, Http::StatusCode newStatus, const char *newReason = NULL);
+    void set(const AnyP::ProtocolVersion &newVersion, Http::StatusCode newStatus, const char *newReason = NULL);
 
     /// retrieve the status code for this status line
     Http::StatusCode status() const { return status_; }
 
     /// retrieve the reason string for this status line
     const char *reason() const;
 
     /// pack fields using Packer
     void packInto(Packer * p) const;
 
     /**
      * Parse a buffer and fill internal structures;
      * \return true on success, false otherwise
      */
     bool parse(const String &protoPrefix, const char *start, const char *end);
 
 public:
     /* public, read only */
 
     /**
      * By rights protocol name should be a constant "HTTP", with no need for this field to exist.
      * However there are protocols which violate HTTP by sending their own custom formats
      * back with other protocol names (ICY streaming format being the current major problem).
      */
-    // XXX: protocol is part of Http::ProtocolVersion. We should be able to use version.protocol instead now.
+    // XXX: protocol is part of AnyP::ProtocolVersion. We should be able to use version.protocol instead now.
     AnyP::ProtocolType protocol;
 
-    Http::ProtocolVersion version;     ///< breakdown of protocol version label: (HTTP/ICY) and (0.9/1.0/1.1)
+    AnyP::ProtocolVersion version;     ///< breakdown of protocol version label: (HTTP/ICY) and (0.9/1.0/1.1)
 
 private:
     /// status code. ie 100 ... 200 ... 404 ... 599
     Http::StatusCode status_;
 
     /// points to a _constant_ string (default or supplied), never free()d
     const char *reason_;
 };
 
 } // namespace Http
 
 #endif /* SQUID_HTTP_STATUSLINE_H */

=== modified file 'src/icmp/net_db.cc'
--- src/icmp/net_db.cc	2014-12-01 04:05:48 +0000
+++ src/icmp/net_db.cc	2014-12-06 18:21:55 +0000
@@ -1276,41 +1276,41 @@
 #if USE_ICMP
     CachePeer *p = (CachePeer *)data;
     char *uri;
     netdbExchangeState *ex;
     StoreIOBuffer tempBuffer;
     CBDATA_INIT_TYPE(netdbExchangeState);
     ex = cbdataAlloc(netdbExchangeState);
     ex->p = cbdataReference(p);
     uri = internalRemoteUri(p->host, p->http_port, "/squid-internal-dynamic/", "netdb");
     debugs(38, 3, "netdbExchangeStart: Requesting '" << uri << "'");
     assert(NULL != uri);
     ex->r = HttpRequest::CreateFromUrl(uri);
 
     if (NULL == ex->r) {
         debugs(38, DBG_IMPORTANT, "netdbExchangeStart: Bad URI " << uri);
         return;
     }
 
     HTTPMSGLOCK(ex->r);
     assert(NULL != ex->r);
-    ex->r->http_ver = Http::ProtocolVersion(1,1);
+    ex->r->http_ver = Http::ProtocolVersion();
     ex->connstate = STATE_HEADER;
     ex->e = storeCreateEntry(uri, uri, RequestFlags(), Http::METHOD_GET);
     ex->buf_sz = NETDB_REQBUF_SZ;
     assert(NULL != ex->e);
     ex->sc = storeClientListAdd(ex->e, ex);
     tempBuffer.offset = 0;
     tempBuffer.length = ex->buf_sz;
     tempBuffer.data = ex->buf;
     storeClientCopy(ex->sc, ex->e, tempBuffer,
                     netdbExchangeHandleReply, ex);
     ex->r->flags.loopDetected = true;	/* cheat! -- force direct */
 
     // XXX: send as Proxy-Authenticate instead
     if (p->login)
         ex->r->url.userInfo(SBuf(p->login));
 
     urlCanonical(ex->r);
 
     FwdState::fwdStart(Comm::ConnectionPointer(), ex->e, ex->r);
 

=== modified file 'src/servers/HttpServer.cc'
--- src/servers/HttpServer.cc	2014-11-10 12:11:20 +0000
+++ src/servers/HttpServer.cc	2014-12-06 18:24:57 +0000
@@ -240,41 +240,41 @@
 {
     debugs(33, 5, "Body Continuation written");
     clientProcessRequest(this, parser_, context.getRaw());
 }
 
 void
 Http::Server::processParsedRequest(ClientSocketContext *context)
 {
     if (!buildHttpRequest(context))
         return;
 
     if (Config.accessList.forceRequestBodyContinuation) {
         ClientHttpRequest *http = context->http;
         HttpRequest *request = http->request;
         ACLFilledChecklist bodyContinuationCheck(Config.accessList.forceRequestBodyContinuation, request, NULL);
         if (bodyContinuationCheck.fastCheck() == ACCESS_ALLOWED) {
             debugs(33, 5, "Body Continuation forced");
             request->forcedBodyContinuation = true;
             //sendControlMsg
             HttpReply::Pointer rep = new HttpReply;
-            rep->sline.set(Http::ProtocolVersion(1,1), Http::scContinue);
+            rep->sline.set(Http::ProtocolVersion(), Http::scContinue);
 
             typedef UnaryMemFunT<Http::Server, ClientSocketContext::Pointer> CbDialer;
             const AsyncCall::Pointer cb = asyncCall(11, 3,  "Http::Server::proceedAfterBodyContinuation", CbDialer(this, &Http::Server::proceedAfterBodyContinuation, ClientSocketContext::Pointer(context)));
             sendControlMsg(HttpControlMsg(rep, cb));
             return;
         }
     }
     clientProcessRequest(this, parser_, context);
 }
 
 void
 Http::Server::noteBodyConsumerAborted(BodyPipe::Pointer ptr)
 {
     ConnStateData::noteBodyConsumerAborted(ptr);
     stopReceiving("virgin request body consumer aborted"); // closes ASAP
 }
 
 void
 Http::Server::handleReply(HttpReply *rep, StoreIOBuffer receivedData)
 {

-------------- next part --------------
A non-text attachment was scrubbed...
Name: HttpProtocolVersion_update_mk1.patch.sig
Type: application/octet-stream
Size: 287 bytes
Desc: not available
URL: <http://lists.squid-cache.org/pipermail/squid-dev/attachments/20141207/f7a4f1a3/attachment-0001.obj>


More information about the squid-dev mailing list