37 int snprintf(
char *str,
size_t size,
const char *format, ...);
41 #include "contiki-net.h"
43 #include "webserver.h"
46 #include "http-strings.h"
49 #include "httpd-cfs.h"
51 #ifndef WEBSERVER_CONF_CFS_CONNS
52 #define CONNS UIP_CONNS
54 #define CONNS WEBSERVER_CONF_CFS_CONNS
57 #ifndef WEBSERVER_CONF_CFS_URLCONV
60 #define URLCONV WEBSERVER_CONF_CFS_URLCONV
63 #define STATE_WAITING 0
64 #define STATE_OUTPUT 1
66 #define SEND_STRING(s, str) PSOCK_SEND(s, (uint8_t *)str, strlen(str))
67 MEMB(conns,
struct httpd_state, CONNS);
70 #define ISO_space 0x20
71 #define ISO_period 0x2e
72 #define ISO_slash 0x2f
76 PT_THREAD(send_file(
struct httpd_state *s))
82 s->len = cfs_read(s->fd, s->outputbuf,
sizeof(s->outputbuf));
86 PSOCK_SEND(&s->sout, (uint8_t *)s->outputbuf, s->len);
96 PT_THREAD(send_string(
struct httpd_state *s,
const char *str))
100 SEND_STRING(&s->sout, str);
106 get_content_type(
const char *filename)
109 ptr = strrchr(filename, ISO_period);
111 ptr = http_content_type_plain;
112 }
else if(strcmp(http_htm, ptr) == 0) {
113 ptr = http_content_type_html;
114 }
else if(strcmp(http_css, ptr) == 0) {
115 ptr = http_content_type_css;
116 }
else if(strcmp(http_png, ptr) == 0) {
117 ptr = http_content_type_png;
118 }
else if(strcmp(http_gif, ptr) == 0) {
119 ptr = http_content_type_gif;
120 }
else if(strcmp(http_jpg, ptr) == 0) {
121 ptr = http_content_type_jpg;
123 ptr = http_content_type_binary;
129 PT_THREAD(send_headers(
struct httpd_state *s,
const char *statushdr))
133 SEND_STRING(&s->sout, statushdr);
134 SEND_STRING(&s->sout, get_content_type(s->filename));
140 PT_THREAD(handle_output(
struct httpd_state *s))
144 petsciiconv_topetscii(s->filename,
sizeof(s->filename));
146 petsciiconv_toascii(s->filename,
sizeof(s->filename));
148 strcpy(s->filename,
"/notfound.htm");
150 petsciiconv_toascii(s->filename,
sizeof(s->filename));
152 send_headers(s, http_header_404));
155 send_string(s,
"not found"));
163 send_headers(s, http_header_200));
173 PT_THREAD(handle_input(
struct httpd_state *s))
179 if(strncmp(s->inputbuf, http_get, 4) != 0) {
184 if(s->inputbuf[0] != ISO_slash) {
190 urlconv_tofilename(s->filename, s->inputbuf,
sizeof(s->filename));
192 if(s->inputbuf[1] == ISO_space) {
193 strncpy(s->filename, http_index_htm,
sizeof(s->filename));
196 strncpy(s->filename, s->inputbuf,
sizeof(s->filename));
200 petsciiconv_topetscii(s->filename,
sizeof(s->filename));
202 petsciiconv_toascii(s->filename,
sizeof(s->filename));
203 s->state = STATE_OUTPUT;
208 if(strncmp(s->inputbuf, http_referer, 8) == 0) {
210 petsciiconv_topetscii(s->inputbuf,
PSOCK_DATALEN(&s->sin) - 2);
211 webserver_log(s->inputbuf);
219 handle_connection(
struct httpd_state *s)
222 if(s->state == STATE_OUTPUT) {
228 httpd_appcall(
void *state)
230 struct httpd_state *s = (
struct httpd_state *)state;
248 PSOCK_INIT(&s->sin, (uint8_t *)s->inputbuf,
sizeof(s->inputbuf) - 1);
249 PSOCK_INIT(&s->sout, (uint8_t *)s->inputbuf,
sizeof(s->inputbuf) - 1);
252 s->state = STATE_WAITING;
254 handle_connection(s);
255 }
else if(s !=
NULL) {
269 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.
int cfs_open(const char *name, int flags)
Open a file.
void timer_restart(struct timer *t)
Restart the timer from the current point in time.
#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 CFS_READ
Specify that cfs_open() should open a file for reading.
#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 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_close()
Close the current connection.
#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 PT_EXIT(pt)
Exit the protothread.
void cfs_close(int fd)
Close an open file.
#define CLOCK_SECOND
A second, measured in system clock time.