httpd.c
来自「NXPl788上lwip的无操作系统移植,基于Embest开发板」· C语言 代码 · 共 1,866 行 · 第 1/5 页
C
1,866 行
/* Set up to send the first header string. */
pState->hdr_index = 0;
pState->hdr_pos = 0;
}
}
#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
/**
* Try to send more data on this pcb.
*
* @param pcb the pcb to send data
* @param hs connection state
*/
static u8_t
http_send_data(struct tcp_pcb *pcb, struct http_state *hs)
{
err_t err;
u16_t len;
u16_t mss;
u8_t data_to_send = false;
#if LWIP_HTTPD_DYNAMIC_HEADERS
u16_t hdrlen, sendlen;
#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_send_data: pcb=%p hs=%p left=%d\n", (void*)pcb,
(void*)hs, hs != NULL ? hs->left : 0));
#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
if (hs->unrecved_bytes != 0) {
return 0;
}
#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */
#if LWIP_HTTPD_DYNAMIC_HEADERS
/* If we were passed a NULL state structure pointer, ignore the call. */
if (hs == NULL) {
return 0;
}
/* Assume no error until we find otherwise */
err = ERR_OK;
/* Do we have any more header data to send for this file? */
if(hs->hdr_index < NUM_FILE_HDR_STRINGS) {
/* How much data can we send? */
len = tcp_sndbuf(pcb);
sendlen = len;
while(len && (hs->hdr_index < NUM_FILE_HDR_STRINGS) && sendlen) {
const void *ptr;
u16_t old_sendlen;
/* How much do we have to send from the current header? */
hdrlen = (u16_t)strlen(hs->hdrs[hs->hdr_index]);
/* How much of this can we send? */
sendlen = (len < (hdrlen - hs->hdr_pos)) ? len : (hdrlen - hs->hdr_pos);
/* Send this amount of data or as much as we can given memory
* constraints. */
ptr = (const void *)(hs->hdrs[hs->hdr_index] + hs->hdr_pos);
old_sendlen = sendlen;
err = http_write(pcb, ptr, &sendlen, HTTP_IS_HDR_VOLATILE(hs, ptr));
if ((err == ERR_OK) && (old_sendlen != sendlen)) {
/* Remember that we added some more data to be transmitted. */
data_to_send = true;
} else if (err != ERR_OK) {
/* special case: http_write does not try to send 1 byte */
sendlen = 0;
}
/* Fix up the header position for the next time round. */
hs->hdr_pos += sendlen;
len -= sendlen;
/* Have we finished sending this string? */
if(hs->hdr_pos == hdrlen) {
/* Yes - move on to the next one */
hs->hdr_index++;
hs->hdr_pos = 0;
}
}
/* If we get here and there are still header bytes to send, we send
* the header information we just wrote immediately. If there are no
* more headers to send, but we do have file data to send, drop through
* to try to send some file data too. */
if((hs->hdr_index < NUM_FILE_HDR_STRINGS) || !hs->file) {
LWIP_DEBUGF(HTTPD_DEBUG, ("tcp_output\n"));
return 1;
}
}
#else /* LWIP_HTTPD_DYNAMIC_HEADERS */
/* Assume no error until we find otherwise */
err = ERR_OK;
#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
/* Have we run out of file data to send? If so, we need to read the next
* block from the file. */
if (hs->left == 0) {
#if LWIP_HTTPD_SSI || LWIP_HTTPD_DYNAMIC_HEADERS
int count;
#endif /* LWIP_HTTPD_SSI || LWIP_HTTPD_DYNAMIC_HEADERS */
/* Do we have a valid file handle? */
if (hs->handle == NULL) {
/* No - close the connection. */
http_close_conn(pcb, hs);
return 0;
}
if (fs_bytes_left(hs->handle) <= 0) {
/* We reached the end of the file so this request is done.
* @todo: don't close here for HTTP/1.1? */
LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n"));
http_close_conn(pcb, hs);
return 0;
}
#if LWIP_HTTPD_SSI || LWIP_HTTPD_DYNAMIC_HEADERS
/* Do we already have a send buffer allocated? */
if(hs->buf) {
/* Yes - get the length of the buffer */
count = hs->buf_len;
} else {
/* We don't have a send buffer so allocate one up to 2mss bytes long. */
count = 2 * tcp_mss(pcb);
do {
hs->buf = (char*)mem_malloc((mem_size_t)count);
if (hs->buf != NULL) {
hs->buf_len = count;
break;
}
count = count / 2;
} while (count > 100);
/* Did we get a send buffer? If not, return immediately. */
if (hs->buf == NULL) {
LWIP_DEBUGF(HTTPD_DEBUG, ("No buff\n"));
return 0;
}
}
/* Read a block of data from the file. */
LWIP_DEBUGF(HTTPD_DEBUG, ("Trying to read %d bytes.\n", count));
count = fs_read(hs->handle, hs->buf, count);
if(count < 0) {
/* We reached the end of the file so this request is done.
* @todo: don't close here for HTTP/1.1? */
LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n"));
http_close_conn(pcb, hs);
return 1;
}
/* Set up to send the block of data we just read */
LWIP_DEBUGF(HTTPD_DEBUG, ("Read %d bytes.\n", count));
hs->left = count;
hs->file = hs->buf;
#if LWIP_HTTPD_SSI
hs->parse_left = count;
hs->parsed = hs->buf;
#endif /* LWIP_HTTPD_SSI */
#else /* LWIP_HTTPD_SSI || LWIP_HTTPD_DYNAMIC_HEADERS */
LWIP_ASSERT("SSI and DYNAMIC_HEADERS turned off but eof not reached", 0);
#endif /* LWIP_HTTPD_SSI || LWIP_HTTPD_DYNAMIC_HEADERS */
}
#if LWIP_HTTPD_SSI
if(!hs->tag_check) {
#endif /* LWIP_HTTPD_SSI */
/* We are not processing an SHTML file so no tag checking is necessary.
* Just send the data as we received it from the file. */
/* We cannot send more data than space available in the send
buffer. */
if (tcp_sndbuf(pcb) < hs->left) {
len = tcp_sndbuf(pcb);
} else {
len = (u16_t)hs->left;
LWIP_ASSERT("hs->left did not fit into u16_t!", (len == hs->left));
}
mss = tcp_mss(pcb);
if(len > (2 * mss)) {
len = 2 * mss;
}
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;
}
#if LWIP_HTTPD_SSI
} else {
/* We are processing an SHTML file so need to scan for tags and replace
* them with insert strings. We need to be careful here since a tag may
* straddle the boundary of two blocks read from the file and we may also
* have to split the insert string between two tcp_write operations. */
/* How much data could we send? */
len = tcp_sndbuf(pcb);
/* Do we have remaining data to send before parsing more? */
if(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);
}
mss = tcp_mss(pcb);
if(len > (2 * mss)) {
len = 2 * mss;
}
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;
}
/* If the send buffer is full, return now. */
if(tcp_sndbuf(pcb) == 0) {
return data_to_send;
}
}
LWIP_DEBUGF(HTTPD_DEBUG, ("State %d, %d left\n", hs->tag_state, hs->parse_left));
/* We have sent all the data that was already parsed so continue parsing
* the buffer contents looking for SSI tags. */
while((hs->parse_left) && (err == ERR_OK)) {
/* @todo: somewhere in this loop, 'len' should grow again... */
if (len == 0) {
return data_to_send;
}
switch(hs->tag_state) {
case TAG_NONE:
/* We are not currently processing an SSI tag so scan for the
* start of the lead-in marker. */
if(*hs->parsed == g_pcTagLeadIn[0]) {
/* We found what could be the lead-in for a new tag so change
* state appropriately. */
hs->tag_state = TAG_LEADIN;
hs->tag_index = 1;
#if !LWIP_HTTPD_SSI_INCLUDE_TAG
hs->tag_started = hs->parsed;
#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */
}
/* Move on to the next character in the buffer */
hs->parse_left--;
hs->parsed++;
break;
case TAG_LEADIN:
/* We are processing the lead-in marker, looking for the start of
* the tag name. */
/* Have we reached the end of the leadin? */
if(hs->tag_index == LEN_TAG_LEAD_IN) {
hs->tag_index = 0;
hs->tag_state = TAG_FOUND;
} else {
/* Have we found the next character we expect for the tag leadin? */
if(*hs->parsed == g_pcTagLeadIn[hs->tag_index]) {
/* Yes - move to the next one unless we have found the complete
* leadin, in which case we start looking for the tag itself */
hs->tag_index++;
} else {
/* We found an unexpected character so this is not a tag. Move
* back to idle state. */
hs->tag_state = TAG_NONE;
}
/* Move on to the next character in the buffer */
hs->parse_left--;
hs->parsed++;
}
break;
case TAG_FOUND:
/* We are reading the tag name, looking for the start of the
* lead-out marker and removing any whitespace found. */
/* Remove leading whitespace between the tag leading and the first
* tag name character. */
if((hs->tag_index == 0) && ((*hs->parsed == ' ') ||
(*hs->parsed == '\t') || (*hs->parsed == '\n') ||
(*hs->parsed == '\r'))) {
/* Move on to the next character in the buffer */
hs->parse_left--;
hs->parsed++;
break;
}
/* Have we found the end of the tag name? This is signalled by
* us finding the first leadout character or whitespace */
if((*hs->parsed == g_pcTagLeadOut[0]) ||
(*hs->parsed == ' ') || (*hs->parsed == '\t') ||
(*hs->parsed == '\n') || (*hs->parsed == '\r')) {
if(hs->tag_index == 0) {
/* We read a zero length tag so ignore it. */
hs->tag_state = TAG_NONE;
} else {
/* We read a non-empty tag so go ahead and look for the
* leadout string. */
hs->tag_state = TAG_LEADOUT;
LWIP_ASSERT("hs->tag_index <= 0xff", hs->tag_index <= 0xff);
hs->tag_name_len = (u8_t)hs->tag_index;
hs->tag_name[hs->tag_index] = '\0';
if(*hs->parsed == g_pcTagLeadOut[0]) {
hs->tag_index = 1;
} else {
hs->tag_index = 0;
}
}
} else {
/* This character is part of the tag name so save it */
if(hs->tag_index < LWIP_HTTPD_MAX_TAG_NAME_LEN) {
hs->tag_name[hs->tag_index++] = *hs->parsed;
} else {
/* The tag was too long so ignore it. */
hs->tag_state = TAG_NONE;
}
}
/* Move on to the next character in the buffer */
hs->parse_left--;
hs->parsed++;
break;
/* We are looking for the end of the lead-out marker. */
case TAG_LEADOUT:
/* Remove leading whitespace between the tag leading and the first
* tag leadout character. */
if((hs->tag_index == 0) && ((*hs->parsed == ' ') ||
(*hs->parsed == '\t') || (*hs->parsed == '\n') ||
(*hs->parsed == '\r'))) {
/* Move on to the next character in the buffer */
hs->parse_left--;
hs->parsed++;
break;
}
/* Have we found the next character we expect for the tag leadout? */
if(*hs->parsed == g_pcTagLeadOut[hs->tag_index]) {
/* Yes - move to the next one unless we have found the complete
* leadout, in which case we need to call the client to process
* the tag. */
/* Move on to the next character in the buffer */
hs->parse_left--;
hs->parsed++;
if(hs->tag_index == (LEN_TAG_LEAD_OUT - 1)) {
/* Call the client to ask for the insert string for the
* tag we just found. */
#if LWIP_HTTPD_SSI_MULTIPART
hs->tag_part = 0; /* start with tag part 0 */
#endif /* LWIP_HTTPD_SSI_MULTIPART */
get_tag_insert(hs);
/* Next time through, we are going to be sending data
* immediately, either the end of the block we start
* sending here or the insert string. */
hs->tag_index = 0;
hs->tag_state = TAG_SENDING;
hs->tag_end = hs->parsed;
#if !LWIP_HTTPD_SSI_INCLUDE_TAG
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?