Reduced code size by reducing the SEND_STRING call sites.
[contiki-2.x.git] / apps / webserver / httpd-cfs.c
blob1695f0a2cfe80f74b2ca02abc880e500b34985cd
1 /*
2 * Copyright (c) 2004, Adam Dunkels.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * This file is part of the Contiki operating system.
31 * Author: Adam Dunkels <adam@sics.se>
33 * $Id: httpd-cfs.c,v 1.16 2010/04/06 11:49:47 oliverschmidt Exp $
36 #include <stdio.h>
37 #ifndef HAVE_SNPRINTF
38 int snprintf(char *str, size_t size, const char *format, ...);
39 #endif /* HAVE_SNPRINTF */
40 #include <string.h>
42 #include "contiki-net.h"
44 #include "webserver.h"
45 #include "cfs/cfs.h"
46 #include "lib/petsciiconv.h"
47 #include "http-strings.h"
49 #include "httpd-cfs.h"
51 #ifndef WEBSERVER_CONF_CFS_CONNS
52 #define CONNS 4
53 #else /* WEBSERVER_CONF_CFS_CONNS */
54 #define CONNS WEBSERVER_CONF_CFS_CONNS
55 #endif /* WEBSERVER_CONF_CFS_CONNS */
57 #define STATE_WAITING 0
58 #define STATE_OUTPUT 1
60 #define SEND_STRING(s, str) PSOCK_SEND(s, (uint8_t *)str, strlen(str))
61 MEMB(conns, struct httpd_state, CONNS);
63 #define ISO_nl 0x0a
64 #define ISO_space 0x20
65 #define ISO_period 0x2e
66 #define ISO_slash 0x2f
68 /*---------------------------------------------------------------------------*/
69 static
70 PT_THREAD(send_file(struct httpd_state *s))
72 PSOCK_BEGIN(&s->sout);
74 do {
75 /* Read data from file system into buffer */
76 s->len = cfs_read(s->fd, s->outputbuf, sizeof(s->outputbuf));
78 /* If there is data in the buffer, send it */
79 if(s->len > 0) {
80 PSOCK_SEND(&s->sout, (uint8_t *)s->outputbuf, s->len);
81 } else {
82 break;
84 } while(s->len > 0);
86 PSOCK_END(&s->sout);
88 /*---------------------------------------------------------------------------*/
89 static
90 PT_THREAD(send_string(struct httpd_state *s, const char *str))
92 PSOCK_BEGIN(&s->sout);
94 SEND_STRING(&s->sout, str);
96 PSOCK_END(&s->sout);
98 /*---------------------------------------------------------------------------*/
99 static
100 PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr))
102 const char *ptr;
104 PSOCK_BEGIN(&s->sout);
106 SEND_STRING(&s->sout, statushdr);
108 ptr = strrchr(s->filename, ISO_period);
109 if(ptr == NULL) {
110 ptr = http_content_type_plain;
111 } else if(strncmp(http_html, ptr, 5) == 0) {
112 ptr = http_content_type_html;
113 } else if(strncmp(http_css, ptr, 4) == 0) {
114 ptr = http_content_type_css;
115 } else if(strncmp(http_png, ptr, 4) == 0) {
116 ptr = http_content_type_png;
117 } else if(strncmp(http_jpg, ptr, 4) == 0) {
118 ptr = http_content_type_jpg;
119 } else {
120 ptr = http_content_type_binary;
122 SEND_STRING(&s->sout, ptr);
123 PSOCK_END(&s->sout);
125 /*---------------------------------------------------------------------------*/
126 static
127 PT_THREAD(handle_output(struct httpd_state *s))
129 PT_BEGIN(&s->outputpt);
131 petsciiconv_topetscii(s->filename, sizeof(s->filename));
132 s->fd = cfs_open(s->filename, CFS_READ);
133 petsciiconv_toascii(s->filename, sizeof(s->filename));
134 if(s->fd < 0) {
135 strcpy(s->filename, "notfound.html");
136 s->fd = cfs_open(s->filename, CFS_READ);
137 petsciiconv_toascii(s->filename, sizeof(s->filename));
138 if(s->fd < 0) {
139 PT_WAIT_THREAD(&s->outputpt,
140 send_headers(s, http_header_404));
141 PT_WAIT_THREAD(&s->outputpt,
142 send_string(s, "not found"));
143 uip_close();
144 webserver_log_file(&uip_conn->ripaddr, "404 (no notfound.html)");
145 PT_EXIT(&s->outputpt);
147 PT_WAIT_THREAD(&s->outputpt,
148 send_headers(s, http_header_404));
149 webserver_log_file(&uip_conn->ripaddr, "404 - notfound.html");
150 } else {
151 PT_WAIT_THREAD(&s->outputpt,
152 send_headers(s, http_header_200));
154 PT_WAIT_THREAD(&s->outputpt, send_file(s));
155 cfs_close(s->fd);
156 s->fd = -1;
157 PSOCK_CLOSE(&s->sout);
158 PT_END(&s->outputpt);
160 /*---------------------------------------------------------------------------*/
161 static
162 PT_THREAD(handle_input(struct httpd_state *s))
164 PSOCK_BEGIN(&s->sin);
166 PSOCK_READTO(&s->sin, ISO_space);
168 if(strncmp(s->inputbuf, http_get, 4) != 0) {
169 PSOCK_CLOSE_EXIT(&s->sin);
171 PSOCK_READTO(&s->sin, ISO_space);
173 if(s->inputbuf[0] != ISO_slash) {
174 PSOCK_CLOSE_EXIT(&s->sin);
177 if(s->inputbuf[1] == ISO_space) {
178 strncpy(s->filename, &http_index_html[1], sizeof(s->filename));
179 } else {
180 s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0;
181 strncpy(s->filename, &s->inputbuf[1], sizeof(s->filename));
184 petsciiconv_topetscii(s->filename, sizeof(s->filename));
185 webserver_log_file(&uip_conn->ripaddr, s->filename);
186 petsciiconv_toascii(s->filename, sizeof(s->filename));
187 s->state = STATE_OUTPUT;
189 while(1) {
190 PSOCK_READTO(&s->sin, ISO_nl);
192 if(strncmp(s->inputbuf, http_referer, 8) == 0) {
193 s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0;
194 petsciiconv_topetscii(s->inputbuf, PSOCK_DATALEN(&s->sin) - 2);
195 webserver_log(s->inputbuf);
199 PSOCK_END(&s->sin);
201 /*---------------------------------------------------------------------------*/
202 static void
203 handle_connection(struct httpd_state *s)
205 handle_input(s);
206 if(s->state == STATE_OUTPUT) {
207 handle_output(s);
210 /*---------------------------------------------------------------------------*/
211 void
212 httpd_appcall(void *state)
214 struct httpd_state *s = (struct httpd_state *)state;
216 if(uip_closed() || uip_aborted() || uip_timedout()) {
217 if(s != NULL) {
218 if(s->fd >= 0) {
219 cfs_close(s->fd);
220 s->fd = -1;
222 memb_free(&conns, s);
224 } else if(uip_connected()) {
225 s = (struct httpd_state *)memb_alloc(&conns);
226 if(s == NULL) {
227 uip_abort();
228 webserver_log_file(&uip_conn->ripaddr, "reset (no memory block)");
229 return;
231 tcp_markconn(uip_conn, s);
232 PSOCK_INIT(&s->sin, (uint8_t *)s->inputbuf, sizeof(s->inputbuf) - 1);
233 PSOCK_INIT(&s->sout, (uint8_t *)s->inputbuf, sizeof(s->inputbuf) - 1);
234 PT_INIT(&s->outputpt);
235 s->fd = -1;
236 s->state = STATE_WAITING;
237 timer_set(&s->timer, CLOCK_SECOND * 10);
238 handle_connection(s);
239 } else if(s != NULL) {
240 if(uip_poll()) {
241 if(timer_expired(&s->timer)) {
242 uip_abort();
243 if(s->fd >= 0) {
244 cfs_close(s->fd);
245 s->fd = -1;
247 memb_free(&conns, s);
248 webserver_log_file(&uip_conn->ripaddr, "reset (timeout)");
250 } else {
251 timer_restart(&s->timer);
253 handle_connection(s);
254 } else {
255 uip_abort();
258 /*---------------------------------------------------------------------------*/
259 void
260 httpd_init(void)
262 tcp_listen(HTONS(80));
263 memb_init(&conns);
265 /*---------------------------------------------------------------------------*/