OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [LINUX_2_4_26_OR32/] [linux/] [linux-2.4/] [net/] [khttpd/] [waitheaders.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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("WaitForHeaders");
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
        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
 
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.