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