httpd.c
来自「NXPl788上lwip的无操作系统移植,基于Embest开发板」· C语言 代码 · 共 1,866 行 · 第 1/5 页
C
1,866 行
hs->parsed = hs->tag_started;
#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/
/* If there is any unsent data in the buffer prior to the
* tag, we need to send it now. */
if (hs->tag_end > hs->file) {
/* How much of the data can we send? */
#if LWIP_HTTPD_SSI_INCLUDE_TAG
if(len > hs->tag_end - hs->file) {
len = (u16_t)(hs->tag_end - hs->file);
}
#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/
if(len > hs->tag_started - hs->file) {
/* we would include the tag in sending */
len = (u16_t)(hs->tag_started - hs->file);
}
#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/
err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
if (err == ERR_OK) {
data_to_send = true;
#if !LWIP_HTTPD_SSI_INCLUDE_TAG
if(hs->tag_started <= hs->file) {
/* pretend to have sent the tag, too */
len += hs->tag_end - hs->tag_started;
}
#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/
hs->file += len;
hs->left -= len;
}
}
} else {
hs->tag_index++;
}
} else {
/* We found an unexpected character so this is not a tag. Move
* back to idle state. */
hs->parse_left--;
hs->parsed++;
hs->tag_state = TAG_NONE;
}
break;
/*
* We have found a valid tag and are in the process of sending
* data as a result of that discovery. We send either remaining data
* from the file prior to the insert point or the insert string itself.
*/
case TAG_SENDING:
/* Do we have any remaining file data to send from the buffer prior
* to the tag? */
if(hs->tag_end > hs->file) {
/* How much of the data can we send? */
#if LWIP_HTTPD_SSI_INCLUDE_TAG
if(len > hs->tag_end - hs->file) {
len = (u16_t)(hs->tag_end - hs->file);
}
#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/
LWIP_ASSERT("hs->started >= hs->file", hs->tag_started >= hs->file);
if (len > hs->tag_started - hs->file) {
/* we would include the tag in sending */
len = (u16_t)(hs->tag_started - hs->file);
}
#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/
if (len != 0) {
err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
} else {
err = ERR_OK;
}
if (err == ERR_OK) {
data_to_send = true;
#if !LWIP_HTTPD_SSI_INCLUDE_TAG
if(hs->tag_started <= hs->file) {
/* pretend to have sent the tag, too */
len += hs->tag_end - hs->tag_started;
}
#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/
hs->file += len;
hs->left -= len;
}
} else {
#if LWIP_HTTPD_SSI_MULTIPART
if(hs->tag_index >= hs->tag_insert_len) {
/* Did the last SSIHandler have more to send? */
if (hs->tag_part != HTTPD_LAST_TAG_PART) {
/* If so, call it again */
hs->tag_index = 0;
get_tag_insert(hs);
}
}
#endif /* LWIP_HTTPD_SSI_MULTIPART */
/* Do we still have insert data left to send? */
if(hs->tag_index < hs->tag_insert_len) {
/* We are sending the insert string itself. How much of the
* insert can we send? */
if(len > (hs->tag_insert_len - hs->tag_index)) {
len = (hs->tag_insert_len - hs->tag_index);
}
/* Note that we set the copy flag here since we only have a
* single tag insert buffer per connection. If we don't do
* this, insert corruption can occur if more than one insert
* is processed before we call tcp_output. */
err = http_write(pcb, &(hs->tag_insert[hs->tag_index]), &len,
HTTP_IS_TAG_VOLATILE(hs));
if (err == ERR_OK) {
data_to_send = true;
hs->tag_index += len;
/* Don't return here: keep on sending data */
}
} else {
/* We have sent all the insert data so go back to looking for
* a new tag. */
LWIP_DEBUGF(HTTPD_DEBUG, ("Everything sent.\n"));
hs->tag_index = 0;
hs->tag_state = TAG_NONE;
#if !LWIP_HTTPD_SSI_INCLUDE_TAG
hs->parsed = hs->tag_end;
#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/
}
break;
}
}
}
/* If we drop out of the end of the for loop, this implies we must have
* file data to send so send it now. In TAG_SENDING state, we've already
* handled this so skip the send if that's the case. */
if((hs->tag_state != TAG_SENDING) && (hs->parsed > hs->file)) {
/* We cannot send more data than space available in the send
buffer. */
if (tcp_sndbuf(pcb) < (hs->parsed - hs->file)) {
len = tcp_sndbuf(pcb);
} else {
LWIP_ASSERT("Data size does not fit into u16_t!",
(hs->parsed - hs->file) <= 0xffff);
len = (u16_t)(hs->parsed - hs->file);
}
if(len > (2 * tcp_mss(pcb))) {
len = 2 * tcp_mss(pcb);
}
err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
if (err == ERR_OK) {
data_to_send = true;
hs->file += len;
hs->left -= len;
}
}
}
#endif /* LWIP_HTTPD_SSI */
if((hs->left == 0) && (fs_bytes_left(hs->handle) <= 0)) {
/* We reached the end of the file so this request is done.
* This adds the FIN flag right into the last data segment.
* @todo: don't close here for HTTP/1.1? */
LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n"));
http_close_conn(pcb, hs);
return 0;
}
LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("send_data end.\n"));
return data_to_send;
}
#if LWIP_HTTPD_SUPPORT_EXTSTATUS
/** Initialize a http connection with a file to send for an error message
*
* @param hs http connection state
* @param error_nr HTTP error number
* @return ERR_OK if file was found and hs has been initialized correctly
* another err_t otherwise
*/
static err_t
http_find_error_file(struct http_state *hs, u16_t error_nr)
{
const char *uri1, *uri2, *uri3;
struct fs_file *file;
if (error_nr == 501) {
uri1 = "/501.html";
uri2 = "/501.htm";
uri3 = "/501.shtml";
} else {
/* 400 (bad request is the default) */
uri1 = "/400.html";
uri2 = "/400.htm";
uri3 = "/400.shtml";
}
file = fs_open(uri1);
if (file == NULL) {
file = fs_open(uri2);
if (file == NULL) {
file = fs_open(uri3);
if (file == NULL) {
LWIP_DEBUGF(HTTPD_DEBUG, ("Error page for error %"U16_F" not found\n",
error_nr));
return ERR_ARG;
}
}
}
return http_init_file(hs, file, 0, NULL);
}
#else /* LWIP_HTTPD_SUPPORT_EXTSTATUS */
#define http_find_error_file(hs, error_nr) ERR_ARG
#endif /* LWIP_HTTPD_SUPPORT_EXTSTATUS */
/**
* Get the file struct for a 404 error page.
* Tries some file names and returns NULL if none found.
*
* @param uri pointer that receives the actual file name URI
* @return file struct for the error page or NULL no matching file was found
*/
static struct fs_file *
http_get_404_file(const char **uri)
{
struct fs_file *file;
*uri = "/404.html";
file = fs_open(*uri);
if(file == NULL) {
/* 404.html doesn't exist. Try 404.htm instead. */
*uri = "/404.htm";
file = fs_open(*uri);
if(file == NULL) {
/* 404.htm doesn't exist either. Try 404.shtml instead. */
*uri = "/404.shtml";
file = fs_open(*uri);
if(file == NULL) {
/* 404.htm doesn't exist either. Indicate to the caller that it should
* send back a default 404 page.
*/
*uri = NULL;
}
}
}
return file;
}
#if LWIP_HTTPD_SUPPORT_POST
static err_t
http_handle_post_finished(struct http_state *hs)
{
/* application error or POST finished */
/* NULL-terminate the buffer */
http_post_response_filename[0] = 0;
httpd_post_finished(hs, http_post_response_filename, LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN);
return http_find_file(hs, http_post_response_filename, 0);
}
/** Pass received POST body data to the application and correctly handle
* returning a response document or closing the connection.
* ATTENTION: The application is responsible for the pbuf now, so don't free it!
*
* @param hs http connection state
* @param p pbuf to pass to the application
* @return ERR_OK if passed successfully, another err_t if the response file
* hasn't been found (after POST finished)
*/
static err_t
http_post_rxpbuf(struct http_state *hs, struct pbuf *p)
{
err_t err;
/* adjust remaining Content-Length */
if (hs->post_content_len_left < p->tot_len) {
hs->post_content_len_left = 0;
} else {
hs->post_content_len_left -= p->tot_len;
}
err = httpd_post_receive_data(hs, p);
if ((err != ERR_OK) || (hs->post_content_len_left == 0)) {
#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
if (hs->unrecved_bytes != 0) {
return ERR_OK;
}
#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */
/* application error or POST finished */
return http_handle_post_finished(hs);
}
return ERR_OK;
}
/** Handle a post request. Called from http_parse_request when method 'POST'
* is found.
*
* @param pcb The tcp_pcb which received this packet.
* @param p The input pbuf (containing the POST header and body).
* @param hs The http connection state.
* @param data HTTP request (header and part of body) from input pbuf(s).
* @param data_len Size of 'data'.
* @param uri The HTTP URI parsed from input pbuf(s).
* @param uri_end Pointer to the end of 'uri' (here, the rest of the HTTP
* header starts).
* @return ERR_OK: POST correctly parsed and accepted by the application.
* ERR_INPROGRESS: POST not completely parsed (no error yet)
* another err_t: Error parsing POST or denied by the application
*/
static err_t
http_post_request(struct tcp_pcb *pcb, struct pbuf **inp, struct http_state *hs,
char *data, u16_t data_len, char *uri, char *uri_end)
{
err_t err;
/* search for end-of-header (first double-CRLF) */
char* crlfcrlf = strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data));
#if LWIP_HTTPD_POST_MANUAL_WND
hs->pcb = pcb;
#else /* LWIP_HTTPD_POST_MANUAL_WND */
LWIP_UNUSED_ARG(pcb); /* only used for LWIP_HTTPD_POST_MANUAL_WND */
#endif /* LWIP_HTTPD_POST_MANUAL_WND */
if (crlfcrlf != NULL) {
/* search for "Content-Length: " */
#define HTTP_HDR_CONTENT_LEN "Content-Length: "
#define HTTP_HDR_CONTENT_LEN_LEN 16
#define HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN 10
char *scontent_len = strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1));
if (scontent_len != NULL) {
char *scontent_len_end = strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN);
if (scontent_len_end != NULL) {
int content_len;
char *conten_len_num = scontent_len + HTTP_HDR_CONTENT_LEN_LEN;
*scontent_len_end = 0;
content_len = atoi(conten_len_num);
if (content_len > 0) {
/* adjust length of HTTP header passed to application */
const char *hdr_start_after_uri = uri_end + 1;
u16_t hdr_len = LWIP_MIN(data_len, crlfcrlf + 4 - data);
u16_t hdr_data_len = LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri);
u8_t post_auto_wnd = 1;
http_post_response_filename[0] = 0;
err = httpd_post_begin(hs, uri, hdr_start_after_uri, hdr_data_len, content_len,
http_post_response_filename, LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN, &post_auto_wnd);
if (err == ERR_OK) {
/* try to pass in data of the first pbuf(s) */
struct pbuf *q = *inp;
u16_t start_offset = hdr_len;
#if LWIP_HTTPD_POST_MANUAL_WND
hs->no_auto_wnd = !post_auto_wnd;
#endif /* LWIP_HTTPD_POST_MANUAL_WND */
/* set the Content-Length to be received for this POST */
hs->post_content_len_left = (u32_t)content_len;
/* get to the pbuf where the body starts */
while((q != NULL) && (q->len <= start_offset)) {
struct pbuf *head = q;
start_offset -= q->len;
q = q->next;
/* free the head pbuf */
head->next = NULL;
pbuf_free(head);
}
*inp = NULL;
if (q != NULL) {
/* hide the remaining HTTP header */
pbuf_header(q, -(s16_t)start_offset);
#if LWIP_HTTPD_POST_MANUAL_WND
if (!post_auto_wnd) {
/* already tcp_recved() this data... */
hs->unrecved_bytes = q->tot_len;
}
#endif /* LWIP_HTTPD_POST_MANUAL_WND */
return http_post_rxpbuf(hs, q);
} else {
return ERR_OK;
}
} else {
/* return file passed from application */
return http_find_file(hs, http_post_response_filename, 0);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?