44 #include <avr/pgmspace.h>
45 #include "contiki-net.h"
47 #ifndef WEBSERVER_CONF_CFS_PATHLEN
48 #define HTTPD_PATHLEN 2
50 #define HTTPD_PATHLEN WEBSERVER_CONF_CFS_PATHLEN
54 typedef char (* httpd_simple_script_t)(
struct httpd_state *s);
58 struct psock sin, sout;
60 char inputbuf[HTTPD_PATHLEN + 30];
62 char filename[HTTPD_PATHLEN];
63 httpd_simple_script_t script;
80 struct httpd_state *sg;
81 #define uip_mss(...) sizeof(uip_aligned_buf)
82 #define uip_appdata (char *) &uip_aligned_buf
85 #ifndef WEBSERVER_CONF_CFS_CONNS
86 #define CONNS UIP_CONNS
88 #define CONNS WEBSERVER_CONF_CFS_CONNS
91 #ifndef WEBSERVER_CONF_CFS_URLCONV
94 #define URLCONV WEBSERVER_CONF_CFS_URLCONV
97 #define STATE_WAITING 0
98 #define STATE_OUTPUT 1
100 MEMB(conns,
struct httpd_state, CONNS);
102 #define webserver_log_file(...)
105 #define ISO_space 0x20
106 #define ISO_period 0x2e
107 #define ISO_slash 0x2f
110 static unsigned short
111 generate_string(
void *sstr)
113 uint8_t slen=strlen((
char *)sstr);
123 static unsigned short
124 generate_string_P(
void *sstr)
126 uint8_t slen=strlen_P((
char *)sstr);
141 PT_THREAD(send_string_P(
struct httpd_state *s,
char *str))
149 char http_content_type_html[] PROGMEM =
"Content-type: text/html\r\n\r\n";
151 PT_THREAD(send_headers(
struct httpd_state *s,
char *statushdr))
159 const char http_index_html[] PROGMEM =
"/index.html";
160 const char http_referer[] PROGMEM =
"Referer:";
161 const char http_get[] PROGMEM =
"GET ";
163 PT_THREAD(handle_input(
struct httpd_state *s))
169 if(strncmp_P(s->inputbuf, http_get, 4) != 0) {
174 if(s->inputbuf[0] != ISO_slash) {
180 urlconv_tofilename(s->filename, s->inputbuf,
sizeof(s->filename));
182 if(s->inputbuf[1] == ISO_space) {
183 strncpy_P(s->filename, http_index_html,
sizeof(s->filename));
186 strncpy(s->filename, s->inputbuf,
sizeof(s->filename));
192 s->state = STATE_OUTPUT;
217 #define ADD(FORMAT,args...) do { \
218 blen += snprintf_P(&buf[blen], sizeof(buf) - blen, PSTR(FORMAT),##args); \
227 a = (addr->u8[i] << 8) + addr->u8[i + 1];
228 if(a == 0 && f >= 0) {
229 if(f++ == 0 &&
sizeof(buf) - blen >= 2) {
236 }
else if(i > 0 && blen <
sizeof(buf)) {
244 char TOP1[] PROGMEM =
"<html><head><title>ContikiRPL(Jackdaw)";
245 char TOP2[] PROGMEM =
"</title></head><body>";
246 char BOTTOM[] PROGMEM =
"</body></html>";
253 PT_THREAD(generate_routes(
struct httpd_state *s))
261 #if UIP_CONF_IPV6 //allow ip4 builds
263 ADD(
"<h2>Neighbors [%u max]</h2>",UIP_DS6_NBR_NB);
266 for(i = 0; i < UIP_DS6_NBR_NB; i++) {
267 if(uip_ds6_nbr_cache[i].isused) {
268 ipaddr_add(&uip_ds6_nbr_cache[i].ipaddr);
277 ADD(
"<h2>Routes [%u max]</h2>",UIP_DS6_ROUTE_NB);
280 for(i = 0; i < UIP_DS6_ROUTE_NB; i++) {
281 if(uip_ds6_routing_table[i].isused) {
282 ipaddr_add(&uip_ds6_routing_table[i].ipaddr);
283 ADD(
"/%u (via ", uip_ds6_routing_table[i].length);
286 ipaddr_add(&uip_ds6_routing_table[i].nexthop);
287 if(uip_ds6_routing_table[i].state.lifetime < 600) {
290 ADD(
") %lus<br>", uip_ds6_routing_table[i].state.lifetime);
304 ADD(
"<h2>Hey, you got ip4 working!</h2>");
314 httpd_simple_script_t
315 httpd_simple_get_script(
const char *name)
317 return generate_routes;
320 char http_header_200[] PROGMEM =
"HTTP/1.0 200 OK\r\nServer: Jackdaw\r\nConnection: close\r\n";
321 char http_header_404[] PROGMEM =
"HTTP/1.0 404 Not found\r\nServer: Jackdaw\r\nConnection: close\r\n";
322 char NOT_FOUND[] PROGMEM =
"<html><body bgcolor=\"white\"><center><h1>404 - file not found</h1></center></body></html>";
324 PT_THREAD(handle_output(
struct httpd_state *s))
329 strcpy_P(s->filename,PSTR(
"/x"));
332 s->script = httpd_simple_get_script(&s->filename[1]);
333 if(s->script ==
NULL) {
334 printf_P(PSTR(
"not found!"));
335 strcpy_P(s->filename, PSTR(
"/notfound.html"));
338 send_headers(s, http_header_404));
340 send_string_P(s, NOT_FOUND));
346 s->script = generate_routes;
351 send_headers(s, http_header_200));
360 handle_connection(
struct httpd_state *s)
366 if(s->state == STATE_OUTPUT) {
373 httpd_appcall(
void *state)
376 struct httpd_state *s;
377 s = sg = (
struct httpd_state *)
memb_alloc(&conns);
380 struct httpd_state *s = (
struct httpd_state *)state;
396 PSOCK_INIT(&s->sin, (uint8_t *)s->inputbuf,
sizeof(s->inputbuf) - 1);
397 PSOCK_INIT(&s->sout, (uint8_t *)s->inputbuf,
sizeof(s->inputbuf) - 1);
400 s->state = STATE_WAITING;
402 handle_connection(s);
403 }
else if(s !=
NULL) {
414 handle_connection(s);
420 PROCESS(httpd_process,
"httpd");