📄 httpreadwrite.c
字号:
* 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 + -