1 /*
2
3 kHTTPd -- the next generation
4
5 Wait for headers on the accepted connections
6
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.
13 *
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.
18 *
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.
22 *
23 ****************************************************************/
24
25 /*
26
27 Purpose:
28
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".
32
33 Return value:
34 The number of requests that changed status
35 */
36
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>
42
43 #include <asm/uaccess.h>
44
45 #include "structure.h"
46 #include "prototypes.h"
47
48 static char *Buffer[CONFIG_KHTTPD_NUMCPU];
49
50
51 static int DecodeHeader(const int CPUNR, struct http_request *Request);
52
53
WaitForHeaders(const int CPUNR)54 int WaitForHeaders(const int CPUNR)
55 {
56 struct http_request *CurrentRequest,**Prev;
57 struct sock *sk;
58 int count = 0;
59
60 EnterFunction("WaitForHeaders");
61
62 CurrentRequest = threadinfo[CPUNR].WaitForHeaderQueue;
63
64 Prev = &(threadinfo[CPUNR].WaitForHeaderQueue);
65
66 while (CurrentRequest!=NULL)
67 {
68
69 /* If the connection is lost, remove from queue */
70
71 if (CurrentRequest->sock->sk->state != TCP_ESTABLISHED
72 && CurrentRequest->sock->sk->state != TCP_CLOSE_WAIT)
73 {
74 struct http_request *Next;
75
76 Next = CurrentRequest->Next;
77
78 *Prev = CurrentRequest->Next;
79 CurrentRequest->Next = NULL;
80
81
82 CleanUpRequest(CurrentRequest);
83 CurrentRequest = Next;
84 continue;
85 }
86
87
88
89 /* If data pending, take action */
90
91 sk = CurrentRequest->sock->sk;
92
93 if (!skb_queue_empty(&(sk->receive_queue))) /* Do we have data ? */
94 {
95 struct http_request *Next;
96
97
98
99 /* Decode header */
100
101 if (DecodeHeader(CPUNR,CurrentRequest)<0)
102 {
103 CurrentRequest = CurrentRequest->Next;
104 continue;
105 }
106
107
108 /* Remove from WaitForHeaderQueue */
109
110 Next= CurrentRequest->Next;
111
112 *Prev = Next;
113 count++;
114
115 /* Add to either the UserspaceQueue or the DataSendingQueue */
116
117 if (CurrentRequest->IsForUserspace!=0)
118 {
119 CurrentRequest->Next = threadinfo[CPUNR].UserspaceQueue;
120 threadinfo[CPUNR].UserspaceQueue = CurrentRequest;
121 } else
122 {
123 CurrentRequest->Next = threadinfo[CPUNR].DataSendingQueue;
124 threadinfo[CPUNR].DataSendingQueue = CurrentRequest;
125 }
126
127 CurrentRequest = Next;
128 continue;
129
130 }
131
132
133 Prev = &(CurrentRequest->Next);
134 CurrentRequest = CurrentRequest->Next;
135 }
136
137 LeaveFunction("WaitForHeaders");
138 return count;
139 }
140
StopWaitingForHeaders(const int CPUNR)141 void StopWaitingForHeaders(const int CPUNR)
142 {
143 struct http_request *CurrentRequest,*Next;
144
145 EnterFunction("StopWaitingForHeaders");
146 CurrentRequest = threadinfo[CPUNR].WaitForHeaderQueue;
147
148 while (CurrentRequest!=NULL)
149 {
150 Next = CurrentRequest->Next;
151 CleanUpRequest(CurrentRequest);
152 CurrentRequest=Next;
153 }
154
155 threadinfo[CPUNR].WaitForHeaderQueue = NULL; /* The queue is empty now */
156
157 free_page((unsigned long)Buffer[CPUNR]);
158 Buffer[CPUNR]=NULL;
159
160 EnterFunction("StopWaitingForHeaders");
161 }
162
163
164 /*
165
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.
168
169 */
170
DecodeHeader(const int CPUNR,struct http_request * Request)171 static int DecodeHeader(const int CPUNR, struct http_request *Request)
172 {
173 struct msghdr msg;
174 struct iovec iov;
175 int len;
176
177 mm_segment_t oldfs;
178
179 EnterFunction("DecodeHeader");
180
181 if (Buffer[CPUNR] == NULL) {
182 /* see comments in main.c regarding buffer managemnet - dank */
183 printk(KERN_CRIT "khttpd: lost my buffer");
184 BUG();
185 }
186
187 /* First, read the data */
188
189 msg.msg_name = 0;
190 msg.msg_namelen = 0;
191 msg.msg_iov = &iov;
192 msg.msg_iovlen = 1;
193 msg.msg_control = NULL;
194 msg.msg_controllen = 0;
195 msg.msg_flags = 0;
196
197 msg.msg_iov->iov_base = &Buffer[CPUNR][0];
198 msg.msg_iov->iov_len = (size_t)4095;
199
200 len = 0;
201 oldfs = get_fs(); set_fs(KERNEL_DS);
202 /* 4095 leaves a "0" to terminate the string */
203
204 len = sock_recvmsg(Request->sock,&msg,4095,MSG_PEEK);
205 set_fs(oldfs);
206
207 if (len<0) {
208 /* WONDERFUL. NO COMMENTS. --ANK */
209 Request->IsForUserspace = 1;
210 return 0;
211 }
212
213 if (len>=4094) /* BIG header, we cannot decode it so leave it to userspace */
214 {
215 Request->IsForUserspace = 1;
216 return 0;
217 }
218
219 /* Then, decode the header */
220
221
222 ParseHeader(Buffer[CPUNR],len,Request);
223
224 Request->filp = OpenFileForSecurity(Request->FileName);
225
226
227 Request->MimeType = ResolveMimeType(Request->FileName,&Request->MimeLength);
228
229
230 if (Request->MimeType==NULL) /* Unknown mime-type */
231 {
232 if (Request->filp!=NULL)
233 {
234 fput(Request->filp);
235 Request->filp = NULL;
236 }
237 Request->IsForUserspace = 1;
238
239 return 0;
240 }
241
242 if (Request->filp==NULL)
243 {
244 Request->IsForUserspace = 1;
245 return 0;
246 }
247 else
248 {
249 Request->FileLength = (int)Request->filp->f_dentry->d_inode->i_size;
250 Request->Time = Request->filp->f_dentry->d_inode->i_mtime;
251 Request->IMS_Time = mimeTime_to_UnixTime(Request->IMS);
252 sprintf(Request->LengthS,"%i",Request->FileLength);
253 time_Unix2RFC(min_t(unsigned int, Request->Time,CurrentTime_i),Request->TimeS);
254 /* The min() is required by rfc1945, section 10.10:
255 It is not allowed to send a filetime in the future */
256
257 if (Request->IMS_Time>Request->Time)
258 { /* Not modified since last time */
259 Send304(Request->sock);
260 Request->FileLength=0;
261 }
262 else /* Normal Case */
263 {
264 Request->sock->sk->tp_pinfo.af_tcp.nonagle = 2; /* this is TCP_CORK */
265 if (Request->HTTPVER!=9) /* HTTP/0.9 doesn't allow a header */
266 SendHTTPHeader(Request);
267 }
268
269
270 }
271
272 LeaveFunction("DecodeHeader");
273 return 0;
274 }
275
276
InitWaitHeaders(int ThreadCount)277 int InitWaitHeaders(int ThreadCount)
278 {
279 int I,I2;
280
281 EnterFunction("InitWaitHeaders");
282 I=0;
283 while (I<ThreadCount)
284 {
285 Buffer[I] = (char*)get_free_page((int)GFP_KERNEL);
286 if (Buffer[I] == NULL)
287 {
288 printk(KERN_CRIT "kHTTPd: Not enough memory for basic needs\n");
289 I2=0;
290 while (I2<I-1)
291 {
292 free_page( (unsigned long)Buffer[I2++]);
293 }
294 return -1;
295 }
296 I++;
297 }
298
299 LeaveFunction("InitWaitHeaders");
300 return 0;
301
302 }
303