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