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 #include "lwip/debug.h"
00034
00035 #include "lwip/stats.h"
00036
00037 #include "httpd.h"
00038
00039 #include "lwip/tcp.h"
00040
00041 #include "fs.h"
00042 #include "printf-stdarg.h"
00043
00044 struct http_state {
00045 char *file;
00046 u16_t left;
00047 u8_t retries;
00048 };
00049
00050
00051 static void
00052 conn_err(void *arg, err_t err)
00053 {
00054 struct http_state *hs;
00055
00056 LWIP_UNUSED_ARG(err);
00057
00058 hs = arg;
00059 mem_free(hs);
00060 }
00061
00062 static void
00063 close_conn(struct tcp_pcb *pcb, struct http_state *hs)
00064 {
00065 tcp_arg(pcb, NULL);
00066 tcp_sent(pcb, NULL);
00067 tcp_recv(pcb, NULL);
00068 mem_free(hs);
00069 tcp_close(pcb);
00070 }
00071
00072 static void
00073 send_data(struct tcp_pcb *pcb, struct http_state *hs)
00074 {
00075 err_t err;
00076 u16_t len;
00077
00078
00079
00080 if (tcp_sndbuf(pcb) < hs->left) {
00081 len = tcp_sndbuf(pcb);
00082 } else {
00083 len = hs->left;
00084 }
00085
00086 do {
00087 err = tcp_write(pcb, hs->file, len, 0);
00088 if (err == ERR_MEM) {
00089 len /= 2;
00090 }
00091 } while (err == ERR_MEM && len > 1);
00092
00093 if (err == ERR_OK) {
00094 hs->file += len;
00095 hs->left -= len;
00096 }
00097 }
00098
00099 static err_t
00100 http_poll(void *arg, struct tcp_pcb *pcb)
00101 {
00102 struct http_state *hs;
00103
00104 hs = arg;
00105
00106 if (hs == NULL) {
00107 tcp_abort(pcb);
00108 return ERR_ABRT;
00109 } else {
00110 ++hs->retries;
00111 if (hs->retries == 4) {
00112 tcp_abort(pcb);
00113 return ERR_ABRT;
00114 }
00115 send_data(pcb, hs);
00116 }
00117
00118 return ERR_OK;
00119 }
00120
00121 static err_t
00122 http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
00123 {
00124 struct http_state *hs;
00125
00126 LWIP_UNUSED_ARG(len);
00127
00128 hs = arg;
00129
00130 hs->retries = 0;
00131
00132 if (hs->left > 0) {
00133 send_data(pcb, hs);
00134 } else {
00135 close_conn(pcb, hs);
00136 }
00137
00138 return ERR_OK;
00139 }
00140
00141 static err_t
00142 http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
00143 {
00144 int i;
00145 char *data;
00146 struct fs_file file;
00147 struct http_state *hs;
00148 hs = arg;
00149
00150 if (err == ERR_OK && p != NULL) {
00151
00152
00153 tcp_recved(pcb, p->tot_len);
00154
00155 if (hs->file == NULL) {
00156 data = p->payload;
00157
00158 if (strncmp(data, "GET ", 4) == 0) {
00159 for(i = 0; i < 40; i++) {
00160 if (((char *)data + 4)[i] == ' ' ||
00161 ((char *)data + 4)[i] == '\r' ||
00162 ((char *)data + 4)[i] == '\n') {
00163 ((char *)data + 4)[i] = 0;
00164 }
00165 }
00166
00167 if (*(char *)(data + 4) == '/' &&
00168 *(char *)(data + 5) == 0) {
00169 fs_open("/index.html", &file);
00170 } else if (!fs_open((char *)data + 4, &file)) {
00171 fs_open("/404.html", &file);
00172 }
00173
00174 hs->file = file.data;
00175 hs->left = file.len;
00176
00177 pbuf_free(p);
00178 send_data(pcb, hs);
00179
00180
00181
00182 tcp_sent(pcb, http_sent);
00183 }
00184 else {
00185 printk("%s\n", p->payload);
00186 pbuf_free(p);
00187 close_conn(pcb, hs);
00188 }
00189 } else {
00190 pbuf_free(p);
00191 }
00192 }
00193
00194 if (err == ERR_OK && p == NULL) {
00195 close_conn(pcb, hs);
00196 }
00197 return ERR_OK;
00198 }
00199
00200 static err_t
00201 http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
00202 {
00203 struct http_state *hs;
00204
00205 LWIP_UNUSED_ARG(arg);
00206 LWIP_UNUSED_ARG(err);
00207
00208 tcp_setprio(pcb, TCP_PRIO_MIN);
00209
00210
00211
00212 hs = (struct http_state *)mem_malloc(sizeof(struct http_state));
00213
00214 if (hs == NULL) {
00215 printk("http_accept: Out of memory\n");
00216 return ERR_MEM;
00217 }
00218
00219
00220 hs->file = NULL;
00221 hs->left = 0;
00222 hs->retries = 0;
00223
00224
00225
00226 tcp_arg(pcb, hs);
00227
00228
00229
00230 tcp_recv(pcb, http_recv);
00231
00232 tcp_err(pcb, conn_err);
00233
00234 tcp_poll(pcb, http_poll, 4);
00235 return ERR_OK;
00236 }
00237
00238 struct tcp_pcb *pcb = NULL;
00239
00240 err_t httpd_start(void)
00241 {
00242 pcb = tcp_new();
00243 if (pcb == NULL)
00244 return ERR_MEM;
00245 tcp_bind(pcb, IP_ADDR_ANY, 80);
00246 pcb = tcp_listen(pcb);
00247 tcp_accept(pcb, http_accept);
00248 return ERR_OK;
00249 }
00250
00251 void httpd_stop(void)
00252 {
00253 if (pcb)
00254 tcp_close(pcb);
00255 }