ban4jp -
/
uIP-1-0_webserver
uIP 1.0 based webserver for LPC1114 + ENC28J60
Embed:
(wiki syntax)
Show/hide line numbers
httpd.cpp
Go to the documentation of this file.
00001 /** 00002 * \addtogroup apps 00003 * @{ 00004 */ 00005 00006 /** 00007 * \defgroup httpd Web server 00008 * @{ 00009 * The uIP web server is a very simplistic implementation of an HTTP 00010 * server. It can serve web pages and files from a read-only ROM 00011 * filesystem, and provides a very small scripting language. 00012 00013 */ 00014 00015 /** 00016 * \file 00017 * Web server 00018 * \author 00019 * Adam Dunkels <adam@sics.se> 00020 */ 00021 00022 00023 /* 00024 * Copyright (c) 2004, Adam Dunkels. 00025 * All rights reserved. 00026 * 00027 * Redistribution and use in source and binary forms, with or without 00028 * modification, are permitted provided that the following conditions 00029 * are met: 00030 * 1. Redistributions of source code must retain the above copyright 00031 * notice, this list of conditions and the following disclaimer. 00032 * 2. Redistributions in binary form must reproduce the above copyright 00033 * notice, this list of conditions and the following disclaimer in the 00034 * documentation and/or other materials provided with the distribution. 00035 * 3. Neither the name of the Institute nor the names of its contributors 00036 * may be used to endorse or promote products derived from this software 00037 * without specific prior written permission. 00038 * 00039 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00040 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00041 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00042 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00043 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00044 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00045 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00046 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00047 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00048 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00049 * SUCH DAMAGE. 00050 * 00051 * This file is part of the uIP TCP/IP stack. 00052 * 00053 * Author: Adam Dunkels <adam@sics.se> 00054 * 00055 * $Id: httpd.c,v 1.2 2006/06/11 21:46:38 adam Exp $ 00056 */ 00057 00058 extern "C" { 00059 #include "uip.h" 00060 #include "httpd.h" 00061 } 00062 //#include "httpd-fs.h" 00063 #include "httpd-cgi.h" 00064 #include "http-strings.h" 00065 00066 #include <string.h> 00067 00068 #define STATE_WAITING 0 00069 #define STATE_OUTPUT 1 00070 00071 #define ISO_nl 0x0a 00072 #define ISO_space 0x20 00073 #define ISO_bang 0x21 00074 #define ISO_percent 0x25 00075 #define ISO_period 0x2e 00076 #define ISO_slash 0x2f 00077 #define ISO_colon 0x3a 00078 00079 00080 /*---------------------------------------------------------------------------*/ 00081 static unsigned short 00082 generate_part_of_file(void *state) 00083 { 00084 struct httpd_state *s = (struct httpd_state *)state; 00085 00086 if(s->file.len > uip_mss()) { 00087 s->len = uip_mss(); 00088 } else { 00089 s->len = s->file.len; 00090 } 00091 memcpy(uip_appdata, s->file.data, s->len); 00092 00093 return s->len; 00094 } 00095 /*---------------------------------------------------------------------------*/ 00096 static 00097 PT_THREAD(send_file(struct httpd_state *s)) 00098 { 00099 PSOCK_BEGIN(&s->sout); 00100 00101 do { 00102 PSOCK_GENERATOR_SEND(&s->sout, generate_part_of_file, s); 00103 s->file.len -= s->len; 00104 s->file.data += s->len; 00105 } while(s->file.len > 0); 00106 00107 PSOCK_END(&s->sout); 00108 } 00109 /*---------------------------------------------------------------------------*/ 00110 static 00111 PT_THREAD(send_part_of_file(struct httpd_state *s)) 00112 { 00113 PSOCK_BEGIN(&s->sout); 00114 00115 PSOCK_SEND(&s->sout, s->file.data, s->len); 00116 00117 PSOCK_END(&s->sout); 00118 } 00119 /*---------------------------------------------------------------------------*/ 00120 static void 00121 next_scriptstate(struct httpd_state *s) 00122 { 00123 char *p; 00124 00125 if((p = strchr(s->scriptptr, ISO_nl)) != NULL) { 00126 p += 1; 00127 s->scriptlen -= (unsigned short)(p - s->scriptptr); 00128 s->scriptptr = p; 00129 } else { 00130 s->scriptlen = 0; 00131 } 00132 } 00133 /*---------------------------------------------------------------------------*/ 00134 static 00135 PT_THREAD(handle_script(struct httpd_state *s)) 00136 { 00137 char *ptr; 00138 00139 PT_BEGIN(&s->scriptpt); 00140 00141 00142 while(s->file.len > 0) { 00143 00144 /* Check if we should start executing a script. */ 00145 if(*s->file.data == ISO_percent && 00146 *(s->file.data + 1) == ISO_bang) { 00147 s->scriptptr = s->file.data + 3; 00148 s->scriptlen = s->file.len - 3; 00149 if(*(s->scriptptr - 1) == ISO_colon) { 00150 httpd_fs_open(s->scriptptr + 1, &s->file); 00151 PT_WAIT_THREAD(&s->scriptpt, send_file(s)); 00152 } else { 00153 PT_WAIT_THREAD(&s->scriptpt, 00154 httpd_cgi(s->scriptptr)(s, s->scriptptr)); 00155 } 00156 next_scriptstate(s); 00157 00158 /* The script is over, so we reset the pointers and continue 00159 sending the rest of the file. */ 00160 s->file.data = s->scriptptr; 00161 s->file.len = s->scriptlen; 00162 } else { 00163 /* See if we find the start of script marker in the block of HTML 00164 to be sent. */ 00165 00166 if(s->file.len > uip_mss()) { 00167 s->len = uip_mss(); 00168 } else { 00169 s->len = s->file.len; 00170 } 00171 00172 if(*s->file.data == ISO_percent) { 00173 ptr = strchr(s->file.data + 1, ISO_percent); 00174 } else { 00175 ptr = strchr(s->file.data, ISO_percent); 00176 } 00177 if(ptr != NULL && 00178 ptr != s->file.data) { 00179 s->len = (int)(ptr - s->file.data); 00180 if(s->len >= uip_mss()) { 00181 s->len = uip_mss(); 00182 } 00183 } 00184 PT_WAIT_THREAD(&s->scriptpt, send_part_of_file(s)); 00185 s->file.data += s->len; 00186 s->file.len -= s->len; 00187 00188 } 00189 } 00190 00191 PT_END(&s->scriptpt); 00192 } 00193 /*---------------------------------------------------------------------------*/ 00194 static 00195 PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr)) 00196 { 00197 char *ptr; 00198 00199 PSOCK_BEGIN(&s->sout); 00200 00201 PSOCK_SEND_STR(&s->sout, statushdr); 00202 00203 ptr = strrchr(s->filename, ISO_period); 00204 if(ptr == NULL) { 00205 PSOCK_SEND_STR(&s->sout, http_content_type_binary); 00206 } else if(strncmp(http_html, ptr, sizeof(http_html)-1) == 0 || 00207 strncmp(http_shtml, ptr, sizeof(http_shtml)-1) == 0) { 00208 PSOCK_SEND_STR(&s->sout, http_content_type_html); 00209 } else if(strncmp(http_json, ptr, sizeof(http_json)-1) == 0) { 00210 PSOCK_SEND_STR(&s->sout, http_content_type_json); 00211 } else if(strncmp(http_xml, ptr, sizeof(http_xml)-1) == 0) { 00212 PSOCK_SEND_STR(&s->sout, http_content_type_xml); 00213 } else if(strncmp(http_css, ptr, sizeof(http_css)-1) == 0) { 00214 PSOCK_SEND_STR(&s->sout, http_content_type_css); 00215 } else if(strncmp(http_png, ptr, sizeof(http_png)-1) == 0) { 00216 PSOCK_SEND_STR(&s->sout, http_content_type_png); 00217 } else if(strncmp(http_gif, ptr, sizeof(http_gif)-1) == 0) { 00218 PSOCK_SEND_STR(&s->sout, http_content_type_gif); 00219 } else if(strncmp(http_jpg, ptr, sizeof(http_jpg)-1) == 0) { 00220 PSOCK_SEND_STR(&s->sout, http_content_type_jpg); 00221 } else { 00222 PSOCK_SEND_STR(&s->sout, http_content_type_plain); 00223 } 00224 PSOCK_END(&s->sout); 00225 } 00226 /*---------------------------------------------------------------------------*/ 00227 static 00228 PT_THREAD(handle_output(struct httpd_state *s)) 00229 { 00230 char *ptr; 00231 00232 PT_BEGIN(&s->outputpt); 00233 00234 if(!httpd_fs_open(s->filename, &s->file)) { 00235 httpd_fs_open(http_404_html, &s->file); 00236 strcpy(s->filename, http_404_html); 00237 PT_WAIT_THREAD(&s->outputpt, 00238 send_headers(s, 00239 http_header_404)); 00240 PT_WAIT_THREAD(&s->outputpt, 00241 send_file(s)); 00242 } else { 00243 PT_WAIT_THREAD(&s->outputpt, 00244 send_headers(s, 00245 http_header_200)); 00246 ptr = strchr(s->filename, ISO_period); 00247 if(ptr != NULL && (strncmp(ptr, http_shtml, sizeof(http_shtml)-1) == 0 || 00248 strncmp(ptr, http_json, sizeof(http_json)-1) == 0 || 00249 strncmp(ptr, http_xml, sizeof(http_xml)-1) == 0)) { 00250 PT_INIT(&s->scriptpt); 00251 PT_WAIT_THREAD(&s->outputpt, handle_script(s)); 00252 } else { 00253 PT_WAIT_THREAD(&s->outputpt, 00254 send_file(s)); 00255 } 00256 } 00257 PSOCK_CLOSE(&s->sout); 00258 PT_END(&s->outputpt); 00259 } 00260 /*---------------------------------------------------------------------------*/ 00261 static 00262 PT_THREAD(handle_input(struct httpd_state *s)) 00263 { 00264 PSOCK_BEGIN(&s->sin); 00265 00266 PSOCK_READTO(&s->sin, ISO_space); 00267 00268 00269 if(strncmp(s->inputbuf, http_get, sizeof(http_get)-1) != 0) { 00270 PSOCK_CLOSE_EXIT(&s->sin); 00271 } 00272 PSOCK_READTO(&s->sin, ISO_space); 00273 00274 if(s->inputbuf[0] != ISO_slash) { 00275 PSOCK_CLOSE_EXIT(&s->sin); 00276 } 00277 00278 if(s->inputbuf[1] == ISO_space) { 00279 strncpy(s->filename, http_index_html, sizeof(s->filename)); 00280 } else { 00281 s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0; 00282 strncpy(s->filename, s->inputbuf, sizeof(s->filename)); 00283 } 00284 00285 /* httpd_log_file(uip_conn->ripaddr, s->filename);*/ 00286 00287 s->state = STATE_OUTPUT; 00288 00289 while(1) { 00290 PSOCK_READTO(&s->sin, ISO_nl); 00291 00292 if(strncmp(s->inputbuf, http_referer, sizeof(http_referer)-1) == 0) { 00293 s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0; 00294 /* httpd_log(&s->inputbuf[9]);*/ 00295 } 00296 } 00297 00298 PSOCK_END(&s->sin); 00299 } 00300 /*---------------------------------------------------------------------------*/ 00301 static void 00302 handle_connection(struct httpd_state *s) 00303 { 00304 handle_input(s); 00305 if(s->state == STATE_OUTPUT) { 00306 handle_output(s); 00307 } 00308 } 00309 /*---------------------------------------------------------------------------*/ 00310 extern "C" void 00311 httpd_appcall(void) 00312 { 00313 struct httpd_state *s = (struct httpd_state *)&(uip_conn->appstate); 00314 00315 if(uip_closed() || uip_aborted() || uip_timedout()) { 00316 } else if(uip_connected()) { 00317 PSOCK_INIT(&s->sin, s->inputbuf, sizeof(s->inputbuf) - 1); 00318 PSOCK_INIT(&s->sout, s->inputbuf, sizeof(s->inputbuf) - 1); 00319 PT_INIT(&s->outputpt); 00320 s->state = STATE_WAITING; 00321 /* timer_set(&s->timer, CLOCK_SECOND * 100);*/ 00322 s->timer = 0; 00323 handle_connection(s); 00324 } else if(s != NULL) { 00325 if(uip_poll()) { 00326 ++s->timer; 00327 if(s->timer >= 20) { 00328 uip_abort(); 00329 } 00330 } else { 00331 s->timer = 0; 00332 } 00333 handle_connection(s); 00334 } else { 00335 uip_abort(); 00336 } 00337 } 00338 /*---------------------------------------------------------------------------*/ 00339 /** 00340 * \brief Initialize the web server 00341 * 00342 * This function initializes the web server and should be 00343 * called at system boot-up. 00344 */ 00345 extern "C" void 00346 httpd_init(void) 00347 { 00348 uip_listen(UIP_HTONS(80)); 00349 } 00350 /*---------------------------------------------------------------------------*/ 00351 /** @} */
Generated on Tue Jul 12 2022 12:52:12 by 1.7.2