]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/client_side_request.cc
Merge form trunk
[thirdparty/squid.git] / src / client_side_request.cc
index bdc3040829cea378409e527355f612e634360b0a..4608f180c052779e73bc7f4cb157503c225e9b2e 100644 (file)
 #include "fde.h"
 #include "HttpReply.h"
 #include "HttpRequest.h"
+#include "ip/QosConfig.h"
 #include "MemObject.h"
 #include "ProtoPort.h"
 #include "Store.h"
 #include "SquidTime.h"
 #include "wordlist.h"
+#include "err_detail_type.h"
 
 
 #if LINGERING_CLOSE
@@ -160,6 +162,7 @@ ClientHttpRequest::ClientHttpRequest(ConnStateData * aConn) :
 {
     start_time = current_time;
     setConn(aConn);
+    clientConnection = aConn->clientConn;
     dlinkAdd(this, &active, &ClientActiveRequests);
 #if USE_ADAPTATION
     request_satisfaction_mode = false;
@@ -274,6 +277,8 @@ ClientHttpRequest::~ClientHttpRequest()
     if (calloutContext)
         delete calloutContext;
 
+    clientConnection = NULL;
+
     if (conn_)
         cbdataReferenceDone(conn_);
 
@@ -621,7 +626,7 @@ ClientRequestContext::clientAccessCheckDone(int answer)
         tmpnoaddr.SetNoAddr();
         repContext->setReplyToError(page_id, status,
                                     http->request->method, NULL,
-                                    http->getConn() != NULL ? http->getConn()->peer : tmpnoaddr,
+                                    http->getConn() != NULL ? http->getConn()->clientConn->remote : tmpnoaddr,
                                     http->request,
                                     NULL,
                                     http->getConn() != NULL && http->getConn()->auth_user_request != NULL ?
@@ -1021,11 +1026,18 @@ ClientRequestContext::clientRedirectDone(char *result)
             if ((t = strchr(result, ':')) != NULL) {
                 http->redirect.status = status;
                 http->redirect.location = xstrdup(t + 1);
+                // TODO: validate the URL produced here is RFC 2616 compliant absolute URI
             } else {
-                debugs(85, 1, "clientRedirectDone: bad input: " << result);
+                if (old_request->http_ver < HttpVersion(1,1))
+                    debugs(85, DBG_CRITICAL, "ERROR: URL-rewrite produces invalid 302 redirect Location: " << result);
+                else
+                    debugs(85, DBG_CRITICAL, "ERROR: URL-rewrite produces invalid 303 redirect Location: " << result);
             }
-        } else if (strcmp(result, http->uri))
-            new_request = HttpRequest::CreateFromUrlAndMethod(result, old_request->method);
+        } else if (strcmp(result, http->uri)) {
+            if (!(new_request = HttpRequest::CreateFromUrlAndMethod(result, old_request->method)))
+                debugs(85, DBG_CRITICAL, "ERROR: URL-rewrite produces invalid request: " <<
+                       old_request->method << " " << result << " HTTP/1.1");
+        }
     }
 
     if (new_request) {
@@ -1161,7 +1173,7 @@ ClientHttpRequest::sslBumpNeeded() const
 
 // called when comm_write has completed
 static void
-SslBumpEstablish(int, char *, size_t, comm_err_t errflag, int, void *data)
+SslBumpEstablish(const Comm::ConnectionPointer &, char *, size_t, comm_err_t errflag, int, void *data)
 {
     ClientHttpRequest *r = static_cast<ClientHttpRequest*>(data);
     debugs(85, 5, HERE << "responded to CONNECT: " << r << " ? " << errflag);
@@ -1193,10 +1205,8 @@ ClientHttpRequest::sslBumpStart()
     debugs(33, 7, HERE << "Confirming CONNECT tunnel on FD " << getConn()->clientConn);
 
     // TODO: Unify with tunnel.cc and add a Server(?) header
-    static const char *const conn_established =
-        "HTTP/1.0 200 Connection established\r\n\r\n";
-    comm_write(getConn()->clientConn->fd, conn_established, strlen(conn_established),
-               &SslBumpEstablish, this, NULL);
+    static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n";
+    comm_write(getConn()->clientConn, conn_established, strlen(conn_established), &SslBumpEstablish, this, NULL);
 }
 
 #endif
@@ -1265,7 +1275,8 @@ ClientHttpRequest::loggingEntry(StoreEntry *newEntry)
  * the callout.  This is strictly for convenience.
  */
 
-extern int aclMapTOS (acl_tos * head, ACLChecklist * ch);
+extern tos_t aclMapTOS (acl_tos * head, ACLChecklist * ch);
+extern nfmark_t aclMapNfmark (acl_nfmark * head, ACLChecklist * ch);
 
 void
 ClientHttpRequest::doCallouts()
@@ -1328,15 +1339,27 @@ ClientHttpRequest::doCallouts()
         }
     }
 
