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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [uIP_Demo_IAR_ARM7/] [uip/] [httpd.c_] - Blame information for rev 583

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 583 jeremybenn
/*$T httpd.c GC 1.138 07/23/05 13:10:49 */
2
 
3
/*
4
 * \addtogroup exampleapps @{ £
5
 * \defgroup httpd Web server @{ The uIP web server is a very simplistic
6
 * implementation of an HTTP server. It can serve web pages and files from a
7
 * read-only ROM filesystem, and provides a very small scripting language. The
8
 * script language is very simple and works as follows. Each script line starts
9
 * with a command character, either "i", "t", "c", "#" or ".". The "i" command
10
 * tells the script interpreter to "include" a file from the virtual file system
11
 * and output it to the web browser. The "t" command should be followed by a line
12
 * of text that is to be output to the browser. The "c" command is used to call
13
 * one of the C functions from the httpd-cgi.c file. A line that starts with a "#"
14
 * is ignored (i.e., the "#" denotes a comment), and the "." denotes the last
15
 * script line. The script that produces the file statistics page looks somewhat
16
 * like this: \code i /header.html t 

File statistics


17
 * width="100%"> t 
/index.html c a
18
 * /index.html t 
/cgi/files c
19
 * a /cgi/files t 
/cgi/tcp c a
20
 * /cgi/tcp t 
/404.html c a
21
 * /404.html t 
i /footer.plain . \endcode £ 22
 * \file HTTP server. \author Adam Dunkels  £
23
 * Copyright (c) 2001, Adam Dunkels. All rights reserved. Redistribution and use
24
 * in source and binary forms, with or without modification, are permitted
25
 * provided that the following conditions are met: 1. Redistributions of source
26
 * code must retain the above copyright notice, this list of conditions and the
27
 * following disclaimer. 2. Redistributions in binary form must reproduce the
28
 * above copyright notice, this list of conditions and the following disclaimer in
29
 * the documentation and/or other materials provided with the distribution. 3. The
30
 * name of the author may not be used to endorse or promote products derived from
31
 * this software without specific prior written permission. THIS SOFTWARE IS
32
 * PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
35
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
36
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
37
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
40
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41
 * This file is part of the uIP TCP/IP stack. $Id: httpd.c,v 1.28.2.6 2003/10/07
42
 * 13:22:27 adam Exp $
43
 */
44
#include "uip.h"
45
#include "httpd.h"
46
#include "fs.h"
47
#include "fsdata.h"
48
#include "cgi.h"
49
 
50
#define NULL    ( void * ) 0
51
 
52
/* The HTTP server states: */
53
#define HTTP_NOGET  0
54
#define HTTP_FILE   1
55
#define HTTP_TEXT   2
56
#define HTTP_FUNC   3
57
#define HTTP_END    4
58
 
59
#ifdef DEBUG
60
#include 
61
#define PRINT( x )
62
#define PRINTLN( x )
63
#else /* DEBUG */
64
#define PRINT( x )
65
#define PRINTLN( x )
66
#endif /* DEBUG */
67
 
68
struct httpd_state              *hs;
69
 
70
extern const struct fsdata_file file_index_html;
71
extern const struct fsdata_file file_404_html;
72
 
73
static void                     next_scriptline( void );
74
static void                     next_scriptstate( void );
75
 
76
#define ISO_G       0x47
77
#define ISO_E       0x45
78
#define ISO_T       0x54
79
#define ISO_slash   0x2f
80
#define ISO_c       0x63
81
#define ISO_g       0x67
82
#define ISO_i       0x69
83
#define ISO_space   0x20
84
#define ISO_nl      0x0a
85
#define ISO_cr      0x0d
86
#define ISO_a       0x61
87
#define ISO_t       0x74
88
#define ISO_hash    0x23
89
#define ISO_period  0x2e
90
 
91
#define httpPORT    80
92
 
93
/*
94
 =======================================================================================================================
95
    Initialize the web server. Starts to listen for incoming connection requests on TCP port 80.
96
 =======================================================================================================================
97
 */
98
void httpd_init( void )
99
{
100
    fs_init();
101
 
102
    /* Listen to port 80. */
103
    uip_listen( HTONS( httpPORT ) );
104
}
105
 
