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

📄 httpreadwrite.c

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 C
📖 第 1 页 / 共 5 页
字号:
*		PARSE_OK - On Success
*		PARSE_FAILURE - Failure to parse data correctly
*		UPNP_E_BAD_HTTPMSG - Socker read() returns an error
*
*	Note :
************************************************************************/
int
ReadResponseLineAndHeaders( IN SOCKINFO * info,
                            IN OUT http_parser_t * parser,
                            IN OUT int *timeout_secs,
                            IN OUT int *http_error_code )
{
    parse_status_t status;
    int num_read;
    char buf[2 * 1024];
    int done = 0;
    int ret_code = 0;

    //read response line

    status = parser_parse_responseline( parser );
    if( status == PARSE_OK ) {
        done = 1;
    } else if( status == PARSE_INCOMPLETE ) {
        done = 0;
    } else {
        //error
        return status;
    }

    while( !done ) {
        num_read = sock_read( info, buf, sizeof( buf ), timeout_secs );
        if( num_read > 0 ) {
            // append data to buffer
            ret_code = membuffer_append( &parser->msg.msg, buf, num_read );
            if( ret_code != 0 ) {
                // set failure status
                parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
                return PARSE_FAILURE;
            }
            status = parser_parse_responseline( parser );
            if( status == PARSE_OK ) {
                done = 1;
            } else if( status == PARSE_INCOMPLETE ) {
                done = 0;
            } else {
                //error
                return status;
            }
        } else if( num_read == 0 ) {

            // partial msg
            *http_error_code = HTTP_BAD_REQUEST;    // or response
            return UPNP_E_BAD_HTTPMSG;

        } else {
            *http_error_code = parser->http_error_code;
            return num_read;
        }
    }

    done = 0;

    status = parser_parse_headers( parser );
    if( ( status == PARSE_OK ) && ( parser->position == POS_ENTITY ) ) {

        done = 1;
    } else if( status == PARSE_INCOMPLETE ) {
        done = 0;
    } else {
        //error
        return status;
    }

    //read headers
    while( !done ) {
        num_read = sock_read( info, buf, sizeof( buf ), timeout_secs );
        if( num_read > 0 ) {
            // append data to buffer
            ret_code = membuffer_append( &parser->msg.msg, buf, num_read );
            if( ret_code != 0 ) {
                // set failure status
                parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
                return PARSE_FAILURE;
            }
            status = parser_parse_headers( parser );
            if( ( status == PARSE_OK )
                && ( parser->position == POS_ENTITY ) ) {

                done = 1;
            } else if( status == PARSE_INCOMPLETE ) {
                done = 0;
            } else {
                //error
                return status;
            }
        } else if( num_read == 0 ) {

            // partial msg
            *http_error_code = HTTP_BAD_REQUEST;    // or response
            return UPNP_E_BAD_HTTPMSG;

        } else {
            *http_error_code = parser->http_error_code;
            return num_read;
        }
    }

    return PARSE_OK;
}

