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

📄 httpparser.c

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

/*************					parser					  **************/

/***********************************************************************/

/***********************************************************************/

/*************				  http_message_t			  **************/

/***********************************************************************/

/************************************************************************
*	Function :	httpmsg_compare
*
*	Parameters :
*		void* param1 ;	
*		void* param2 ;	
*
*	Description :	Compares name id in the http headers.
*
*	Return : int ;
*
*	Note :
************************************************************************/
static int
httpmsg_compare( void *param1,
                 void *param2 )
{
    assert( param1 != NULL );
    assert( param2 != NULL );

    return ( ( http_header_t * ) param1 )->name_id ==
        ( ( http_header_t * ) param2 )->name_id;
}

/************************************************************************
*	Function :	httpheader_free
*
*	Parameters :
*		void *msg ;	
*
*	Description :	Free memory allocated for the http header
*
*	Return : void ;
*
*	Note :
************************************************************************/
static void
httpheader_free( void *msg )
{
    http_header_t *hdr = ( http_header_t * ) msg;

    membuffer_destroy( &hdr->name_buf );
    membuffer_destroy( &hdr->value );
    free( hdr );
}

/************************************************************************
*	Function :	httpmsg_init
*
*	Parameters :
*		INOUT http_message_t* msg ;	HTTP Message Object
*
*	Description :	Initialize and allocate memory for http message
*
*	Return : void ;
*
*	Note :
************************************************************************/
void
httpmsg_init( INOUT http_message_t * msg )
{
    msg->initialized = 1;
    msg->entity.buf = NULL;
    msg->entity.length = 0;
    ListInit( &msg->headers, httpmsg_compare, httpheader_free );
    membuffer_init( &msg->msg );
    membuffer_init( &msg->status_msg );
}

/************************************************************************
*	Function :	httpmsg_destroy
*
*	Parameters :
*		INOUT http_message_t* msg ;	HTTP Message Object
*
*	Description :	Free memory allocated for the http message
*
*	Return : void ;
*
*	Note :
************************************************************************/
void
httpmsg_destroy( INOUT http_message_t * msg )
{
    assert( msg != NULL );

    if( msg->initialized == 1 ) {
        ListDestroy( &msg->headers, 1 );
        membuffer_destroy( &msg->msg );
        membuffer_destroy( &msg->status_msg );
        free( msg->urlbuf );
        msg->initialized = 0;
    }
}

/************************************************************************
*	Function :	httpmsg_find_hdr_str
*
*	Parameters :
*		IN http_message_t* msg ;	HTTP Message Object
*		IN const char* header_name ; Header name to be compared with	
*
*	Description :	Compares the header name with the header names stored 
*		in	the linked list of messages
*
*	Return : http_header_t* - Pointer to a header on success;
*			 NULL on failure														
*
*	Note :
************************************************************************/
http_header_t *
httpmsg_find_hdr_str( IN http_message_t * msg,
                      IN const char *header_name )
{
    http_header_t *header;

    ListNode *node;

    node = ListHead( &msg->headers );
    while( node != NULL ) {

        header = ( http_header_t * ) node->item;

        if( memptr_cmp_nocase( &header->name, header_name ) == 0 ) {
            return header;
        }

        node = ListNext( &msg->headers, node );
    }
    return NULL;
}

/************************************************************************
*	Function :	httpmsg_find_hdr
*
*	Parameters :
*		IN http_message_t* msg ; HTTP Message Object
*		IN int header_name_id ;	 Header Name ID to be compared with
*		OUT memptr* value ;		 Buffer to get the ouput to.
*
*	Description :	Finds header from a list, with the given 'name_id'.
*
*	Return : http_header_t*  - Pointer to a header on success;										*
*			 NULL on failure														
*
*	Note :
************************************************************************/
http_header_t *
httpmsg_find_hdr( IN http_message_t * msg,
                  IN int header_name_id,
                  OUT memptr * value )
{
    http_header_t header;       // temp header for searching

    ListNode *node;

    http_header_t *data;

    header.name_id = header_name_id;

    node = ListFind( &msg->headers, NULL, &header );

    if( node == NULL ) {
        return NULL;
    }

    data = ( http_header_t * ) node->item;

    if( value != NULL ) {
        value->buf = data->value.buf;
        value->length = data->value.length;
    }

    return data;
}

/***********************************************************************/

/*************				  http_parser_t				  **************/

/***********************************************************************/

/************************************************************************
*	Function :	skip_blank_lines
*
*	Parameters :
*		INOUT scanner_t* scanner ;	Scanner Object
*
*	Description :	skips blank lines at the start of a msg.
*
*	Return : int ;
*
*	Note :
************************************************************************/
static XINLINE int
skip_blank_lines( INOUT scanner_t * scanner )
{
    memptr token;
    token_type_t tok_type;
    parse_status_t status;

    // skip ws, crlf
    do {
        status = scanner_get_token( scanner, &token, &tok_type );
    } while( status == PARSE_OK &&
             ( tok_type == TT_WHITESPACE || tok_type == TT_CRLF ) );

    if( status == PARSE_OK ) {
        // pushback a non-whitespace token
        scanner->cursor -= token.length;
        //scanner_pushback( scanner, token.length );
    }

    return status;
}

