The unified diff between revisions [a8f17161..] and [4d68673c..] is displayed below. It can also be downloaded as a raw diff.

#
#
# patch "include/autoconf.h.in"
#  from [8eb88c7b2be03f205a474a72d77f991efb926408]
#    to [e31503b186fbbd9d8929fc359d4f8854a0ae73ba]
#
# patch "src/HttpRequest.c"
#  from [597291cfa1e0f424bbe5163a389fac4d3df15ca6]
#    to [c7bf9949beedd2ef15ebf64c1e516d81aa8f2185]
#
# patch "src/client_side.c"
#  from [88a65f4660b1ec5b9f8f47f165c77182055cc453]
#    to [aeb1c49f1a704cceb4928f31ac6df0b91c200cad]
#
# patch "src/forward.c"
#  from [e2fc1a6c5fd200cd0174d0c5c2743c0e2c4942be]
#    to [bde01cf37e23444aea4910eed79e76d3371277fb]
#
# patch "src/http.c"
#  from [b0bbfbeb452d1642a4dc436c4c59565fd7a66354]
#    to [69d4e2cd7969e575f5cdba81916aab1f9b2c6223]
#
# patch "src/pconn.c"
#  from [29ed4b99506a1610a2e266faf97e49fc4f027913]
#    to [5f83c46e535d572c2a6d6f55389e635926c3feee]
#
# patch "src/protos.h"
#  from [0415ef0095c3ae7a42ac90385638ebe76af6d316]
#    to [d924404fa81b7d01e6af2836d2ff9e49c5ddabcd]
#
# patch "src/structs.h"
#  from [cc6dcb3d613d4ba93f19194205ec9916efd19e7d]
#    to [8c514b042f35f6fd32b0a73cf21a9643cf2d6cd4]
#
============================================================
--- include/autoconf.h.in	8eb88c7b2be03f205a474a72d77f991efb926408
+++ include/autoconf.h.in	e31503b186fbbd9d8929fc359d4f8854a0ae73ba
@@ -154,6 +154,11 @@
 #define USE_WCCP 1

 /*
+ * Define to enable WCCPv2
+ */
+#define	USE_WCCPv2	1
+
+/*
  * Define this to include code which lets you specify access control
  * elements based on ethernet hardware addresses.  This code uses
  * functions found in 4.4 BSD derviations (e.g. FreeBSD, ?).
============================================================
--- src/HttpRequest.c	597291cfa1e0f424bbe5163a389fac4d3df15ca6
+++ src/HttpRequest.c	c7bf9949beedd2ef15ebf64c1e516d81aa8f2185
@@ -67,9 +67,6 @@ requestDestroy(request_t * req)
 	httpHdrCcDestroy(req->cache_control);
     if (req->range)
 	httpHdrRangeDestroy(req->range);
-    if (req->pinned_connection)
-	cbdataUnlock(req->pinned_connection);
-    req->pinned_connection = NULL;
     memFree(req, MEM_REQUEST_T);
 }

============================================================
--- src/client_side.c	88a65f4660b1ec5b9f8f47f165c77182055cc453
+++ src/client_side.c	aeb1c49f1a704cceb4928f31ac6df0b91c200cad
@@ -965,8 +965,6 @@ connStateFree(int fd, void *data)
 	safe_free(connState->in.buf);
     /* XXX account connState->in.buf */
     pconnHistCount(0, connState->nrequests);
-    if (connState->pinning.fd >= 0)
-	comm_close(connState->pinning.fd);
     cbdataFree(connState);
 #ifdef _SQUID_LINUX_
     /* prevent those nasty RST packets */
@@ -1035,32 +1033,10 @@ clientInterpretRequestHeaders(clientHttp
 	if (request->range)
 	    request->flags.range = 1;
     }
