7 * \defgroup httpd Web server
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.
19 * Adam Dunkels <adam@sics.se>
23 * Copyright (c) 2004, Adam Dunkels.
24 * All rights reserved.
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. Neither the name of the Institute nor the names of its contributors
35 * may be used to endorse or promote products derived from this software
36 * without specific prior written permission.
38 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * This file is part of the uIP TCP/IP stack.
52 * Author: Adam Dunkels <adam@sics.se>
54 * $Id: httpd.c,v 1.2 2006/06/11 21:46:38 adam Exp $
57 #include "apps/httpd/httpd.h"
58 #include "apps/httpd/httpd-fs.h"
59 #include "apps/httpd/httpd-cgi.h"
60 #include "apps/httpd/http-strings.h"
64 #define STATE_WAITING 0
65 #define STATE_OUTPUT 1
68 #define ISO_space 0x20
70 #define ISO_percent 0x25
71 #define ISO_period 0x2e
72 #define ISO_slash 0x2f
73 #define ISO_colon 0x3a
75 /*---------------------------------------------------------------------------*/
76 static unsigned short generate_part_of_file( void *state
)
78 struct httpd_state
*s
= ( struct httpd_state
* ) state
;
80 if( s
->file
.len
> uip_mss() )
89 memcpy( uip_appdata
, s
->file
.data
, s
->len
);
94 /*---------------------------------------------------------------------------*/
95 static PT_THREAD( send_file ( struct httpd_state
*s
) )
97 PSOCK_BEGIN( &s
->sout
);
101 PSOCK_GENERATOR_SEND( &s
->sout
, generate_part_of_file
, s
);
102 s
->file
.len
-= s
->len
;
103 s
->file
.data
+= s
->len
;
104 } while( s
->file
.len
> 0 );
106 PSOCK_END( &s
->sout
);
109 /*---------------------------------------------------------------------------*/
110 static PT_THREAD( send_part_of_file ( struct httpd_state
*s
) )
112 PSOCK_BEGIN( &s
->sout
);
114 PSOCK_SEND( &s
->sout
, s
->file
.data
, s
->len
);
116 PSOCK_END( &s
->sout
);
119 /*---------------------------------------------------------------------------*/
120 static void next_scriptstate( struct httpd_state
*s
)
123 p
= strchr( s
->scriptptr
, ISO_nl
) + 1;
124 s
->scriptlen
-= ( unsigned short ) ( p
- s
->scriptptr
);
128 /*---------------------------------------------------------------------------*/
129 static PT_THREAD( handle_script ( struct httpd_state
*s
) )
133 PT_BEGIN( &s
->scriptpt
);
135 while( s
->file
.len
> 0 )
137 /* Check if we should start executing a script. */
138 if( *s
->file
.data
== ISO_percent
&& *(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
)
144 httpd_fs_open( s
->scriptptr
+ 1, &s
->file
);
145 PT_WAIT_THREAD( &s
->scriptpt
, send_file(s
) );
149 PT_WAIT_THREAD( &s
->scriptpt
, httpd_cgi(s
->scriptptr
) (s
, s
->scriptptr
) );
152 next_scriptstate( s
);
154 /* The script is over, so we reset the pointers and continue
155 sending the rest of the file. */
156 s
->file
.data
= s
->scriptptr
;
157 s
->file
.len
= s
->scriptlen
;
161 /* See if we find the start of script marker in the block of HTML
163 if( s
->file
.len
> uip_mss() )
169 s
->len
= s
->file
.len
;
172 if( *s
->file
.data
== ISO_percent
)
174 ptr
= strchr( s
->file
.data
+ 1, ISO_percent
);
178 ptr
= strchr( s
->file
.data
, ISO_percent
);
181 if( ptr
!= NULL
&& ptr
!= s
->file
.data
)
183 s
->len
= ( int ) ( ptr
- s
->file
.data
);
184 if( s
->len
>= uip_mss() )
190 PT_WAIT_THREAD( &s
->scriptpt
, send_part_of_file(s
) );
191 s
->file
.data
+= s
->len
;
192 s
->file
.len
-= s
->len
;
196 PT_END( &s
->scriptpt
);
199 /*---------------------------------------------------------------------------*/
200 static PT_THREAD( send_headers ( struct httpd_state
*s
, const char *statushdr
) )
204 PSOCK_BEGIN( &s
->sout
);
206 PSOCK_SEND_STR( &s
->sout
, statushdr
);
208 ptr
= strrchr( s
->filename
, ISO_period
);
211 PSOCK_SEND_STR( &s
->sout
, http_content_type_binary
);
213 else if( strncmp(http_html
, ptr
, 5) == 0 || strncmp(http_shtml
, ptr
, 6) == 0 )
215 PSOCK_SEND_STR( &s
->sout
, http_content_type_html
);
217 else if( strncmp(http_css
, ptr
, 4) == 0 )
219 PSOCK_SEND_STR( &s
->sout
, http_content_type_css
);
221 else if( strncmp(http_png
, ptr
, 4) == 0 )
223 PSOCK_SEND_STR( &s
->sout
, http_content_type_png
);
225 else if( strncmp(http_gif
, ptr
, 4) == 0 )
227 PSOCK_SEND_STR( &s
->sout
, http_content_type_gif
);
229 else if( strncmp(http_jpg
, ptr
, 4) == 0 )
231 PSOCK_SEND_STR( &s
->sout
, http_content_type_jpg
);
235 PSOCK_SEND_STR( &s
->sout
, http_content_type_plain
);
238 PSOCK_END( &s
->sout
);
241 /*---------------------------------------------------------------------------*/
242 static PT_THREAD( handle_output ( struct httpd_state
*s
) )
246 PT_BEGIN( &s
->outputpt
);
248 if( !httpd_fs_open(s
->filename
, &s
->file
) )
250 httpd_fs_open( http_404_html
, &s
->file
);
251 strcpy( s
->filename
, http_404_html
);
252 PT_WAIT_THREAD( &s
->outputpt
, send_headers(s
, http_header_404
) );
253 PT_WAIT_THREAD( &s
->outputpt
, send_file(s
) );
257 PT_WAIT_THREAD( &s
->outputpt
, send_headers(s
, http_header_200
) );
258 ptr
= strchr( s
->filename
, ISO_period
);
259 if( ptr
!= NULL
&& strncmp(ptr
, http_shtml
, 6) == 0 )
261 PT_INIT( &s
->scriptpt
);
262 PT_WAIT_THREAD( &s
->outputpt
, handle_script(s
) );
266 PT_WAIT_THREAD( &s
->outputpt
, send_file(s
) );
270 PSOCK_CLOSE( &s
->sout
);
271 PT_END( &s
->outputpt
);
274 /*---------------------------------------------------------------------------*/
275 static PT_THREAD( handle_input ( struct httpd_state
*s
) )
277 PSOCK_BEGIN( &s
->sin
);
279 PSOCK_READTO( &s
->sin
, ISO_space
);
281 if( strncmp(s
->inputbuf
, http_get
, 4) != 0 )
283 PSOCK_CLOSE_EXIT( &s
->sin
);
286 PSOCK_READTO( &s
->sin
, ISO_space
);
288 if( s
->inputbuf
[0] != ISO_slash
)
290 PSOCK_CLOSE_EXIT( &s
->sin
);
293 if( s
->inputbuf
[1] == ISO_space
)
295 strncpy( s
->filename
, http_index_html
, sizeof(s
->filename
) );
299 s
->inputbuf
[PSOCK_DATALEN( &s
->sin
) - 1] = 0;
301 /* Process any form input being sent to the server. */
302 #if UIP_CONF_PROCESS_HTTPD_FORMS == 1
304 extern void vApplicationProcessFormInput( char *pcInputString
);
305 vApplicationProcessFormInput( s
->inputbuf
);
309 strncpy( s
->filename
, &s
->inputbuf
[0], sizeof(s
->filename
) );
312 /* httpd_log_file(uip_conn->ripaddr, s->filename);*/
313 s
->state
= STATE_OUTPUT
;
317 PSOCK_READTO( &s
->sin
, ISO_nl
);
319 if( strncmp(s
->inputbuf
, http_referer
, 8) == 0 )
321 s
->inputbuf
[PSOCK_DATALEN( &s
->sin
) - 2] = 0;
323 /* httpd_log(&s->inputbuf[9]);*/
327 PSOCK_END( &s
->sin
);
330 /*---------------------------------------------------------------------------*/
331 static void handle_connection( struct httpd_state
*s
)
334 if( s
->state
== STATE_OUTPUT
)
340 /*---------------------------------------------------------------------------*/
341 void httpd_appcall( void )
343 struct httpd_state
*s
= ( struct httpd_state
* ) &( uip_conn
->appstate
);
345 if( uip_closed() || uip_aborted() || uip_timedout() )
348 else if( uip_connected() )
350 PSOCK_INIT( &s
->sin
, s
->inputbuf
, sizeof(s
->inputbuf
) - 1 );
351 PSOCK_INIT( &s
->sout
, s
->inputbuf
, sizeof(s
->inputbuf
) - 1 );
352 PT_INIT( &s
->outputpt
);
353 s
->state
= STATE_WAITING
;
355 /* timer_set(&s->timer, CLOCK_SECOND * 100);*/
357 handle_connection( s
);
374 handle_connection( s
);
382 /*---------------------------------------------------------------------------*/
385 * \brief Initialize the web server
387 * This function initializes the web server and should be
388 * called at system boot-up.
390 void httpd_init( void )
392 uip_listen( HTONS(80) );
395 /*---------------------------------------------------------------------------*/