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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [uIP/] [uip-1.0/] [apps/] [webserver/] [httpd.c] - Blame information for rev 606

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 606 jeremybenn
/**
2
 * \addtogroup apps
3
 * @{
4
 */
5
 
6
/**
7
 * \defgroup httpd Web server
8
 * @{
9
 * The uIP web server is a very simplistic implementation of an HTTP
10
 * server. It can serve web pages and files from a read-only ROM
11
 * filesystem, and provides a very small scripting language.
12
 
13
 */
14
 
15
/**
16
 * \file
17
 *         Web server
18
 * \author
19
 *         Adam Dunkels <adam@sics.se>
20
 */
21
 
22
 
23
/*
24
 * Copyright (c) 2004, Adam Dunkels.
25
 * All rights reserved.
26
 *
27
 * Redistribution and use in source and binary forms, with or without
28
 * modification, are permitted provided that the following conditions
29
 * are met:
30
 * 1. Redistributions of source code must retain the above copyright
31
 *    notice, this list of conditions and the following disclaimer.
32
 * 2. Redistributions in binary form must reproduce the above copyright
33
 *    notice, this list of conditions and the following disclaimer in the
34
 *    documentation and/or other materials provided with the distribution.
35
 * 3. Neither the name of the Institute nor the names of its contributors
36
 *    may be used to endorse or promote products derived from this software
37
 *    without specific prior written permission.
38
 *
39
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
40
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
43
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
44
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
45
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
48
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
49
 * SUCH DAMAGE.
50
 *
51
 * This file is part of the uIP TCP/IP stack.
52
 *
53
 * Author: Adam Dunkels <adam@sics.se>
54
 *
55
 * $Id: httpd.c 2 2011-07-17 20:13:17Z filepang@gmail.com $
56
 */
57
 
58
#include "uip.h"
59
#include "httpd.h"
60
#include "httpd-fs.h"
61
#include "httpd-cgi.h"
62
#include "http-strings.h"
63
 
64
#include <string.h>
65
 
66
#define STATE_WAITING 0
67
#define STATE_OUTPUT  1
68
 
69
#define ISO_nl      0x0a
70
#define ISO_space   0x20
71
#define ISO_bang    0x21
72
#define ISO_percent 0x25
73
#define ISO_period  0x2e
74
#define ISO_slash   0x2f
75
#define ISO_colon   0x3a
76
 
77
 
