38 #include "contiki-net.h"
40 #include "webserver.h"
42 #include "httpd-cgi.h"
44 #include "http-strings.h"
48 #ifndef WEBSERVER_CONF_CGI_CONNS
49 #define CONNS UIP_CONNS
51 #define CONNS WEBSERVER_CONF_CGI_CONNS
54 #define STATE_WAITING 0
55 #define STATE_OUTPUT 1
57 #define SEND_STRING(s, str) PSOCK_SEND(s, (uint8_t *)str, (unsigned int)strlen(str))
58 MEMB(conns,
struct httpd_state, CONNS);
61 #define ISO_space 0x20
63 #define ISO_percent 0x25
64 #define ISO_period 0x2e
65 #define ISO_slash 0x2f
66 #define ISO_colon 0x3a
72 struct httpd_state *s = (
struct httpd_state *)state;
85 PT_THREAD(send_file(
struct httpd_state *s))
91 s->file.len -= s->len;
92 s->file.data += s->len;
93 }
while(s->file.len > 0);
99 PT_THREAD(send_part_of_file(
struct httpd_state *s))
103 PSOCK_SEND(&s->sout, (uint8_t *)s->file.data, s->len);
109 next_scriptstate(
struct httpd_state *s)
113 if((p = strchr(s->scriptptr, ISO_nl)) !=
NULL) {
115 s->scriptlen -= (
unsigned short)(p - s->scriptptr);
127 PT_THREAD(handle_script(
struct httpd_state *s))
133 while(s->file.len > 0) {
136 if(*s->file.data == ISO_percent &&
137 *(s->file.data + 1) == ISO_bang) {
138 s->scriptptr = s->file.data + 3;
139 s->scriptlen = s->file.len - 3;
140 if(*(s->scriptptr - 1) == ISO_colon) {
141 httpd_fs_open(s->scriptptr + 1, &s->file);
145 httpd_cgi(s->scriptptr)(s, s->scriptptr));
151 s->file.data = s->scriptptr;
152 s->file.len = s->scriptlen;
160 s->len = s->file.len;
163 if(*s->file.data == ISO_percent) {
164 ptr = strchr(s->file.data + 1, ISO_percent);
166 ptr = strchr(s->file.data, ISO_percent);
169 ptr != s->file.data) {
170 s->len = (int)(ptr - s->file.data);
176 s->file.data += s->len;
177 s->file.len -= s->len;
185 PT_THREAD(send_headers(
struct httpd_state *s,
const char *statushdr))
190 static const char *ptr =
NULL;
194 SEND_STRING(&s->sout, statushdr);
196 ptr = strrchr(s->filename, ISO_period);
198 ptr = http_content_type_binary;
199 }
else if(strncmp(http_html, ptr, 5) == 0 ||
200 strncmp(http_shtml, ptr, 6) == 0) {
201 ptr = http_content_type_html;
202 }
else if(strncmp(http_css, ptr, 4) == 0) {
203 ptr = http_content_type_css;
204 }
else if(strncmp(http_png, ptr, 4) == 0) {
205 ptr = http_content_type_png;
206 }
else if(strncmp(http_gif, ptr, 4) == 0) {
207 ptr = http_content_type_gif;
208 }
else if(strncmp(http_jpg, ptr, 4) == 0) {
209 ptr = http_content_type_jpg;
211 ptr = http_content_type_plain;
213 SEND_STRING(&s->sout, ptr);
218 PT_THREAD(handle_output(
struct httpd_state *s))
224 if(!httpd_fs_open(s->filename, &s->file)) {
225 strcpy(s->filename, http_404_html);
226 httpd_fs_open(s->filename, &s->file);
236 ptr = strrchr(s->filename, ISO_period);
237 if(ptr !=
NULL && strncmp(ptr, http_shtml, 6) == 0) {
250 PT_THREAD(handle_input(
struct httpd_state *s))
256 if(strncmp(s->inputbuf, http_get, 4) != 0) {
261 if(s->inputbuf[0] != ISO_slash) {
265 if(s->inputbuf[1] == ISO_space) {
266 strncpy(s->filename, http_index_html,
sizeof(s->filename));
269 strncpy(s->filename, s->inputbuf,
sizeof(s->filename));
272 petsciiconv_topetscii(s->filename,
sizeof(s->filename));
274 petsciiconv_toascii(s->filename,
sizeof(s->filename));
275 s->state = STATE_OUTPUT;
280 if(strncmp(s->inputbuf, http_referer, 8) == 0) {
282 petsciiconv_topetscii(s->inputbuf,
PSOCK_DATALEN(&s->sin) - 2);
283 webserver_log(s->inputbuf);
291 handle_connection(
struct httpd_state *s)
294 if(s->state == STATE_OUTPUT) {
300 httpd_appcall(
void *state)
302 struct httpd_state *s = (
struct httpd_state *)state;
315 PSOCK_INIT(&s->sin, (uint8_t *)s->inputbuf,
sizeof(s->inputbuf) - 1);
316 PSOCK_INIT(&s->sout, (uint8_t *)s->inputbuf,
sizeof(s->inputbuf) - 1);
318 s->state = STATE_WAITING;
321 handle_connection(s);
322 }
else if(s !=
NULL) {
332 handle_connection(s);
348 httpd_sprint_ip6(uip_ip6addr_t addr,
char * result)
351 unsigned char zerocnt = 0;
352 unsigned char numprinted = 0;
353 char * starting = result;
356 while (numprinted < 8) {
357 if ((addr.u16[i] == 0) && (zerocnt == 0)) {
358 while(addr.u16[zerocnt + i] == 0) zerocnt++;
365 numprinted += zerocnt;
367 result += sprintf(result,
"%x", (
unsigned int)(uip_ntohs(addr.u16[i])));
371 if (numprinted != 8) *result++ =
':';
375 return (result - starting);
#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 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.
#define uip_connected()
Has the connection just been connected?
#define uip_abort()
Abort the current connection.
PETSCII/ASCII conversion functions.
#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_SEND(psock, data, datalen)
Send data.
#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.