📄 httpparser.c
字号:
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_tparser_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_tparser_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_tparser_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_tparser_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_tparser_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: * PARSE_INCOMPLETE_ENTITY ************************************************************************/static XINLINE parse_status_tparser_parse_entity_until_close( INOUT http_parser_t * parser ){ size_t cursor; assert( parser->ent_position == ENTREAD_UNTIL_CLOSE ); // eat any and all data cursor = parser->msg.msg.length; // update entity length parser->msg.entity.length = cursor - parser->entity_start_position; // update pointer parser->msg.entity.buf = parser->msg.msg.buf + parser->entity_start_position; parser->scanner.cursor = cursor; return PARSE_INCOMPLETE_ENTITY; // add anything}/************************************************************************* Function: parser_get_entity_read_method * * Parameters: * INOUT http_parser_t* parser ; HTTP Parser object * * Description: Determines method to read entity * * Returns: * PARSE_OK * PARSE_FAILURE * PARSE_COMPLETE -- no more reading to do ************************************************************************/XINLINE parse_status_tparser_get_entity_read_method( INOUT http_parser_t * parser ){ http_message_t *hmsg = &parser->msg; int response_code; memptr hdr_value; assert( parser->ent_position == ENTREAD_DETERMINE_READ_METHOD ); // entity points to start of msg body parser->msg.entity.buf = scanner_get_str( &parser->scanner ); parser->msg.entity.length = 0; // remember start of body parser->entity_start_position = parser->scanner.cursor; // std http rules for determining content length // * no body for 1xx, 204, 304 and HEAD, GET, // SUBSCRIBE, UNSUBSCRIBE if( hmsg->is_request ) { switch ( hmsg->method ) { case HTTPMETHOD_HEAD: case HTTPMETHOD_GET: //case HTTPMETHOD_POST: case HTTPMETHOD_SUBSCRIBE: case HTTPMETHOD_UNSUBSCRIBE: case HTTPMETHOD_MSEARCH: // no body; mark as done parser->position
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -