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)&&(totalbytesiov_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 (BufferAgent,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);