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