diff -u linux/net/khttpd/accept.c /usr/src/linux/net/khttpd/accept.c
--- linux/net/khttpd/accept.c	Sat Jan 22 20:54:58 2000
+++ /usr/src/linux/net/khttpd/accept.c	Mon Jun 12 15:12:59 2000
@@ -107,6 +107,7 @@
 		memset(NewRequest,0,sizeof(struct http_request));  
 		
 		NewRequest->sock = NewSock;
+		NewRequest->LastActive = jiffies;
 		
 		NewRequest->Next = threadinfo[CPUNR].WaitForHeaderQueue;
 		
diff -u linux/net/khttpd/logging.c /usr/src/linux/net/khttpd/logging.c
--- linux/net/khttpd/logging.c	Wed Aug 18 18:45:10 1999
+++ /usr/src/linux/net/khttpd/logging.c	Mon Jun 12 15:43:29 2000
@@ -30,6 +30,7 @@
 #include "structure.h"
 #include "prototypes.h"
 
+
 /*
 
 Purpose:
@@ -58,14 +59,23 @@
 	while (CurrentRequest!=NULL)
 	{
 
+		CurrentRequest->ReqCount++;
+		CurrentRequest->LastActive = jiffies;
+
+
 		Req = CurrentRequest->Next;
+	
 
-		CleanUpRequest(CurrentRequest);
+		if (CurrentRequest->Persistent) {
+			sanitize_request(CurrentRequest);
+			CurrentRequest->Next = threadinfo[CPUNR].WaitForHeaderQueue;
+			threadinfo[CPUNR].WaitForHeaderQueue = CurrentRequest;
+		}
+		else 
+			CleanUpRequest(CurrentRequest);
 		
 		threadinfo[CPUNR].LoggingQueue = Req;
-			
 		CurrentRequest = Req;
-	
 		count++;
 		
 	}
diff -u linux/net/khttpd/misc.c /usr/src/linux/net/khttpd/misc.c
--- linux/net/khttpd/misc.c	Thu Sep  2 20:47:20 1999
+++ /usr/src/linux/net/khttpd/misc.c	Mon Jun 12 18:10:29 2000
@@ -132,6 +132,89 @@
 	LeaveFunction("CleanUpRequest");
 }
 
+static char Buffer[1024];
+
+static void DummyRead(struct socket *sock, int Size)
+{
+	struct msghdr		msg;
+	struct iovec		iov;
+	int			len,totalbytes=0;
+
+	mm_segment_t		oldfs;
+	
+	
+	EnterFunction("DummyRead");
+	
+	
+	if (sock->sk==NULL)
+		return;
+
+	len = 1;
+	
+	totalbytes = 0;
+	
+	while ((len>0)&&(totalbytes<Size)) {
+		msg.msg_name     = 0;
+		msg.msg_namelen  = 0;
+		msg.msg_iov	 = &iov;
+		msg.msg_iovlen   = 1;
+		msg.msg_control  = NULL;
+		msg.msg_controllen = 0;
+		msg.msg_flags    = MSG_DONTWAIT;
+	
+		msg.msg_iov->iov_base = &Buffer[0];
+		msg.msg_iov->iov_len  = (__kernel_size_t)max(1024,Size-totalbytes);
+	
+		len = 0;
+		oldfs = get_fs(); set_fs(KERNEL_DS);
+		len = sock_recvmsg(sock,&msg,1024,MSG_DONTWAIT);
+		set_fs(oldfs);
+		if (len>0)
+			totalbytes+=len;
+	}
+	LeaveFunction("DummyRead");
+}
+
+
+
+/*
+sanitize_request
+@request: the request to clean
+
+sanitize_requests cleans all URL specific parts of a request, while
+saving the connection specific parts in order to do persistent connections.
+  
+*/
+void sanitize_request(struct http_request *request)
+{
+	EnterFunction("sanitize_request");
+	/* Close the file-pointer */
+	if (request->filp!=NULL)
+	{
+	    	fput(request->filp);
+	    	request->filp = NULL;
+	}
+	
+	DummyRead(request->sock,request->Headersize);
+
+	request->FileLength = 0;
+	request->Time = 0;
+	request->BytesSent = 0;
+	request->FileName[0]=0;
+	request->FileNameLength = 0;
+	request->IMS[0]=0;
+	request->Host[0]=0;
+	request->IMS_Time =0;
+	request->TimeS[0] =0;
+	request->LengthS[0] =0;
+	request->MimeType = NULL;
+	request->MimeLength = 0;
+	
+	LeaveFunction("sanitize_request");
+
+}
+
+
 
 /*
 
@@ -215,6 +298,7 @@
 */
 
 static char NoPerm[] = "HTTP/1.0 403 Forbidden\r\nServer: kHTTPd 0.1.6\r\n\r\n";
