httpparser.c
来自「原来由英特尔制定的UPnP SDK的」· C语言 代码 · 共 2,179 行 · 第 1/5 页
C
2,179 行
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 UPNP_INLINE 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 UPNP_INLINE 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 UPNP_INLINE 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 UPNP_INLINE 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; 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 UPNP_INLINE 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************************************************************************/UPNP_INLINE 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 = POS_COMPLETE; return PARSE_SUCCESS; break; default: ; // do nothing } } else // response { response_code = hmsg->status_code; if( response_code == 204 || response_code == 304 || ( response_code >= 100 && response_code <= 199 ) || hmsg->request_method == HTTPMETHOD_HEAD || hmsg->request_method == HTTPMETHOD_MSEARCH || hmsg->request_method == HTTPMETHOD_SUBSCRIBE || hmsg->request_method == HTTPMETHOD_UNSUBSCRIBE || hmsg->request_method == HTTPMETHOD_NOTIFY ) { parser->position = POS_COMPLETE; return PARSE_SUCCESS; } } // * transfer-encoding -- used to indicate chunked data if( httpmsg_find_hdr( hmsg, HDR_TRANSFER_ENCODING, &hdr_value ) ) { if( raw_find_str( &hdr_value, "chunked" ) >= 0 ) { // read method to use chunked transfer encoding parser->ent_position = ENTREAD_USING_CHUNKED; UpnpPrintf( UPNP_INFO, HTTP, __FILE__, __LINE__, "Found Chunked Encoding ....\n" ); return PARSE_CONTINUE_1; } } // * use content length if( httpmsg_find_hdr( hmsg, HDR_CONTENT_LENGTH, &hdr_value ) ) { parser->content_length = raw_to_int( &hdr_value, 10 ); if( parser->content_length < 0 ) { // bad content-length return PARSE_FAILURE; } parser->ent_position = ENTREAD_USING_CLEN;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?