The following patch adds the following functionality to khttpd:

- Range support. Only simple ranges (from-to) are supported. Range suport
  enables the debian apt tool to resume aborted http file-transfers. Very
  important if one plans to run a kernel/debian mirror with khttpd.

- Virtual Host support (see docs in patch)

- Persistant connections

- simple logging via printk if /proc/sys/net/khttpd/logging is set to 1.

diff -urN linux-orig/net/khttpd/accept.c linux/net/khttpd/accept.c
--- linux-orig/net/khttpd/accept.c      Sat Jan 22 11:54:58 2000
+++ linux/net/khttpd/accept.c   Fri Jan 12 21:19:55 2001
@@ -107,6 +107,7 @@
                memset(NewRequest,0,sizeof(struct http_request));  
                
                NewRequest->sock = NewSock;
+               NewRequest->LastActive = jiffies;
                
                NewRequest->Next = threadinfo[CPUNR].WaitForHeaderQueue;
                
diff -urN linux-orig/net/khttpd/datasending.c linux/net/khttpd/datasending.c
--- linux-orig/net/khttpd/datasending.c Fri Nov 17 11:36:27 2000
+++ linux/net/khttpd/datasending.c      Sat Jan 13 17:58:21 2001
@@ -105,7 +105,7 @@
                
                Space = sock_wspace(CurrentRequest->sock->sk);
                
-               ReadSize = min(4*4096,CurrentRequest->FileLength - 
CurrentRequest->BytesSent);
+               ReadSize = min(4*4096,CurrentRequest->End - 
+(CurrentRequest->BytesSent+CurrentRequest->Offset));
                ReadSize = min(ReadSize , Space );
 
                if (ReadSize>0)
@@ -119,7 +119,7 @@
                                read_descriptor_t desc;
                                loff_t *ppos;
                
-                               CurrentRequest->filp->f_pos = 
CurrentRequest->BytesSent;
+                               CurrentRequest->filp->f_pos = 
+CurrentRequest->BytesSent+CurrentRequest->Offset;
 
                                ppos = &CurrentRequest->filp->f_pos;
 
