]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/tunnel.cc
Supply AccessLogEntry (ALE) for more fast ACL checks. (#182)
[thirdparty/squid.git] / src / tunnel.cc
index c50bf70a9c25cf407a97a98438daf4e6454c1d9b..28bfb4b74563659d428e54c1b8cb80b3c76aa78c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
@@ -416,6 +416,7 @@ TunnelStateData::readServer(char *, size_t len, Comm::Flag errcode, int xerrno)
         server.bytesIn(len);
         statCounter.server.all.kbytes_in += len;
         statCounter.server.other.kbytes_in += len;
+        request->hier.notePeerRead();
     }
 
     if (keepGoingAfterRead(len, errcode, xerrno, server, client))
@@ -437,6 +438,7 @@ TunnelStateData::readConnectResponseDone(char *, size_t len, Comm::Flag errcode,
         server.bytesIn(len);
         statCounter.server.all.kbytes_in += len;
         statCounter.server.other.kbytes_in += len;
+        request->hier.notePeerRead();
     }
 
     if (keepGoingAfterRead(len, errcode, xerrno, server, client))
@@ -522,19 +524,13 @@ TunnelStateData::handleConnectResponse(const size_t chunkSize)
     }
 
     // CONNECT response was successfully parsed
-    *status_ptr = rep.sline.status();
-
-    // we need to relay the 401/407 responses when login=PASS(THRU)
-    const CachePeer *peer = server.conn->getPeer();
-    const char *pwd = (peer ? peer->login : nullptr);
-    const bool relay = pwd && (strcmp(pwd, "PASS") == 0 || strcmp(pwd, "PASSTHRU") == 0) &&
-                       (*status_ptr == Http::scProxyAuthenticationRequired ||
-                        *status_ptr == Http::scUnauthorized);
+    request->hier.peer_reply_status = rep.sline.status();
 
     // bail if we did not get an HTTP 200 (Connection Established) response
     if (rep.sline.status() != Http::scOkay) {
         // if we ever decide to reuse the peer connection, we must extract the error response first
-        informUserOfPeerError("unsupported CONNECT response status code", (relay ? rep.hdr_sz : 0));
+        *status_ptr = rep.sline.status(); // we are relaying peer response
+        informUserOfPeerError("unsupported CONNECT response status code", rep.hdr_sz);
         return;
     }
 
