khttpd patch fixes

Christoph Lameter (christoph@lameter.com)
Tue, 23 Jan 2001 14:34:18 -0800 (PST)


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 <christoph@lameter.com>, 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 majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/