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 + -
显示快捷键?