43 #include <avr/pgmspace.h>
44 #include "contiki-net.h"
46 #ifndef WEBSERVER_CONF_CFS_PATHLEN
47 #define HTTPD_PATHLEN 2
49 #define HTTPD_PATHLEN WEBSERVER_CONF_CFS_PATHLEN
53 typedef char (* httpd_simple_script_t)(
struct httpd_state *s);
57 struct psock sin, sout;
59 char inputbuf[HTTPD_PATHLEN + 30];
61 char filename[HTTPD_PATHLEN];
62 httpd_simple_script_t script;
79 struct httpd_state *sg;
80 #define uip_mss(...) sizeof(uip_aligned_buf)
81 #define uip_appdata (char *) &uip_aligned_buf
84 #ifndef WEBSERVER_CONF_CFS_CONNS
85 #define CONNS UIP_CONNS
87 #define CONNS WEBSERVER_CONF_CFS_CONNS
90 #ifndef WEBSERVER_CONF_CFS_URLCONV
93 #define URLCONV WEBSERVER_CONF_CFS_URLCONV
96 #define STATE_WAITING 0
97 #define STATE_OUTPUT 1
99 MEMB(conns,
struct httpd_state, CONNS);
101 #define webserver_log_file(...)
104 #define ISO_space 0x20
105 #define ISO_period 0x2e
106 #define ISO_slash 0x2f
109 static unsigned short
110 generate_string(
void *sstr)
112 uint8_t slen=strlen((
char *)sstr);
122 static unsigned short
123 generate_string_P(
void *sstr)
125 uint8_t slen=strlen_P((
char *)sstr);
140 PT_THREAD(send_string_P(
struct httpd_state *s,
char *str))
148 const char http_content_type_html[]
PROGMEM =
"Content-type: text/html\r\n\r\n";
150 PT_THREAD(send_headers(
struct httpd_state *s,
const char *statushdr))
158 const char http_index_html[] PROGMEM =
"/index.html";
159 const char http_referer[] PROGMEM =
"Referer:";
160 const char http_get[] PROGMEM =
"GET ";
162 PT_THREAD(handle_input(
struct httpd_state *s))
168 if(strncmp_P(s->inputbuf, http_get, 4) != 0) {
173 if(s->inputbuf[0] != ISO_slash) {
179 urlconv_tofilename(s->filename, s->inputbuf,
sizeof(s->filename));
181 if(s->inputbuf[1] == ISO_space) {
182 strncpy_P(s->filename, http_index_html,
sizeof(s->filename));
185 strncpy(s->filename, s->inputbuf,
sizeof(s->filename));
191 s->state = STATE_OUTPUT;
216 #define ADD(FORMAT,args...) do { \
217 blen += snprintf_P(&buf[blen], sizeof(buf) - blen, PSTR(FORMAT),##args); \
221 ipaddr_add(
const uip_ipaddr_t *addr)
225 for(i = 0, f = 0; i <
sizeof(uip_ipaddr_t); i += 2) {
226 a = (addr->u8[i] << 8) + addr->u8[i + 1];
227 if(a == 0 && f >= 0) {
228 if(f++ == 0 &&
sizeof(buf) - blen >= 2) {
235 }
else if(i > 0 && blen <
sizeof(buf)) {
243 const char TOP1[] PROGMEM =
"<html><head><title>ContikiRPL(Jackdaw)";
244 const char TOP2[] PROGMEM =
"</title></head><body>";
245 const char BOTTOM[] PROGMEM =
"</body></html>";
248 PT_THREAD(generate_routes(
struct httpd_state *s))
256 #if UIP_CONF_IPV6 //allow ip4 builds
258 ADD(
"<h2>Neighbors [%u max]</h2>",NBR_TABLE_CONF_MAX_NEIGHBORS);
262 for(nbr = nbr_table_head(ds6_neighbors);
264 nbr = nbr_table_next(ds6_neighbors, nbr)) {
265 ipaddr_add(&nbr->ipaddr);
273 ADD(
"<h2>Routes [%u max]</h2>",UIP_DS6_ROUTE_NB);
277 for(route = uip_ds6_route_head();
279 route = uip_ds6_route_next(route)) {
280 ipaddr_add(&route->ipaddr);
281 ADD(
"/%u (via ", route->length);
284 ipaddr_add(uip_ds6_route_nexthop(route));
285 if(route->state.lifetime < 600) {
288 ADD(
") %lus<br>", route->state.lifetime);
301 ADD(
"<h2>Hey, you got ip4 working!</h2>");
311 httpd_simple_script_t
312 httpd_simple_get_script(
const char *name)
314 return generate_routes;
317 const char http_header_200[] PROGMEM =
"HTTP/1.0 200 OK\r\nServer: Jackdaw\r\nConnection: close\r\n";
318 const char http_header_404[] PROGMEM =
"HTTP/1.0 404 Not found\r\nServer: Jackdaw\r\nConnection: close\r\n";
319 const char NOT_FOUND[] PROGMEM =
"<html><body bgcolor=\"white\"><center><h1>404 - file not found</h1></center></body></html>";
321 PT_THREAD(handle_output(
struct httpd_state *s))
326 strcpy_P(s->filename,PSTR(
"/x"));
329 s->script = httpd_simple_get_script(&s->filename[1]);
330 if(s->script ==
NULL) {
331 printf_P(PSTR(
"not found!"));
332 strcpy_P(s->filename, PSTR(
"/notfound.html"));
335 send_headers(s, http_header_404));
337 send_string_P(s, NOT_FOUND));
343 s->script = generate_routes;
348 send_headers(s, http_header_200));
357 handle_connection(
struct httpd_state *s)
363 if(s->state == STATE_OUTPUT) {
370 httpd_appcall(
void *state)
373 struct httpd_state *s;
374 s = sg = (
struct httpd_state *)
memb_alloc(&conns);
377 struct httpd_state *s = (
struct httpd_state *)state;
393 PSOCK_INIT(&s->sin, (uint8_t *)s->inputbuf,
sizeof(s->inputbuf) - 1);
394 PSOCK_INIT(&s->sout, (uint8_t *)s->inputbuf,
sizeof(s->inputbuf) - 1);
397 s->state = STATE_WAITING;
399 handle_connection(s);
400 }
else if(s !=
NULL) {
411 handle_connection(s);
417 PROCESS(httpd_process,
"httpd");
An entry in the routing table.
#define PT_WAIT_THREAD(pt, thread)
Block and wait until a child protothread completes.
#define PSOCK_READTO(psock, c)
Read data up to a specified character.
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
#define PSOCK_CLOSE_EXIT(psock)
Close a protosocket and exit the protosocket's protothread.
void timer_restart(struct timer *t)
Restart the timer from the current point in time.
#define PROCESS_BEGIN()
Define the beginning of a process.
#define PSOCK_BEGIN(psock)
Start the protosocket protothread in a function.
Representation of a uIP TCP connection.
#define uip_aborted()
Has the connection been aborted by the other end?
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
#define NULL
The null pointer.
#define PT_INIT(pt)
Initialize a protothread.
#define uip_poll()
Is the connection being polled by uIP?
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
#define PT_THREAD(name_args)
Declaration of a protothread.
const uint32_t OIDSupportedList[] PROGMEM
List of supported RNDIS OID's.
#define uip_connected()
Has the connection just been connected?
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define PROCESS_END()
Define the end of a process.
#define uip_abort()
Abort the current connection.
#define PSOCK_INIT(psock, buffer, buffersize)
Initialize a protosocket.
#define PSOCK_GENERATOR_SEND(psock, generator, arg)
Generate data with a function and send it.
#define MEMB(name, structure, num)
Declare a memory block.
#define PSOCK_CLOSE(psock)
Close a protosocket.
#define PROCESS_WAIT_EVENT_UNTIL(c)
Wait for an event to be posted to the process, with an extra condition.
The representation of a protosocket.
#define PSOCK_END(psock)
Declare the end of a protosocket's protothread.
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
#define PROCESS(name, strname)
Declare a process.
#define uip_close()
Close the current connection.
process_event_t tcpip_event
The uIP event.
#define uip_timedout()
Has the connection timed out?
#define PT_END(pt)
Declare the end of a protothread.
CCIF void tcp_listen(uint16_t port)
Open a TCP port.
#define PSOCK_DATALEN(psock)
The length of the data that was previously read.
#define uip_closed()
Has the connection been closed by the other end?
uip_ipaddr_t ripaddr
The IP address of the remote host.
int timer_expired(struct timer *t)
Check if a timer has expired.
#define UIP_TCP_MSS
The TCP maximum segment size.
#define PT_EXIT(pt)
Exit the protothread.
uip_appdata
Pointer to the application data in the packet buffer.
#define CLOCK_SECOND
A second, measured in system clock time.
An entry in the nbr cache.