Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2004, Adam Dunkels. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 * 00031 * Author: Adam Dunkels <adam@sics.se> 00032 * 00033 * $Id: httpd-cfs.c,v 1.2 2010/10/19 18:29:05 adamdunkels Exp $ 00034 */ 00035 00036 #include <string.h> 00037 00038 #include "contiki-net.h" 00039 00040 #include "webserver.h" 00041 #include "cfs/cfs.h" 00042 #include "lib/petsciiconv.h" 00043 #include "http-strings.h" 00044 00045 #include "httpd-cfs.h" 00046 00047 #ifndef WEBSERVER_CONF_CFS_CONNS 00048 #define CONNS 4 00049 #else /* WEBSERVER_CONF_CFS_CONNS */ 00050 #define CONNS WEBSERVER_CONF_CFS_CONNS 00051 #endif /* WEBSERVER_CONF_CFS_CONNS */ 00052 00053 #define STATE_WAITING 0 00054 #define STATE_OUTPUT 1 00055 00056 #define SEND_STRING(s, str) PSOCK_SEND(s, (uint8_t *)str, strlen(str)) 00057 MEMB(conns, struct httpd_state, CONNS); 00058 00059 #define ISO_nl 0x0a 00060 #define ISO_space 0x20 00061 #define ISO_period 0x2e 00062 #define ISO_slash 0x2f 00063 00064 /*---------------------------------------------------------------------------*/ 00065 static 00066 PT_THREAD(send_file(struct httpd_state *s)) 00067 { 00068 PSOCK_BEGIN(&s->sout); 00069 00070 do { 00071 /* Read data from file system into buffer */ 00072 s->len = cfs_read(s->fd, s->outputbuf, sizeof(s->outputbuf)); 00073 00074 /* If there is data in the buffer, send it */ 00075 if(s->len > 0) { 00076 PSOCK_SEND(&s->sout, (uint8_t *)s->outputbuf, s->len); 00077 } else { 00078 break; 00079 } 00080 } while(s->len > 0); 00081 00082 PSOCK_END(&s->sout); 00083 } 00084 /*---------------------------------------------------------------------------*/ 00085 static 00086 PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr)) 00087 { 00088 char *ptr; 00089 00090 PSOCK_BEGIN(&s->sout); 00091 00092 SEND_STRING(&s->sout, statushdr); 00093 00094 ptr = strrchr(s->filename, ISO_period); 00095 if(ptr == NULL) { 00096 SEND_STRING(&s->sout, http_content_type_plain); 00097 } else if(strncmp(http_html, ptr, 5) == 0) { 00098 SEND_STRING(&s->sout, http_content_type_html); 00099 } else if(strncmp(http_css, ptr, 4) == 0) { 00100 SEND_STRING(&s->sout, http_content_type_css); 00101 } else if(strncmp(http_png, ptr, 4) == 0) { 00102 SEND_STRING(&s->sout, http_content_type_png); 00103 } else if(strncmp(http_jpg, ptr, 4) == 0) { 00104 SEND_STRING(&s->sout, http_content_type_jpg); 00105 } else { 00106 SEND_STRING(&s->sout, http_content_type_binary); 00107 } 00108 PSOCK_END(&s->sout); 00109 } 00110 /*---------------------------------------------------------------------------*/ 00111 static 00112 PT_THREAD(handle_output(struct httpd_state *s)) 00113 { 00114 PT_BEGIN(&s->outputpt); 00115 00116 petsciiconv_topetscii(s->filename, sizeof(s->filename)); 00117 s->fd = cfs_open(s->filename, CFS_READ); 00118 petsciiconv_toascii(s->filename, sizeof(s->filename)); 00119 if(s->fd < 0) { 00120 s->fd = cfs_open("notfound.html", CFS_READ); 00121 if(s->fd < 0) { 00122 uip_abort(); 00123 memb_free(&conns, s); 00124 webserver_log_file(&uip_conn->ripaddr, "reset (no notfound.html)"); 00125 PT_EXIT(&s->outputpt); 00126 } 00127 PT_WAIT_THREAD(&s->outputpt, 00128 send_headers(s, http_header_404)); 00129 } else { 00130 PT_WAIT_THREAD(&s->outputpt, 00131 send_headers(s, http_header_200)); 00132 } 00133 PT_WAIT_THREAD(&s->outputpt, send_file(s)); 00134 cfs_close(s->fd); 00135 s->fd = -1; 00136 PSOCK_CLOSE(&s->sout); 00137 PT_END(&s->outputpt); 00138 } 00139 /*---------------------------------------------------------------------------*/ 00140 static 00141 PT_THREAD(handle_input(struct httpd_state *s)) 00142 { 00143 PSOCK_BEGIN(&s->sin); 00144 00145 PSOCK_READTO(&s->sin, ISO_space); 00146 00147 if(strncmp(s->inputbuf, http_get, 4) != 0) { 00148 PSOCK_CLOSE_EXIT(&s->sin); 00149 } 00150 PSOCK_READTO(&s->sin, ISO_space); 00151 00152 if(s->inputbuf[0] != ISO_slash) { 00153 PSOCK_CLOSE_EXIT(&s->sin); 00154 } 00155 00156 if(s->inputbuf[1] == ISO_space) { 00157 strncpy(s->filename, &http_index_html[1], sizeof(s->filename)); 00158 } else { 00159 s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0; 00160 strncpy(s->filename, &s->inputbuf[1], sizeof(s->filename)); 00161 } 00162 00163 petsciiconv_topetscii(s->filename, sizeof(s->filename)); 00164 webserver_log_file(&uip_conn->ripaddr, s->filename); 00165 petsciiconv_toascii(s->filename, sizeof(s->filename)); 00166 s->state = STATE_OUTPUT; 00167 00168 while(1) { 00169 PSOCK_READTO(&s->sin, ISO_nl); 00170 00171 if(strncmp(s->inputbuf, http_referer, 8) == 0) { 00172 s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0; 00173 petsciiconv_topetscii(s->inputbuf, PSOCK_DATALEN(&s->sin) - 2); 00174 webserver_log(s->inputbuf); 00175 } 00176 } 00177 00178 PSOCK_END(&s->sin); 00179 } 00180 /*---------------------------------------------------------------------------*/ 00181 static void 00182 handle_connection(struct httpd_state *s) 00183 { 00184 handle_input(s); 00185 if(s->state == STATE_OUTPUT) { 00186 handle_output(s); 00187 } 00188 } 00189 /*---------------------------------------------------------------------------*/ 00190 void 00191 httpd_appcall(void *state) 00192 { 00193 struct httpd_state *s = (struct httpd_state *)state; 00194 00195 if(uip_closed() || uip_aborted() || uip_timedout()) { 00196 if(s != NULL) { 00197 if(s->fd >= 0) { 00198 cfs_close(s->fd); 00199 s->fd = -1; 00200 } 00201 memb_free(&conns, s); 00202 } 00203 } else if(uip_connected()) { 00204 s = (struct httpd_state *)memb_alloc(&conns); 00205 if(s == NULL) { 00206 uip_abort(); 00207 webserver_log_file(&uip_conn->ripaddr, "reset (no memory block)"); 00208 return; 00209 } 00210 tcp_markconn(uip_conn, s); 00211 PSOCK_INIT(&s->sin, (uint8_t *)s->inputbuf, sizeof(s->inputbuf) - 1); 00212 PSOCK_INIT(&s->sout, (uint8_t *)s->inputbuf, sizeof(s->inputbuf) - 1); 00213 PT_INIT(&s->outputpt); 00214 s->fd = -1; 00215 s->state = STATE_WAITING; 00216 timer_set(&s->timer, CLOCK_SECOND * 10); 00217 handle_connection(s); 00218 } else if(s != NULL) { 00219 if(uip_poll()) { 00220 if(timer_expired(&s->timer)) { 00221 uip_abort(); 00222 if(s->fd >= 0) { 00223 cfs_close(s->fd); 00224 s->fd = -1; 00225 } 00226 memb_free(&conns, s); 00227 webserver_log_file(&uip_conn->ripaddr, "reset (timeout)"); 00228 } 00229 } else { 00230 timer_reset(&s->timer); 00231 } 00232 handle_connection(s); 00233 } else { 00234 uip_abort(); 00235 } 00236 } 00237 /*---------------------------------------------------------------------------*/ 00238 void 00239 httpd_init(void) 00240 { 00241 tcp_listen(UIP_HTONS(80)); 00242 memb_init(&conns); 00243 } 00244 /*---------------------------------------------------------------------------*/