⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httpparser.c

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 C
📖 第 1 页 / 共 5 页
字号:
                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 + -