📄 httpparser.c
字号:
parser->msg.method = SOAPMETHOD_POST;
}
header_id = Http_Header_Names[index].id;
orig_header =
httpmsg_find_hdr( &parser->msg, header_id, NULL );
} else {
header_id = HDR_UNKNOWN;
save_char = token.buf[token.length];
token.buf[token.length] = '\0';
orig_header = httpmsg_find_hdr_str( &parser->msg, token.buf );
token.buf[token.length] = save_char; // restore
}
if( orig_header == NULL ) {
//
// add new header
//
header = ( http_header_t * ) malloc( sizeof( http_header_t ) );
if( header == NULL ) {
parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
return PARSE_FAILURE;
}
membuffer_init( &header->name_buf );
membuffer_init( &header->value );
// value can be 0 length
if( hdr_value.length == 0 ) {
hdr_value.buf = "\0";
hdr_value.length = 1;
}
// save in header in buffers
if( membuffer_assign
( &header->name_buf, token.buf, token.length ) != 0
|| membuffer_assign( &header->value, hdr_value.buf,
hdr_value.length ) != 0 ) {
// not enuf mem
parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
return PARSE_FAILURE;
}
header->name.buf = header->name_buf.buf;
header->name.length = header->name_buf.length;
header->name_id = header_id;
ListAddTail( &parser->msg.headers, header );
//NNS: ret = dlist_append( &parser->msg.headers, header );
if( ret == UPNP_E_OUTOF_MEMORY ) {
parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
return PARSE_FAILURE;
}
} else if( hdr_value.length > 0 ) {
//
// append value to existing header
//
// append space
ret = membuffer_append_str( &orig_header->value, ", " );
// append continuation of header value
ret2 = membuffer_append( &orig_header->value,
hdr_value.buf, hdr_value.length );
if( ret == UPNP_E_OUTOF_MEMORY || ret2 == UPNP_E_OUTOF_MEMORY ) {
// not enuf mem
parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
return PARSE_FAILURE;
}
}
} // end while
}
////////////////////////////////////////////////////////////////////////
#ifdef HIGHLY_UNLIKELY
// **************
static parse_status_t
parser_parse_headers_old( INOUT http_parser_t * parser )
{
parse_status_t status;
memptr token;
memptr hdr_value;
token_type_t tok_type;
scanner_t *scanner = &parser->scanner;
size_t save_pos;
http_header_t *header;
int header_id;
int ret = 0;
int index;
http_header_t *orig_header;
char save_char;
int ret2,
ret3;
assert( parser->position == POS_HEADERS ||
parser->ent_position == ENTREAD_CHUNKY_HEADERS );
while( TRUE ) {
save_pos = scanner->cursor;
//
// check end of headers
//
status = scanner_get_token( scanner, &token, &tok_type );
if( status != PARSE_OK ) {
return status;
}
if( tok_type == TT_CRLF ) {
// end of headers
parser->position = POS_ENTITY; // read entity next
return PARSE_OK;
}
//
// not end; read header
//
if( tok_type != TT_IDENTIFIER ) {
return PARSE_FAILURE; // didn't see header name
}
status = match( scanner, " : %R%c", &hdr_value );
if( status != PARSE_OK ) {
// pushback tokens; useful only on INCOMPLETE error
scanner->cursor = save_pos;
return status;
}
//
// add header
//
// find header
index = map_str_to_int( token.buf, token.length, Http_Header_Names,
NUM_HTTP_HEADER_NAMES, FALSE );
if( index != -1 ) {
header_id = Http_Header_Names[index].id;
orig_header =
httpmsg_find_hdr( &parser->msg, header_id, NULL );
} else {
header_id = HDR_UNKNOWN;
save_char = token.buf[token.length];
token.buf[token.length] = '\0';
orig_header = httpmsg_find_hdr_str( &parser->msg, token.buf );
token.buf[token.length] = save_char; // restore
}
if( orig_header == NULL ) {
//
// add new header
//
header = ( http_header_t * ) malloc( sizeof( http_header_t ) );
if( header == NULL ) {
parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
return PARSE_FAILURE;
}
membuffer_init( &header->multi_hdr_buf );
header->name = token;
header->value = hdr_value;
header->name_id = header_id;
ret = dlist_append( &parser->msg.headers, header );
if( ret == UPNP_E_OUTOF_MEMORY ) {
parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
return PARSE_FAILURE;
}
} else if( hdr_value.length > 0 ) {
//
// append value to existing header
//
if( orig_header->multi_hdr_buf.buf == NULL ) {
// store in buffer
ret = membuffer_append( &orig_header->multi_hdr_buf,
orig_header->value.buf,
orig_header->value.length );
}
// append space
ret2 =
membuffer_append( &orig_header->multi_hdr_buf, ", ", 2 );
// append continuation of header value
ret3 = membuffer_append( &orig_header->multi_hdr_buf,
hdr_value.buf, hdr_value.length );
if( ret == UPNP_E_OUTOF_MEMORY ||
ret2 == UPNP_E_OUTOF_MEMORY ||
ret3 == UPNP_E_OUTOF_MEMORY ) {
// not enuf mem
parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
return PARSE_FAILURE;
}
// header value points to allocated buf
orig_header->value.buf = orig_header->multi_hdr_buf.buf;
orig_header->value.length = orig_header->multi_hdr_buf.length;
}
} // end while
}
#endif
// ******************************
/************************************************************************
* Function: parser_parse_entity_using_clen
*
* Parameters:
* INOUT http_parser_t* parser ; HTTP Parser object
*
* Description: reads entity using content-length
*
* Returns:
* PARSE_INCOMPLETE
* PARSE_FAILURE -- entity length > content-length value
* PARSE_SUCCESS
************************************************************************/
static XINLINE parse_status_t
parser_parse_entity_using_clen( INOUT http_parser_t * parser )
{
//int entity_length;
assert( parser->ent_position == ENTREAD_USING_CLEN );
// determine entity (i.e. body) length so far
//entity_length = parser->msg.msg.length - parser->entity_start_position;
parser->msg.entity.length =
parser->msg.msg.length - parser->entity_start_position;
if( parser->msg.entity.length < parser->content_length ) {
// more data to be read
return PARSE_INCOMPLETE;
} else {
if( parser->msg.entity.length > parser->content_length ) {
// silently discard extra data
parser->msg.msg.buf[parser->entity_start_position +
parser->content_length] = '\0';
}
// save entity length
parser->msg.entity.length = parser->content_length;
// save entity start ptr; (the very last thing to do)
parser->msg.entity.buf = parser->msg.msg.buf +
parser->entity_start_position;
// done reading entity
parser->position = POS_COMPLETE;
return PARSE_SUCCESS;
}
}
/************************************************************************
* Function: parser_parse_chunky_body
*
* Parameters:
* INOUT http_parser_t* parser ; HTTP Parser object
*
* Description: Read data in the chunks
*
* Returns:
* PARSE_INCOMPLETE
* PARSE_FAILURE -- entity length > content-length value
* PARSE_SUCCESS
************************************************************************/
static XINLINE parse_status_t
parser_parse_chunky_body( INOUT http_parser_t * parser )
{
parse_status_t status;
size_t save_pos;
// if 'chunk_size' of bytes have been read; read next chunk
if( ( int )( parser->msg.msg.length - parser->scanner.cursor ) >=
parser->chunk_size ) {
// move to next chunk
parser->scanner.cursor += parser->chunk_size;
save_pos = parser->scanner.cursor;
//discard CRLF
status = match( &parser->scanner, "%c" );
if( status != PARSE_OK ) {
parser->scanner.cursor -= parser->chunk_size; //move back
//parser->scanner.cursor = save_pos;
return status;
}
membuffer_delete( &parser->msg.msg, save_pos,
( parser->scanner.cursor - save_pos ) );
parser->scanner.cursor = save_pos;
parser->msg.entity.length += parser->chunk_size; //update temp
parser->ent_position = ENTREAD_USING_CHUNKED;
return PARSE_CONTINUE_1;
} else {
return PARSE_INCOMPLETE; // need more data for chunk
}
}
/************************************************************************
* Function: parser_parse_chunky_headers
*
* Parameters:
* INOUT http_parser_t* parser ; HTTP Parser object
*
* Description: Read headers at the end of the chunked entity
*
* Returns:
* PARSE_INCOMPLETE
* PARSE_FAILURE -- entity length > content-length value
* PARSE_SUCCESS
************************************************************************/
static XINLINE parse_status_t
parser_parse_chunky_headers( INOUT http_parser_t * parser )
{
parse_status_t status;
size_t save_pos;
save_pos = parser->scanner.cursor;
status = parser_parse_headers( parser );
if( status == PARSE_OK ) {
// finally, done with the whole msg
parser->position = POS_COMPLETE;
// save entity start ptr as the very last thing to do
parser->msg.entity.buf = parser->msg.msg.buf +
parser->entity_start_position;
membuffer_delete( &parser->msg.msg, save_pos,
( parser->scanner.cursor - save_pos ) );
parser->scanner.cursor = save_pos;
return PARSE_SUCCESS;
} else {
return status;
}
}
/************************************************************************
* Function: parser_parse_chunky_entity
*
* Parameters:
* INOUT http_parser_t* parser - HTTP Parser Object
*
* Description: Read headers at the end of the chunked entity
*
* Returns:
* PARSE_INCOMPLETE
* PARSE_FAILURE -- entity length > content-length value
* PARSE_SUCCESS
* PARSE_CONTINUE_1
************************************************************************/
static XINLINE parse_status_t
parser_parse_chunky_entity( INOUT http_parser_t * parser )
{
scanner_t *scanner = &parser->scanner;
parse_status_t status;
size_t save_pos;
memptr dummy;
assert( parser->ent_position == ENTREAD_USING_CHUNKED );
save_pos = scanner->cursor;
// get size of chunk, discard extension, discard CRLF
status = match( scanner, "%x%L%c", &parser->chunk_size, &dummy );
if( status != PARSE_OK ) {
scanner->cursor = save_pos;
DBGONLY( UpnpPrintf
( UPNP_INFO, HTTP, __FILE__, __LINE__,
"CHUNK COULD NOT BE PARSED\n" ); )
return status;
}
// remove chunk info just matched; just retain data
membuffer_delete( &parser->msg.msg, save_pos,
( scanner->cursor - save_pos ) );
scanner->cursor = save_pos; // adjust scanner too
if( parser->chunk_size == 0 ) {
// done reading entity; determine length of entity
parser->msg.entity.length = parser->scanner.cursor -
parser->entity_start_position;
// read entity headers
parser->ent_position = ENTREAD_CHUNKY_HEADERS;
} else {
// read chunk body
parser->ent_position = ENTREAD_CHUNKY_BODY;
}
return PARSE_CONTINUE_1; // continue to reading body
}
/************************************************************************
* Function: parser_parse_entity_until_close
*
* Parameters:
* INOUT http_parser_t* parser ; HTTP Parser object
*
* Description: Read headers at the end of the chunked entity
*
* Returns:
* P
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -