38 #include "contiki-net.h"
40 #include "webserver.h"
42 #include "httpd-cgi.h"
44 #include "raven-lcd.h"
48 #include "cfs-coffee-arch.h"
65 struct httpd_state *sg;
66 #define uip_mss(...) 512
67 #define uip_appdata TCPBUF
72 #if HTTPD_STRING_TYPE==PROGMEM_TYPE
73 #define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
81 #ifndef WEBSERVER_CONF_CGI_CONNS
84 #define CONNS WEBSERVER_CONF_CGI_CONNS
87 #define STATE_WAITING 0
88 #define STATE_OUTPUT 1
91 MEMB(conns,
struct httpd_state, CONNS);
94 #define MAX_SCRIPT_NAME_LENGTH 20
98 #define ISO_space 0x20
100 #define ISO_percent 0x25
101 #define ISO_period 0x2e
102 #define ISO_slash 0x2f
103 #define ISO_colon 0x3a
106 static unsigned short
107 generate(
void *state)
109 struct httpd_state *s = (
struct httpd_state *)state;
114 s->len = s->file.len;
125 PT_THREAD(send_file(
struct httpd_state *s))
131 s->file.len -= s->len;
132 s->file.data += s->len;
133 }
while(s->file.len > 0);
139 PT_THREAD(send_part_of_file(
struct httpd_state *s))
143 static int oldfilelen, oldlen;
144 static char * olddata;
147 oldfilelen = s->file.len;
149 olddata = s->file.data;
152 s->file.len = s->len;
156 s->file.len -= s->len;
157 s->file.data += s->len;
158 }
while(s->file.len > 0);
161 s->file.len = oldfilelen;
162 s->file.data = olddata;
168 next_scriptstate(
struct httpd_state *s)
172 if((p = (
char *)httpd_fs_strchr(s->scriptptr, ISO_nl)) !=
NULL) {
174 s->scriptlen -= (
unsigned short)(p - s->scriptptr);
188 get_scriptname(
char *dest,
char *fromfile)
194 dest[i]=httpd_fs_getchar(fromfile++);
195 if (dest[i]==ISO_colon) {
if (!skip)
break;}
196 else if (dest[i]==ISO_tab ) {
if (skip)
continue;
else break;}
197 else if (dest[i]==ISO_space) {
if (skip)
continue;
else break;}
198 else if (dest[i]==ISO_nl )
break;
199 else if (dest[i]==ISO_cr )
break;
200 else if (dest[i]==0 )
break;
203 }
while (i<(MAX_SCRIPT_NAME_LENGTH+1));
205 while ((dest[i]==ISO_space) || (dest[i]==ISO_tab)) dest[i]=httpd_fs_getchar(++fromfile);
212 PT_THREAD(handle_script(
struct httpd_state *s))
215 static char scriptname[MAX_SCRIPT_NAME_LENGTH+1],*pptr;
216 static uint16_t filelength;
220 filelength=s->file.len;
221 while(s->file.len > 0) {
223 if (s->file.len > filelength)
break;
226 if(httpd_fs_getchar(s->file.data) == ISO_percent &&
227 httpd_fs_getchar(s->file.data + 1) == ISO_bang) {
230 s->scriptptr=get_scriptname(scriptname,s->file.data+2);
231 s->scriptlen=s->file.len-(s->scriptptr-s->file.data);
232 PRINTF(
"httpd: Handle script named %s\n",scriptname);
233 if(scriptname[0] == ISO_colon) {
234 if (httpd_fs_open(&scriptname[1], &s->file)) {
238 PT_WAIT_THREAD(&s->scriptpt,httpd_cgi(scriptname)(s, s->scriptptr));
243 s->file.data = s->scriptptr;
244 s->file.len = s->scriptlen;
251 s->len = s->file.len;
254 if(httpd_fs_getchar(s->file.data) == ISO_percent) {
255 pptr = (
char *) httpd_fs_strchr(s->file.data + 1, ISO_percent);
257 pptr = (
char *) httpd_fs_strchr(s->file.data, ISO_percent);
260 if(pptr !=
NULL && pptr != s->file.data) {
261 s->len = (int)(pptr - s->file.data);
266 PRINTF(
"httpd: Sending %u bytes from 0x%04x\n",s->file.len,(
unsigned int)s->file.data);
268 s->file.data += s->len;
269 s->file.len -= s->len;
276 const char httpd_http[] HTTPD_STRING_ATTR =
"HTTP/1.0 ";
277 const char httpd_server[] HTTPD_STRING_ATTR =
"\r\nServer: Contiki/2.0 http://www.sics.se/contiki/\r\nConnection: close\r\n";
278 static unsigned short
279 generate_status(
void *sstr)
281 uint8_t slen=httpd_strlen((
char *)sstr);
282 httpd_memcpy(
uip_appdata, httpd_http,
sizeof(httpd_http)-1);
283 httpd_memcpy(
uip_appdata+
sizeof(httpd_http)-1, (
char *)sstr, slen);
284 slen+=
sizeof(httpd_http)-1;
285 httpd_memcpy(
uip_appdata+slen, httpd_server,
sizeof(httpd_server)-1);
289 return slen+
sizeof(httpd_server)-1;
293 const char httpd_content[] HTTPD_STRING_ATTR =
"Content-type: ";
294 const char httpd_crlf[] HTTPD_STRING_ATTR =
"\r\n\r\n";
295 static unsigned short
296 generate_header(
void *hstr)
298 uint8_t slen=httpd_strlen((
char *)hstr);
299 httpd_memcpy(
uip_appdata,httpd_content,
sizeof(httpd_content)-1);
300 httpd_memcpy(
uip_appdata+
sizeof(httpd_content)-1, (
char *)hstr, slen);
301 slen+=
sizeof(httpd_content)-1;
302 httpd_memcpy(
uip_appdata+slen,httpd_crlf,
sizeof(httpd_crlf)-1);
310 char http_htm[10] PROGMEM =
"text/html";
311 char http_css[ 9] PROGMEM =
"text/css";
312 const char httpd_mime_htm[] HTTPD_STRING_ATTR =
"text/html";
313 const char httpd_mime_css[] HTTPD_STRING_ATTR =
"text/css";
314 const char httpd_mime_png[] HTTPD_STRING_ATTR =
"image/png";
315 const char httpd_mime_gif[] HTTPD_STRING_ATTR =
"image/gif";
316 const char httpd_mime_jpg[] HTTPD_STRING_ATTR =
"image/jpeg";
317 const char httpd_mime_txt[] HTTPD_STRING_ATTR =
"text/plain";
318 const char httpd_mime_bin[] HTTPD_STRING_ATTR =
"application/octet-stream";
319 const char httpd_jpg [] HTTPD_STRING_ATTR =
"jpg";
320 const char httpd_shtml [] HTTPD_STRING_ATTR =
".shtml";
323 PT_THREAD(send_headers(
struct httpd_state *s,
const char *statushdr))
330 ptr = strrchr(s->filename, ISO_period);
331 if (httpd_strncmp(
"4", statushdr, 1)==0) {
333 }
else if(ptr ==
NULL) {
337 if(httpd_strncmp(ptr, &httpd_mime_htm[5],3)== 0 ||httpd_strncmp(ptr, &httpd_shtml[1], 4) == 0) {
339 }
else if(httpd_strcmp(ptr, &httpd_mime_css[5]) == 0) {
341 }
else if(httpd_strcmp(ptr, &httpd_mime_png[6]) == 0) {
343 }
else if(httpd_strcmp(ptr, &httpd_mime_gif[6])== 0) {
345 }
else if(httpd_strcmp(ptr, httpd_mime_jpg) == 0) {
354 const char httpd_indexfn [] HTTPD_STRING_ATTR =
"/index.html";
355 const char httpd_404fn [] HTTPD_STRING_ATTR =
"/404.html";
356 const char httpd_404notf [] HTTPD_STRING_ATTR =
"404 Not found";
357 const char httpd_200ok [] HTTPD_STRING_ATTR =
"200 OK";
359 PT_THREAD(handle_output(
struct httpd_state *s))
365 httpd_strcpy(s->filename,httpd_indexfn);
367 if(!httpd_fs_open(s->filename, &s->file)) {
368 httpd_strcpy(s->filename, httpd_404fn);
369 httpd_fs_open(s->filename, &s->file);
374 ptr = strchr(s->filename, ISO_period);
375 if((ptr !=
NULL && httpd_strncmp(ptr, httpd_shtml, 6) == 0) || httpd_strcmp(s->filename,httpd_indexfn)==0) {
386 const char httpd_get[] HTTPD_STRING_ATTR =
"GET ";
387 const char httpd_ref[] HTTPD_STRING_ATTR =
"Referer:";
389 PT_THREAD(handle_input(
struct httpd_state *s))
396 if(httpd_strncmp(s->inputbuf, httpd_get, 4) != 0) {
401 if(s->inputbuf[0] != ISO_slash) {
405 if(s->inputbuf[1] == ISO_space) {
406 httpd_strcpy(s->filename, httpd_indexfn);
409 strncpy(s->filename, &s->inputbuf[0],
sizeof(s->filename));
413 for (i=0;i<
sizeof(s->inputbuf);i++) {
414 if (s->inputbuf[i]==
'?') {
415 raven_lcd_show_text(&s->inputbuf[i]);
416 if (i<
sizeof(s->filename)) s->filename[i]=0;
419 if (s->inputbuf[i]==0)
break;
426 s->state = STATE_OUTPUT;
431 if(httpd_strncmp(s->inputbuf, httpd_ref, 8) == 0) {
433 petsciiconv_topetscii(s->inputbuf,
PSOCK_DATALEN(&s->sin) - 2);
434 webserver_log(s->inputbuf);
441 handle_connection(
struct httpd_state *s)
447 if(s->state == STATE_OUTPUT) {
454 httpd_appcall(
void *state)
457 struct httpd_state *s;
458 s = sg = (
struct httpd_state *)
memb_alloc(&conns);
461 struct httpd_state *s = (
struct httpd_state *)state;
474 PSOCK_INIT(&s->sin, (uint8_t *)s->inputbuf,
sizeof(s->inputbuf) - 1);
475 PSOCK_INIT(&s->sout, (uint8_t *)s->inputbuf,
sizeof(s->inputbuf) - 1);
477 s->state = STATE_WAITING;
480 handle_connection(s);
481 }
else if(s !=
NULL) {
491 handle_connection(s);