Index: src/client_side.c
===================================================================
RCS file: /cvsroot/squid/squid/src/client_side.c,v
retrieving revision 1.108
diff -u -r1.108 client_side.c
--- src/client_side.c	30 May 2006 22:50:36 -0000	1.108
+++ src/client_side.c	1 Jun 2006 11:27:39 -0000
@@ -1306,7 +1306,6 @@
     /* If any connection has been pinned to this client, force keep alive */
     if (http->conn->pinned) {
 	request->flags.must_keepalive = 1;
-	request->flags.auth = 1;
 	request->flags.pinned = 1;
     }
     if (httpHeaderHas(req_hdr, HDR_AUTHORIZATION))
Index: src/comm.c
===================================================================
RCS file: /cvsroot/squid/squid/src/comm.c,v
retrieving revision 1.38
diff -u -r1.38 comm.c
--- src/comm.c	29 May 2006 16:51:13 -0000	1.38
+++ src/comm.c	1 Jun 2006 11:27:40 -0000
@@ -710,6 +710,9 @@
 comm_close(int fd)
 {
     fde *F = &fd_table[fd];
+    fde *server_fde;
+    int i,server_fd;
+    PF *callback;
 
     debug(5, 5) ("comm_close: FD %d\n", fd);
     assert(fd >= 0);
@@ -726,6 +729,31 @@
     assert(F->flags.open);
     assert(F->type != FD_FILE);
     F->flags.closing = 1;
+
+    /* Check for server-side fds that need closing */
+    if(F->pinned_server.nused) {
+	debug(5, 3) ("comm_close: Checking %d pinned connections on fd %d\n", F->pinned_server.nused, fd);
+	for(i=F->pinned_server.nused - 1;i>=0;i--) {
+	    server_fd=F->pinned_server.fds[i];
+	    server_fde=&fd_table[server_fd];
+
+	    debug(5, 3) ("comm_close: Checking pinned server fd %d\n", server_fd);
+	    /* Make sure we don't mess with a server fd incorrectly.
+	     *
+	     * If the server fd has been re-used, pinned_client_fd will change,
+	     * if it has been closed, there will be no timeout handler
+	     */
+	    if((server_fde->pinned_client_fd == fd) && (server_fde->timeout_handler)) {
+		callback=server_fde->timeout_handler;
+		server_fde->timeout_handler = NULL;
+
+		debug(5, 3) ("comm_close: Closing pinned server fd %d\n", server_fd);
+		callback(server_fd,server_fde->timeout_data);
+	    }
+	}
+	xfree(F->pinned_server.fds);
+    }
+
     CommWriteStateCallbackAndFree(fd, COMM_ERR_CLOSING);
     commCallCloseHandlers(fd);
     if (F->uses)		/* assume persistent connect count */
Index: src/fd.c
===================================================================
RCS file: /cvsroot/squid/squid/src/fd.c,v
retrieving revision 1.14
diff -u -r1.14 fd.c
--- src/fd.c	30 May 2006 13:50:25 -0000	1.14
+++ src/fd.c	1 Jun 2006 11:27:40 -0000
@@ -50,6 +50,48 @@
 
 static void fdUpdateBiggest(int fd, int);
 
+void
+fdAddPinnedServer(int clientfd, int serverfd)
+{
+    fde *F = &fd_table[clientfd];
+    int i;
+    int *old;
+
+    assert(clientfd < Squid_MaxFD);
+    assert(clientfd >= 0);
+    assert(serverfd < Squid_MaxFD);
+    assert(serverfd >= 0);
+
+    debug(51, 5) ("fdAddPinnedServer: checking %d -> %d\n", clientfd, serverfd);
+    if(!(F->pinned_server.nalloc)) {
+	F->pinned_server.nalloc = 8;
+	F->pinned_server.fds=xmalloc(F->pinned_server.nalloc * sizeof(int));
+
+        debug(51, 5) ("fdAddPinnedServer: Adding first entry (%d)\n",F->pinned_server.nused);
+	F->pinned_server.fds[F->pinned_server.nused++] = serverfd;
+    }
+    else
+    {
+	for(i = F->pinned_server.nused - 1;i >= 0; i--) {
+	    if(F->pinned_server.fds[i] == serverfd)
+		break;
+	}
+
+	if(i < 0 ) {
+	    if(F->pinned_server.nalloc == F->pinned_server.nused) {
+		F->pinned_server.nalloc <<= 1;
+		old = F->pinned_server.fds;
+		F->pinned_server.fds = xmalloc(F->pinned_server.nalloc * sizeof(int));
+		xmemcpy(F->pinned_server.fds, old, F->pinned_server.nused * sizeof(int));
+		xfree(old);
+	    }
+
+            debug(51, 5) ("fdAddPinnedServer: Adding next entry (%d)\n",F->pinned_server.nused);
+	    F->pinned_server.fds[F->pinned_server.nused++] = serverfd;
+	}
+    }
+}
+
 static void
 fdUpdateBiggest(int fd, int opening)
 {
@@ -120,6 +162,7 @@
     F->flags.open = 1;
     F->read_method = &default_read_method;
     F->write_method = &default_write_method;
+    F->pinned_client_fd = -1;
     fdUpdateBiggest(fd, 1);
     if (desc)
 	xstrncpy(F->desc, desc, FD_DESC_SZ);
Index: src/forward.c
===================================================================
RCS file: /cvsroot/squid/squid/src/forward.c,v
retrieving revision 1.30
diff -u -r1.30 forward.c
--- src/forward.c	30 May 2006 13:50:25 -0000	1.30
+++ src/forward.c	1 Jun 2006 11:27:41 -0000
@@ -495,11 +495,16 @@
     if (ftimeout < ctimeout)
 	ctimeout = ftimeout;
     if (fwdState->request->flags.pinned)
-	fd = pconnPop(name, port, domain, &fwdState->request->client_addr, fwdState->request->client_port);
+	/* We've already done a pconnLookup, so this should never fail */
+	if((fd = pconnPop(name, port, NULL, &fwdState->request->client_addr, fwdState->request->client_port)) < 0) {
+	        debug(17, 1) ("fwdConnectStart: pconnPop failed.  If this cache uses parents, unusual results may follow\n");
+		fwdState->request->flags.pinned = 0;
+		fwdState->request->flags.auth = 0;
+	}
 #if LINUX_TPROXY
     if (fd == -1 && (Config.onoff.linux_tproxy) &&
 	((fwdState->request->my_port == Config.tproxy_port) || (Config.tproxy_port == 0)))
-	fd = pconnPop(name, port, domain, &fwdState->request->client_addr, 0);
+	fd = pconnPop(name, port, NULL, &fwdState->request->client_addr, 0);
 #endif
     if (fd == -1)
 	fd = pconnPop(name, port, domain, NULL, 0);
@@ -775,6 +780,7 @@
 fwdStart(int fd, StoreEntry * e, request_t * r)
 {
     FwdState *fwdState;
+    FwdServer *peer = NULL;
     aclCheck_t ch;
     int answer;
     ErrorState *err;
@@ -851,7 +857,18 @@
     storeLockObject(e);
     EBIT_SET(e->flags, ENTRY_FWD_HDR_WAIT);
     storeRegisterAbort(e, fwdAbort, fwdState);
-    peerSelect(r, e, fwdStartComplete, fwdState);
+    if((r->flags.pinned) && (pconnLookup(r->host,r->port,NULL,&r->client_addr,r->client_port))) {
+	debug(17, 3) ("fwdStart: reusing persistent pinned connection\n");
+	r->flags.auth=1;
+	peerAddFwdServer(&peer,NULL,HIER_DIRECT);
+	fwdStartComplete(peer,fwdState);
+    }
+    else
+    {
+	/* Make sure we remove the pinned flag */
+	r->flags.pinned=0;
+	peerSelect(r, e, fwdStartComplete, fwdState);
+    }
 }
 
 int
Index: src/http.c
===================================================================
RCS file: /cvsroot/squid/squid/src/http.c,v
retrieving revision 1.36
diff -u -r1.36 http.c
--- src/http.c	27 May 2006 12:50:34 -0000	1.36
+++ src/http.c	1 Jun 2006 11:27:43 -0000
@@ -559,8 +559,6 @@
     int bin;
     int clen;
     size_t read_sz = SQUID_TCP_SO_RCVBUF;
-    struct in_addr *client_addr = NULL;
-    u_short client_port = 0;
 #if DELAY_POOLS
     delay_id delay_id;
 #endif
@@ -727,16 +725,6 @@
 		    }
 		}
 		if (keep_alive) {
-		    if (httpState->request->flags.pinned) {
-			client_addr = &httpState->request->client_addr;
-			client_port = httpState->request->client_port;
-		    }
-#if LINUX_TPROXY
-		    else if ((Config.onoff.linux_tproxy) &&
-			((httpState->request->my_port == Config.tproxy_port) || (Config.tproxy_port == 0))) {
-			client_addr = &httpState->request->client_addr;
-		    }
-#endif
 		    /* yes we have to clear all these! */
 		    commSetDefer(fd, NULL, NULL);
 		    commSetTimeout(fd, -1, NULL, NULL);
@@ -746,14 +734,27 @@
 #endif
 		    comm_remove_close_handler(fd, httpStateFree, httpState);
 		    fwdUnregister(fd, httpState->fwd);
-		    if (httpState->peer) {
+		    if (httpState->request->flags.pinned) {
+			fde *F = &fd_table[fd];
+
+			F->pinned_client_fd = httpState->fwd->client_fd;
+			fdAddPinnedServer(httpState->fwd->client_fd,fd);
+
+			pconnPush(fd, request->host, request->port, NULL, &httpState->request->client_addr, httpState->request->client_port);
+		    } else if (httpState->peer) {
 			if (httpState->peer->options.originserver)
-			    pconnPush(fd, httpState->peer->name, httpState->peer->http_port, httpState->orig_request->host, client_addr, client_port);
+			    pconnPush(fd, httpState->peer->name, httpState->peer->http_port, httpState->orig_request->host, NULL, 0);
 			else
-			    pconnPush(fd, httpState->peer->name, httpState->peer->http_port, NULL, client_addr, client_port);
-		    } else {
-			pconnPush(fd, request->host, request->port, NULL, client_addr, client_port);
+			    pconnPush(fd, httpState->peer->name, httpState->peer->http_port, NULL, NULL, 0);
 		    }
+#if LINUX_TPROXY
+		    else if ((Config.onoff.linux_tproxy) &&
+			((httpState->request->my_port == Config.tproxy_port) || (Config.tproxy_port == 0))) {
+			pconnPush(fd, request->host, request->port, NULL, &httpState->request->client_addr, 0);
+#endif
+		    else
+			pconnPush(fd, request->host, request->port, NULL, NULL, 0);
+
 		    fwdComplete(httpState->fwd);
 		    httpState->fd = -1;
 		    httpStateFree(fd, httpState);
Index: src/protos.h
===================================================================
RCS file: /cvsroot/squid/squid/src/protos.h,v
retrieving revision 1.96
diff -u -r1.96 protos.h
--- src/protos.h	30 May 2006 22:50:36 -0000	1.96
+++ src/protos.h	1 Jun 2006 11:27:45 -0000
@@ -258,6 +258,7 @@
 extern void fd_open(int fd, unsigned int type, const char *);
 extern void fd_note(int fd, const char *);
 extern void fd_bytes(int fd, int len, unsigned int type);
+extern void fdAddPinnedServer(int clientfd, int serverfd);
 extern void fdFreeMemory(void);
 extern void fdDumpOpen(void);
 extern int fdNFree(void);
Index: src/structs.h
===================================================================
RCS file: /cvsroot/squid/squid/src/structs.h,v
retrieving revision 1.101
diff -u -r1.101 structs.h
--- src/structs.h	30 May 2006 23:50:50 -0000	1.101
+++ src/structs.h	1 Jun 2006 11:27:47 -0000
@@ -869,6 +869,12 @@
     squid_off_t bytes_read;
     squid_off_t bytes_written;
     int uses;			/* ie # req's over persistent conn */
+    int pinned_client_fd;	/* The client fd this connection is pinned to */
+    struct _pinnedconn {
+	int *fds;		/* The server fd's this client has pinned */
+	int nalloc;		/* The number of allocated fds */
+	int nused;		/* The number of used fds */
+    } pinned_server; 
 #if USE_EPOLL
     unsigned epoll_state;	/* keep track of the epoll state */
     unsigned epoll_backoff;	/* keep track of whether the fd is backed off */