-    if (http->conn->pinning.fd != -1) {
+    if ((httpHeaderHas(req_hdr, HDR_AUTHORIZATION)) || (request->flags.pinned))
 	request->flags.auth = 1;
-	request->pinned_connection = http->conn;
-	cbdataLock(request->pinned_connection);
-    } else if (httpHeaderHas(req_hdr, HDR_AUTHORIZATION)) {
-	HttpHeaderPos pos = HttpHeaderInitPos;
-	HttpHeaderEntry *e;
+    if (request->login[0] != '\0')
 	request->flags.auth = 1;
-	if (!Config.onoff.pipeline_prefetch) {
-	    while ((e = httpHeaderGetEntry(req_hdr, &pos))) {
-		if (e->id == HDR_AUTHORIZATION) {
-		    const char *value = strBuf(e->value);
-		    if ((strncasecmp(value, "NTLM", 4) == 0 &&
-			    (value[4] == '\0' || value[4] == ' '))
-			||
-			(strncasecmp(value, "Negotiate", 9) == 0 &&
-			    (value[9] == '\0' || value[9] == ' '))) {
-			request->pinned_connection = http->conn;
-			cbdataLock(request->pinned_connection);
-			break;
-		    }
-		}
-	    }
-	}
-    } else if (request->login[0] != '\0')
-	request->flags.auth = 1;
     if (httpHeaderHas(req_hdr, HDR_VIA)) {
 	String s = httpHeaderGetList(req_hdr, HDR_VIA);
 	/*
@@ -1470,6 +1446,7 @@ clientBuildReplyHeader(clientHttpRequest
 			(value[9] == '\0' || value[9] == ' '))) {
 		    httpHeaderPutStr(hdr, HDR_PROXY_SUPPORT, "Session-Based-Authentication");
 		    httpHeaderPutStr(hdr, HDR_CONNECTION, "Proxy-support");
+		    request->flags.pinned=1;
 		    break;
 		}
 	    }
@@ -2194,11 +2171,6 @@ clientKeepaliveNextRequest(clientHttpReq
     debug(33, 3) ("clientKeepaliveNextRequest: FD %d\n", conn->fd);
     conn->defer.until = 0;	/* Kick it to read a new request */
     httpRequestFree(http);
-    if (conn->pinning.pinned && conn->pinning.fd == -1) {
-	debug(33, 2) ("clientKeepaliveNextRequest: FD %d Connection was pinned but server side gone. Terminating client connection\n", conn->fd);
-	comm_close(conn->fd);
-	return;
-    }
     if ((http = conn->chr) == NULL) {
 	debug(33, 5) ("clientKeepaliveNextRequest: FD %d reading next req\n",
 	    conn->fd);
@@ -3608,7 +3580,6 @@ httpAccept(int sock, void *data)
 	connState->fd = fd;
 	connState->in.size = CLIENT_REQ_BUF_SZ;
 	connState->in.buf = memAllocate(MEM_CLIENT_REQ_BUF);
-	connState->pinning.fd = -1;
 	/* XXX account connState->in.buf */
 	comm_add_close_handler(fd, connStateFree, connState);
 	if (Config.onoff.log_fqdn)
@@ -4025,26 +3996,3 @@ varyEvaluateMatch(StoreEntry * entry, re
 	}
     }
 }
-
-/* This is a handler normally called by comm_close() */
-static void
-clientPinnedConnectionClosed(int fd, void *data)
-{
-    ConnStateData *conn = data;
-    conn->pinning.fd = -1;
-    safe_free(conn->pinning.host);
-    /* NOTE: pinning.pinned should be kept. This combined with fd == -1 indicates that the host connection has gone away */
-}
-
-void
-clientPinConnection(ConnStateData *conn, const char *host, int port, int fd)
-{
-    if (conn->pinning.fd == fd)
-	return;
-    assert(conn->pinning.fd == -1);
-    conn->pinning.fd = fd;
-    conn->pinning.host = xstrdup(host);
-    conn->pinning.port = port;
-    conn->pinning.pinned = 1;
-    comm_add_close_handler(fd, clientPinnedConnectionClosed, conn);
-}
============================================================
--- src/forward.c	e2fc1a6c5fd200cd0174d0c5c2743c0e2c4942be
+++ src/forward.c	bde01cf37e23444aea4910eed79e76d3371277fb
@@ -150,7 +150,7 @@ fwdCheckRetry(FwdState * fwdState)
 	return 0;
     if (fwdState->request->flags.body_sent)
 	return 0;
