98 #define HTTP11_CONNECTIONKEEPALIVE "Connection: keep-alive" 101 #define LWIP_HTTPD_IS_SSI(hs) ((hs)->ssi) 103 #define LWIP_HTTPD_IS_SSI(hs) 0 110 #ifndef HTTP_IS_DATA_VOLATILE 113 #define HTTP_IS_DATA_VOLATILE(hs) ((hs)->ssi ? TCP_WRITE_FLAG_COPY : 0) 116 #define HTTP_IS_DATA_VOLATILE(hs) (((hs->file != NULL) && (hs->handle != NULL) && (hs->file == \ 117 (const char*)hs->handle->data + hs->handle->len - hs->left)) \ 118 ? 0 : TCP_WRITE_FLAG_COPY) 123 #ifndef HTTP_IS_HDR_VOLATILE 124 #define HTTP_IS_HDR_VOLATILE(hs, ptr) 0 128 #define HTTP_DATA_TO_SEND_BREAK 2 129 #define HTTP_DATA_TO_SEND_CONTINUE 1 130 #define HTTP_NO_DATA_TO_SEND 0 138 const default_filename g_psDefaultFilenames[] = {
139 {
"/index.shtml", 1 },
146 #define NUM_DEFAULT_FILENAMES (sizeof(g_psDefaultFilenames) / \ 147 sizeof(default_filename)) 149 #if LWIP_HTTPD_SUPPORT_REQUESTLIST 154 #if LWIP_HTTPD_SUPPORT_POST 159 #if LWIP_HTTPD_DYNAMIC_HEADERS 163 #define NUM_FILE_HDR_STRINGS 3 168 #define HTTPD_LAST_TAG_PART 0xFFFF 170 enum tag_check_state {
178 struct http_ssi_state {
180 #if !LWIP_HTTPD_SSI_INCLUDE_TAG 181 const char *tag_started;
186 u16_t tag_insert_len;
187 #if LWIP_HTTPD_SSI_MULTIPART 193 enum tag_check_state tag_state;
198 #if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 199 struct http_state *next;
206 #if LWIP_HTTPD_SUPPORT_REQUESTLIST 210 #if LWIP_HTTPD_DYNAMIC_FILE_READ 216 #if LWIP_HTTPD_SUPPORT_11_KEEPALIVE 220 struct http_ssi_state *ssi;
226 #if LWIP_HTTPD_DYNAMIC_HEADERS 227 const char *hdrs[NUM_FILE_HDR_STRINGS];
232 #if LWIP_HTTPD_TIMING 235 #if LWIP_HTTPD_SUPPORT_POST 236 u32_t post_content_len_left;
237 #if LWIP_HTTPD_POST_MANUAL_WND 238 u32_t unrecved_bytes;
245 #if HTTPD_USE_MEM_POOL 247 #define HTTP_ALLOC_HTTP_STATE() (struct http_state *)LWIP_MEMPOOL_ALLOC(HTTPD_STATE) 248 #define HTTP_FREE_HTTP_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_STATE, (x)) 252 #define HTTP_ALLOC_SSI_STATE() (struct http_ssi_state *)LWIP_MEMPOOL_ALLOC(HTTPD_SSI_STATE) 253 #define HTTP_FREE_SSI_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_SSI_STATE, (x)) 256 #define HTTP_ALLOC_HTTP_STATE() (struct http_state *)mem_malloc(sizeof(struct http_state)) 257 #define HTTP_FREE_HTTP_STATE(x) mem_free(x) 259 #define HTTP_ALLOC_SSI_STATE() (struct http_ssi_state *)mem_malloc(sizeof(struct http_ssi_state)) 260 #define HTTP_FREE_SSI_STATE(x) mem_free(x) 264 static err_t http_close_conn(
struct tcp_pcb *pcb,
struct http_state *hs);
265 static err_t http_close_or_abort_conn(
struct tcp_pcb *pcb,
struct http_state *hs,
u8_t abort_conn);
266 static err_t http_find_file(
struct http_state *hs,
const char *uri,
int is_09);
267 static err_t http_init_file(
struct http_state *hs,
struct fs_file *file,
int is_09,
const char *uri,
u8_t tag_check);
268 static err_t http_poll(
void *arg,
struct tcp_pcb *pcb);
269 static u8_t http_check_eof(
struct tcp_pcb *pcb,
struct http_state *hs);
270 #if LWIP_HTTPD_FS_ASYNC_READ 271 static void http_continue(
void *connection);
276 tSSIHandler g_pfnSSIHandler =
NULL;
278 const char **g_ppcTags =
NULL;
280 #define LEN_TAG_LEAD_IN 5 281 const char *
const g_pcTagLeadIn =
"<!--#";
283 #define LEN_TAG_LEAD_OUT 3 284 const char *
const g_pcTagLeadOut =
"-->";
293 #if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 296 static struct http_state *http_connections;
299 #if LWIP_HTTPD_STRNSTR_PRIVATE 302 strnstr(
const char* buffer,
const char* token,
size_t n)
305 int tokenlen = (int)strlen(token);
307 return (
char *)(size_t)buffer;
309 for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) {
310 if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) {
311 return (
char *)(size_t)p;
318 #if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 320 http_kill_oldest_connection(
u8_t ssi_required)
322 struct http_state *hs = http_connections;
323 struct http_state *hs_free_next =
NULL;
324 while(hs && hs->next) {
327 if (hs->next->ssi !=
NULL) {
339 if (hs_free_next !=
NULL) {
341 LWIP_ASSERT(
"hs_free_next->next->pcb != NULL", hs_free_next->next->pcb !=
NULL);
343 http_close_or_abort_conn(hs_free_next->next->pcb, hs_free_next->next, 1);
350 static struct http_ssi_state*
351 http_ssi_state_alloc(
void)
353 struct http_ssi_state *ret = HTTP_ALLOC_SSI_STATE();
354 #if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 356 http_kill_oldest_connection(1);
357 ret = HTTP_ALLOC_SSI_STATE();
361 memset(ret, 0,
sizeof(
struct http_ssi_state));
368 http_ssi_state_free(
struct http_ssi_state *ssi)
371 HTTP_FREE_SSI_STATE(ssi);
379 http_state_init(
struct http_state* hs)
382 memset(hs, 0,
sizeof(
struct http_state));
383 #if LWIP_HTTPD_DYNAMIC_HEADERS 385 hs->hdr_index = NUM_FILE_HDR_STRINGS;
390 static struct http_state*
391 http_state_alloc(
void)
393 struct http_state *ret = HTTP_ALLOC_HTTP_STATE();
394 #if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 396 http_kill_oldest_connection(0);
397 ret = HTTP_ALLOC_HTTP_STATE();
401 http_state_init(ret);
402 #if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 404 if (http_connections ==
NULL) {
405 http_connections = ret;
407 struct http_state *last;
408 for(last = http_connections; last->next !=
NULL; last = last->next);
421 http_state_eof(
struct http_state *hs)
424 #if LWIP_HTTPD_TIMING 428 ms_needed, hs->handle->len, ((((
u32_t)hs->handle->len) * 10) / needed)));
433 #if LWIP_HTTPD_DYNAMIC_FILE_READ 434 if (hs->buf !=
NULL) {
441 http_ssi_state_free(hs->ssi);
445 #if LWIP_HTTPD_SUPPORT_REQUESTLIST 457 http_state_free(
struct http_state *hs)
461 #if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 463 if (http_connections) {
464 if (http_connections == hs) {
465 http_connections = hs->next;
467 struct http_state *last;
468 for(last = http_connections; last->next !=
NULL; last = last->next) {
469 if (last->next == hs) {
470 last->next = hs->next;
477 HTTP_FREE_HTTP_STATE(hs);
491 http_write(
struct tcp_pcb *pcb,
const void* ptr,
u16_t *length,
u8_t apiflags)
501 max_len = tcp_sndbuf(pcb);
505 #ifdef HTTPD_MAX_WRITE_LEN 514 err = tcp_write(pcb, ptr, len, apiflags);
516 if ((tcp_sndbuf(pcb) == 0) ||
524 (
"Send failed, trying less (%d bytes)\n", len));
526 }
while ((err ==
ERR_MEM) && (len > 1));
547 http_close_or_abort_conn(
struct tcp_pcb *pcb,
struct http_state *hs,
u8_t abort_conn)
552 #if LWIP_HTTPD_SUPPORT_POST 554 if ((hs->post_content_len_left != 0)
556 || ((hs->no_auto_wnd != 0) && (hs->unrecved_bytes != 0))
560 http_post_response_filename[0] = 0;
570 tcp_poll(pcb,
NULL, 0);
580 err = tcp_close(pcb);
597 http_close_conn(
struct tcp_pcb *pcb,
struct http_state *hs)
599 return http_close_or_abort_conn(pcb, hs, 0);
606 http_eof(
struct tcp_pcb *pcb,
struct http_state *hs)
609 #if LWIP_HTTPD_SUPPORT_11_KEEPALIVE 610 if (hs->keepalive && !LWIP_HTTPD_IS_SSI(hs)) {
611 #if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 612 struct http_state* next = hs->next;
617 #if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 625 http_close_conn(pcb, hs);
640 extract_uri_parameters(
struct http_state *hs,
char *params)
647 if(!params || (params[0] ==
'\0')) {
659 hs->params[loop] = pair;
666 pair = strchr(pair,
'&');
673 pair = strchr(equals,
' ');
684 equals = strchr(equals,
'=');
687 hs->param_vals[loop] = equals + 1;
689 hs->param_vals[loop] =
NULL;
709 get_tag_insert(
struct http_state *hs)
713 struct http_ssi_state *ssi;
717 #if LWIP_HTTPD_SSI_MULTIPART 718 u16_t current_tag_part = ssi->tag_part;
719 ssi->tag_part = HTTPD_LAST_TAG_PART;
722 if(g_pfnSSIHandler && g_ppcTags && g_iNumTags) {
725 for(loop = 0; loop < g_iNumTags; loop++) {
726 if(strcmp(ssi->tag_name, g_ppcTags[loop]) == 0) {
727 ssi->tag_insert_len = g_pfnSSIHandler(loop, ssi->tag_insert,
730 , current_tag_part, &ssi->tag_part
744 #define UNKNOWN_TAG1_TEXT "<b>***UNKNOWN TAG " 745 #define UNKNOWN_TAG1_LEN 18 746 #define UNKNOWN_TAG2_TEXT "***</b>" 747 #define UNKNOWN_TAG2_LEN 7 750 MEMCPY(ssi->tag_insert, UNKNOWN_TAG1_TEXT, UNKNOWN_TAG1_LEN);
751 MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN], ssi->tag_name, len);
752 MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN + len], UNKNOWN_TAG2_TEXT, UNKNOWN_TAG2_LEN);
753 ssi->tag_insert[UNKNOWN_TAG1_LEN + len + UNKNOWN_TAG2_LEN] = 0;
755 len = strlen(ssi->tag_insert);
757 ssi->tag_insert_len = (
u16_t)len;
761 #if LWIP_HTTPD_DYNAMIC_HEADERS 767 get_http_headers(
struct http_state *pState,
char *pszURI)
779 pState->hdrs[1] = g_psHTTPHeaderStrings[HTTP_HDR_SERVER];
783 if (pszURI ==
NULL) {
784 pState->hdrs[0] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND];
785 pState->hdrs[2] = g_psHTTPHeaderStrings[DEFAULT_404_HTML];
788 pState->hdr_index = 0;
796 if (strstr(pszURI,
"404")) {
797 pState->hdrs[0] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND];
798 }
else if (strstr(pszURI,
"400")) {
799 pState->hdrs[0] = g_psHTTPHeaderStrings[HTTP_HDR_BAD_REQUEST];
800 }
else if (strstr(pszURI,
"501")) {
801 pState->hdrs[0] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_IMPL];
803 pState->hdrs[0] = g_psHTTPHeaderStrings[HTTP_HDR_OK];
808 pszVars = strchr(pszURI,
'?');
816 pszWork = strchr(pszURI,
'.');
818 pszExt = pszWork + 1;
819 pszWork = strchr(pszExt,
'.');
823 for(iLoop = 0; (iLoop < NUM_HTTP_HEADERS) && pszExt; iLoop++) {
825 if(!strcmp(g_psHTTPHeaders[iLoop].extension, pszExt)) {
826 pState->hdrs[2] = g_psHTTPHeaders[iLoop].content_type;
843 pState->hdr_index = NUM_FILE_HDR_STRINGS;
846 if(iLoop == NUM_HTTP_HEADERS) {
848 pState->hdrs[2] = HTTP_HDR_DEFAULT_TYPE;
852 pState->hdr_index = 0;
865 http_send_headers(
struct tcp_pcb *pcb,
struct http_state *hs)
869 u8_t data_to_send = HTTP_NO_DATA_TO_SEND;
870 u16_t hdrlen, sendlen;
873 len = tcp_sndbuf(pcb);
876 while(len && (hs->hdr_index < NUM_FILE_HDR_STRINGS) && sendlen) {
881 hdrlen = (
u16_t)strlen(hs->hdrs[hs->hdr_index]);
884 sendlen = (len < (hdrlen - hs->hdr_pos)) ? len : (hdrlen - hs->hdr_pos);
888 ptr = (
const void *)(hs->hdrs[hs->hdr_index] + hs->hdr_pos);
889 old_sendlen = sendlen;
890 apiflags = HTTP_IS_HDR_VOLATILE(hs, ptr);
891 if (hs->hdr_index < NUM_FILE_HDR_STRINGS - 1) {
892 apiflags |= TCP_WRITE_FLAG_MORE;
894 err = http_write(pcb, ptr, &sendlen, apiflags);
895 if ((err ==
ERR_OK) && (old_sendlen != sendlen)) {
897 data_to_send = HTTP_DATA_TO_SEND_CONTINUE;
898 }
else if (err !=
ERR_OK) {
904 hs->hdr_pos += sendlen;
908 if(hs->hdr_pos == hdrlen) {
915 if ((hs->hdr_index >= NUM_FILE_HDR_STRINGS) && (hs->file ==
NULL)) {
919 if(http_check_eof(pcb, hs)) {
920 data_to_send = HTTP_DATA_TO_SEND_CONTINUE;
927 if((hs->hdr_index < NUM_FILE_HDR_STRINGS) || !hs->file) {
929 return HTTP_DATA_TO_SEND_BREAK;
942 http_check_eof(
struct tcp_pcb *pcb,
struct http_state *hs)
945 #if LWIP_HTTPD_DYNAMIC_FILE_READ 947 #ifdef HTTPD_MAX_WRITE_LEN 953 if (hs->handle ==
NULL) {
959 if (bytes_left <= 0) {
965 #if LWIP_HTTPD_DYNAMIC_FILE_READ 972 count = tcp_sndbuf(pcb);
973 if(bytes_left < count) {
976 #ifdef HTTPD_MAX_WRITE_LEN 979 if (count > max_write_len) {
980 count = max_write_len;
985 if (hs->buf !=
NULL) {
990 }
while (count > 100);
993 if (hs->buf ==
NULL) {
1002 #if LWIP_HTTPD_FS_ASYNC_READ 1003 count = fs_read_async(hs->handle, hs->buf, count, http_continue, hs);
1005 count =
fs_read(hs->handle, hs->buf, count);
1025 hs->ssi->parse_left = count;
1026 hs->ssi->parsed = hs->buf;
1030 LWIP_ASSERT(
"SSI and DYNAMIC_HEADERS turned off but eof not reached", 0);
1041 http_send_data_nonssi(
struct tcp_pcb *pcb,
struct http_state *hs)
1045 u8_t data_to_send = 0;
1051 err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
1058 return data_to_send;
1068 http_send_data_ssi(
struct tcp_pcb *pcb,
struct http_state *hs)
1072 u8_t data_to_send = 0;
1074 struct http_ssi_state *ssi = hs->ssi;
1082 len = tcp_sndbuf(pcb);
1085 if(ssi->parsed > hs->file) {
1088 err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
1096 if(tcp_sndbuf(pcb) == 0) {
1097 return data_to_send;
1105 while((ssi->parse_left) && (err ==
ERR_OK)) {
1107 return data_to_send;
1109 switch(ssi->tag_state) {
1113 if(*ssi->parsed == g_pcTagLeadIn[0]) {
1116 ssi->tag_state = TAG_LEADIN;
1118 #if !LWIP_HTTPD_SSI_INCLUDE_TAG 1119 ssi->tag_started = ssi->parsed;
1133 if(ssi->tag_index == LEN_TAG_LEAD_IN) {
1135 ssi->tag_state = TAG_FOUND;
1138 if(*ssi->parsed == g_pcTagLeadIn[ssi->tag_index]) {
1145 ssi->tag_state = TAG_NONE;
1160 if((ssi->tag_index == 0) && ((*ssi->parsed ==
' ') ||
1161 (*ssi->parsed ==
'\t') || (*ssi->parsed ==
'\n') ||
1162 (*ssi->parsed ==
'\r'))) {
1171 if((*ssi->parsed == g_pcTagLeadOut[0]) ||
1172 (*ssi->parsed ==
' ') || (*ssi->parsed ==
'\t') ||
1173 (*ssi->parsed ==
'\n') || (*ssi->parsed ==
'\r')) {
1175 if(ssi->tag_index == 0) {
1177 ssi->tag_state = TAG_NONE;
1181 ssi->tag_state = TAG_LEADOUT;
1182 LWIP_ASSERT(
"ssi->tag_index <= 0xff", ssi->tag_index <= 0xff);
1183 ssi->tag_name_len = (
u8_t)ssi->tag_index;
1184 ssi->tag_name[ssi->tag_index] =
'\0';
1185 if(*ssi->parsed == g_pcTagLeadOut[0]) {
1194 ssi->tag_name[ssi->tag_index++] = *ssi->parsed;
1197 ssi->tag_state = TAG_NONE;
1211 if((ssi->tag_index == 0) && ((*ssi->parsed ==
' ') ||
1212 (*ssi->parsed ==
'\t') || (*ssi->parsed ==
'\n') ||
1213 (*ssi->parsed ==
'\r'))) {
1221 if(*ssi->parsed == g_pcTagLeadOut[ssi->tag_index]) {
1230 if(ssi->tag_index == (LEN_TAG_LEAD_OUT - 1)) {
1233 #if LWIP_HTTPD_SSI_MULTIPART 1242 ssi->tag_state = TAG_SENDING;
1243 ssi->tag_end = ssi->parsed;
1244 #if !LWIP_HTTPD_SSI_INCLUDE_TAG 1245 ssi->parsed = ssi->tag_started;
1250 if (ssi->tag_end > hs->file) {
1252 #if LWIP_HTTPD_SSI_INCLUDE_TAG 1259 err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
1262 #if !LWIP_HTTPD_SSI_INCLUDE_TAG 1263 if(ssi->tag_started <= hs->file) {
1265 len += ssi->tag_end - ssi->tag_started;
1280 ssi->tag_state = TAG_NONE;
1292 if(ssi->tag_end > hs->file) {
1294 #if LWIP_HTTPD_SSI_INCLUDE_TAG 1297 LWIP_ASSERT(
"hs->started >= hs->file", ssi->tag_started >= hs->file);
1302 err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
1308 #if !LWIP_HTTPD_SSI_INCLUDE_TAG 1309 if(ssi->tag_started <= hs->file) {
1311 len += ssi->tag_end - ssi->tag_started;
1318 #if LWIP_HTTPD_SSI_MULTIPART 1319 if(ssi->tag_index >= ssi->tag_insert_len) {
1321 if (ssi->tag_part != HTTPD_LAST_TAG_PART) {
1330 if(ssi->tag_index < ssi->tag_insert_len) {
1333 len = (ssi->tag_insert_len - ssi->tag_index);
1339 err = http_write(pcb, &(ssi->tag_insert[ssi->tag_index]), &len,
1343 ssi->tag_index += len;
1347 #if LWIP_HTTPD_SSI_MULTIPART 1348 if (ssi->tag_part == HTTPD_LAST_TAG_PART)
1355 ssi->tag_state = TAG_NONE;
1356 #if !LWIP_HTTPD_SSI_INCLUDE_TAG 1357 ssi->parsed = ssi->tag_end;
1372 if((ssi->tag_state != TAG_SENDING) && (ssi->parsed > hs->file)) {
1375 err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
1382 return data_to_send;
1393 http_send(
struct tcp_pcb *pcb,
struct http_state *hs)
1395 u8_t data_to_send = HTTP_NO_DATA_TO_SEND;
1398 (
void*)hs, hs !=
NULL ? (
int)hs->left : 0));
1400 #if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND 1401 if (hs->unrecved_bytes != 0) {
1411 #if LWIP_HTTPD_FS_ASYNC_READ 1414 if (!fs_is_file_ready(hs->handle, http_continue, hs)) {
1419 #if LWIP_HTTPD_DYNAMIC_HEADERS 1421 if(hs->hdr_index < NUM_FILE_HDR_STRINGS) {
1422 data_to_send = http_send_headers(pcb, hs);
1423 if (data_to_send != HTTP_DATA_TO_SEND_CONTINUE) {
1424 return data_to_send;
1431 if (hs->left == 0) {
1432 if (!http_check_eof(pcb, hs)) {
1439 data_to_send = http_send_data_ssi(pcb, hs);
1443 data_to_send = http_send_data_nonssi(pcb, hs);
1454 return data_to_send;
1457 #if LWIP_HTTPD_SUPPORT_EXTSTATUS 1466 http_find_error_file(
struct http_state *hs,
u16_t error_nr)
1468 const char *uri1, *uri2, *uri3;
1471 if (error_nr == 501) {
1474 uri3 =
"/501.shtml";
1479 uri3 =
"/400.shtml";
1481 err =
fs_open(&hs->file_handle, uri1);
1483 err =
fs_open(&hs->file_handle, uri2);
1485 err =
fs_open(&hs->file_handle, uri3);
1493 return http_init_file(hs, &hs->file_handle, 0,
NULL, 0);
1496 #define http_find_error_file(hs, error_nr) ERR_ARG 1507 http_get_404_file(
struct http_state *hs,
const char **uri)
1512 err =
fs_open(&hs->file_handle, *uri);
1516 err =
fs_open(&hs->file_handle, *uri);
1519 *uri =
"/404.shtml";
1520 err =
fs_open(&hs->file_handle, *uri);
1531 return &hs->file_handle;
1534 #if LWIP_HTTPD_SUPPORT_POST 1536 http_handle_post_finished(
struct http_state *hs)
1538 #if LWIP_HTTPD_POST_MANUAL_WND 1541 if (hs->post_finished) {
1544 hs->post_finished = 1;
1548 http_post_response_filename[0] = 0;
1550 return http_find_file(hs, http_post_response_filename, 0);
1563 http_post_rxpbuf(
struct http_state *hs,
struct pbuf *p)
1568 if (hs->post_content_len_left < p->
tot_len) {
1569 hs->post_content_len_left = 0;
1571 hs->post_content_len_left -= p->
tot_len;
1573 err = httpd_post_receive_data(hs, p);
1576 hs->post_content_len_left = 0;
1578 if (hs->post_content_len_left == 0) {
1579 #if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND 1580 if (hs->unrecved_bytes != 0) {
1585 return http_handle_post_finished(hs);
1606 http_post_request(
struct pbuf *inp,
struct http_state *hs,
1607 char *
data,
u16_t data_len,
char *uri,
char *uri_end)
1611 char* crlfcrlf = strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data));
1613 if (crlfcrlf !=
NULL) {
1615 #define HTTP_HDR_CONTENT_LEN "Content-Length: " 1616 #define HTTP_HDR_CONTENT_LEN_LEN 16 1617 #define HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN 10 1618 char *scontent_len = strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1));
1619 if (scontent_len !=
NULL) {
1620 char *scontent_len_end = strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN);
1621 if (scontent_len_end !=
NULL) {
1623 char *conten_len_num = scontent_len + HTTP_HDR_CONTENT_LEN_LEN;
1624 content_len = atoi(conten_len_num);
1625 if (content_len > 0) {
1627 const char *hdr_start_after_uri = uri_end + 1;
1629 u16_t hdr_data_len =
LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri);
1630 u8_t post_auto_wnd = 1;
1631 http_post_response_filename[0] = 0;
1632 err = httpd_post_begin(hs, uri, hdr_start_after_uri, hdr_data_len, content_len,
1636 struct pbuf *q = inp;
1637 u16_t start_offset = hdr_len;
1638 #if LWIP_HTTPD_POST_MANUAL_WND 1639 hs->no_auto_wnd = !post_auto_wnd;
1642 hs->post_content_len_left = (
u32_t)content_len;
1645 while((q !=
NULL) && (q->
len <= start_offset)) {
1646 start_offset -= q->
len;
1652 #if LWIP_HTTPD_POST_MANUAL_WND 1653 if (!post_auto_wnd) {
1655 hs->unrecved_bytes = q->
tot_len;
1659 return http_post_rxpbuf(hs, q);
1665 return http_find_file(hs, http_post_response_filename, 0);
1681 #if LWIP_HTTPD_SUPPORT_REQUESTLIST 1688 #if LWIP_HTTPD_POST_MANUAL_WND 1697 void httpd_post_data_recved(
void *connection,
u16_t recved_len)
1699 struct http_state *hs = (
struct http_state*)connection;
1701 if (hs->no_auto_wnd) {
1702 u16_t len = recved_len;
1703 if (hs->unrecved_bytes >= recved_len) {
1704 hs->unrecved_bytes -= recved_len;
1707 len = (
u16_t)hs->unrecved_bytes;
1708 hs->unrecved_bytes = 0;
1710 if (hs->pcb !=
NULL) {
1712 tcp_recved(hs->pcb, len);
1714 if ((hs->post_content_len_left == 0) && (hs->unrecved_bytes == 0)) {
1716 http_handle_post_finished(hs);
1717 http_send(hs->pcb, hs);
1727 #if LWIP_HTTPD_FS_ASYNC_READ 1732 http_continue(
void *connection)
1734 struct http_state *hs = (
struct http_state*)connection;
1735 if (hs && (hs->pcb) && (hs->handle)) {
1738 if (http_send(hs->pcb, hs)) {
1741 tcp_output(hs->pcb);
1759 http_parse_request(
struct pbuf *inp,
struct http_state *hs,
struct tcp_pcb *pcb)
1764 struct pbuf *p = inp;
1765 #if LWIP_HTTPD_SUPPORT_REQUESTLIST 1768 #if LWIP_HTTPD_SUPPORT_POST 1776 if ((hs->handle !=
NULL) || (hs->file !=
NULL)) {
1783 #if LWIP_HTTPD_SUPPORT_REQUESTLIST 1790 if (hs->req ==
NULL) {
1801 if (hs->req->next !=
NULL) {
1804 data = httpd_req_buf;
1816 if (data_len >= MIN_REQ_LEN) {
1818 crlf = strnstr(data, CRLF, data_len);
1820 #if LWIP_HTTPD_SUPPORT_POST 1825 u16_t left_len, uri_len;
1828 if (!strncmp(data,
"GET ", 4)) {
1832 #if LWIP_HTTPD_SUPPORT_POST 1833 }
else if (!strncmp(data,
"POST ", 5)) {
1846 return http_find_error_file(hs, 501);
1849 left_len = (
u16_t)(data_len - ((sp1 +1) - data));
1850 sp2 = strnstr(sp1 + 1,
" ", left_len);
1851 #if LWIP_HTTPD_SUPPORT_V09 1854 sp2 = strnstr(sp1 + 1, CRLF, left_len);
1856 #if LWIP_HTTPD_SUPPORT_POST 1864 uri_len = (
u16_t)(sp2 - (sp1 + 1));
1865 if ((sp2 != 0) && (sp2 > sp1)) {
1867 if (strnstr(data, CRLF CRLF, data_len) !=
NULL) {
1868 char *uri = sp1 + 1;
1869 #if LWIP_HTTPD_SUPPORT_11_KEEPALIVE 1870 if (!is_09 && strnstr(data, HTTP11_CONNECTIONKEEPALIVE, data_len)) {
1881 #if LWIP_HTTPD_SUPPORT_POST 1883 #if LWIP_HTTPD_SUPPORT_REQUESTLIST 1884 struct pbuf *q = hs->req;
1886 struct pbuf *q = inp;
1888 err = http_post_request(q, hs, data, data_len, uri, sp2);
1902 return http_find_file(hs, uri, is_09);
1911 #if LWIP_HTTPD_SUPPORT_REQUESTLIST 1920 #if LWIP_HTTPD_SUPPORT_POST 1925 return http_find_error_file(hs, 400);
1939 http_find_file(
struct http_state *hs,
const char *uri,
int is_09)
1956 if((uri[0] ==
'/') && (uri[1] == 0)) {
1959 for (loop = 0; loop < NUM_DEFAULT_FILENAMES; loop++) {
1961 err =
fs_open(&hs->file_handle, g_psDefaultFilenames[loop].name);
1962 uri = g_psDefaultFilenames[loop].name;
1964 file = &hs->file_handle;
1967 tag_check = g_psDefaultFilenames[loop].shtml;
1974 file = http_get_404_file(hs, &uri);
1982 params = (
char *)strchr(uri,
'?');
1983 if (params !=
NULL) {
1991 if (g_iNumCGIs && g_pCGIs) {
1992 for (i = 0; i < g_iNumCGIs; i++) {
1993 if (strcmp(uri, g_pCGIs[i].pcCGIName) == 0) {
1998 count = extract_uri_parameters(hs, params);
1999 uri = g_pCGIs[i].pfnCGIHandler(i, count, hs->params,
2009 err =
fs_open(&hs->file_handle, uri);
2011 file = &hs->file_handle;
2013 file = http_get_404_file(hs, &uri);
2020 for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) {
2021 if (strstr(uri, g_pcSSIExtensions[loop])) {
2029 return http_init_file(hs, file, is_09, uri, tag_check);
2044 http_init_file(
struct http_state *hs,
struct fs_file *file,
int is_09,
const char *uri,
u8_t tag_check)
2050 struct http_ssi_state *ssi = http_ssi_state_alloc();
2053 ssi->tag_state = TAG_NONE;
2054 ssi->parsed = file->
data;
2055 ssi->parse_left = file->
len;
2056 ssi->tag_end = file->
data;
2064 hs->file = file->
data;
2066 hs->left = file->
len;
2068 #if LWIP_HTTPD_TIMING 2071 #if !LWIP_HTTPD_DYNAMIC_HEADERS 2072 LWIP_ASSERT(
"HTTP headers not included in file system", hs->handle->http_header_included);
2074 #if LWIP_HTTPD_SUPPORT_V09 2075 if (hs->handle->http_header_included && is_09) {
2078 const char *file_start = strnstr(hs->file, CRLF CRLF, hs->left);
2079 if (file_start !=
NULL) {
2080 size_t diff = file_start + 4 - hs->file;
2082 hs->left -= (
u32_t)diff;
2092 #if LWIP_HTTPD_DYNAMIC_HEADERS 2095 if ((hs->handle ==
NULL) || !hs->handle->http_header_included) {
2096 get_http_headers(hs, (
char*)uri);
2109 http_err(
void *arg,
err_t err)
2111 struct http_state *hs = (
struct http_state *)arg;
2117 http_state_free(hs);
2126 http_sent(
void *arg,
struct tcp_pcb *pcb,
u16_t len)
2128 struct http_state *hs = (
struct http_state *)arg;
2153 http_poll(
void *arg,
struct tcp_pcb *pcb)
2155 struct http_state *hs = (
struct http_state *)arg;
2157 (
void*)pcb, (
void*)hs, tcp_debug_state_str(pcb->state)));
2163 closed = http_close_conn(pcb,
NULL);
2165 #if LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR 2176 http_close_conn(pcb, hs);
2183 if(hs && (hs->handle)) {
2185 if(http_send(pcb, hs)) {
2201 http_recv(
void *arg,
struct tcp_pcb *pcb,
struct pbuf *p,
err_t err)
2203 struct http_state *hs = (
struct http_state *)arg;
2218 http_close_conn(pcb, hs);
2222 #if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND 2223 if (hs->no_auto_wnd) {
2224 hs->unrecved_bytes += p->
tot_len;
2232 #if LWIP_HTTPD_SUPPORT_POST 2233 if (hs->post_content_len_left > 0) {
2237 http_post_rxpbuf(hs, p);
2239 if (hs->post_content_len_left == 0) {
2247 if (hs->handle ==
NULL) {
2248 err_t parsed = http_parse_request(p, hs, pcb);
2251 #if LWIP_HTTPD_SUPPORT_REQUESTLIST 2254 if (hs->req !=
NULL) {
2262 #if LWIP_HTTPD_SUPPORT_POST 2263 if (hs->post_content_len_left == 0)
2269 }
else if (parsed ==
ERR_ARG) {
2271 http_close_conn(pcb, hs);
2286 http_accept(
void *arg,
struct tcp_pcb *pcb,
err_t err)
2288 struct http_state *hs;
2289 struct tcp_pcb_listen *lpcb = (
struct tcp_pcb_listen*)arg;
2300 hs = http_state_alloc();
2312 tcp_recv(pcb, http_recv);
2313 tcp_err(pcb, http_err);
2315 tcp_sent(pcb, http_sent);
2324 httpd_init_addr(
const ip_addr_t *local_addr)
2326 struct tcp_pcb *pcb;
2335 pcb = tcp_listen_dual(pcb);
2339 tcp_accept(pcb, http_accept);
2350 #if HTTPD_USE_MEM_POOL 2357 httpd_init_addr(IP_ADDR_ANY);
2369 http_set_ssi_handler(tSSIHandler ssi_handler,
const char **tags,
int num_tags)
2375 LWIP_ASSERT(
"invalid number of tags", num_tags > 0);
2377 g_pfnSSIHandler = ssi_handler;
2379 g_iNumTags = num_tags;
2391 http_set_cgi_handlers(
const tCGI *cgis,
int num_handlers)
2394 LWIP_ASSERT(
"invalid number of handlers", num_handlers > 0);
2397 g_iNumCGIs = num_handlers;
#define LWIP_HTTPD_FILE_STATE
#define LWIP_HTTPD_SSI_MULTIPART
int fs_bytes_left(struct fs_file *file)
void mem_free(void *rmem)
#define LWIP_DBG_LEVEL_WARNING
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
#define LWIP_HTTPD_MAX_TAG_NAME_LEN
#define MEMCPY(dst, src, len)
#define LWIP_HTTPD_MAX_TAG_INSERT_LEN
u8_t pbuf_free(struct pbuf *p)
#define HTTPD_SERVER_PORT
#define LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN
#define LWIP_MEMPOOL_INIT(name)
#define LWIP_ASSERT(message, assertion)
#define LWIP_HTTPD_POST_MANUAL_WND
#define LWIP_MEMPOOL_DECLARE(name, num, size, desc)
#define LWIP_HTTPD_MAX_CGI_PARAMETERS
void pbuf_ref(struct pbuf *p)
#define LWIP_HTTPD_REQ_BUFSIZE
#define HTTP_IS_TAG_VOLATILE(ptr)
#define LWIP_HTTPD_REQ_QUEUELEN
void fs_close(struct fs_file *file)
u16_t pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
u8_t pbuf_clen(struct pbuf *p)
#define LWIP_HTTPD_MAX_REQ_LENGTH
void pbuf_cat(struct pbuf *h, struct pbuf *t)
#define HTTPD_MAX_RETRIES
void * mem_malloc(mem_size_t size)
#define HTTPD_DEBUG_TIMING
#define HTTPD_POLL_INTERVAL
struct fs_file * fs_open(const char *name)
#define HTTPD_MAX_WRITE_LEN(pcb)
#define LWIP_DEBUGF(debug, message)
#define LWIP_UNUSED_ARG(x)
int fs_read(struct fs_file *file, char *buffer, int count)