00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <string.h>
00037
00038 #include "contiki-net.h"
00039 #include "cfs/cfs.h"
00040
00041 #include "webserver.h"
00042 #include "libconio_arch-small.h"
00043
00044 #include "httpd-cfs.h"
00045
00046 #define STATE_WAITING 0
00047 #define STATE_OUTPUT 1
00048
00049 #define SEND_STRING(s, str) PSOCK_SEND(s, str, strlen(str))
00050 MEMB(conns, struct httpd_state, 2);
00051
00052
00053 static
00054 PT_THREAD(send_file(struct httpd_state *s))
00055 {
00056 PSOCK_BEGIN(&s->sout);
00057
00058 do {
00059
00060 s->len = cfs_read(s->fd, s->outputbuf, sizeof(s->outputbuf));
00061
00062
00063 if(s->len > 0) {
00064 PSOCK_SEND(&s->sout, s->outputbuf, s->len);
00065 } else {
00066 break;
00067 }
00068 } while(s->len > 0);
00069
00070 PSOCK_END(&s->sout);
00071 }
00072
00073 static
00074 PT_THREAD(send_headers(struct httpd_state *s, char *statushdr))
00075 {
00076 char *ptr;
00077
00078 PSOCK_BEGIN(&s->sout);
00079
00080 SEND_STRING(&s->sout, statushdr);
00081 SEND_STRING(&s->sout, "Server: " CONTIKI_VERSION_STRING "\r\n");
00082
00083 ptr = strrchr(s->filename, '.');
00084 if(ptr == NULL) {
00085 SEND_STRING(&s->sout, "Content-type: text/plain\r\n\r\n");
00086 } else if(strncmp(".html", ptr, 5) == 0) {
00087 SEND_STRING(&s->sout, "Content-type: text/html\r\n\r\n");
00088 } else if(strncmp(".css", ptr, 4) == 0) {
00089 SEND_STRING(&s->sout, "Content-type: text/css\r\n\r\n");
00090 } else if(strncmp(".png", ptr, 4) == 0) {
00091 SEND_STRING(&s->sout, "Content-type: image/png\r\n\r\n");
00092 } else if(strncmp(".jpg", ptr, 4) == 0) {
00093 SEND_STRING(&s->sout, "Content-type: image/jpeg\r\n\r\n");
00094 } else {
00095 SEND_STRING(&s->sout, "Content-type: application/octet-stream\r\n\r\n");
00096 }
00097 PSOCK_END(&s->sout);
00098 }
00099
00100 static
00101 PT_THREAD(handle_output(struct httpd_state *s))
00102 {
00103 PT_BEGIN(&s->outputpt);
00104
00105 s->fd = cfs_open(s->filename, CFS_READ);
00106 if(s->fd < 0) {
00107 s->fd = cfs_open("404.html", CFS_READ);
00108 if(s->fd < 0) {
00109 uip_abort();
00110 PT_EXIT(&s->outputpt);
00111 }
00112 PT_WAIT_THREAD(&s->outputpt,
00113 send_headers(s, "HTTP/1.0 404 Not found\r\n"));
00114 PT_WAIT_THREAD(&s->outputpt,
00115 send_file(s));
00116 } else {
00117 PT_WAIT_THREAD(&s->outputpt,
00118 send_headers(s, "HTTP/1.0 200 OK\r\n"));
00119 PT_WAIT_THREAD(&s->outputpt,
00120 send_file(s));
00121 cfs_close(s->fd);
00122 }
00123 PSOCK_CLOSE(&s->sout);
00124 PT_END(&s->outputpt);
00125 }
00126
00127 static
00128 PT_THREAD(handle_input(struct httpd_state *s))
00129 {
00130 PSOCK_BEGIN(&s->sin);
00131
00132 PSOCK_READTO(&s->sin, ' ');
00133
00134 if(strncmp(s->inputbuf, "GET ", 4) != 0) {
00135 PSOCK_CLOSE_EXIT(&s->sin);
00136 }
00137 PSOCK_READTO(&s->sin, ' ');
00138
00139 if(s->inputbuf[0] != '/') {
00140 PSOCK_CLOSE_EXIT(&s->sin);
00141 }
00142
00143 if(s->inputbuf[1] == ' ') {
00144 strncpy(s->filename, "index.html", sizeof(s->filename));
00145 } else {
00146 s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0;
00147 strncpy(s->filename, &s->inputbuf[1], sizeof(s->filename));
00148 }
00149
00150
00151 libputs_arch(s->filename);
00152 s->state = STATE_OUTPUT;
00153
00154 while(1) {
00155 PSOCK_READTO(&s->sin, '\n');
00156
00157 if(strncmp(s->inputbuf, "Referer:", 8) == 0) {
00158 s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0;
00159 libputs_arch(&s->inputbuf[9]);
00160
00161 }
00162 }
00163
00164 PSOCK_END(&s->sin);
00165 }
00166
00167 static void
00168 handle_connection(struct httpd_state *s)
00169 {
00170 handle_input(s);
00171 if(s->state == STATE_OUTPUT) {
00172 handle_output(s);
00173 }
00174 }
00175
00176 void
00177 httpd_appcall(void *state)
00178 {
00179 struct httpd_state *s = (struct httpd_state *)state;
00180
00181 if(uip_closed() || uip_aborted() || uip_timedout()) {
00182 if(s != NULL) {
00183 memb_free(&conns, s);
00184 }
00185 } else if(uip_connected()) {
00186 s = (struct httpd_state *)memb_alloc(&conns);
00187 if(s == NULL) {
00188 uip_abort();
00189 return;
00190 }
00191 tcp_markconn(uip_conn, s);
00192 PSOCK_INIT(&s->sin, s->inputbuf, sizeof(s->inputbuf) - 1);
00193 PSOCK_INIT(&s->sout, s->inputbuf, sizeof(s->inputbuf) - 1);
00194 PT_INIT(&s->outputpt);
00195 s->state = STATE_WAITING;
00196 timer_set(&s->timer, CLOCK_SECOND * 10);
00197 handle_connection(s);
00198 } else if(s != NULL) {
00199 if(uip_poll()) {
00200 if(timer_expired(&s->timer)) {
00201 uip_abort();
00202 }
00203 } else {
00204 timer_reset(&s->timer);
00205 }
00206 handle_connection(s);
00207 } else {
00208 uip_abort();
00209 }
00210 }
00211
00212 void
00213 httpd_init(void)
00214 {
00215 tcp_listen(UIP_HTONS(80));
00216 memb_init(&conns);
00217 }
00218