@@ -137,7 +137,7 @@
                        else  /* FS doesn't support sendfile() */
                        {
                                mm_segment_t oldfs;
-                               CurrentRequest->filp->f_pos = 
CurrentRequest->BytesSent;
+                               CurrentRequest->filp->f_pos = 
+CurrentRequest->BytesSent+CurrentRequest->Offset;
                                
                                oldfs = get_fs(); set_fs(KERNEL_DS);
                                retval = 
CurrentRequest->filp->f_op->read(CurrentRequest->filp, Block[CPUNR], ReadSize, 
&CurrentRequest->filp->f_pos);
@@ -160,7 +160,7 @@
                   If end-of-file or closed connection: Finish this request 
                   by moving it to the "logging" queue. 
                */
-               if ((CurrentRequest->BytesSent>=CurrentRequest->FileLength)||
+               if 
+((CurrentRequest->BytesSent+CurrentRequest->Offset>=CurrentRequest->End)||
                    (CurrentRequest->sock->sk->state!=TCP_ESTABLISHED
                     && CurrentRequest->sock->sk->state!=TCP_CLOSE_WAIT))
                {
diff -urN linux-orig/net/khttpd/logging.c linux/net/khttpd/logging.c
--- linux-orig/net/khttpd/logging.c     Wed Aug 18 09:45:10 1999
+++ linux/net/khttpd/logging.c  Fri Jan 12 21:27:05 2001
@@ -29,6 +29,8 @@
 #include <asm/uaccess.h>
 #include "structure.h"
 #include "prototypes.h"
+#include "sysctl.h"
+
 
 /*
 
@@ -58,9 +60,22 @@
        while (CurrentRequest!=NULL)
        {
 
+               CurrentRequest->ReqCount++; 
+               CurrentRequest->LastActive = jiffies;
+
+               if (sysctl_khttpd_logging) {
+                       CurrentRequest->FileName[CurrentRequest->FileNameLength]=0;
+                       printk(KERN_NOTICE "File=%s Host=%s Length=%d 
+Userspace=%d\n",CurrentRequest->FileName,CurrentRequest->Host,CurrentRequest->FileLength,CurrentRequest->IsForUserspace);
+               }
                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;
                        
diff -urN linux-orig/net/khttpd/misc.c linux/net/khttpd/misc.c
--- linux-orig/net/khttpd/misc.c        Thu Sep  2 11:47:20 1999
+++ linux/net/khttpd/misc.c     Fri Jan 12 21:19:55 2001
@@ -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 -urN linux-orig/net/khttpd/prototypes.h linux/net/khttpd/prototypes.h
--- linux-orig/net/khttpd/prototypes.h  Mon Dec 11 13:32:10 2000
+++ linux/net/khttpd/prototypes.h       Sat Jan 13 13:45:36 2001
@@ -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 -urN linux-orig/net/khttpd/rfc.c linux/net/khttpd/rfc.c
--- linux-orig/net/khttpd/rfc.c Mon Aug 23 10:41:25 1999
+++ linux/net/khttpd/rfc.c      Sat Jan 13 18:45:28 2001
@@ -23,6 +23,34 @@
  *
  ****************************************************************/
 
+/*
+  Virtual Host parser by Christoph Lameter <[EMAIL PROTECTED]>, January 10, 2001
+  
+  The proc file in /proc/sys/net/khttpd/document can either be set to a single 
+webroot or
+  can contain a specification of a pathlist of webroots. Each path is prefixed by the 
+virtual
+  hostnames in parentheses. For example.
+  
+  echo 
+"(home.lameter.com,localhost)/a/christoph/new:(virtual3.cc.com)/home/richard:/var/www"
+ >documentroot
+  
+  would redirect requests for http://lameter.com and http://localhost to 
+/a/christoph/new.
+  Requests for http://virtual3.cc.com will be served from /home/richard.
+  Requests for other domains will be served from /var/www.
+
+  The syntax for specifying virtual host mappings is:
+  
+  <virtual-hostmap> { : <virtual_hostmap> } : <defaultpath>
+  
+  where
+  
+  <defaultmap>         =       Unix path
+  <virtual-hostmap>    =       ( <hostname> { , <hostname> } ) : <path>
+  <hostname>           =       legal DNS name of a host
+  <path>               =       Unix path
+  
+  An additional enhancement of khttpd is that no attempt is made to open directories.
+  Instead index.html is appended to a directory to simulate classic webserver 
+behavior.
+  
+*/
 
 #include <linux/kernel.h>
 
@@ -156,85 +184,26 @@
 
 
 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 HeaderPart2[] = "HTTP/1.0 206 Partial Content\r\nServer: 
+kHTTPd/0.1.6\r\nDate: ";
+static char HeaderPart3[] = "\r\nContent-Type: ";
+static char HeaderPart5[] = "\r\nLast-Modified: ";
+static char HeaderPart7[] = "\r\nContent-Length: ";
+static char HeaderPart9[] = "\r\nConnection: Keep-Alive\r\n\r\n";
+static char HeaderPart9close[] = "\r\nConnection: Close\r\n\r\n";
+static char HeaderPartPartial[] = "\r\nContent-Range: bytes %u-%u/%u";
 
-#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];
+       struct iovec    iov[10];
        int             len,len2;
-       
+       int             cindex;
        
        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;
-       mm_segment_t    oldfs;
-       struct iovec    iov[9];
-       int             len,len2;
-       __kernel_size_t slen;
-       
-       EnterFunction("SendHTTPHeader");
-       
-       msg.msg_name     = 0;
-       msg.msg_namelen  = 0;
-       msg.msg_iov      = &(iov[0]);
-       msg.msg_iovlen   = 9;
-       msg.msg_control  = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags    = 0;  /* Synchronous for now */
-       
-       iov[0].iov_base = HeaderPart1;
-       iov[0].iov_len  = 45;
+       iov[0].iov_base = Request->Offset ? HeaderPart2: HeaderPart1;
+       iov[0].iov_len  = strlen(iov[0].iov_base);
        iov[1].iov_base = CurrentTime;
        iov[1].iov_len  = 29;
        iov[2].iov_base = HeaderPart3;
@@ -250,12 +219,32 @@
        iov[6].iov_base = HeaderPart7;
        iov[6].iov_len  = 18;
        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;
+       iov[7].iov_len = strlen(Request->LengthS); 
+       
+       cindex = 8;
+       if (Request->Offset || Request->End < Request->FileLength) {
+               
+sprintf(Request->ContentRange,HeaderPartPartial,Request->Offset,Request->End,Request->FileLength);
+               iov[cindex].iov_base = Request->ContentRange;
+               iov[cindex].iov_len = strlen(Request->ContentRange);
+               cindex++;
+       }
+       iov[cindex].iov_base = HeaderPart9close;
+       iov[cindex].iov_len  = 23;
+
+       if (Request->Persistent) {
+               iov[cindex].iov_base = HeaderPart9;
+               iov[cindex].iov_len  = 28;
+       }
+
+       msg.msg_name     = 0;
+       msg.msg_namelen  = 0;
+       msg.msg_iov      = &(iov[0]);
+       msg.msg_iovlen   = cindex+1;
+       msg.msg_control  = NULL;
+       msg.msg_controllen = 0;
+       msg.msg_flags    = 0;  /* Synchronous for now */
        
-       len2=45+2*29+16+17+18+slen+4+iov[3].iov_len;
+       len2=0;while (cindex>=0) { len2+=iov[cindex].iov_len;cindex--; }
        
        len = 0;
 
@@ -264,10 +253,8 @@
        set_fs(oldfs);
        LeaveFunction("SendHTTPHeader");
        
-
        return; 
 }
-#endif
 
 
 
@@ -280,6 +267,8 @@
 void ParseHeader(char *Buffer,const int length, struct http_request *Head)
 {
        char *Endval,*EOL,*tmp;
+       char *filename=NULL;
+       int filenamelen;
        
        EnterFunction("ParseHeader");
        Endval = Buffer + length;
@@ -288,6 +277,8 @@
        tmp = strstr(Buffer,"\r\n\r\n"); 
        if (tmp!=NULL)
            Endval = tmp;
+           
+       Head->Headersize = Endval - Buffer+4;
        
        
        while (Buffer<Endval)
@@ -311,7 +302,6 @@
                
                if (strncmp("GET ",Buffer,4)==0)
                {
-                       int PrefixLen;
                        Buffer+=4;
                        
                        tmp=strchr(Buffer,' ');
@@ -323,12 +313,9 @@
                                Head->HTTPVER = 10;
                        
                        if (tmp>Endval) continue;
-                       
-                       
strncpy(Head->FileName,sysctl_khttpd_docroot,sizeof(Head->FileName));
-                       PrefixLen = strlen(sysctl_khttpd_docroot);
-                       Head->FileNameLength = min(255,tmp-Buffer+PrefixLen);          
 
-                       
-                       strncat(Head->FileName,Buffer,min(255-PrefixLen,tmp-Buffer));
+
+                       filename=Buffer;
+                       filenamelen=tmp-Buffer;
                                        
                        Buffer=EOL+1;   
 #ifdef BENCHMARK
@@ -347,6 +334,16 @@
                        continue;
                }
 
+               if (strncmp("If-Range: ",Buffer,10)==0)
+               {
+                       Buffer+=10;
+                       
+                       strncpy(Head->IfRange,Buffer,min(127,EOL-Buffer-1));
+                                       
+                       Buffer=EOL+1;   
+                       continue;
+               }
+
                if (strncmp("User-Agent: ",Buffer,12)==0)
                {
                        Buffer+=12;
@@ -361,14 +358,96 @@
                if (strncmp("Host: ",Buffer,6)==0)
                {
                        Buffer+=6;
-                       
-                       strncpy(Head->Host,Buffer,min(127,EOL-Buffer-1));
-                                       
+
+                       Head->Host[min(126,EOL-Buffer-1)]=0;
+                       strncpy(Head->Host,Buffer,min(126,EOL-Buffer-1));              
+ 
                        Buffer=EOL+1;   
                        continue;
                }
 #endif         
+               if (strncmp("Connection: Keep-Alive",Buffer,22)==0)
+               {
+                       Buffer+=22;
+                       Buffer=EOL+1;
+                       Head->Persistent = 1;
+                       continue;
+               }
+
+               if (strncmp("Range: bytes=",Buffer,13)==0)
+               {
+                       Buffer+=13;
+                       if (*Buffer!='-') Head->Offset = 
+simple_strtoul(Buffer,&Buffer,10);
+                       if (*Buffer == '-') {
+                               Buffer++;
+                               Head->End = simple_strtoul(Buffer,NULL,10);
+                       } else Head->Offset=0;
+                       Buffer=EOL+1;
+                       continue;
+               }
+
                Buffer = EOL+1;  /* Skip line */
+       }
+       if (filename) {
+
+           char PrefixLen;
+
+           if (sysctl_khttpd_docroot[0]=='(') {
+
+               char *p=sysctl_khttpd_docroot;
+               char *q;
+
+               while (*p=='(') {
+                       do {
+                               p++;
+                               q=p;    /* Mark position of virtual hostname */
+
+                               while (*p && *p!=')' && *p!=',') p++;           /* 
+Find the end of the hostname */
+
+                               if (*p==0) { printk(KERN_ERR ") missing in virtual 
+host string.\n");return; }
+
+                               if (strnicmp(Head->Host,q,p-q)==0) {
+                                       /* virtual hostname match */
+                                       while (*p && *p!=')') p++;      /* Skip to the 
+end of the vhostname list */
+                                       if (*p == 0) printk(KERN_ERR "path missing for 
+virtual host");
+
+                                       p++;
+                                       goto rootfound;
+                               }
+                       } while (*p==',');
+
+                       if (*p==')') { /* at end of virtual host names need to skip 
+the webroot since nothing matched */
+
+                               while (*p && *p!=':') p++;
+                               if (*p==0) { printk(KERN_ERR "closing : of virtual 
+host specification missing.\n");return; }
+                               p++;
+                       }
+
+               }
+       rootfound:
+               if (*p==0) { printk(KERN_ERR "Error in virtual host 
+specification.\n");return; }
+
+               /* p is pointing to matching webroot for this virtual host or the 
+default root */
+               q=p;while (*p && *p!=':') p++;          /* Find the end of the 
+pathname */
+               PrefixLen=p-q;
+               strncpy(Head->FileName,q,PrefixLen);
+
+           } else {
+
+              strncpy(Head->FileName,sysctl_khttpd_docroot,sizeof(Head->FileName));
+              PrefixLen = strlen(sysctl_khttpd_docroot);
+
+           }
+
+           Head->FileNameLength = min(255,filenamelen+PrefixLen);
+           strncat(Head->FileName,filename,min(255-PrefixLen,filenamelen));
+           
+           if (Head->FileName[Head->FileNameLength-1]=='/' && 
+Head->FileNameLength<255-10) {
+           
+               /* A directory! khttpd will not be able to successfully open it. But 
+it might be able to access index.html */
+               memcpy(Head->FileName+Head->FileNameLength,"index.html",10);
+               Head->FileNameLength+=10;
+           }
+           Head->FileName[Head->FileNameLength]=0;
        }
        LeaveFunction("ParseHeader");
 }
diff -urN linux-orig/net/khttpd/structure.h linux/net/khttpd/structure.h
--- linux-orig/net/khttpd/structure.h   Mon Dec 11 13:32:10 2000
+++ linux/net/khttpd/structure.h        Sat Jan 13 13:44:59 2001
@@ -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,15 @@
        /* 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 */
+       char            Agent[128];
        int             HTTPVER;        /* HTTP-version; 9 for 0.9,   10 for 1.0 and 
above */
+       int             Headersize;     /* Size of the request in bytes */
+       unsigned long   Offset;         /* If !=0 then a range request has been 
+parsed. */
+       unsigned long   End;            /* End of Range if specified */
+       char            IfRange[200];   /* IfRange time, rfc string format */
+       char            ContentRange[50];       /* HTTP header piece for ranges */
 
 
        /* Derived date from the above fields */        
diff -urN linux-orig/net/khttpd/sysctl.c linux/net/khttpd/sysctl.c
--- linux-orig/net/khttpd/sysctl.c      Mon Aug 23 13:44:03 1999
+++ linux/net/khttpd/sysctl.c   Fri Jan 12 21:19:55 2001
@@ -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 -urN linux-orig/net/khttpd/sysctl.h linux/net/khttpd/sysctl.h
--- linux-orig/net/khttpd/sysctl.h      Wed Aug 18 09:45:10 1999
+++ linux/net/khttpd/sysctl.h   Fri Jan 12 21:19:55 2001
@@ -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
diff -urN linux-orig/net/khttpd/waitheaders.c linux/net/khttpd/waitheaders.c
--- linux-orig/net/khttpd/waitheaders.c Sun Apr  2 15:53:28 2000
+++ linux/net/khttpd/waitheaders.c      Sat Jan 13 18:01:06 2001
@@ -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);
@@ -243,15 +285,31 @@
                Request->FileLength = (int)Request->filp->f_dentry->d_inode->i_size;
                Request->Time       = Request->filp->f_dentry->d_inode->i_mtime;
                Request->IMS_Time   = mimeTime_to_UnixTime(Request->IMS);
-               sprintf(Request->LengthS,"%i",Request->FileLength);
+               
+               if (Request->End ==0) Request->End = Request->FileLength;
+
+               if (Request->Offset >= Request->FileLength)
+               {       /* Bad Range request. Fall back to transferring whole page  */
+                       Request->Offset=0;
+               }
+
                time_Unix2RFC(min(Request->Time,CurrentTime_i),Request->TimeS);
                /* The min() is required by rfc1945, section 10.10:
                   It is not allowed to send a filetime in the future */
+               
+               if (Request->Offset && 
+mimeTime_to_UnixTime(Request->IfRange)>Request->Time)
+               {       /* Modified since last piece was transferred. Fall back to 
+beginning */
+                       Request->Offset=0;
+               }
+
+               sprintf(Request->LengthS,"%i",Request->End-Request->Offset);
 
                if (Request->IMS_Time>Request->Time)
                {       /* Not modified since last time */
                        Send304(Request->sock);
                        Request->FileLength=0;
+                       Request->End=0;
+                       Request->Offset=0;
                }
                else   /* Normal Case */
                {

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to