-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathhttpd.cpp
128 lines (106 loc) · 3.01 KB
/
httpd.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "arduino_app.h"
#include "mbed.h"
#include "SDFileSystem.h"
#include <cstring>
#include "netconf.h"
#include "netlib.h"
#include "util.h"
#define HTTP_BUF_LEN 4096
//SDFileSystem sd(P8_5, P8_6, P8_3, P8_4, "sd");
struct content_type_entry{
const char *extension;
const char *content_type;
};
const char *DOCUMENT_ROOT = "/sd/public_html/";
const char *ERROR_ROOT = "/sd/error_html/";
static content_type_entry content_type_dict[] = {
{"txt", "text/plain"},
{"csv", "text/csv"},
{"htm", "text/html"},
{"html", "text/html"},
{"css", "text/css"},
{"js", "text/javascript"},
{"pdf", "application/pdf"},
{"zip", "application/zip"},
{"jpg", "image/jpeg"},
{"jpeg", "image/jpeg"},
{"png", "image/png"},
{"gif", "image/gif"},
{"bmp", "image/bmp"},
{"mp3", "audio/mpeg"},
{"mp4", "audio/mp4"},
{NULL, "text/plain"}, //該当しないものはテキストとして送る
};
void start_httpd(){
act_tsk(HTTPD_TASK);
}
static const char *get_content_type(const char *extension){
content_type_entry *ptr = content_type_dict;
while(ptr->extension != NULL && strcmp(ptr->extension, extension) != 0)
ptr++;
return ptr->content_type;
}
static int http_respond(int s, const char *st_code_str, const char *cont_str, const char *path){
static char buf[HTTP_BUF_LEN];
sprintf(buf,
"HTTP/1.1 %s\x0d\x0a"
"Connection: close\x0d\x0a"
"Content-type: %s\x0d\x0a\x0d\x0a",
st_code_str, cont_str);
send(s, buf, strlen(buf), 0, TIMEOUT_NOTUSE);
FILE *fp = fopen(path, "rb");
if(fp == NULL){
return -1;
}else{
int readlen;
while((readlen = fread(buf, 1, HTTP_BUF_LEN, fp)) > 0)
if(send(s, buf, readlen, 0, TIMEOUT_NOTUSE)<0){
break;
}
}
fclose(fp);
return 0;
}
void httpd_task(intptr_t exinf){
LOG("httpd start");
uint8_t clientaddr[IP_ADDR_LEN];
uint16_t clientport;
static char buf[512];
static char path_buf[256];
int s = socket(SOCK_STREAM);
bind(s, 80);
if(listen(s, 10)<0){
LOG("httpd: listen() failed.");
return;
}
while(true){
int s2;
if((s2=accept(s, clientaddr, &clientport, TIMEOUT_NOTUSE))<0){
LOG("httpd: accept() failed.");
continue;
}
if(recv_line(s2, buf, sizeof(buf), 0, 200)>0){
char *method = strtok(buf, " ");
if(strncmp(method, "GET", 3) == 0){
char *path = strtok(NULL, " ");
if(strcmp("/", path) == 0){
path = "/index.html";
}
sprintf(path_buf, "%s%s", DOCUMENT_ROOT, path+1);
//LOG("httpd: method:%s, path:%s", method, path_buf);
FILE *fp = fopen(path_buf, "rb"); //pathに1加えることで先頭の/を取り除く
if(fp == NULL){
sprintf(path_buf, "%s%s", ERROR_ROOT, "404.html");
http_respond(s2, "400 Not Found", get_content_type("html"), path_buf);
}else{
char *ext; //拡張子を探す(手抜きだが、はじめに見つかったドット以降を拡張子とする)
for(ext = path_buf+1; !(*ext == '\0' || *ext == '.'); ext++);
if(*ext!=NULL)
ext++;
http_respond(s2, "200 OK", get_content_type(ext), path_buf);
}
}
}
close(s2);
}
}