101#if HTTPD_ENABLE_HTTPS
104#ifdef LWIP_HOOK_FILENAME
105#include LWIP_HOOK_FILENAME
115#if LWIP_TCP && LWIP_CALLBACK_API
121#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
122#define HTTP11_CONNECTIONKEEPALIVE "Connection: keep-alive"
123#define HTTP11_CONNECTIONKEEPALIVE2 "Connection: Keep-Alive"
126#if LWIP_HTTPD_DYNAMIC_FILE_READ
127#define HTTP_IS_DYNAMIC_FILE(hs) ((hs)->buf != NULL)
129#define HTTP_IS_DYNAMIC_FILE(hs) 0
134#ifndef HTTP_IS_DATA_VOLATILE
136#define HTTP_IS_DATA_VOLATILE(hs) (HTTP_IS_DYNAMIC_FILE(hs) ? TCP_WRITE_FLAG_COPY : 0)
139#ifndef HTTP_IS_HDR_VOLATILE
140#define HTTP_IS_HDR_VOLATILE(hs, ptr) 0
144#define HTTP_DATA_TO_SEND_FREED 3
145#define HTTP_DATA_TO_SEND_BREAK 2
146#define HTTP_DATA_TO_SEND_CONTINUE 1
147#define HTTP_NO_DATA_TO_SEND 0
154static const default_filename httpd_default_filenames[] = {
155 {
"/index.shtml", 1 },
162#define NUM_DEFAULT_FILENAMES LWIP_ARRAYSIZE(httpd_default_filenames)
164#if LWIP_HTTPD_SUPPORT_REQUESTLIST
169#if LWIP_HTTPD_SUPPORT_POST
170#if LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN > LWIP_HTTPD_MAX_REQUEST_URI_LEN
171#define LWIP_HTTPD_URI_BUF_LEN LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN
174#ifndef LWIP_HTTPD_URI_BUF_LEN
175#define LWIP_HTTPD_URI_BUF_LEN LWIP_HTTPD_MAX_REQUEST_URI_LEN
177#if LWIP_HTTPD_URI_BUF_LEN
180static char http_uri_buf[LWIP_HTTPD_URI_BUF_LEN + 1];
183#if LWIP_HTTPD_DYNAMIC_HEADERS
187#define NUM_FILE_HDR_STRINGS 5
188#define HDR_STRINGS_IDX_HTTP_STATUS 0
189#define HDR_STRINGS_IDX_SERVER_NAME 1
190#define HDR_STRINGS_IDX_CONTENT_LEN_KEEPALIVE 2
191#define HDR_STRINGS_IDX_CONTENT_LEN_NR 3
192#define HDR_STRINGS_IDX_CONTENT_TYPE 4
195#define LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET 3
196#ifndef LWIP_HTTPD_MAX_CONTENT_LEN_SIZE
199#define LWIP_HTTPD_MAX_CONTENT_LEN_SIZE (9 + LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET)
205#define HTTPD_LAST_TAG_PART 0xFFFF
207enum tag_check_state {
215struct http_ssi_state {
217#if !LWIP_HTTPD_SSI_INCLUDE_TAG
218 const char *tag_started;
223 u16_t tag_insert_len;
224#if LWIP_HTTPD_SSI_MULTIPART
231 enum tag_check_state tag_state;
234struct http_ssi_tag_description {
236 const char *lead_out;
242#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
243 struct http_state *
next;
250#if LWIP_HTTPD_SUPPORT_REQUESTLIST
254#if LWIP_HTTPD_DYNAMIC_FILE_READ
260#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
264 struct http_ssi_state *ssi;
270#if LWIP_HTTPD_DYNAMIC_HEADERS
271 const char *hdrs[NUM_FILE_HDR_STRINGS];
272 char hdr_content_len[LWIP_HTTPD_MAX_CONTENT_LEN_SIZE];
280#if LWIP_HTTPD_SUPPORT_POST
281 u32_t post_content_len_left;
282#if LWIP_HTTPD_POST_MANUAL_WND
283 u32_t unrecved_bytes;
290#if HTTPD_USE_MEM_POOL
291LWIP_MEMPOOL_DECLARE(HTTPD_STATE, MEMP_NUM_PARALLEL_HTTPD_CONNS,
sizeof(
struct http_state),
"HTTPD_STATE")
293LWIP_MEMPOOL_DECLARE(HTTPD_SSI_STATE, MEMP_NUM_PARALLEL_HTTPD_SSI_CONNS,
sizeof(
struct http_ssi_state),
"HTTPD_SSI_STATE")
294#define HTTP_FREE_SSI_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_SSI_STATE, (x))
295#define HTTP_ALLOC_SSI_STATE() (struct http_ssi_state *)LWIP_MEMPOOL_ALLOC(HTTPD_SSI_STATE)
297#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)LWIP_MEMPOOL_ALLOC(HTTPD_STATE)
298#define HTTP_FREE_HTTP_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_STATE, (x))
300#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)mem_malloc(sizeof(struct http_state))
301#define HTTP_FREE_HTTP_STATE(x) mem_free(x)
303#define HTTP_ALLOC_SSI_STATE() (struct http_ssi_state *)mem_malloc(sizeof(struct http_ssi_state))
304#define HTTP_FREE_SSI_STATE(x) mem_free(x)
308static err_t http_close_conn(
struct altcp_pcb *pcb,
struct http_state *hs);
309static err_t http_close_or_abort_conn(
struct altcp_pcb *pcb,
struct http_state *hs,
u8_t abort_conn);
310static err_t http_find_file(
struct http_state *hs,
const char *
uri,
int is_09);
313static u8_t http_check_eof(
struct altcp_pcb *pcb,
struct http_state *hs);
314#if LWIP_HTTPD_FS_ASYNC_READ
315static void http_continue(
void *connection);
320static tSSIHandler httpd_ssi_handler;
321#if !LWIP_HTTPD_SSI_RAW
322static int httpd_num_tags;
323static const char **httpd_tags;
329const struct http_ssi_tag_description http_ssi_tag_desc[] = {
338static const tCGI *httpd_cgis;
339static int httpd_num_cgis;
340static int http_cgi_paramcount;
341#define http_cgi_params hs->params
342#define http_cgi_param_vals hs->param_vals
343#elif LWIP_HTTPD_CGI_SSI
348#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
351static struct http_state *http_connections;
354http_add_connection(
struct http_state *hs)
357 hs->next = http_connections;
358 http_connections = hs;
362http_remove_connection(
struct http_state *hs)
365 if (http_connections) {
366 if (http_connections == hs) {
367 http_connections = hs->next;
369 struct http_state *
last;
371 if (
last->next == hs) {
372 last->next = hs->next;
381http_kill_oldest_connection(
u8_t ssi_required)
383 struct http_state *hs = http_connections;
384 struct http_state *hs_free_next =
NULL;
385 while (hs && hs->next) {
388 if (hs->next->ssi !=
NULL) {
401 if (hs_free_next !=
NULL) {
403 LWIP_ASSERT(
"hs_free_next->next->pcb != NULL", hs_free_next->next->pcb !=
NULL);
405 http_close_or_abort_conn(hs_free_next->next->pcb, hs_free_next->next, 1);
410#define http_add_connection(hs)
411#define http_remove_connection(hs)
417static struct http_ssi_state *
418http_ssi_state_alloc(
void)
420 struct http_ssi_state *
ret = HTTP_ALLOC_SSI_STATE();
421#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
423 http_kill_oldest_connection(1);
424 ret = HTTP_ALLOC_SSI_STATE();
428 memset(
ret, 0,
sizeof(
struct http_ssi_state));
435http_ssi_state_free(
struct http_ssi_state *ssi)
438 HTTP_FREE_SSI_STATE(ssi);
446http_state_init(
struct http_state *hs)
449 memset(hs, 0,
sizeof(
struct http_state));
450#if LWIP_HTTPD_DYNAMIC_HEADERS
452 hs->hdr_index = NUM_FILE_HDR_STRINGS;
457static struct http_state *
458http_state_alloc(
void)
460 struct http_state *
ret = HTTP_ALLOC_HTTP_STATE();
461#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
463 http_kill_oldest_connection(0);
464 ret = HTTP_ALLOC_HTTP_STATE();
468 http_state_init(
ret);
469 http_add_connection(
ret);
478http_state_eof(
struct http_state *hs)
485 ms_needed, hs->handle->len, ((((
u32_t)hs->handle->len) * 10) / needed)));
490#if LWIP_HTTPD_DYNAMIC_FILE_READ
491 if (hs->buf !=
NULL) {
498 http_ssi_state_free(hs->ssi);
502#if LWIP_HTTPD_SUPPORT_REQUESTLIST
514http_state_free(
struct http_state *hs)
518 http_remove_connection(hs);
519 HTTP_FREE_HTTP_STATE(hs);
547#ifdef HTTPD_MAX_WRITE_LEN
566 (
"Send failed, trying less (%d bytes)\n",
len));
578#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
596http_close_or_abort_conn(
struct altcp_pcb *pcb,
struct http_state *hs,
u8_t abort_conn)
601#if LWIP_HTTPD_SUPPORT_POST
603 if ((hs->post_content_len_left != 0)
605 || ((hs->no_auto_wnd != 0) && (hs->unrecved_bytes != 0))
610 httpd_post_finished(hs, http_uri_buf, LWIP_HTTPD_URI_BUF_LEN);
646http_close_conn(
struct altcp_pcb *pcb,
struct http_state *hs)
648 return http_close_or_abort_conn(pcb, hs, 0);
655http_eof(
struct altcp_pcb *pcb,
struct http_state *hs)
658#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
660 http_remove_connection(hs);
667 http_add_connection(hs);
673 http_close_conn(pcb, hs);
677#if LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI
688extract_uri_parameters(
struct http_state *hs,
char *
params)
709 http_cgi_params[loop] =
pair;
734 equals =
strchr(equals,
'=');
737 http_cgi_param_vals[loop] = equals + 1;
739 http_cgi_param_vals[loop] =
NULL;
759get_tag_insert(
struct http_state *hs)
761#if LWIP_HTTPD_SSI_RAW
767 struct http_ssi_state *ssi;
768#if LWIP_HTTPD_SSI_MULTIPART
769 u16_t current_tag_part;
775#if LWIP_HTTPD_SSI_MULTIPART
776 current_tag_part = ssi->tag_part;
777 ssi->tag_part = HTTPD_LAST_TAG_PART;
779#if LWIP_HTTPD_SSI_RAW
783 if (httpd_ssi_handler
785 && httpd_tags && httpd_num_tags
790#if LWIP_HTTPD_SSI_RAW
793 for (
tag = 0;
tag < httpd_num_tags;
tag++) {
794 if (
strcmp(ssi->tag_name, httpd_tags[
tag]) == 0)
797 ssi->tag_insert_len = httpd_ssi_handler(
tag, ssi->tag_insert,
800 , current_tag_part, &ssi->tag_part
803 , (hs->handle ? hs->handle->state :
NULL)
806#if LWIP_HTTPD_SSI_RAW
807 if (ssi->tag_insert_len != HTTPD_SSI_TAG_UNKNOWN)
819#define UNKNOWN_TAG1_TEXT "<b>***UNKNOWN TAG "
820#define UNKNOWN_TAG1_LEN 18
821#define UNKNOWN_TAG2_TEXT "***</b>"
822#define UNKNOWN_TAG2_LEN 7
825 MEMCPY(ssi->tag_insert, UNKNOWN_TAG1_TEXT, UNKNOWN_TAG1_LEN);
826 MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN], ssi->tag_name,
len);
827 MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN +
len], UNKNOWN_TAG2_TEXT, UNKNOWN_TAG2_LEN);
828 ssi->tag_insert[UNKNOWN_TAG1_LEN +
len + UNKNOWN_TAG2_LEN] = 0;
836#if LWIP_HTTPD_DYNAMIC_HEADERS
842get_http_headers(
struct http_state *hs,
const char *
uri)
851 hs->hdrs[HDR_STRINGS_IDX_SERVER_NAME] = g_psHTTPHeaderStrings[HTTP_HDR_SERVER];
852 hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEEPALIVE] =
NULL;
853 hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_NR] =
NULL;
858 hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND];
859#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
861 hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaderStrings[DEFAULT_404_HTML_PERSISTENT];
865 hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaderStrings[DEFAULT_404_HTML];
878 hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND];
879 }
else if (
memcmp(
uri,
"/400.", 5) == 0) {
880 hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_BAD_REQUEST];
881 }
else if (
memcmp(
uri,
"/501.", 5) == 0) {
882 hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_IMPL];
884 hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_OK];
919#if LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI
926 hs->hdr_index = NUM_FILE_HDR_STRINGS;
933 hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaders[
content_type].content_type;
936 hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = HTTP_HDR_APP;
939 hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = HTTP_HDR_DEFAULT_TYPE;
948get_http_content_length(
struct http_state *hs)
950 u8_t add_content_len = 0;
952 LWIP_ASSERT(
"already been here?", hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEEPALIVE] ==
NULL);
963 if (add_content_len) {
965 lwip_itoa(hs->hdr_content_len, (
size_t)LWIP_HTTPD_MAX_CONTENT_LEN_SIZE,
968 if (
len <= LWIP_HTTPD_MAX_CONTENT_LEN_SIZE - LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) {
970 hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_NR] = hs->hdr_content_len;
975#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
976 if (add_content_len) {
977 hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_KEEPALIVE_LEN];
979 hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE];
983 if (add_content_len) {
984 hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH];
998http_send_headers(
struct altcp_pcb *pcb,
struct http_state *hs)
1002 u8_t data_to_send = HTTP_NO_DATA_TO_SEND;
1003 u16_t hdrlen, sendlen;
1005 if (hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEEPALIVE] ==
NULL) {
1007 get_http_content_length(hs);
1014 while (
len && (hs->hdr_index < NUM_FILE_HDR_STRINGS) && sendlen) {
1022 sendlen = (
len < (hdrlen - hs->hdr_pos)) ?
len : (hdrlen - hs->hdr_pos);
1026 ptr = (
const void *)(hs->hdrs[hs->hdr_index] + hs->hdr_pos);
1027 old_sendlen = sendlen;
1028 apiflags = HTTP_IS_HDR_VOLATILE(hs,
ptr);
1029 if (hs->hdr_index == HDR_STRINGS_IDX_CONTENT_LEN_NR) {
1031 apiflags |= TCP_WRITE_FLAG_COPY;
1033 if (hs->hdr_index < NUM_FILE_HDR_STRINGS - 1) {
1034 apiflags |= TCP_WRITE_FLAG_MORE;
1036 err = http_write(pcb,
ptr, &sendlen, apiflags);
1037 if ((
err ==
ERR_OK) && (old_sendlen != sendlen)) {
1039 data_to_send = HTTP_DATA_TO_SEND_CONTINUE;
1046 hs->hdr_pos += sendlen;
1050 if (hs->hdr_pos == hdrlen) {
1054 while ((hs->hdr_index < NUM_FILE_HDR_STRINGS) &&
1055 (hs->hdrs[hs->hdr_index] ==
NULL)) {
1062 if ((hs->hdr_index >= NUM_FILE_HDR_STRINGS) && (hs->file ==
NULL)) {
1066 if (http_check_eof(pcb, hs)) {
1067 data_to_send = HTTP_DATA_TO_SEND_BREAK;
1071 return HTTP_DATA_TO_SEND_FREED;
1078 if ((hs->hdr_index < NUM_FILE_HDR_STRINGS) || !hs->file) {
1080 return HTTP_DATA_TO_SEND_BREAK;
1082 return data_to_send;
1093http_check_eof(
struct altcp_pcb *pcb,
struct http_state *hs)
1096#if LWIP_HTTPD_DYNAMIC_FILE_READ
1098#ifdef HTTPD_MAX_WRITE_LEN
1104 if (hs->handle ==
NULL) {
1110 if (bytes_left <= 0) {
1116#if LWIP_HTTPD_DYNAMIC_FILE_READ
1124 if (bytes_left <
count) {
1127#ifdef HTTPD_MAX_WRITE_LEN
1130 if (
count > max_write_len) {
1131 count = max_write_len;
1136 if (hs->buf !=
NULL) {
1137 hs->buf_len =
count;
1141 }
while (
count > 100);
1144 if (hs->buf ==
NULL) {
1153#if LWIP_HTTPD_FS_ASYNC_READ
1154 count = fs_read_async(hs->handle, hs->buf,
count, http_continue, hs);
1176 hs->ssi->parse_left =
count;
1177 hs->ssi->parsed = hs->buf;
1181 LWIP_ASSERT(
"SSI and DYNAMIC_HEADERS turned off but eof not reached", 0);
1192http_send_data_nonssi(
struct altcp_pcb *pcb,
struct http_state *hs)
1196 u8_t data_to_send = 0;
1202 err = http_write(pcb, hs->file, &
len, HTTP_IS_DATA_VOLATILE(hs));
1209 return data_to_send;
1219http_send_data_ssi(
struct altcp_pcb *pcb,
struct http_state *hs)
1223 u8_t data_to_send = 0;
1226 struct http_ssi_state *ssi = hs->ssi;
1237 if (ssi->parsed > hs->file) {
1240 err = http_write(pcb, hs->file, &
len, HTTP_IS_DATA_VOLATILE(hs));
1249 return data_to_send;
1257 while (((ssi->tag_state == TAG_SENDING) || ssi->parse_left) && (
err ==
ERR_OK)) {
1259 return data_to_send;
1261 switch (ssi->tag_state) {
1265 for (tag_type = 0; tag_type <
LWIP_ARRAYSIZE(http_ssi_tag_desc); tag_type++) {
1266 if (*ssi->parsed == http_ssi_tag_desc[tag_type].lead_in[0]) {
1269 ssi->tag_type = tag_type;
1270 ssi->tag_state = TAG_LEADIN;
1272 #if !LWIP_HTTPD_SSI_INCLUDE_TAG
1273 ssi->tag_started = ssi->parsed;
1289 if (http_ssi_tag_desc[ssi->tag_type].lead_in[ssi->tag_index] == 0) {
1291 ssi->tag_state = TAG_FOUND;
1294 if (*ssi->parsed == http_ssi_tag_desc[ssi->tag_type].lead_in[ssi->tag_index]) {
1304#if LWIP_HTTPD_DYNAMIC_FILE_READ && !LWIP_HTTPD_SSI_INCLUDE_TAG
1305 if ((ssi->tag_state ==
TAG_NONE) &&
1306 (ssi->parsed - hs->file < ssi->tag_index)) {
1307 for(
u16_t i = 0;
i < ssi->tag_index;
i++) {
1308 ssi->tag_insert[
i] = http_ssi_tag_desc[ssi->tag_type].lead_in[
i];
1310 ssi->tag_insert_len = ssi->tag_index;
1311 hs->file += ssi->parsed - hs->file;
1312 hs->left -= ssi->parsed - hs->file;
1313 ssi->tag_end = hs->file;
1315 ssi->tag_state = TAG_SENDING;
1332 if ((ssi->tag_index == 0) && ((*ssi->parsed ==
' ') ||
1333 (*ssi->parsed ==
'\t') || (*ssi->parsed ==
'\n') ||
1334 (*ssi->parsed ==
'\r'))) {
1343 if ((*ssi->parsed == http_ssi_tag_desc[ssi->tag_type].lead_out[0]) ||
1344 (*ssi->parsed ==
' ') || (*ssi->parsed ==
'\t') ||
1345 (*ssi->parsed ==
'\n') || (*ssi->parsed ==
'\r')) {
1347 if (ssi->tag_index == 0) {
1353 ssi->tag_state = TAG_LEADOUT;
1354 LWIP_ASSERT(
"ssi->tag_index <= 0xff", ssi->tag_index <= 0xff);
1355 ssi->tag_name_len = (
u8_t)ssi->tag_index;
1356 ssi->tag_name[ssi->tag_index] =
'\0';
1357 if (*ssi->parsed == http_ssi_tag_desc[ssi->tag_type].lead_out[0]) {
1366 ssi->tag_name[ssi->tag_index++] = *ssi->parsed;
1383 if ((ssi->tag_index == 0) && ((*ssi->parsed ==
' ') ||
1384 (*ssi->parsed ==
'\t') || (*ssi->parsed ==
'\n') ||
1385 (*ssi->parsed ==
'\r'))) {
1393 if (*ssi->parsed == http_ssi_tag_desc[ssi->tag_type].lead_out[ssi->tag_index]) {
1403 if (http_ssi_tag_desc[ssi->tag_type].lead_out[ssi->tag_index] == 0) {
1406#if LWIP_HTTPD_SSI_MULTIPART
1415 ssi->tag_state = TAG_SENDING;
1416 ssi->tag_end = ssi->parsed;
1417#if !LWIP_HTTPD_SSI_INCLUDE_TAG
1418 ssi->parsed = ssi->tag_started;
1423 if (ssi->tag_end > hs->file) {
1425#if LWIP_HTTPD_SSI_INCLUDE_TAG
1432 err = http_write(pcb, hs->file, &
len, HTTP_IS_DATA_VOLATILE(hs));
1435#if !LWIP_HTTPD_SSI_INCLUDE_TAG
1436 if (ssi->tag_started <= hs->file) {
1438 len += (
u16_t)(ssi->tag_end - ssi->tag_started);
1463 if (ssi->tag_end > hs->file) {
1465#if LWIP_HTTPD_SSI_INCLUDE_TAG
1468 LWIP_ASSERT(
"hs->started >= hs->file", ssi->tag_started >= hs->file);
1473 err = http_write(pcb, hs->file, &
len, HTTP_IS_DATA_VOLATILE(hs));
1479#if !LWIP_HTTPD_SSI_INCLUDE_TAG
1480 if (ssi->tag_started <= hs->file) {
1482 len += (
u16_t)(ssi->tag_end - ssi->tag_started);
1489#if LWIP_HTTPD_SSI_MULTIPART
1490 if (ssi->tag_index >= ssi->tag_insert_len) {
1492 if (ssi->tag_part != HTTPD_LAST_TAG_PART) {
1501 if (ssi->tag_index < ssi->tag_insert_len) {
1504 len = (ssi->tag_insert_len - ssi->tag_index);
1510 err = http_write(pcb, &(ssi->tag_insert[ssi->tag_index]), &
len,
1514 ssi->tag_index +=
len;
1518#if LWIP_HTTPD_SSI_MULTIPART
1519 if (ssi->tag_part == HTTPD_LAST_TAG_PART)
1527#if !LWIP_HTTPD_SSI_INCLUDE_TAG
1528 ssi->parsed = ssi->tag_end;
1542 if ((ssi->tag_state != TAG_SENDING) && (ssi->parsed > hs->file)) {
1543#if LWIP_HTTPD_DYNAMIC_FILE_READ && !LWIP_HTTPD_SSI_INCLUDE_TAG
1544 if ((ssi->tag_state !=
TAG_NONE) && (ssi->tag_started > ssi->tag_end)) {
1547 len = (
u16_t)(ssi->tag_started - hs->file);
1548 hs->left -= (ssi->parsed - ssi->tag_started);
1549 ssi->parsed = ssi->tag_started;
1550 ssi->tag_started = hs->buf;
1557 err = http_write(pcb, hs->file, &
len, HTTP_IS_DATA_VOLATILE(hs));
1564 return data_to_send;
1575http_send(
struct altcp_pcb *pcb,
struct http_state *hs)
1577 u8_t data_to_send = HTTP_NO_DATA_TO_SEND;
1580 (
void *)hs, hs !=
NULL ? (
int)hs->left : 0));
1582#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
1583 if (hs->unrecved_bytes != 0) {
1593#if LWIP_HTTPD_FS_ASYNC_READ
1596 if (!fs_is_file_ready(hs->handle, http_continue, hs)) {
1601#if LWIP_HTTPD_DYNAMIC_HEADERS
1603 if (hs->hdr_index < NUM_FILE_HDR_STRINGS) {
1604 data_to_send = http_send_headers(pcb, hs);
1605 if ((data_to_send == HTTP_DATA_TO_SEND_FREED) ||
1606 ((data_to_send != HTTP_DATA_TO_SEND_CONTINUE) &&
1607 (hs->hdr_index < NUM_FILE_HDR_STRINGS))) {
1608 return data_to_send;
1614 if (hs->ssi && (hs->ssi->tag_state == TAG_SENDING)) {
1620 if (hs->left == 0) {
1621 if (!http_check_eof(pcb, hs)) {
1628 data_to_send = http_send_data_ssi(pcb, hs);
1629 if (hs->ssi->tag_state == TAG_SENDING) {
1630 return data_to_send;
1635 data_to_send = http_send_data_nonssi(pcb, hs);
1646 return data_to_send;
1649#if LWIP_HTTPD_SUPPORT_EXTSTATUS
1658http_find_error_file(
struct http_state *hs,
u16_t error_nr)
1660 const char *
uri, *uri1, *uri2, *uri3;
1662 if (error_nr == 501) {
1665 uri3 =
"/501.shtml";
1670 uri3 =
"/400.shtml";
1683 return http_init_file(hs, &hs->file_handle, 0,
uri, 0,
NULL);
1686#define http_find_error_file(hs, error_nr) ERR_ARG
1697http_get_404_file(
struct http_state *hs,
const char **
uri)
1709 *
uri =
"/404.shtml";
1721 return &hs->file_handle;
1724#if LWIP_HTTPD_SUPPORT_POST
1726http_handle_post_finished(
struct http_state *hs)
1728#if LWIP_HTTPD_POST_MANUAL_WND
1731 if (hs->post_finished) {
1734 hs->post_finished = 1;
1738 http_uri_buf[0] = 0;
1739 httpd_post_finished(hs, http_uri_buf, LWIP_HTTPD_URI_BUF_LEN);
1740 return http_find_file(hs, http_uri_buf, 0);
1753http_post_rxpbuf(
struct http_state *hs,
struct pbuf *
p)
1759 if (hs->post_content_len_left <
p->tot_len) {
1760 hs->post_content_len_left = 0;
1762 hs->post_content_len_left -=
p->tot_len;
1765#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
1767 hs->unrecved_bytes++;
1770 err = httpd_post_receive_data(hs,
p);
1774#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
1775 hs->unrecved_bytes--;
1779 hs->post_content_len_left = 0;
1781 if (hs->post_content_len_left == 0) {
1782#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
1783 if (hs->unrecved_bytes != 0) {
1788 return http_handle_post_finished(hs);
1809http_post_request(
struct pbuf *inp,
struct http_state *hs,
1814 char *crlfcrlf =
lwip_strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 -
data));
1816 if (crlfcrlf !=
NULL) {
1818#define HTTP_HDR_CONTENT_LEN "Content-Length: "
1819#define HTTP_HDR_CONTENT_LEN_LEN 16
1820#define HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN 10
1821 char *scontent_len =
lwip_strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1));
1822 if (scontent_len !=
NULL) {
1823 char *scontent_len_end =
lwip_strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN);
1824 if (scontent_len_end !=
NULL) {
1826 char *content_len_num = scontent_len + HTTP_HDR_CONTENT_LEN_LEN;
1827 content_len =
atoi(content_len_num);
1828 if (content_len == 0) {
1830 if ((content_len_num[0] !=
'0') || (content_len_num[1] !=
'\r')) {
1834 if (content_len >= 0) {
1836 const char *hdr_start_after_uri = uri_end + 1;
1839 u8_t post_auto_wnd = 1;
1840 http_uri_buf[0] = 0;
1843 err = httpd_post_begin(hs,
uri, hdr_start_after_uri, hdr_data_len, content_len,
1844 http_uri_buf, LWIP_HTTPD_URI_BUF_LEN, &post_auto_wnd);
1847 struct pbuf *
q = inp;
1848 u16_t start_offset = hdr_len;
1849#if LWIP_HTTPD_POST_MANUAL_WND
1850 hs->no_auto_wnd = !post_auto_wnd;
1853 hs->post_content_len_left = (
u32_t)content_len;
1856 while ((
q !=
NULL) && (
q->len <= start_offset)) {
1857 start_offset -=
q->
len;
1863#if LWIP_HTTPD_POST_MANUAL_WND
1864 if (!post_auto_wnd) {
1866 hs->unrecved_bytes =
q->tot_len;
1870 return http_post_rxpbuf(hs,
q);
1871 }
else if (hs->post_content_len_left == 0) {
1873 return http_post_rxpbuf(hs,
q);
1879 return http_find_file(hs, http_uri_buf, 0);
1895#if LWIP_HTTPD_SUPPORT_REQUESTLIST
1902#if LWIP_HTTPD_POST_MANUAL_WND
1913void httpd_post_data_recved(
void *connection,
u16_t recved_len)
1915 struct http_state *hs = (
struct http_state *)connection;
1917 if (hs->no_auto_wnd) {
1919 if (hs->unrecved_bytes >= recved_len) {
1920 hs->unrecved_bytes -= recved_len;
1924 hs->unrecved_bytes = 0;
1926 if (hs->pcb !=
NULL) {
1930 if ((hs->post_content_len_left == 0) && (hs->unrecved_bytes == 0)) {
1932 http_handle_post_finished(hs);
1933 http_send(hs->pcb, hs);
1943#if LWIP_HTTPD_FS_ASYNC_READ
1948http_continue(
void *connection)
1950 struct http_state *hs = (
struct http_state *)connection;
1952 if (hs && (hs->pcb) && (hs->handle)) {
1955 if (http_send(hs->pcb, hs)) {
1976http_parse_request(
struct pbuf *inp,
struct http_state *hs,
struct altcp_pcb *pcb)
1981 struct pbuf *
p = inp;
1982#if LWIP_HTTPD_SUPPORT_REQUESTLIST
1985#if LWIP_HTTPD_SUPPORT_POST
1993 if ((hs->handle !=
NULL) || (hs->file !=
NULL)) {
2000#if LWIP_HTTPD_SUPPORT_REQUESTLIST
2007 if (hs->req ==
NULL) {
2018 if (hs->req->next !=
NULL) {
2021 data = httpd_req_buf;
2025 data = (
char *)
p->payload;
2027 if (
p->len !=
p->tot_len) {
2033 if (data_len >= MIN_REQ_LEN) {
2037#if LWIP_HTTPD_SUPPORT_POST
2042 u16_t left_len, uri_len;
2049#if LWIP_HTTPD_SUPPORT_POST
2063 return http_find_error_file(hs, 501);
2066 left_len = (
u16_t)(data_len - ((sp1 + 1) -
data));
2068#if LWIP_HTTPD_SUPPORT_V09
2073#if LWIP_HTTPD_SUPPORT_POST
2081 uri_len = (
u16_t)(sp2 - (sp1 + 1));
2082 if ((sp2 !=
NULL) && (sp2 > sp1)) {
2085 char *
uri = sp1 + 1;
2086#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
2101#if LWIP_HTTPD_SUPPORT_POST
2103#if LWIP_HTTPD_SUPPORT_REQUESTLIST
2104 struct pbuf *
q = hs->req;
2106 struct pbuf *
q = inp;
2108 err = http_post_request(
q, hs,
data, data_len,
uri, sp2);
2122 return http_find_file(hs,
uri, is_09);
2131#if LWIP_HTTPD_SUPPORT_REQUESTLIST
2140#if LWIP_HTTPD_SUPPORT_POST
2145 return http_find_error_file(hs, 400);
2149#if LWIP_HTTPD_SSI && (LWIP_HTTPD_SSI_BY_FILE_EXTENSION == 1)
2176 for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) {
2200http_find_file(
struct http_state *hs,
const char *
uri,
int is_09)
2216#if LWIP_HTTPD_MAX_REQUEST_URI_LEN
2218 if ((uri_len > 0) && (
uri[uri_len - 1] ==
'/') &&
2219 ((
uri != http_uri_buf) || (uri_len == 1))) {
2220 size_t copy_len =
LWIP_MIN(
sizeof(http_uri_buf) - 1, uri_len - 1);
2223 http_uri_buf[copy_len] = 0;
2226 if ((
uri[0] ==
'/') && (
uri[1] == 0)) {
2230 for (loop = 0; loop < NUM_DEFAULT_FILENAMES; loop++) {
2232#if LWIP_HTTPD_MAX_REQUEST_URI_LEN
2234 size_t len_left =
sizeof(http_uri_buf) - copy_len - 1;
2236 size_t name_len =
strlen(httpd_default_filenames[loop].
name);
2237 size_t name_copy_len =
LWIP_MIN(len_left, name_len);
2238 MEMCPY(&http_uri_buf[copy_len], httpd_default_filenames[loop].
name, name_copy_len);
2239 http_uri_buf[copy_len + name_copy_len] = 0;
2245 file_name = httpd_default_filenames[loop].name;
2251 file = &hs->file_handle;
2254 tag_check = httpd_default_filenames[loop].shtml;
2271 http_cgi_paramcount = -1;
2273 if (httpd_num_cgis && httpd_cgis) {
2274 for (
i = 0;
i < httpd_num_cgis;
i++) {
2275 if (
strcmp(
uri, httpd_cgis[
i].pcCGIName) == 0) {
2280 http_cgi_paramcount = extract_uri_parameters(hs,
params);
2281 uri = httpd_cgis[
i].pfnCGIHandler(
i, http_cgi_paramcount, hs->params,
2293 file = &hs->file_handle;
2295 file = http_get_404_file(hs, &
uri);
2302#if LWIP_HTTPD_SSI_BY_FILE_EXTENSION
2303 tag_check = http_uri_is_ssi(
file,
uri);
2311 file = http_get_404_file(hs, &
uri);
2313 return http_init_file(hs,
file, is_09,
uri, tag_check,
params);
2329http_init_file(
struct http_state *hs,
struct fs_file *
file,
int is_09,
const char *
uri,
2332#if !LWIP_HTTPD_SUPPORT_V09
2337#if !LWIP_HTTPD_DYNAMIC_FILE_READ
2344 struct http_ssi_state *ssi = http_ssi_state_alloc();
2348 ssi->parsed =
file->data;
2349 ssi->parse_left =
file->len;
2350 ssi->tag_end =
file->data;
2358#if LWIP_HTTPD_CGI_SSI
2363 if (http_cgi_paramcount >= 0) {
2364 count = http_cgi_paramcount;
2370 httpd_cgi_handler(
file,
uri,
count, http_cgi_params, http_cgi_param_vals
2379 hs->file =
file->data;
2381#if LWIP_HTTPD_CUSTOM_FILES
2391#if LWIP_HTTPD_TIMING
2394#if !LWIP_HTTPD_DYNAMIC_HEADERS
2395 LWIP_ASSERT(
"HTTP headers not included in file system",
2398#if LWIP_HTTPD_SUPPORT_V09
2402 char *file_start =
lwip_strnstr(hs->file, CRLF CRLF, hs->left);
2403 if (file_start !=
NULL) {
2404 int diff = file_start + 4 - hs->file;
2406 hs->left -= (
u32_t)diff;
2416#if LWIP_HTTPD_DYNAMIC_HEADERS
2420 get_http_headers(hs,
uri);
2425#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
2426 if (hs->keepalive) {
2428 if (hs->ssi !=
NULL) {
2433 if ((hs->handle !=
NULL) &&
2450 struct http_state *hs = (
struct http_state *)
arg;
2456 http_state_free(hs);
2467 struct http_state *hs = (
struct http_state *)
arg;
2494 struct http_state *hs = (
struct http_state *)
arg;
2496 (
void *)pcb, (
void *)hs, tcp_debug_state_str(altcp_dbg_get_tcp_state(pcb))));
2502 closed = http_close_conn(pcb,
NULL);
2504#if LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR
2515 http_close_conn(pcb, hs);
2524 if (http_send(pcb, hs)) {
2542 struct http_state *hs = (
struct http_state *)
arg;
2557 http_close_conn(pcb, hs);
2561#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
2562 if (hs->no_auto_wnd) {
2563 hs->unrecved_bytes +=
p->tot_len;
2571#if LWIP_HTTPD_SUPPORT_POST
2572 if (hs->post_content_len_left > 0) {
2576 http_post_rxpbuf(hs,
p);
2578 if (hs->post_content_len_left == 0) {
2586 if (hs->handle ==
NULL) {
2587 err_t parsed = http_parse_request(
p, hs, pcb);
2590#if LWIP_HTTPD_SUPPORT_REQUESTLIST
2593 if (hs->req !=
NULL) {
2601#if LWIP_HTTPD_SUPPORT_POST
2602 if (hs->post_content_len_left == 0)
2608 }
else if (parsed ==
ERR_ARG) {
2610 http_close_conn(pcb, hs);
2627 struct http_state *hs;
2641 hs = http_state_alloc();
2687#if HTTPD_USE_MEM_POOL
2702#if HTTPD_ENABLE_HTTPS
2709httpd_inits(
struct altcp_tls_config *conf)
2731http_set_ssi_handler(tSSIHandler ssi_handler,
const char **
tags,
int num_tags)
2736 httpd_ssi_handler = ssi_handler;
2738#if LWIP_HTTPD_SSI_RAW
2743 LWIP_ASSERT(
"invalid number of tags", num_tags > 0);
2746 httpd_num_tags = num_tags;
2760http_set_cgi_handlers(
const tCGI *cgis,
int num_handlers)
int strcmp(const char *String1, const char *String2)
char * strstr(char *String1, char *String2)
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
ACPI_SIZE strlen(const char *String)
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
char * strchr(const char *String, int ch)
#define altcp_sndqueuelen
#define altcp_nagle_enable
#define altcp_nagle_disable
#define altcp_tcp_new_ip_type
#define LWIP_ARRAYSIZE(x)
#define mem_free(ptr, bsize)
static unsigned int num_handlers(const APPLYSTATEFUNC *funcs)
static const WCHAR crlf[]
static const WCHAR *const ext[]
int fs_bytes_left(struct fs_file *file)
err_t fs_open(struct fs_file *file, const char *name)
void fs_close(struct fs_file *file)
void * mem_malloc(mem_size_t size_in)
#define FS_FILE_FLAGS_CUSTOM
#define FS_FILE_FLAGS_SSI
#define LWIP_DEBUGF(debug, message)
#define LWIP_ASSERT(message, assertion)
#define FS_FILE_FLAGS_HEADER_INCLUDED
#define FS_FILE_FLAGS_HEADER_PERSISTENT
GLuint GLuint GLsizei count
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLdouble GLdouble GLdouble GLdouble q
GLenum const GLfloat * params
GLenum GLuint GLenum GLsizei const GLchar * buf
GLuint GLsizei GLsizei * length
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
#define LWIP_UNUSED_ARG(x)
#define LWIP_DBG_LEVEL_WARNING
#define HTTPD_SERVER_PORT
#define LWIP_HTTPD_MAX_REQ_LENGTH
#define LWIP_HTTPD_SSI_MULTIPART
#define LWIP_HTTPD_SSI_RAW
#define HTTPD_DEBUG_TIMING
#define HTTP_IS_TAG_VOLATILE(ptr)
#define LWIP_HTTPD_POST_MANUAL_WND
#define LWIP_HTTPD_MAX_CGI_PARAMETERS
#define LWIP_HTTPD_REQ_BUFSIZE
#define LWIP_HTTPD_MAX_TAG_INSERT_LEN
#define HTTPD_MAX_WRITE_LEN(pcb)
#define LWIP_HTTPD_MAX_TAG_NAME_LEN
#define HTTPD_POLL_INTERVAL
#define HTTPD_MAX_RETRIES
#define LWIP_HTTPD_FILE_STATE
#define LWIP_HTTPD_REQ_QUEUELEN
#define HTTPD_SERVER_PORT_HTTPS
#define LWIP_ASSERT_CORE_LOCKED()
#define SMEMCPY(dst, src, len)
#define LWIP_MEMPOOL_DECLARE(name, num, size, desc)
#define LWIP_MEMPOOL_INIT(name)
void pbuf_ref(struct pbuf *p)
void pbuf_cat(struct pbuf *h, struct pbuf *t)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u8_t pbuf_free(struct pbuf *p)
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
int lwip_stricmp(const char *str1, const char *str2)
char * lwip_strnstr(const char *buffer, const char *token, size_t n)
void lwip_itoa(char *result, size_t bufsize, int number)
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
#define MEMCPY(DST, SRC, BYTES)
u16_t pbuf_clen(const struct pbuf *p)
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size_decrement)
static unsigned __int64 next
static FILE * file_handle
void fs_read(off_t pos, int size, void *data)