This is a patch against 2.4.1-pre8 implementing range support, persistent
connections and virtual hosts in khttpd. Two problems in my last patch
were fixed:

1. Range support: The Content-Range header did not give the correct value
   for the endpoint of the range retrieved. It always added 1....

2. Range headers. The "206 Partial content" header was not send when doing
   ranges 0-x where x <filesize.



diff -urN linux/net/khttpd/accept.c linux.new/net/khttpd/accept.c
--- linux/net/khttpd/accept.c   Sat Jan 22 11:54:58 2000
+++ linux.new/net/khttpd/accept.c       Thu Jan 18 15:05:20 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/net/khttpd/datasending.c linux.new/net/khttpd/datasending.c
--- linux/net/khttpd/datasending.c      Fri Nov 17 11:36:27 2000
+++ linux.new/net/khttpd/datasending.c  Thu Jan 18 15:05:20 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/net/khttpd/logging.c linux.new/net/khttpd/logging.c
--- linux/net/khttpd/logging.c  Wed Aug 18 09:45:10 1999
+++ linux.new/net/khttpd/logging.c      Thu Jan 18 15:05:20 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/net/khttpd/misc.c linux.new/net/khttpd/misc.c
--- linux/net/khttpd/misc.c     Thu Sep  2 11:47:20 1999
+++ linux.new/net/khttpd/misc.c Thu Jan 18 15:05:20 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/net/khttpd/prototypes.h linux.new/net/khttpd/prototypes.h
--- linux/net/khttpd/prototypes.h       Mon Dec 11 13:32:10 2000
+++ linux.new/net/khttpd/prototypes.h   Thu Jan 18 15:53:25 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/net/khttpd/rfc.c linux.new/net/khttpd/rfc.c
--- linux/net/khttpd/rfc.c      Mon Aug 23 10:41:25 1999
+++ linux.new/net/khttpd/rfc.c  Tue Jan 23 13:33:43 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 || Request->End< Request->FileLength) ? 
+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-1,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/net/khttpd/structure.h linux.new/net/khttpd/structure.h
--- linux/net/khttpd/structure.h        Mon Dec 11 13:32:10 2000
+++ linux.new/net/khttpd/structure.h    Thu Jan 18 15:53:25 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/net/khttpd/sysctl.c linux.new/net/khttpd/sysctl.c
--- linux/net/khttpd/sysctl.c   Mon Aug 23 13:44:03 1999
+++ linux.new/net/khttpd/sysctl.c       Thu Jan 18 15:05:20 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/net/khttpd/sysctl.h linux.new/net/khttpd/sysctl.h
--- linux/net/khttpd/sysctl.h   Wed Aug 18 09:45:10 1999
+++ linux.new/net/khttpd/sysctl.h       Thu Jan 18 15:05:20 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/net/khttpd/waitheaders.c linux.new/net/khttpd/waitheaders.c
--- linux/net/khttpd/waitheaders.c      Sun Apr  2 15:53:28 2000
+++ linux.new/net/khttpd/waitheaders.c  Thu Jan 18 15:05:20 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