/************************************************************************
*	Function :	http_ReadHttpGet
*
*	Parameters :
*		IN void *Handle :			Handle to the HTTP get object
*		IN OUT char *buf :			Buffer to get the read and parsed data
*		IN OUT unsigned int *size :	Size of tge buffer passed
*		IN int timeout :			time out value
*
*	Description :	Parses already existing data, then gets new data.
*		Parses and extracts information from the new data.
*
*	Return : int ;
*		UPNP_E_SUCCESS - On Sucess ;
*		UPNP_E_INVALID_PARAM  - Invalid Parameter;
*		UPNP_E_BAD_RESPONSE ;
*		UPNP_E_BAD_HTTPMSG ;
*
*	Note :
************************************************************************/
int
http_ReadHttpGet( IN void *Handle,
                  IN OUT char *buf,
                  IN OUT unsigned int *size,
                  IN int timeout )
{
    http_get_handle_t *handle = Handle;

    parse_status_t status;
    int num_read;
    xboolean ok_on_close = FALSE;
    char tempbuf[2 * 1024];

    int ret_code = 0;

    if( ( !handle ) || ( !size ) || ( ( ( *size ) > 0 ) && !buf )
        || ( ( *size ) < 0 ) ) {
        ( *size ) = 0;
        return UPNP_E_INVALID_PARAM;
    }
    //first parse what has already been gotten
    if( handle->response.position != POS_COMPLETE ) {
        status = parser_parse_entity( &handle->response );
    } else {
        status = PARSE_SUCCESS;
    }

    if( status == PARSE_INCOMPLETE_ENTITY ) {
        // read until close
        ok_on_close = TRUE;
    } else if( ( status != PARSE_SUCCESS )
               && ( status != PARSE_CONTINUE_1 )
               && ( status != PARSE_INCOMPLETE ) ) {
        //error
        ( *size ) = 0;
        return UPNP_E_BAD_RESPONSE;
    }
    //read more if necessary entity
    while( ( ( handle->entity_offset + ( *size ) ) >
             handle->response.msg.entity.length )
           && ( handle->response.position != POS_COMPLETE ) ) {
        num_read =
            sock_read( &handle->sock_info, tempbuf, sizeof( tempbuf ),
                       &timeout );
        if( num_read > 0 ) {
            // append data to buffer
            ret_code = membuffer_append( &handle->response.msg.msg,
                                         tempbuf, num_read );
            if( ret_code != 0 ) {
                // set failure status
                handle->response.http_error_code =
                    HTTP_INTERNAL_SERVER_ERROR;
                ( *size ) = 0;
                return PARSE_FAILURE;
            }
            status = parser_parse_entity( &handle->response );
            if( status == PARSE_INCOMPLETE_ENTITY ) {
                // read until close
                ok_on_close = TRUE;
            } else if( ( status != PARSE_SUCCESS )
                       && ( status != PARSE_CONTINUE_1 )
                       && ( status != PARSE_INCOMPLETE ) ) {
                //error
                ( *size ) = 0;
                return UPNP_E_BAD_RESPONSE;
            }
        } else if( num_read == 0 ) {
            if( ok_on_close ) {
                DBGONLY( UpnpPrintf( UPNP_INFO, HTTP, __FILE__, __LINE__,
                                     "<<< (RECVD) <<<\n%s\n-----------------\n",
                                     handle->response.msg.msg.buf );
                         //print_http_headers( &parser->msg );
                     )
                    handle->response.position = POS_COMPLETE;
            } else {
                // partial msg
                ( *size ) = 0;
                handle->response.http_error_code = HTTP_BAD_REQUEST;    // or response
                return UPNP_E_BAD_HTTPMSG;
            }
        } else {
            ( *size ) = 0;
            return num_read;
        }
    }

    if( ( handle->entity_offset + ( *size ) ) >
        handle->response.msg.entity.length ) {
        ( *size ) =
            handle->response.msg.entity.length - handle->entity_offset;
    }

    memcpy( buf,
            &handle->response.msg.msg.buf[handle->
                                          response.entity_start_position +
                                          handle->entity_offset],
            ( *size ) );
    handle->entity_offset += ( *size );
    return UPNP_E_SUCCESS;
}

/************************************************************************
*	Function :	http_CloseHttpGet
*
*	Parameters :
*		IN void *Handle ;	Handle to HTTP get object
*
*	Description :	Clears the handle allocated for the HTTP GET operation
*		Clears socket states and memory allocated for socket operations. 
*
*	Return : int ;
*		UPNP_E_SUCCESS - On Success
*		UPNP_E_INVALID_PARAM - Invalid Parameter
*
*	Note :
************************************************************************/
int
http_CloseHttpGet( IN void *Handle )
{
    http_get_handle_t *handle = Handle;

    if( !handle ) {
        return UPNP_E_INVALID_PARAM;
    }

    sock_destroy( &handle->sock_info, SD_BOTH );    //should shutdown completely
    httpmsg_destroy( &handle->response.msg );
    handle->entity_offset = 0;
    free( handle );
    return UPNP_E_SUCCESS;
}

/************************************************************************
*	Function :	http_OpenHttpGet
*
*	Parameters :
*		IN const char *url_str :	String as a URL
*		IN OUT void **Handle :		Pointer to buffer to store HTTP
*									post handle
*		IN OUT char **contentType :	Type of content
*		OUT int *contentLength :	length of content
*		OUT int *httpStatus :		HTTP status returned on receiving a
*									response message
*		IN int timeout :			time out value
*
*	Description :	Makes the HTTP GET message, connects to the peer, 
*		sends the HTTP GET request, gets the response and parses the 
*		response.
*
*	Return : int;
*		UPNP_E_SUCCESS - On Success ;
*		UPNP_E_INVALID_PARAM - Invalid Paramters ;
*		UPNP_E_OUTOF_MEMORY ;
*		UPNP_E_SOCKET_ERROR ;
*		UPNP_E_BAD_RESPONSE ;
*
*	Note :
*
************************************************************************/
int
http_OpenHttpGet( IN const char *url_str,
                  IN OUT void **Handle,
                  IN OUT char **contentType,
                  OUT int *contentLength,
                  OUT int *httpStatus,
                  IN int timeout )
{
    int ret_code;
    int http_error_code;
    memptr ctype;
    SOCKET tcp_connection;
    membuffer request;
    http_get_handle_t *handle = NULL;
    uri_type url;
    parse_status_t status;

    if( ( !url_str ) || ( !Handle ) || ( !contentType )
        || ( !httpStatus ) ) {
        return UPNP_E_INVALID_PARAM;
    }

    ( *httpStatus ) = 0;
    ( *Handle ) = handle;
    ( *contentType ) = NULL;
    ( *contentLength ) = 0;

    if( ( ret_code =
          MakeGetMessage( url_str, &request, &url ) ) != UPNP_E_SUCCESS ) {
        return ret_code;
    }

    handle = ( http_get_handle_t * ) malloc( sizeof( http_get_handle_t ) );

    if( handle == NULL ) {
        return UPNP_E_OUTOF_MEMORY;
    }

    handle->entity_offset = 0;
    parser_response_init( &handle->response, HTTPMETHOD_GET );

    tcp_connection = socket( AF_INET, SOCK_STREAM, 0 );
    if( tcp_connection == UPNP_INVALID_SOCKET ) {
        ret_code = UPNP_E_SOCKET_ERROR;
        goto errorHandler;
    }

    if( sock_init( &handle->sock_info, tcp_connection ) != UPNP_E_SUCCESS )
    {
        sock_destroy( &handle->sock_info, SD_BOTH );
        ret_code = UPNP_E_SOCKET_ERROR;
        goto errorHandler;
    }

    ret_code = connect( handle->sock_info.socket,
                        ( struct sockaddr * )&url.hostport.IPv4address,
                        sizeof( struct sockaddr_in ) );

    if( ret_code == UPNP_SOCKETERROR ) {
#ifdef _WIN32
		DBGONLY(
			UpnpPrintf(UPNP_CRITICAL, HTTP, __FILE__, __LINE__,
			"connect error: %d\n", WSAGetLastError());
		)
#endif
		sock_destroy( &handle->sock_info, SD_BOTH );
        ret_code = UPNP_E_SOCKET_CONNECT;
        goto errorHandler;
    }
    // send request
    ret_code = http_SendMessage( &handle->sock_info, &timeout, "b",
                                 request.buf, request.length );
    if( ret_code != 0 ) {
        sock_destroy( &handle->sock_info, SD_BOTH );
        goto errorHandler;
    }

    status =
        ReadResponseLineAndHeaders( &handle->sock_info, &handle->response,
                                    &timeout, &http_error_code );

    if( status != PARSE_OK ) {
        ret_code = UPNP_E_BAD_RESPONSE;
        goto errorHandler;
    }

    status = parser_get_entity_read_method( &handle->response );

    if( ( status != PARSE_CONTINUE_1 ) && ( status != PARSE_SUCCESS ) ) {
        ret_code = UPNP_E_BAD_RESPONSE;
        goto errorHandler;
    }

    ( *httpStatus ) = handle->response.msg.status_code;
    ret_code = UPNP_E_SUCCESS;

    if( httpmsg_find_hdr( &handle->response.msg, HDR_CONTENT_TYPE, &ctype )
        == NULL ) {
        *contentType = NULL;    // no content-type
    } else {

⌨️ 快捷键说明

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