-    if (!calloutContext->clientside_tos_done) {
-        calloutContext->clientside_tos_done = true;
+    if (!calloutContext->tosToClientDone) {
+        calloutContext->tosToClientDone = true;
         if (getConn() != NULL && Comm::IsConnOpen(getConn()->clientConn)) {
             ACLFilledChecklist ch(NULL, request, NULL);
             ch.src_addr = request->client_addr;
             ch.my_addr = request->my_addr;
-            int tos = aclMapTOS(Config.accessList.clientside_tos, &ch);
+            tos_t tos = aclMapTOS(Ip::Qos::TheConfig.tosToClient, &ch);
             if (tos)
-                comm_set_tos(getConn()->clientConn->fd, tos);
+                Ip::Qos::setSockTos(getConn()->clientConn, tos);
+        }
+    }
+
+    if (!calloutContext->nfmarkToClientDone) {
+        calloutContext->nfmarkToClientDone = true;
+        if (getConn() != NULL && Comm::IsConnOpen(getConn()->clientConn)) {
+            ACLFilledChecklist ch(NULL, request, NULL);
+            ch.src_addr = request->client_addr;
+            ch.my_addr = request->my_addr;
+            nfmark_t mark = aclMapNfmark(Ip::Qos::TheConfig.nfmarkToClient, &ch);
+            if (mark)
+                Ip::Qos::setSockNfmark(getConn()->clientConn, mark);
         }
     }
 
@@ -1434,7 +1457,7 @@ ClientHttpRequest::noteAdaptationQueryAbort(bool final)
 {
     clearAdaptation(virginHeadSource);
     assert(!adaptedBodySource);
-    handleAdaptationFailure(!final);
+    handleAdaptationFailure(ERR_DETAIL_ICAP_REQMOD_ABORT, !final);
 }
 
 void
@@ -1487,11 +1510,11 @@ ClientHttpRequest::noteBodyProducerAborted(BodyPipe::Pointer)
 {
     assert(!virginHeadSource);
     stopConsumingFrom(adaptedBodySource);
-    handleAdaptationFailure();
+    handleAdaptationFailure(ERR_DETAIL_ICAP_RESPMOD_CLT_SIDE_BODY);
 }
 
 void
-ClientHttpRequest::handleAdaptationFailure(bool bypassable)
+ClientHttpRequest::handleAdaptationFailure(int errDetail, bool bypassable)
 {
     debugs(85,3, HERE << "handleAdaptationFailure(" << bypassable << ")");
 
@@ -1520,10 +1543,12 @@ ClientHttpRequest::handleAdaptationFailure(bool bypassable)
     ConnStateData * c = getConn();
     repContext->setReplyToError(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR,
                                 request->method, NULL,
-                                (c != NULL ? c->peer : noAddr), request, NULL,
+                                (c != NULL ? c->clientConn->remote : noAddr), request, NULL,
                                 (c != NULL && c->auth_user_request != NULL ?
                                  c->auth_user_request : request->auth_user_request));
 
+    request->detailError(ERR_ICAP_FAILURE, errDetail);
+
     node = (clientStreamNode *)client_stream.tail->data;
     clientStreamRead(node, this, node->readBuffer);
 }