File: /usr/src/linux/net/khttpd/waitheaders.c

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     
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("WaitHeaders");
138     	return count;
139     }
140     
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     
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     	/* First, read the data */
182     
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;
190     	
191     	msg.msg_iov->iov_base = &Buffer[CPUNR][0];
192     	msg.msg_iov->iov_len  = (size_t)4095;
193     	
194     	len = 0;
195     	oldfs = get_fs(); set_fs(KERNEL_DS);
196     	/* 4095 leaves a "0" to terminate the string */
197     	
198     	len = sock_recvmsg(Request->sock,&msg,4095,MSG_PEEK);
199     	set_fs(oldfs);
200     
201     	if (len<0) {
202     		/* WONDERFUL. NO COMMENTS. --ANK */
203     		Request->IsForUserspace = 1;
204     		return 0;
205     	}
206     
207     	if (len>=4094) /* BIG header, we cannot decode it so leave it to userspace */	
208     	{
209     		Request->IsForUserspace = 1;
210     		return 0;
211     	}
212     	
213     	/* Then, decode the header */
214     	
215     	
216     	ParseHeader(Buffer[CPUNR],len,Request);
217     	
218     	Request->filp = OpenFileForSecurity(Request->FileName);
219     	
220     	
221     	Request->MimeType = ResolveMimeType(Request->FileName,&Request->MimeLength);
222     	
223     	
224     	if (Request->MimeType==NULL) /* Unknown mime-type */
225     	{
226     		if (Request->filp!=NULL)
227     		{
228     			fput(Request->filp);
229     			Request->filp = NULL;
230     		}
231     		Request->IsForUserspace = 1;
232     		
233     		return 0;
234     	}
235     
236     	if (Request->filp==NULL)
237     	{
238     		Request->IsForUserspace = 1;
239     		return 0;
240     	}
241     	else
242     	{
243     		Request->FileLength = (int)Request->filp->f_dentry->d_inode->i_size;
244     		Request->Time       = Request->filp->f_dentry->d_inode->i_mtime;
245     		Request->IMS_Time   = mimeTime_to_UnixTime(Request->IMS);
246     		sprintf(Request->LengthS,"%i",Request->FileLength);
247     		time_Unix2RFC(min_t(unsigned int, Request->Time,CurrentTime_i),Request->TimeS);
248        	        /* The min() is required by rfc1945, section 10.10:
249        	           It is not allowed to send a filetime in the future */
250     
251     		if (Request->IMS_Time>Request->Time)
252     		{	/* Not modified since last time */
253     			Send304(Request->sock);
254     			Request->FileLength=0;
255     		}
256     		else   /* Normal Case */
257     		{
258     			Request->sock->sk->tp_pinfo.af_tcp.nonagle = 2; /* this is TCP_CORK */
259     			if (Request->HTTPVER!=9)  /* HTTP/0.9 doesn't allow a header */
260     				SendHTTPHeader(Request);
261     		}
262     		
263     	
264     	}
265     	
266     	LeaveFunction("DecodeHeader");
267     	return 0;
268     }
269     
270     
271     int InitWaitHeaders(int ThreadCount)
272     {
273     	int I,I2;
274     
275     	EnterFunction("InitWaitHeaders");
276     	I=0;	
277     	while (I<ThreadCount)
278     	{
279     		Buffer[I] = (char*)get_free_page((int)GFP_KERNEL);
280     		if (Buffer[I] == NULL) 
281     		{
282     			printk(KERN_CRIT "kHTTPd: Not enough memory for basic needs\n");
283     			I2=0;
284     			while (I2<I-1)
285     			{
286     				free_page( (unsigned long)Buffer[I2++]);
287     			}
288     			return -1;
289     		}
290     		I++;
291     	}
292     	
293     	LeaveFunction("InitWaitHeaders");	
294     	return 0;
295     
296     }
297