Import 2.3.41pre2
[davej-history.git] / net / khttpd / waitheaders.c
blob47fa1581d55788365d67b463cba21f787ff83305
1 /*
3 kHTTPd -- the next generation
5 Wait for headers on the accepted connections
7 */
8 /****************************************************************
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 ****************************************************************/
27 Purpose:
29 WaitForHeaders polls all connections in "WaitForHeaderQueue" to see if
30 headers have arived. If so, the headers are decoded and the request is
31 moved to either the "SendingDataQueue" or the "UserspaceQueue".
33 Return value:
34 The number of requests that changed status
37 #include <linux/config.h>
38 #include <linux/kernel.h>
39 #include <linux/skbuff.h>
40 #include <linux/smp_lock.h>
41 #include <linux/file.h>
43 #include <asm/uaccess.h>
45 #include "structure.h"
46 #include "prototypes.h"
48 static char *Buffer[CONFIG_KHTTPD_NUMCPU];
51 static int DecodeHeader(const int CPUNR, struct http_request *Request);
54 int WaitForHeaders(const int CPUNR)
56 struct http_request *CurrentRequest,**Prev;
57 struct sock *sk;
58 int count = 0;
60 EnterFunction("WaitForHeaders");
62 CurrentRequest = threadinfo[CPUNR].WaitForHeaderQueue;
64 Prev = &(threadinfo[CPUNR].WaitForHeaderQueue);
66 while (CurrentRequest!=NULL)
69 /* If the connection is lost, remove from queue */
71 if (CurrentRequest->sock->sk->state != TCP_ESTABLISHED
72 && CurrentRequest->sock->sk->state != TCP_CLOSE_WAIT)
74 struct http_request *Next;
76 Next = CurrentRequest->Next;
78 *Prev = CurrentRequest->Next;
79 CurrentRequest->Next = NULL;
82 CleanUpRequest(CurrentRequest);
83 CurrentRequest = Next;
84 continue;
89 /* If data pending, take action */
91 sk = CurrentRequest->sock->sk;
93 if (!skb_queue_empty(&(sk->receive_queue))) /* Do we have data ? */
95 struct http_request *Next;
99 /* Decode header */
101 if (DecodeHeader(CPUNR,CurrentRequest)<0)
103 CurrentRequest = CurrentRequest->Next;
104 continue;
108 /* Remove from WaitForHeaderQueue */
110 Next= CurrentRequest->Next;
112 *Prev = Next;
113 count++;
115 /* Add to either the UserspaceQueue or the DataSendingQueue */
117 if (CurrentRequest->IsForUserspace!=0)
119 CurrentRequest->Next = threadinfo[CPUNR].UserspaceQueue;
120 threadinfo[CPUNR].UserspaceQueue = CurrentRequest;
121 } else
123 CurrentRequest->Next = threadinfo[CPUNR].DataSendingQueue;
124 threadinfo[CPUNR].DataSendingQueue = CurrentRequest;
127 CurrentRequest = Next;
128 continue;
133 Prev = &(CurrentRequest->Next);
134 CurrentRequest = CurrentRequest->Next;
137 LeaveFunction("WaitHeaders");
138 return count;
141 void StopWaitingForHeaders(const int CPUNR)
143 struct http_request *CurrentRequest,*Next;
145 EnterFunction("StopWaitingForHeaders");
146 CurrentRequest = threadinfo[CPUNR].WaitForHeaderQueue;
148 while (CurrentRequest!=NULL)
150 Next = CurrentRequest->Next;
151 CleanUpRequest(CurrentRequest);
152 CurrentRequest=Next;
155 threadinfo[CPUNR].WaitForHeaderQueue = NULL; /* The queue is empty now */
157 free_page((unsigned long)Buffer[CPUNR]);
158 Buffer[CPUNR]=NULL;
160 EnterFunction("StopWaitingForHeaders");
166 DecodeHeader peeks at the TCP/IP data, determines what the request is,
167 fills the request-structure and sends the HTTP-header when apropriate.
171 static int DecodeHeader(const int CPUNR, struct http_request *Request)
173 struct msghdr msg;
174 struct iovec iov;
175 int len;
177 mm_segment_t oldfs;
179 EnterFunction("DecodeHeader");
181 /* First, read the data */
183 msg.msg_name = 0;
184 msg.msg_namelen = 0;
185 msg.msg_iov = &iov;
186 msg.msg_iovlen = 1;
187 msg.msg_control = NULL;
188 msg.msg_controllen = 0;
189 msg.msg_flags = 0;
191 msg.msg_iov->iov_base = &Buffer[CPUNR][0];
192 msg.msg_iov->iov_len = (size_t)4095;
194 len = 0;
195 oldfs = get_fs(); set_fs(KERNEL_DS);
196 /* 4095 leaves a "0" to terminate the string */
198 len = sock_recvmsg(Request->sock,&msg,4095,MSG_PEEK);
199 set_fs(oldfs);
201 if (len<0) {
202 /* WONDERFUL. NO COMMENTS. --ANK */
203 Request->IsForUserspace = 1;
204 return 0;
207 if (len>=4094) /* BIG header, we cannot decode it so leave it to userspace */
209 Request->IsForUserspace = 1;
210 return 0;
213 /* Then, decode the header */
216 ParseHeader(Buffer[CPUNR],len,Request);
218 Request->filp = OpenFileForSecurity(Request->FileName);
221 Request->MimeType = ResolveMimeType(Request->FileName,&Request->MimeLength);
224 if (Request->MimeType==NULL) /* Unknown mime-type */
226 if (Request->filp!=NULL)
228 fput(Request->filp);
229 Request->filp = NULL;
231 Request->IsForUserspace = 1;
233 return 0;
236 if (Request->filp==NULL)
238 Request->IsForUserspace = 1;
239 return 0;
241 else
242 if ((Request->filp->f_dentry!=NULL)&&(Request->filp->f_dentry->d_inode!=NULL))
244 Request->FileLength = (int)Request->filp->f_dentry->d_inode->i_size;
245 Request->Time = Request->filp->f_dentry->d_inode->i_mtime;
246 Request->IMS_Time = mimeTime_to_UnixTime(Request->IMS);
247 sprintf(Request->LengthS,"%i",Request->FileLength);
248 time_Unix2RFC(min(Request->Time,CurrentTime_i),Request->TimeS);
249 /* The min() is required by rfc1945, section 10.10:
250 It is not allowed to send a filetime in the future */
252 if (Request->IMS_Time>Request->Time)
253 { /* Not modified since last time */
254 Send304(Request->sock);
255 Request->FileLength=0;
257 else /* Normal Case */
259 Request->sock->sk->tp_pinfo.af_tcp.nonagle = 2; /* this is TCP_CORK */
260 if (Request->HTTPVER!=9) /* HTTP/0.9 doesn't allow a header */
261 SendHTTPHeader(Request);
265 } else
267 /* Ehhh... */
269 printk(KERN_CRIT "kHTTPd: Unexpected filesystem response\n");
270 return -1;
273 LeaveFunction("DecodeHeader");
274 return 0;
278 int InitWaitHeaders(int ThreadCount)
280 int I,I2;
282 EnterFunction("InitWaitHeaders");
283 I=0;
284 while (I<ThreadCount)
286 Buffer[I] = (char*)get_free_page((int)GFP_KERNEL);
287 if (Buffer[I] == NULL)
289 printk(KERN_CRIT "kHTTPd: Not enough memory for basic needs\n");
290 I2=0;
291 while (I2<I-1)
293 free_page( (unsigned long)Buffer[I2++]);
295 return -1;
297 I++;
300 LeaveFunction("InitWaitHeaders");
301 return 0;