@@ -664,12 +660,15 @@ TunnelStateData::writeServerDone(char *, size_t len, Comm::Flag flag, int xerrno
 {
     debugs(26, 3, HERE  << server.conn << ", " << len << " bytes written, flag=" << flag);
 
+    if (flag == Comm::ERR_CLOSING)
+        return;
+
+    request->hier.notePeerWrite();
+
     /* Error? */
     if (flag != Comm::OK) {
-        if (flag != Comm::ERR_CLOSING) {
-            debugs(26, 4, HERE << "calling TunnelStateData::server.error(" << xerrno <<")");
-            server.error(xerrno); // may call comm_close
-        }
+        debugs(26, 4, "to-server write failed: " << xerrno);
+        server.error(xerrno); // may call comm_close
         return;
     }
 
@@ -719,6 +718,7 @@ TunnelStateData::Connection::dataSent(size_t amount)
 
     if (size_ptr)
         *size_ptr += amount;
+
 }
 
 void
@@ -733,12 +733,13 @@ TunnelStateData::writeClientDone(char *, size_t len, Comm::Flag flag, int xerrno
 {
     debugs(26, 3, HERE << client.conn << ", " << len << " bytes written, flag=" << flag);
 
+    if (flag == Comm::ERR_CLOSING)
+        return;
+
     /* Error? */
     if (flag != Comm::OK) {
-        if (flag != Comm::ERR_CLOSING) {
-            debugs(26, 4, HERE << "Closing client connection due to comm flags.");
-            client.error(xerrno); // may call comm_close
-        }
+        debugs(26, 4, "from-client read failed: " << xerrno);
+        client.error(xerrno); // may call comm_close
         return;
     }
 
@@ -928,19 +929,24 @@ tunnelConnectedWriteDone(const Comm::ConnectionPointer &conn, char *, size_t len
 
 /// Called when we are done writing CONNECT request to a peer.
 static void
-tunnelConnectReqWriteDone(const Comm::ConnectionPointer &conn, char *, size_t, Comm::Flag flag, int, void *data)
+tunnelConnectReqWriteDone(const Comm::ConnectionPointer &conn, char *, size_t ioSize, Comm::Flag flag, int, void *data)
 {
     TunnelStateData *tunnelState = (TunnelStateData *)data;
     debugs(26, 3, conn << ", flag=" << flag);
     tunnelState->server.writer = NULL;
     assert(tunnelState->waitingForConnectRequest());
 
+    tunnelState->request->hier.notePeerWrite();
+
     if (flag != Comm::OK) {
         *tunnelState->status_ptr = Http::scInternalServerError;
         tunnelErrorComplete(conn->fd, data, 0);
         return;
     }
 
+    statCounter.server.all.kbytes_out += ioSize;
+    statCounter.server.other.kbytes_out += ioSize;
+
     tunnelState->connectReqWriting = false;
     tunnelState->connectExchangeCheckpoint();
 }
@@ -971,6 +977,7 @@ tunnelConnected(const Comm::ConnectionPointer &server, void *data)
     if (!tunnelState->clientExpectsConnectResponse())
         tunnelStartShoveling(tunnelState); // ssl-bumped connection, be quiet
     else {
+        *tunnelState->status_ptr = Http::scOkay;
         AsyncCall::Pointer call = commCbCall(5,5, "tunnelConnectedWriteDone",
                                              CommIoCbPtrFun(tunnelConnectedWriteDone, tunnelState));
         tunnelState->client.write(conn_established, strlen(conn_established), call, NULL);
@@ -1043,7 +1050,7 @@ tunnelConnectDone(const Comm::ConnectionPointer &conn, Comm::Flag status, int xe
         tunnelState->server.setDelayId(DelayId());
 #endif
 
-    tunnelState->request->hier.note(conn, tunnelState->getHost());
+    tunnelState->request->hier.resetPeerNotes(conn, tunnelState->getHost());
 
     tunnelState->server.conn = conn;
     tunnelState->request->peer_host = conn->getPeer() ? conn->getPeer()->host : NULL;
@@ -1095,9 +1102,11 @@ tunnelStart(ClientHttpRequest * http)
          * default is to allow.
          */
         ACLFilledChecklist ch(Config.accessList.miss, request, NULL);
+        ch.al = http->al;
         ch.src_addr = request->client_addr;
         ch.my_addr = request->my_addr;
-        if (ch.fastCheck() == ACCESS_DENIED) {
+        ch.syncAle(request, http->log_uri);
+        if (ch.fastCheck().denied()) {
             debugs(26, 4, HERE << "MISS access forbidden.");
             err = new ErrorState(ERR_FORWARDING_DENIED, Http::scForbidden, request);
             http->al->http.code = Http::scForbidden;
@@ -1220,7 +1229,7 @@ void
 TunnelStateData::noteDestinationsEnd(ErrorState *selectionError)
 {
     PeerSelectionInitiator::subscribed = false;
-    if (const bool wasBlocked = serverDestinations.empty()) {
+    if (serverDestinations.empty()) { // was blocked, waiting for more paths
 
         if (selectionError)
             return sendError(selectionError, "path selection has failed");
@@ -1343,7 +1352,7 @@ switchToTunnel(HttpRequest *request, Comm::ConnectionPointer &clientConn, Comm::
     fd_table[clientConn->fd].read_method = &default_read_method;
     fd_table[clientConn->fd].write_method = &default_write_method;
 
-    request->hier.note(srvConn, tunnelState->getHost());
+    request->hier.resetPeerNotes(srvConn, tunnelState->getHost());
 
     tunnelState->server.conn = srvConn;