Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
httpd.cpp
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