106
/*
107
 =======================================================================================================================
108
 =======================================================================================================================
109
 */
110
void httpd_appcall( void )
111
{
112
    /*~~~~~~~~~~~~~~~~~~~*/
113
    struct fs_file  fsfile;
114
    u8_t            i;
115
    /*~~~~~~~~~~~~~~~~~~~*/
116
 
117
    switch( uip_conn->lport )
118
    {
119
    /* This is the web server: */
120
    case HTONS( httpPORT ):
121
        /* Pick out the application state from the uip_conn structure. */
122
        hs = ( struct httpd_state * ) ( uip_conn->appstate );
123
 
124
        /*
125
         * We use the uip_ test functions to deduce why we were called. If uip_connected()
126
         * is non-zero, we were called because a remote host has connected to us. If
127
         * uip_newdata() is non-zero, we were called because the remote host has sent us
128
         * new data, and if uip_acked() is non-zero, the remote host has acknowledged the
129
         * data we previously sent to it.
130
         */
131
        if( uip_connected() )
132
        {
133
            /*
134
             * Since we have just been connected with the remote host, we reset the state for
135
             * this connection. The ->count variable contains the amount of data that is yet
136
             * to be sent to the remote host, and the ->state is set to HTTP_NOGET to signal
137
             * that we haven't received any HTTP GET request for this connection yet.
138
             */
139
            hs->state = HTTP_NOGET;
140
            hs->count = 0;
141
            return;
142
        }
143
        else if( uip_poll() )
144
        {
145
            /*
146
             * If we are polled ten times, we abort the connection. This is because we don't
147
             * want connections lingering indefinately in the system.
148
             */
149
            if( hs->count++ >= 10 )
150
            {
151
                uip_abort();
152
            }
153
 
154
            return;
155
        }
156
        else if( uip_newdata() && hs->state == HTTP_NOGET )
157
        {
158
            /*
159
             * This is the first data we receive, and it should contain a GET. £
160
             * Check for GET.
161
             */
162
            if
163
            (
164
                uip_appdata[0] != ISO_G
165
            ||  uip_appdata[1] != ISO_E
166
            ||  uip_appdata[2] != ISO_T
167
            ||  uip_appdata[3] != ISO_space
168
            )
169
            {
170
                /* If it isn't a GET, we abort the connection. */
171
                uip_abort();
172
                return;
173
            }
174
 
175
            /* Find the file we are looking for. */
176
            for( i = 4; i < 40; ++i )
177
            {
178
                if( uip_appdata[i] == ISO_space || uip_appdata[i] == ISO_cr || uip_appdata[i] == ISO_nl )
179
                {
180
                    uip_appdata[i] = 0;
181
                    break;
182
                }
183
            }
184
 
185
            PRINT( "request for file " );
186
            PRINTLN( &uip_appdata[4] );
187
 
188
            /* Check for a request for "/". */
189
            if( uip_appdata[4] == ISO_slash && uip_appdata[5] == 0 )
190
            {
191
                fs_open( file_index_html.name, &fsfile );
192
            }
193
            else
194
            {
195
                if( !fs_open( ( const char * ) &uip_appdata[4], &fsfile ) )
196
                {
197
                    PRINTLN( "couldn't open file" );
198
                    fs_open( file_404_html.name, &fsfile );
199
                }
200
            }
201
 
202
            if
203
            (
204
                uip_appdata[4] == ISO_slash
205
            &&  uip_appdata[5] == ISO_c
206
            &&  uip_appdata[6] == ISO_g
207
            &&  uip_appdata[7] == ISO_i
208
            &&  uip_appdata[8] == ISO_slash
209
            )
210
            {
211
                /*
212
                 * If the request is for a file that starts with "/cgi/", we prepare for invoking
213
                 * a script.
214
                 */
215
                hs->script = fsfile.data;
216
                next_scriptstate();
217
            }
218
            else
219
            {
220
                hs->script = NULL;
221
 
222
                /*
223
                 * The web server is now no longer in the HTTP_NOGET state, but in the HTTP_FILE
224
                 * state since is has now got the GET from the client and will start transmitting
225
                 * the file.
226
                 */
227
                hs->state = HTTP_FILE;
228
 
229
                /*
230
                 * Point the file pointers in the connection state to point to the first byte of
231
                 * the file.
232
                 */
233
                hs->dataptr = fsfile.data;
234
                hs->count = fsfile.len;
235
            }
236
        }
237
 
238
        if( hs->state != HTTP_FUNC )
239
        {
240
            /*
241
             * Check if the client (remote end) has acknowledged any data that we've
242
             * previously sent. If so, we move the file pointer further into the file and send
243
             * back more data. If we are out of data to send, we close the connection.
244
             */
245
            if( uip_acked() )
246
            {
247
                if( hs->count >= uip_conn->len )
248
                {
249
                    hs->count -= uip_conn->len;
250
                    hs->dataptr += uip_conn->len;
251
                }
252
                else
253
                {
254
                    hs->count = 0;
255
                }
256
 
257
                if( hs->count == 0 )
258
                {
259
                    if( hs->script != NULL )
260
                    {
261
                        next_scriptline();
262
                        next_scriptstate();
263
                    }
264
                    else
265
                    {
266
                        uip_close();
267
                    }
268
                }
269
            }
270
        }
271
        else
272
        {
273
            /* Call the CGI function. */
274
            if( cgitab[hs->script[2] - ISO_a](uip_acked()) )
275
            {
276
                /* If the function returns non-zero, we jump to the next line in the script. */
277
                next_scriptline();
278
                next_scriptstate();
279
            }
280
        }
281
 
282
        if( hs->state != HTTP_FUNC && !uip_poll() )
283
        {
284
            /* Send a piece of data, but not more than the MSS of the connection. */
285
            uip_send( ( void * ) hs->dataptr, hs->count );
286
        }
287
 
288
        /* Finally, return to uIP. Our outgoing packet will soon be on its way... */
289
        return;
290
 
291
    default:
292
        /* Should never happen. */
293
        uip_abort();
294
        break;
295
    }
296
}
297
 
