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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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