+static char TimeOut[] = "HTTP/1.0 408 Request timed out\r\nServer: kHTTPd 0.1.6\r\nConnection: close\r\n\r\n";
 static char TryLater[] = "HTTP/1.0 503 Service Unavailable\r\nServer: kHTTPd 0.1.6\r\nContent-Length: 15\r\n\r\nTry again later";
 static char NotModified[] = "HTTP/1.0 304 Not Modified\r\nServer: kHTTPd 0.1.6\r\n\r\n";
 
@@ -225,6 +309,14 @@
 	(void)SendBuffer(sock,NoPerm,strlen(NoPerm));
 	LeaveFunction("Send403");
 }
+
+void Send408(struct socket *sock)
+{
+	EnterFunction("Send408");
+	(void)SendBuffer(sock,TimeOut,strlen(TimeOut));
+	LeaveFunction("Send408");
+}
+
 
 void Send304(struct socket *sock)
 {
diff -u linux/net/khttpd/prototypes.h /usr/src/linux/net/khttpd/prototypes.h
--- linux/net/khttpd/prototypes.h	Wed Aug 18 18:45:10 1999
+++ /usr/src/linux/net/khttpd/prototypes.h	Mon Jun 12 17:15:09 2000
@@ -65,9 +65,11 @@
 /* misc.c */
 
 void CleanUpRequest(struct http_request *Req);
+void sanitize_request(struct http_request *request);
 int SendBuffer(struct socket *sock, const char *Buffer,const size_t Length);
 int SendBuffer_async(struct socket *sock, const char *Buffer,const size_t Length);
 void Send403(struct socket *sock);
+void Send408(struct socket *sock);
 void Send304(struct socket *sock);
 void Send50x(struct socket *sock);
 
diff -u linux/net/khttpd/rfc.c /usr/src/linux/net/khttpd/rfc.c
--- linux/net/khttpd/rfc.c	Mon Aug 23 19:41:25 1999
+++ /usr/src/linux/net/khttpd/rfc.c	Mon Jun 12 17:14:55 2000
@@ -156,65 +156,12 @@
 
 
 static char HeaderPart1[] = "HTTP/1.0 200 OK\r\nServer: kHTTPd/0.1.6\r\nDate: ";
-#ifdef BENCHMARK
-static char HeaderPart1b[] ="HTTP/1.0 200 OK";
-#endif
 static char HeaderPart3[] = "\r\nContent-type: ";
 static char HeaderPart5[] = "\r\nLast-modified: ";
 static char HeaderPart7[] = "\r\nContent-length: ";
-static char HeaderPart9[] = "\r\n\r\n";
+static char HeaderPart9[] = "\r\nConnection: Keep-Alive\r\n\r\n";
+static char HeaderPart9close[] = "\r\nConnection: Close\r\n\r\n";
 
-#ifdef BENCHMARK
-/* In BENCHMARK-mode, just send the bare essentials */
-void SendHTTPHeader(struct http_request *Request)
-{
-	struct msghdr	msg;
-	mm_segment_t	oldfs;
-	struct iovec	iov[9];
-	int 		len,len2;
-	
-	
-	EnterFunction("SendHTTPHeader");
-		
-	msg.msg_name     = 0;
-	msg.msg_namelen  = 0;
-	msg.msg_iov	 = &iov[0];
-	msg.msg_iovlen   = 6;
-	msg.msg_control  = NULL;
-	msg.msg_controllen = 0;
-	msg.msg_flags    = 0;  /* Synchronous for now */
-	
-	iov[0].iov_base = HeaderPart1b;
-	iov[0].iov_len  = 15;
-	iov[1].iov_base = HeaderPart3;
-	iov[1].iov_len  = 16;
-	iov[2].iov_base = Request->MimeType;
-	iov[2].iov_len  = Request->MimeLength;
-	
-	iov[3].iov_base = HeaderPart7;
-	iov[3].iov_len  = 18;
-	
-	
-	sprintf(Request->LengthS,"%i",Request->FileLength);
-	iov[4].iov_base = Request->LengthS;
-	iov[4].iov_len  = strlen(Request->LengthS);
-	iov[5].iov_base = HeaderPart9;
-	iov[5].iov_len  = 4;
-	
-	len2=15+16+18+iov[2].iov_len+iov[4].iov_len+4;
-	
-	
-	len = 0;
-	
-
-	oldfs = get_fs(); set_fs(KERNEL_DS);
-	len = sock_sendmsg(Request->sock,&msg,len2);
-	set_fs(oldfs);
-
-	
-	return;	
-}
-#else
 void SendHTTPHeader(struct http_request *Request)
 {
 	struct msghdr	msg;
@@ -252,10 +199,16 @@
 	iov[7].iov_base = &(Request->LengthS[0]);
 	slen = strlen(Request->LengthS); 
 	iov[7].iov_len  = slen;
-	iov[8].iov_base = HeaderPart9;
-	iov[8].iov_len  = 4;
 	
-	len2=45+2*29+16+17+18+slen+4+iov[3].iov_len;
+	iov[8].iov_base = HeaderPart9close;
+	iov[8].iov_len  = 23;
+
+	if (Request->Persistent) {
+		iov[8].iov_base = HeaderPart9;
+		iov[8].iov_len  = 28;
+	}
+	
+	len2=45+2*29+16+17+18+slen+iov[3].iov_len+iov[8].iov_len;
 	
 	len = 0;
 
@@ -267,7 +220,6 @@
 
 	return;	
 }
-#endif
 
 
 
@@ -288,6 +240,8 @@
 	tmp = strstr(Buffer,"\r\n\r\n"); 
 	if (tmp!=NULL)
 	    Endval = tmp;
+	    
+	Head->Headersize = Endval - Buffer+4;
 	
 	
 	while (Buffer<Endval)
@@ -347,24 +301,22 @@
 			continue;
 		}
 