-    if (fwdState->request->pinned_connection)
+    if (fwdState->request->flags.pinned)
 	return 0;
     return 1;
 }
@@ -345,19 +345,6 @@ getOutgoingTOS(request_t * request)
     return aclMapTOS(Config.accessList.outgoing_tos, &ch);
 }

-static int
-getPinnedFD(ConnStateData *conn, request_t *request)
-{
-    if (conn->pinning.fd < 0)
-	return -1;
-    if (strcasecmp(conn->pinning.host, request->host) != 0)
-	return -1;
-    if (conn->pinning.port != request->port)
-	return -1;
-
-    return conn->pinning.fd;
-}
-
 static void
 fwdConnectStart(void *data)
 {
@@ -372,12 +359,21 @@ fwdConnectStart(void *data)
     int ftimeout = Config.Timeout.forward - (squid_curtime - fwdState->start);
     struct in_addr outgoing;
     unsigned short tos;
-    struct in_addr *local=NULL;
+    struct in_addr *client_addr=NULL;
+    u_short client_port=0;
 #if LINUX_TPROXY
     struct in_tproxy itp;
+#endif

-    if ( Config.onoff.linux_tproxy )
-        local=&fwdState->src.sin_addr;
+    if(fwdState->request->flags.pinned) {
+	client_addr=&fwdState->request->client_addr;
+	client_port=fwdState->request->client_port;
+    }
+#if LINUX_TPROXY
+    else if ( ( Config.onoff.linux_tproxy ) &&
+      ( (fwdState->request->my_port == Config.tproxy_port) || (Config.tproxy_port == 0) )) {
+        client_addr=&fwdState->request->client_addr;
+    }
 #endif

     assert(fs);
@@ -402,20 +398,7 @@ fwdConnectStart(void *data)
 	ftimeout = 5;
     if (ftimeout < ctimeout)
 	ctimeout = ftimeout;
-    if (fwdState->request->pinned_connection) {
-       	fd = getPinnedFD(fwdState->request->pinned_connection, fwdState->request);
-	if (fd < 0) {
-	    debug(17, 1) ("fwdConnectStart: Pinned connection to %s:%d gone, aborting request\n", fwdState->request->host, fwdState->request->port);
-	    storeAbort(fwdState->entry);
-	    return;
-	}
-	fwdState->server_fd = fd;
-	fwdState->n_tries++;
-	comm_add_close_handler(fd, fwdServerClosed, fwdState);
-	fwdConnectDone(fd, COMM_OK, fwdState);
-	return;
-    }
-    if ((fd = pconnPop(host, port, local)) >= 0) {
+    if ((fd = pconnPop(host, port, client_addr, client_port)) >= 0) {
 	if (fwdCheckRetriable(fwdState)) {
 	    debug(17, 3) ("fwdConnectStart: reusing pconn FD %d\n", fd);
 	    fwdState->server_fd = fd;
============================================================
--- src/http.c	b0bbfbeb452d1642a4dc436c4c59565fd7a66354
+++ src/http.c	69d4e2cd7969e575f5cdba81916aab1f9b2c6223
@@ -550,30 +550,6 @@ httpPconnTransferDone(HttpStateData * ht
     return 1;
 }

-/* Small helper function to verify if connection pinning is supported or not
- */
-static int
-peer_supports_connection_pinning(HttpStateData *httpState)
-{
-    const HttpReply *rep = httpState->entry->mem_obj->reply;
-    const HttpHeader *hdr = &rep->header;
-    int rc;
-    String header;
-
-    if (!httpState->peer)
-	return 1;
-
-    if (!httpHeaderHas(hdr, HDR_PROXY_SUPPORT))
-	return 0;
-
-    header = httpHeaderGetStrOrList(hdr, HDR_PROXY_SUPPORT);
-    /* XXX This ought to be done in a case-insensitive manner */
-    rc = (strStr(header, "Session-Based-Authentication") != NULL);
-    stringClean(&header);
-
-    return rc;
-}
-
 /* This will be called when data is ready to be read from fd.  Read until
  * error or connection closed. */
 /* XXX this function is too long! */
@@ -588,7 +564,8 @@ httpReadReply(int fd, void *data)
     int bin;
     int clen;
     size_t read_sz = SQUID_TCP_SO_RCVBUF;
-    struct in_addr *local=NULL;
+    struct in_addr *client_addr=NULL;
+    u_short client_port=0;
 #if DELAY_POOLS
     delay_id delay_id;
 #endif
@@ -604,10 +581,15 @@ httpReadReply(int fd, void *data)
     else
 	delay_id = delayMostBytesAllowed(entry->mem_obj, &read_sz);
 #endif
-
+    if ( httpState->request->flags.pinned ) {
+	client_addr=&httpState->request->client_addr;
+	client_port=httpState->request->client_port;
+    }
 #if LINUX_TPROXY
-    if ( Config.onoff.linux_tproxy )
-        local=&httpState->request->client_addr;
+    else if ( ( Config.onoff.linux_tproxy ) &&
+      ( (httpState->request->my_port == Config.tproxy_port) || (Config.tproxy_port == 0) )) {
+        client_addr=&httpState->request->client_addr;
+    }
 #endif

     errno = 0;
@@ -769,12 +751,10 @@ httpReadReply(int fd, void *data)
 #endif
 		    comm_remove_close_handler(fd, httpStateFree, httpState);
 		    fwdUnregister(fd, httpState->fwd);
-		    if (request->pinned_connection && peer_supports_connection_pinning(httpState))
-			clientPinConnection(request->pinned_connection, request->host, request->port, fd);
-		    else if (request->flags.accelerated && Config.Accel.single_host && Config.Accel.host)
-			pconnPush(fd, Config.Accel.host, Config.Accel.port, local);
+		    if (request->flags.accelerated && Config.Accel.single_host && Config.Accel.host)
+			pconnPush(fd, Config.Accel.host, Config.Accel.port, client_addr, client_port);
 		    else
-			pconnPush(fd, request->host, request->port, local);
+			pconnPush(fd, request->host, request->port, client_addr, client_port);
 		    fwdComplete(httpState->fwd);
 		    httpState->fd = -1;
 		    httpStateFree(fd, httpState);
============================================================
--- src/pconn.c	29ed4b99506a1610a2e266faf97e49fc4f027913
+++ src/pconn.c	5f83c46e535d572c2a6d6f55389e635926c3feee
@@ -57,16 +57,16 @@ static MemPool *pconn_fds_pool = NULL;
 static MemPool *pconn_data_pool = NULL;
 static MemPool *pconn_fds_pool = NULL;

-#define PCONN_KEYLEN (SQUIDHOSTNAMELEN + 24)
+#define PCONN_KEYLEN (SQUIDHOSTNAMELEN + 30)

 static inline const int
-pconnKey(char *buf, const char *peer, u_short port, struct in_addr *local)
+pconnKey(char *buf, const char *peer, u_short port, struct in_addr *client_address, u_short client_port)
 {
-    if ( local == NULL ) {
+    if ( client_address == NULL ) {
         return snprintf(buf, PCONN_KEYLEN, "%s.%d", peer, (int) port);
     }else{
-        return snprintf(buf, PCONN_KEYLEN, "%s.%d.%s",
-		peer, (int) port, inet_ntoa(*local));
+        return snprintf(buf, PCONN_KEYLEN, "%s.%d.%s.%d",
+		peer, (int) port, inet_ntoa(*client_address), (int) client_port);
     }
 }

@@ -188,7 +188,7 @@ void
 }

 void
-pconnPush(int fd, const char *peer, u_short port, struct in_addr *local)
+pconnPush(int fd, const char *peer, u_short port, struct in_addr *client_address, u_short client_port)
 {
     struct _pconn *p;
     int *old;
@@ -203,7 +203,7 @@ pconnPush(int fd, const char *peer, u_sh
 	return;
     }
     assert(table != NULL);
-    pconnKey(key, peer, port, local);
+    pconnKey(key, peer, port, client_address, client_port);
     p = (struct _pconn *) hash_lookup(table, key);
     if (p == NULL)
 	p = pconnNew(key);
@@ -227,14 +227,14 @@ int
 }

 int
-pconnPop(const char *peer, u_short port, struct in_addr *local)
+pconnPop(const char *peer, u_short port, struct in_addr *client_address, u_short client_port)
 {
     struct _pconn *p;
     hash_link *hptr;
     int fd = -1;
     LOCAL_ARRAY(char, key, PCONN_KEYLEN);
     assert(table != NULL);
-    pconnKey(key, peer, port, local);
+    pconnKey(key, peer, port, client_address, client_port);
     hptr = hash_lookup(table, key);
     if (hptr != NULL) {
 	p = (struct _pconn *) hptr;
============================================================
--- src/protos.h	0415ef0095c3ae7a42ac90385638ebe76af6d316
+++ src/protos.h	d924404fa81b7d01e6af2836d2ff9e49c5ddabcd
@@ -141,7 +141,6 @@ extern int isTcpHit(log_type);
 extern void clientHttpConnectionsClose(void);
 extern StoreEntry *clientCreateStoreEntry(clientHttpRequest *, method_t, request_flags);
 extern int isTcpHit(log_type);
-extern void clientPinConnection(ConnStateData *conn, const char *host, int port, int fd);

 extern int commSetNonBlocking(int fd);
 extern int commUnsetNonBlocking(int fd);
@@ -1147,8 +1146,8 @@ extern ErrorState *errorCon(err_type typ
 extern int errorReservePageId(const char *page_name);
 extern ErrorState *errorCon(err_type type, http_status);

-extern void pconnPush(int, const char *peer, u_short port, struct in_addr *local);
-extern int pconnPop(const char *peer, u_short port, struct in_addr *local);
+extern void pconnPush(int, const char *peer, u_short port, struct in_addr *client_address, u_short client_port);
+extern int pconnPop(const char *peer, u_short port, struct in_addr *client_address, u_short client_port);
 extern void pconnInit(void);

 extern int asnMatchIp(void *, struct in_addr);
============================================================
--- src/structs.h	cc6dcb3d613d4ba93f19194205ec9916efd19e7d
+++ src/structs.h	8c514b042f35f6fd32b0a73cf21a9643cf2d6cd4
@@ -1168,12 +1168,6 @@ struct _ConnStateData {
 	int n;
 	time_t until;
     } defer;
-    struct {
-	int fd;		/* pinned server side connection */
-	char *host;	/* host name of pinned connection */
-	int port;	/* port of pinned connection */
-	int pinned;	/* this connection was pinned */
-    } pinning;
 };

 struct _ipcache_addrs {
@@ -1669,6 +1663,7 @@ struct _request_flags {
     unsigned int body_sent:1;
     unsigned int reset_tcp:1;
     unsigned int must_keepalive:1;
+    unsigned int pinned:1;			/* If set, this request is tightly tied to a client-side connection */
 };

 struct _link_list {
@@ -1727,7 +1722,6 @@ struct _request_t {
     const char *vary_headers;	/* Used when varying entities are detected. Changes how the store key is calculated */
     BODY_HANDLER *body_reader;
     void *body_reader_data;
-    ConnStateData *pinned_connection; /* If set then this request is tighly tied to the corresponding client side connetion */
 };

 struct _cachemgr_passwd {