298
/*
299
 =======================================================================================================================
300
    next_scriptline(): Reads the script until it finds a newline.
301
 =======================================================================================================================
302
 */
303
static void next_scriptline( void )
304
{
305
    /* Loop until we find a newline character. */
306
    do
307
    {
308
        ++( hs->script );
309
    } while( hs->script[0] != ISO_nl );
310
 
311
    /* Eat up the newline as well. */
312
    ++( hs->script );
313
}
314
 
315
/*
316
 =======================================================================================================================
317
    next_sciptstate: Reads one line of script and decides what to do next.
318
 =======================================================================================================================
319
 */
320
static void next_scriptstate( void )
321
{
322
    /*~~~~~~~~~~~~~~~~~~~*/
323
    struct fs_file  fsfile;
324
    u8_t            i;
325
    /*~~~~~~~~~~~~~~~~~~~*/
326
 
327
again:
328
    switch( hs->script[0] )
329
    {
330
    case ISO_t:
331
        /* Send a text string. */
332
        hs->state = HTTP_TEXT;
333
        hs->dataptr = &hs->script[2];
334
 
335
        /* Calculate length of string. */
336
        for( i = 0; hs->dataptr[i] != ISO_nl; ++i );
337
        hs->count = i;
338
        break;
339
 
340
    case ISO_c:
341
        /* Call a function. */
342
        hs->state = HTTP_FUNC;
343
        hs->dataptr = NULL;
344
        hs->count = 0;
345
        cgitab[hs->script[2] - ISO_a]( 0 );
346
        break;
347
 
348
    case ISO_i:
349
        /* Include a file. */
350
        hs->state = HTTP_FILE;
351
        if( !fs_open( &hs->script[2], &fsfile ) )
352
        {
353
            uip_abort();
354
        }
355
 
356
        hs->dataptr = fsfile.data;
357
        hs->count = fsfile.len;
358
        break;
359
 
360
    case ISO_hash:
361
        /* Comment line. */
362
        next_scriptline();
363
        goto again;
364
 
365
    case ISO_period:
366
        /* End of script. */
367
        hs->state = HTTP_END;
368
        uip_close();
369
        break;
370
 
371
    default:
372
        uip_abort();
373
        break;
374
    }
375
}
376
 
377
/*
378
 * @} £
379
 * @}
380
 */

powered by: WebSVN 2.1.0

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