-		if (strncmp("User-Agent: ",Buffer,12)==0)
+		if (strncmp("Host: ",Buffer,6)==0)
 		{
-			Buffer+=12;
+			Buffer+=6;
 			
-			strncpy(Head->Agent,Buffer,min(127,EOL-Buffer-1));
+			strncpy(Head->Host,Buffer,min(127,EOL-Buffer-1));
 					
 			Buffer=EOL+1;	
 			continue;
 		}
-		
 
-		if (strncmp("Host: ",Buffer,6)==0)
+		if (strncmp("Connection: Keep-Alive",Buffer,22)==0)
 		{
-			Buffer+=6;
+			Buffer+=22;
 			
-			strncpy(Head->Host,Buffer,min(127,EOL-Buffer-1));
-					
 			Buffer=EOL+1;	
+			Head->Persistent = 1;
 			continue;
 		}
 #endif		
diff -u linux/net/khttpd/structure.h /usr/src/linux/net/khttpd/structure.h
--- linux/net/khttpd/structure.h	Thu Feb 10 04:47:20 2000
+++ /usr/src/linux/net/khttpd/structure.h	Mon Jun 12 17:14:00 2000
@@ -15,6 +15,11 @@
 	/* Network and File data */
 	struct socket	*sock;		
 	struct file	*filp;		
+	
+	/* Info for persistent connections / timeouts */
+	int		ReqCount; 	/* Number of requests served already */
+	int		Persistent;	/* 1 if the socket needs to remain open */
+	unsigned long	LastActive;	/* Last active, in absolute jiffies */
 
 	/* Raw data about the file */
 	
@@ -30,10 +35,10 @@
 	/* HTTP request information */
 	char		FileName[256];	/* The requested filename */
 	int		FileNameLength; /* The length of the string representing the filename */