/************************************************************************
*	Function :	skip_lws
*
*	Parameters :
*		INOUT scanner_t* scanner ;	Scanner Object
*
*	Description :	skip linear whitespace.
*
*	Return : int ;
*		PARSE_OK: (LWS)* removed from input								
*		PARSE_FAILURE: bad input											
*		PARSE_INCOMPLETE: incomplete input									
*
*	Note :
************************************************************************/
static XINLINE int
skip_lws( INOUT scanner_t * scanner )
{
    memptr token;
    token_type_t tok_type;
    parse_status_t status;
    size_t save_pos;
    xboolean matched;

    do {
        save_pos = scanner->cursor;
        matched = FALSE;

        // get CRLF or WS
        status = scanner_get_token( scanner, &token, &tok_type );
        if( status == PARSE_OK ) {
            if( tok_type == TT_CRLF ) {
                // get WS
                status = scanner_get_token( scanner, &token, &tok_type );
            }

            if( status == PARSE_OK && tok_type == TT_WHITESPACE ) {
                matched = TRUE;
            } else {
                // did not match LWS; pushback token(s)
                scanner->cursor = save_pos;
            }
        }
    } while( matched );

    // if entire msg is loaded, ignore an 'incomplete' warning
    if( status == PARSE_INCOMPLETE && scanner->entire_msg_loaded ) {
        status = PARSE_OK;
    }

    return status;
}

/************************************************************************
*	Function :	match_non_ws_string
*
*	Parameters :
*		INOUT scanner_t* scanner ;	Scanner Object
*		OUT memptr* str ;	Buffer to get the scanner buffer contents.
*
*	Description :	Match a string without whitespace or CRLF (%S)
*
*	Return : XINLINE parse_status_t ;
*		PARSE_OK															
*		PARSE_NO_MATCH														
*		PARSE_FAILURE														
*		PARSE_INCOMPLETE													
*
*	Note :
************************************************************************/
static XINLINE parse_status_t
match_non_ws_string( INOUT scanner_t * scanner,
                     OUT memptr * str )
{
    memptr token;
    token_type_t tok_type;
    parse_status_t status;
    xboolean done = FALSE;
    size_t save_cursor;

    save_cursor = scanner->cursor;

    str->length = 0;
    str->buf = scanner_get_str( scanner );  // point to next char in input

    while( !done ) {
        status = scanner_get_token( scanner, &token, &tok_type );
        if( status == PARSE_OK &&
            tok_type != TT_WHITESPACE && tok_type != TT_CRLF ) {
            // append non-ws token
            str->length += token.length;
        } else {
            done = TRUE;
        }
    }

    if( status == PARSE_OK ) {
        // last token was WS; push it back in
        scanner->cursor -= token.length;
    }
    // tolerate 'incomplete' msg
    if( status == PARSE_OK ||
        ( status == PARSE_INCOMPLETE && scanner->entire_msg_loaded )
         ) {
        if( str->length == 0 ) {
            // no strings found
            return PARSE_NO_MATCH;
        } else {
            return PARSE_OK;
        }
    } else {
        // error -- pushback tokens
        scanner->cursor = save_cursor;
        return status;
    }
}

/************************************************************************
*	Function :	match_raw_value
*
*	Parameters :
*		INOUT scanner_t* scanner ;	Scanner Object
*		OUT memptr* raw_value ;	    Buffer to get the scanner buffer 
*									contents
*
*	Description :	Matches a raw value in a the input; value's length 
*		can	be 0 or more. Whitespace after value is trimmed. On success,
*		scanner points the CRLF that ended the value						
*
*	Return : parse_status_t ;
*		PARSE_OK													
*		PARSE_INCOMPLETE													
*		PARSE_FAILURE														
*
*	Note :
************************************************************************/
static XINLINE parse_status_t
match_raw_value( INOUT scanner_t * scanner,
                 OUT memptr * raw_value )
{
    memptr token;
    token_type_t tok_type;
    parse_status_t status;
    xboolean done = FALSE;
    xboolean saw_crlf = FALSE;
    size_t pos_at_crlf = 0;
    size_t save_pos;
    char c;

    save_pos = scanner->cursor;

    // value points to start of input
    raw_value->buf = scanner_get_str( scanner );
    raw_value->length = 0;

    while( !done ) {
        status = scanner_get_token( scanner, &token, &tok_type );
        if( status == PARSE_OK ) {
            if( !saw_crlf ) {
                if( tok_type == TT_CRLF ) {
                    // CRLF could end value
                    saw_crlf = TRUE;

                    // save input position at start of CRLF
                    pos_at_crlf = scanner->cursor - token.length;
                }
                // keep appending value
                raw_value->length += token.length;
            } else              // already seen CRLF
            {
                if( tok_type == TT_WHITESPACE ) {
                    // start again; forget CRLF
                    saw_crlf = FALSE;
                    raw_value->length += token.length;
                } else {
                    // non-ws means value ended just before CRLF
                    done = TRUE;

                    // point to the crlf which ended the value
                    scanner->cursor = pos_at_crlf;
                }
            }
        } else {
            // some kind of error; restore scanner position

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -