37 #include "contiki-net.h"
39 #include "webserver.h"
41 #include "httpd-cgi.h"
43 #include "raven-lcd.h"
47 #include "cfs-coffee-arch.h"
64 struct httpd_state *sg;
65 #define uip_mss(...) 512
66 #define uip_appdata TCPBUF
71 #if HTTPD_STRING_TYPE==PROGMEM_TYPE
72 #define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
80 #ifndef WEBSERVER_CONF_CGI_CONNS
83 #define CONNS WEBSERVER_CONF_CGI_CONNS
86 #define STATE_WAITING 0
87 #define STATE_OUTPUT 1
90 MEMB(conns,
struct httpd_state, CONNS);
93 #define MAX_SCRIPT_NAME_LENGTH 20
97 #define ISO_space 0x20
99 #define ISO_percent 0x25
100 #define ISO_period 0x2e
101 #define ISO_slash 0x2f
102 #define ISO_colon 0x3a
105 static unsigned short
106 generate(
void *state)
108 struct httpd_state *s = (
struct httpd_state *)state;
113 s->len = s->file.len;
124 PT_THREAD(send_file(
struct httpd_state *s))
130 s->file.len -= s->len;
131 s->file.data += s->len;
132 }
while(s->file.len > 0);
138 PT_THREAD(send_part_of_file(
struct httpd_state *s))
142 static int oldfilelen, oldlen;
143 static char * olddata;
146 oldfilelen = s->file.len;
148 olddata = s->file.data;
151 s->file.len = s->len;
155 s->file.len -= s->len;
156 s->file.data += s->len;
157 }
while(s->file.len > 0);
160 s->file.len = oldfilelen;
161 s->file.data = olddata;
167 next_scriptstate(
struct httpd_state *s)
171 if((p = (
char *)httpd_fs_strchr(s->scriptptr, ISO_nl)) !=
NULL) {
173 s->scriptlen -= (
unsigned short)(p - s->scriptptr);
187 get_scriptname(
char *dest,
char *fromfile)
193 dest[i]=httpd_fs_getchar(fromfile++);
194 if (dest[i]==ISO_colon) {
if (!skip)
break;}
195 else if (dest[i]==ISO_tab ) {
if (skip)
continue;
else break;}
196 else if (dest[i]==ISO_space) {
if (skip)
continue;
else break;}
197 else if (dest[i]==ISO_nl )
break;
198 else if (dest[i]==ISO_cr )
break;
199 else if (dest[i]==0 )
break;
202 }
while (i<(MAX_SCRIPT_NAME_LENGTH+1));
204 while ((dest[i]==ISO_space) || (dest[i]==ISO_tab)) dest[i]=httpd_fs_getchar(++fromfile);
211 PT_THREAD(handle_script(
struct httpd_state *s))
214 static char scriptname[MAX_SCRIPT_NAME_LENGTH+1],*pptr;
215 static uint16_t filelength;
219 filelength=s->file.len;
220 while(s->file.len > 0) {
222 if (s->file.len > filelength)
break;
225 if(httpd_fs_getchar(s->file.data) == ISO_percent &&
226 httpd_fs_getchar(s->file.data + 1) == ISO_bang) {
229 s->scriptptr=get_scriptname(scriptname,s->file.data+2);
230 s->scriptlen=s->file.len-(s->scriptptr-s->file.data);
231 PRINTF(
"httpd: Handle script named %s\n",scriptname);
232 if(scriptname[0] == ISO_colon) {
233 if (httpd_fs_open(&scriptname[1], &s->file)) {
237 PT_WAIT_THREAD(&s->scriptpt,httpd_cgi(scriptname)(s, s->scriptptr));
242 s->file.data = s->scriptptr;
243 s->file.len = s->scriptlen;
250 s->len = s->file.len;
253 if(httpd_fs_getchar(s->file.data) == ISO_percent) {
254 pptr = (
char *) httpd_fs_strchr(s->file.data + 1, ISO_percent);
256 pptr = (
char *) httpd_fs_strchr(s->file.data, ISO_percent);
259 if(pptr !=
NULL && pptr != s->file.data) {
260 s->len = (int)(pptr - s->file.data);
265 PRINTF(
"httpd: Sending %u bytes from 0x%04x\n",s->file.len,(
unsigned int)s->file.data);
267 s->file.data += s->len;
268 s->file.len -= s->len;
275 const char httpd_http[] HTTPD_STRING_ATTR =
"HTTP/1.0 ";
276 const char httpd_server[] HTTPD_STRING_ATTR =
"\r\nServer: Contiki/2.0 http://www.sics.se/contiki/\r\nConnection: close\r\n";
277 static unsigned short
278 generate_status(
void *sstr)
280 uint8_t slen=httpd_strlen((
char *)sstr);
281 httpd_memcpy(
uip_appdata, httpd_http,
sizeof(httpd_http)-1);
282 httpd_memcpy(
uip_appdata+
sizeof(httpd_http)-1, (
char *)sstr, slen);
283 slen+=
sizeof(httpd_http)-1;
284 httpd_memcpy(
uip_appdata+slen, httpd_server,
sizeof(httpd_server)-1);
288 return slen+
sizeof(httpd_server)-1;
292 const char httpd_content[] HTTPD_STRING_ATTR =
"Content-type: ";
293 const char httpd_crlf[] HTTPD_STRING_ATTR =
"\r\n\r\n";
294 static unsigned short
295 generate_header(
void *hstr)
297 uint8_t slen=httpd_strlen((
char *)hstr);
298 httpd_memcpy(
uip_appdata,httpd_content,
sizeof(httpd_content)-1);
299 httpd_memcpy(
uip_appdata+
sizeof(httpd_content)-1, (
char *)hstr, slen);
300 slen+=
sizeof(httpd_content)-1;
301 httpd_memcpy(
uip_appdata+slen,httpd_crlf,
sizeof(httpd_crlf)-1);
309 char http_htm[10]
PROGMEM =
"text/html";
310 char http_css[ 9] PROGMEM =
"text/css";
311 const char httpd_mime_htm[] HTTPD_STRING_ATTR =
"text/html";
312 const char httpd_mime_css[] HTTPD_STRING_ATTR =
"text/css";
313 const char httpd_mime_png[] HTTPD_STRING_ATTR =
"image/png";
314 const char httpd_mime_gif[] HTTPD_STRING_ATTR =
"image/gif";
315 const char httpd_mime_jpg[] HTTPD_STRING_ATTR =
"image/jpeg";
316 const char httpd_mime_txt[] HTTPD_STRING_ATTR =
"text/plain";
317 const char httpd_mime_bin[] HTTPD_STRING_ATTR =
"application/octet-stream";
318 const char httpd_jpg [] HTTPD_STRING_ATTR =
"jpg";
319 const char httpd_shtml [] HTTPD_STRING_ATTR =
".shtml";
322 PT_THREAD(send_headers(
struct httpd_state *s,
const char *statushdr))
329 ptr = strrchr(s->filename, ISO_period);
330 if (httpd_strncmp(
"4", statushdr, 1)==0) {
332 }
else if(ptr ==
NULL) {
336 if(httpd_strncmp(ptr, &httpd_mime_htm[5],3)== 0 ||httpd_strncmp(ptr, &httpd_shtml[1], 4) == 0) {
338 }
else if(httpd_strcmp(ptr, &httpd_mime_css[5]) == 0) {
340 }
else if(httpd_strcmp(ptr, &httpd_mime_png[6]) == 0) {
342 }
else if(httpd_strcmp(ptr, &httpd_mime_gif[6])== 0) {
344 }
else if(httpd_strcmp(ptr, httpd_mime_jpg) == 0) {
353 const char httpd_indexfn [] HTTPD_STRING_ATTR =
"/index.html";
354 const char httpd_404fn [] HTTPD_STRING_ATTR =
"/404.html";
355 const char httpd_404notf [] HTTPD_STRING_ATTR =
"404 Not found";
356 const char httpd_200ok [] HTTPD_STRING_ATTR =
"200 OK";
358 PT_THREAD(handle_output(
struct httpd_state *s))
364 httpd_strcpy(s->filename,httpd_indexfn);
366 if(!httpd_fs_open(s->filename, &s->file)) {
367 httpd_strcpy(s->filename, httpd_404fn);
368 httpd_fs_open(s->filename, &s->file);
373 ptr = strchr(s->filename, ISO_period);
374 if((ptr !=
NULL && httpd_strncmp(ptr, httpd_shtml, 6) == 0) || httpd_strcmp(s->filename,httpd_indexfn)==0) {
385 const char httpd_get[] HTTPD_STRING_ATTR =
"GET ";
386 const char httpd_ref[] HTTPD_STRING_ATTR =
"Referer:";
388 PT_THREAD(handle_input(
struct httpd_state *s))
395 if(httpd_strncmp(s->inputbuf, httpd_get, 4) != 0) {
400 if(s->inputbuf[0] != ISO_slash) {
404 if(s->inputbuf[1] == ISO_space) {
405 httpd_strcpy(s->filename, httpd_indexfn);
408 strncpy(s->filename, &s->inputbuf[0],
sizeof(s->filename));
412 for (i=0;i<
sizeof(s->inputbuf);i++) {
413 if (s->inputbuf[i]==
'?') {
414 raven_lcd_show_text(&s->inputbuf[i]);
415 if (i<
sizeof(s->filename)) s->filename[i]=0;
418 if (s->inputbuf[i]==0)
break;
425 s->state = STATE_OUTPUT;
430 if(httpd_strncmp(s->inputbuf, httpd_ref, 8) == 0) {
432 petsciiconv_topetscii(s->inputbuf,
PSOCK_DATALEN(&s->sin) - 2);
433 webserver_log(s->inputbuf);
440 handle_connection(
struct httpd_state *s)
446 if(s->state == STATE_OUTPUT) {
453 httpd_appcall(
void *state)
456 struct httpd_state *s;
457 s = sg = (
struct httpd_state *)
memb_alloc(&conns);
460 struct httpd_state *s = (
struct httpd_state *)state;
461 #if RF230BB_CONF_LEDONPORTE1
462 extern uint16_t ledtimer;
463 PORTE|=(1<<PE1);ledtimer=1000;
477 PSOCK_INIT(&s->sin, (uint8_t *)s->inputbuf,
sizeof(s->inputbuf) - 1);
478 PSOCK_INIT(&s->sout, (uint8_t *)s->inputbuf,
sizeof(s->inputbuf) - 1);
480 s->state = STATE_WAITING;
483 handle_connection(s);
484 }
else if(s !=
NULL) {
494 handle_connection(s);
#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.
#define PORTE
Peripheral PORTE base pointer.
#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?
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
#define uip_mss()
Get the current maximum segment size that can be sent on the current connection.
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 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 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 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.
uip_appdata
Pointer to the application data in the packet buffer.