78
/*---------------------------------------------------------------------------*/
79
static unsigned short
80
generate_part_of_file(void *state)
81
{
82
  struct httpd_state *s = (struct httpd_state *)state;
83
 
84
  if(s->file.len > uip_mss()) {
85
    s->len = uip_mss();
86
  } else {
87
    s->len = s->file.len;
88
  }
89
  memcpy(uip_appdata, s->file.data, s->len);
90
 
91
  return s->len;
92
}
93
/*---------------------------------------------------------------------------*/
94
static
95
PT_THREAD(send_file(struct httpd_state *s))
96
{
97
  PSOCK_BEGIN(&s->sout);
98
 
99
  do {
100
    PSOCK_GENERATOR_SEND(&s->sout, generate_part_of_file, s);
101
    s->file.len -= s->len;
102
    s->file.data += s->len;
103
  } while(s->file.len > 0);
104
 
105
  PSOCK_END(&s->sout);
106
}
107
/*---------------------------------------------------------------------------*/
108
static
109
PT_THREAD(send_part_of_file(struct httpd_state *s))
110
{
111
  PSOCK_BEGIN(&s->sout);
112
 
113
  PSOCK_SEND(&s->sout, s->file.data, s->len);
114
 
115
  PSOCK_END(&s->sout);
116
}
117
/*---------------------------------------------------------------------------*/
118
static void
119
next_scriptstate(struct httpd_state *s)
120
{
121
  char *p;
122
  p = strchr(s->scriptptr, ISO_nl) + 1;
123
  s->scriptlen -= (unsigned short)(p - s->scriptptr);
124
  s->scriptptr = p;
125
}
126
/*---------------------------------------------------------------------------*/
127
static
128
PT_THREAD(handle_script(struct httpd_state *s))
129
{
130
  char *ptr;
131
 
132
  PT_BEGIN(&s->scriptpt);
133
 
134
 
135
  while(s->file.len > 0) {
136
 
137
    /* Check if we should start executing a script. */
138
    if(*s->file.data == ISO_percent &&
139
       *(s->file.data + 1) == ISO_bang) {
140
      s->scriptptr = s->file.data + 3;
141
      s->scriptlen = s->file.len - 3;
142
      if(*(s->scriptptr - 1) == ISO_colon) {
143
        httpd_fs_open(s->scriptptr + 1, &s->file);
144
        PT_WAIT_THREAD(&s->scriptpt, send_file(s));
145
      } else {
146
        PT_WAIT_THREAD(&s->scriptpt,
147
                       httpd_cgi(s->scriptptr)(s, s->scriptptr));
148
      }
149
      next_scriptstate(s);
150
 
151
      /* The script is over, so we reset the pointers and continue
152
         sending the rest of the file. */
153
      s->file.data = s->scriptptr;
154
      s->file.len = s->scriptlen;
155
    } else {
156
      /* See if we find the start of script marker in the block of HTML
157
         to be sent. */
158
 
159
      if(s->file.len > uip_mss()) {
160
        s->len = uip_mss();
161
      } else {
162
        s->len = s->file.len;
163
      }
164
 
165
      if(*s->file.data == ISO_percent) {
166
        ptr = strchr(s->file.data + 1, ISO_percent);
167
      } else {
168
        ptr = strchr(s->file.data, ISO_percent);
169
      }
170
      if(ptr != NULL &&
171
         ptr != s->file.data) {
172
        s->len = (int)(ptr - s->file.data);
173
        if(s->len >= uip_mss()) {
174
          s->len = uip_mss();
175
        }
176
      }
177
      PT_WAIT_THREAD(&s->scriptpt, send_part_of_file(s));
178
      s->file.data += s->len;
179
      s->file.len -= s->len;
180
 
181
    }
182
  }
183
 
184
  PT_END(&s->scriptpt);
185
}
186
/*---------------------------------------------------------------------------*/
187
static
188
PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr))
189
{
190
  char *ptr;
191
 
192
  PSOCK_BEGIN(&s->sout);
193
 
194
  PSOCK_SEND_STR(&s->sout, statushdr);
195
 
196
  ptr = strrchr(s->filename, ISO_period);
197
  if(ptr == NULL) {
198
    PSOCK_SEND_STR(&s->sout, http_content_type_binary);
199
  } else if(strncmp(http_html, ptr, 5) == 0 ||
200
            strncmp(http_shtml, ptr, 6) == 0) {
201
    PSOCK_SEND_STR(&s->sout, http_content_type_html);
202
  } else if(strncmp(http_css, ptr, 4) == 0) {
203
    PSOCK_SEND_STR(&s->sout, http_content_type_css);
204
  } else if(strncmp(http_png, ptr, 4) == 0) {
205
    PSOCK_SEND_STR(&s->sout, http_content_type_png);
206
  } else if(strncmp(http_gif, ptr, 4) == 0) {
207
    PSOCK_SEND_STR(&s->sout, http_content_type_gif);
208
  } else if(strncmp(http_jpg, ptr, 4) == 0) {
209
    PSOCK_SEND_STR(&s->sout, http_content_type_jpg);
210
  } else {
211
    PSOCK_SEND_STR(&s->sout, http_content_type_plain);
212
  }
213
  PSOCK_END(&s->sout);
214
}
215
/*---------------------------------------------------------------------------*/
216
static
217
PT_THREAD(handle_output(struct httpd_state *s))
218
{
219
  char *ptr;
220
 
221
  PT_BEGIN(&s->outputpt);
222
 
223
  if(!httpd_fs_open(s->filename, &s->file)) {
224
    httpd_fs_open(http_404_html, &s->file);
225
    strcpy(s->filename, http_404_html);
226
    PT_WAIT_THREAD(&s->outputpt,
227
                   send_headers(s,
228
                   http_header_404));
229
    PT_WAIT_THREAD(&s->outputpt,
230
                   send_file(s));
231
  } else {
232
    PT_WAIT_THREAD(&s->outputpt,
233
                   send_headers(s,
234
                   http_header_200));
235
    ptr = strchr(s->filename, ISO_period);
236
    if(ptr != NULL && strncmp(ptr, http_shtml, 6) == 0) {
237
      PT_INIT(&s->scriptpt);
238
      PT_WAIT_THREAD(&s->outputpt, handle_script(s));
239
    } else {
240
      PT_WAIT_THREAD(&s->outputpt,
241
                     send_file(s));
242
    }
243
  }
244
  PSOCK_CLOSE(&s->sout);
245
  PT_END(&s->outputpt);
246
}
247
/*---------------------------------------------------------------------------*/
248
static
249
PT_THREAD(handle_input(struct httpd_state *s))
250
{
251
  PSOCK_BEGIN(&s->sin);
252
 
253
  PSOCK_READTO(&s->sin, ISO_space);
254
 
255
 
256
  if(strncmp(s->inputbuf, http_get, 4) != 0) {
257
    PSOCK_CLOSE_EXIT(&s->sin);
258
  }
259
  PSOCK_READTO(&s->sin, ISO_space);
260
 
261
  if(s->inputbuf[0] != ISO_slash) {
262
    PSOCK_CLOSE_EXIT(&s->sin);
263
  }
264
 
265
  if(s->inputbuf[1] == ISO_space) {
266
    strncpy(s->filename, http_index_html, sizeof(s->filename));
267
  } else {
268
    s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0;
269
    strncpy(s->filename, &s->inputbuf[0], sizeof(s->filename));
270
  }
271
 
272
  /*  httpd_log_file(uip_conn->ripaddr, s->filename);*/
273
 
274
  s->state = STATE_OUTPUT;
275
 
276
  while(1) {
277
    PSOCK_READTO(&s->sin, ISO_nl);
278
 
279
    if(strncmp(s->inputbuf, http_referer, 8) == 0) {
280
      s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0;
281
      /*      httpd_log(&s->inputbuf[9]);*/
282
    }
283
  }
284
 
285
  PSOCK_END(&s->sin);
286
}
287
/*---------------------------------------------------------------------------*/
288
static void
289
handle_connection(struct httpd_state *s)
290
{
291
  handle_input(s);
292
  if(s->state == STATE_OUTPUT) {
293
    handle_output(s);
294
  }
295
}
296
/*---------------------------------------------------------------------------*/
297
void
298
httpd_appcall(void)
299
{
300
  struct httpd_state *s = (struct httpd_state *)&(uip_conn->appstate);
301
 
302
  if(uip_closed() || uip_aborted() || uip_timedout()) {
303
  } else if(uip_connected()) {
304
    PSOCK_INIT(&s->sin, s->inputbuf, sizeof(s->inputbuf) - 1);
305
    PSOCK_INIT(&s->sout, s->inputbuf, sizeof(s->inputbuf) - 1);
306
    PT_INIT(&s->outputpt);
307
    s->state = STATE_WAITING;
308
    /*    timer_set(&s->timer, CLOCK_SECOND * 100);*/
309
    s->timer = 0;
310
    handle_connection(s);
311
  } else if(s != NULL) {
312
    if(uip_poll()) {
313
      ++s->timer;
314
      if(s->timer >= 20) {
315
        uip_abort();
316
      }
317
    } else {
318
      s->timer = 0;
319
    }
320
    handle_connection(s);
321
  } else {
322
    uip_abort();
323
  }
324
}
325
/*---------------------------------------------------------------------------*/
326
/**
327
 * \brief      Initialize the web server
328
 *
329
 *             This function initializes the web server and should be
330
 *             called at system boot-up.
331
 */
332
void
333
httpd_init(void)
334
{
335
  uip_listen(HTONS(80));
336
}
337
/*---------------------------------------------------------------------------*/
338
/** @} */

powered by: WebSVN 2.1.0

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