-	char		Agent[128];	/* The agent-string of the remote browser */
 	char		IMS[128];	/* If-modified-since time, rfc string format */
 	char		Host[128];	/* Value given by the Host: header */
 	int		HTTPVER;        /* HTTP-version; 9 for 0.9,   10 for 1.0 and above */
+	int		Headersize;	/* Size of the request in bytes */
 
 
 	/* Derived date from the above fields */	
diff -u linux/net/khttpd/sysctl.c /usr/src/linux/net/khttpd/sysctl.c
--- linux/net/khttpd/sysctl.c	Mon Aug 23 22:44:03 1999
+++ /usr/src/linux/net/khttpd/sysctl.c	Mon Jun 12 14:18:30 2000
@@ -63,6 +63,7 @@
 int 	sysctl_khttpd_sloppymime= 0;
 int	sysctl_khttpd_threads	= 2;
 int	sysctl_khttpd_maxconnect = 1000;
+int 	sysctl_khttpd_timeout	= 20;
 
 
 static struct ctl_table_header *khttpd_table_header;
diff -u linux/net/khttpd/sysctl.h /usr/src/linux/net/khttpd/sysctl.h
--- linux/net/khttpd/sysctl.h	Wed Aug 18 18:45:10 1999
+++ /usr/src/linux/net/khttpd/sysctl.h	Mon Jun 12 14:05:48 2000
@@ -13,5 +13,6 @@
 extern int 	sysctl_khttpd_sloppymime;
 extern int 	sysctl_khttpd_threads;
 extern int	sysctl_khttpd_maxconnect;
+extern int	sysctl_khttpd_timeout;
 
 #endif
Only in /usr/src/linux/net/khttpd: times.h
diff -u linux/net/khttpd/waitheaders.c /usr/src/linux/net/khttpd/waitheaders.c
--- linux/net/khttpd/waitheaders.c	Mon Apr  3 00:53:28 2000
+++ /usr/src/linux/net/khttpd/waitheaders.c	Mon Jun 12 16:45:38 2000
@@ -44,6 +44,7 @@
 
 #include "structure.h"
 #include "prototypes.h"
+#include "sysctl.h"
 
 static	char			*Buffer[CONFIG_KHTTPD_NUMCPU];
 
@@ -57,8 +58,12 @@
 	struct sock *sk;
 	int count = 0;
 	
+	unsigned long timeout;
+	
 	EnterFunction("WaitForHeaders");
 	
+	timeout = jiffies - sysctl_khttpd_timeout * HZ;
+	
 	CurrentRequest = threadinfo[CPUNR].WaitForHeaderQueue;
 	
 	Prev = &(threadinfo[CPUNR].WaitForHeaderQueue);
@@ -94,6 +99,7 @@
 		{
 			struct http_request *Next;
 			
+			CurrentRequest->LastActive = jiffies;
 			
 			
 			/* Decode header */
@@ -127,7 +133,43 @@
 			CurrentRequest = Next;
 			continue;
 		
-		}	
+		} else {  /* No data */
+			if ( CurrentRequest->LastActive < timeout ) {
+				struct http_request *Next;
+				
+				/* Timed out session.
+				 *
+				 * There are 2 possibilities here:
+				 * 1) It is a "fresh" connection; this is tricky and should
+				 *    be left to userspace
+				 * 2) It is a "Keep-alive" connection; RFC 2616 is clear on this and
+				 *    we MAY close it with a 408 message.
+				 */
+	
+				/* Remove from WaitForHeaderQueue */		
+			
+				Next= CurrentRequest->Next;
+		
+				*Prev = Next;
+				count++;
+			
+			
+				if (CurrentRequest->ReqCount==0)
+				{
+					CurrentRequest->Next = threadinfo[CPUNR].UserspaceQueue;
+					threadinfo[CPUNR].UserspaceQueue = CurrentRequest;	
+				} else
+				{
+					Send408(CurrentRequest->sock);
+					CurrentRequest->Next = threadinfo[CPUNR].LoggingQueue;
+					threadinfo[CPUNR].LoggingQueue = CurrentRequest;
+					CurrentRequest->Persistent=0; /* We don't want to continue */	
+				} 	
+				
+				CurrentRequest = Next;
+				continue;
+			}
+		}
 
 		
 		Prev = &(CurrentRequest->Next);
