📄 httpreadwrite.c
字号:
amount_to_be_read, Fp );
}
amount_to_be_read = amount_to_be_read - num_read;
if( Instr->ReadSendSize < 0 ) {
//read until close
amount_to_be_read = Data_Buf_Size;
}
} else {
num_read = fread( file_buf, 1, Data_Buf_Size, Fp );
}
if( num_read == 0 ) // EOF so no more to send.
{
if( Instr && Instr->IsChunkActive ) {
num_written = sock_write( info, "0\r\n\r\n",
strlen( "0\r\n\r\n" ),
TimeOut );
} else {
RetVal = UPNP_E_FILE_READ_ERROR;
}
goto Cleanup_File;
}
// Create chunk for the current buffer.
if( Instr && Instr->IsChunkActive ) {
//Copy CRLF at the end of the chunk
memcpy( file_buf + num_read, "\r\n", 2 );
//Hex length for the chunk size.
sprintf( Chunk_Header, "%x", num_read );
//itoa(num_read,Chunk_Header,16);
strcat( Chunk_Header, "\r\n" );
//Copy the chunk size header
memcpy( file_buf - strlen( Chunk_Header ),
Chunk_Header, strlen( Chunk_Header ) );
// on the top of the buffer.
//file_buf[num_read+strlen(Chunk_Header)] = NULL;
//printf("Sending %s\n",file_buf-strlen(Chunk_Header));
num_written = sock_write( info,
file_buf -
strlen( Chunk_Header ),
num_read +
strlen( Chunk_Header ) + 2,
TimeOut );
if( num_written !=
num_read + ( int )strlen( Chunk_Header )
+ 2 ) {
goto Cleanup_File; //Send error nothing we can do.
}
} else {
// write data
num_written = sock_write( info, file_buf, num_read,
TimeOut );
DBGONLY( UpnpPrintf
( UPNP_INFO, HTTP, __FILE__, __LINE__,
">>> (SENT) >>>\n%.*s\n------------\n",
( int )num_written, file_buf );
)
//Send error nothing we can do
if( num_written != num_read ) {
goto Cleanup_File;
}
}
} //While
Cleanup_File:
va_end( argp );
if( Instr && Instr->IsVirtualFile )
virtualDirCallback.close( Fp );
else
fclose( Fp );
free( ChunkBuf );
return RetVal;
} else if( c == 'b' ) { // memory buffer
buf = ( char * )va_arg( argp, char * );
buf_length = ( size_t ) va_arg( argp, size_t );
if( buf_length > 0 ) {
num_written = sock_write( info, buf, buf_length, TimeOut );
DBGONLY( UpnpPrintf( UPNP_INFO, HTTP, __FILE__, __LINE__,
">>> num bytes sent = %d\n----------\n",
num_written);
)
if( ( size_t ) num_written != buf_length )
goto end;
DBGONLY( UpnpPrintf( UPNP_INFO, HTTP, __FILE__, __LINE__,
">>> (SENT) >>>\n%.*s\n------------\n",
( int )buf_length, buf );
)
}
}
}
end:
va_end( argp );
free( ChunkBuf );
return 0;
}
/************************************************************************
* Function: http_RequestAndResponse
*
* Parameters:
* IN uri_type* destination ; Destination URI object which contains
* remote IP address among other elements
* IN const char* request ; Request to be sent
* IN size_t request_length ; Length of the request
* IN http_method_t req_method ; HTTP Request method
* IN int timeout_secs ; time out value
* OUT http_parser_t* response ; Parser object to receive the repsonse
*
* Description: Initiates socket, connects to the destination, sends a
* request and waits for the response from the remote end
*
* Returns:
* UPNP_E_SOCKET_ERROR
* UPNP_E_SOCKET_CONNECT
* Error Codes returned by http_SendMessage
* Error Codes returned by http_RecvMessage
************************************************************************/
int
http_RequestAndResponse( IN uri_type * destination,
IN const char *request,
IN size_t request_length,
IN http_method_t req_method,
IN int timeout_secs,
OUT http_parser_t * response )
{
SOCKET tcp_connection;
int ret_code;
int http_error_code;
#ifdef _WIN32
int retVal;
#endif
SOCKINFO info;
tcp_connection = socket( AF_INET, SOCK_STREAM, 0 );
if( tcp_connection == UPNP_INVALID_SOCKET ) {
parser_response_init( response, req_method );
return UPNP_E_SOCKET_ERROR;
}
if( sock_init( &info, tcp_connection ) != UPNP_E_SUCCESS )
{
sock_destroy( &info, SD_BOTH );
parser_response_init( response, req_method );
return UPNP_E_SOCKET_ERROR;
}
// connect
ret_code = connect( info.socket,
( struct sockaddr * )&destination->hostport.
IPv4address, sizeof( struct sockaddr_in ) );
if( ret_code == UPNP_SOCKETERROR ) {
#ifdef _WIN32
retVal = WSAGetLastError();
DBGONLY(
UpnpPrintf(UPNP_CRITICAL, HTTP, __FILE__, __LINE__,
"connect error: %d\n", retVal);
)
#endif
sock_destroy( &info, SD_BOTH );
parser_response_init( response, req_method );
return UPNP_E_SOCKET_CONNECT;
}
// send request
ret_code = http_SendMessage( &info, &timeout_secs, "b",
request, request_length );
if( ret_code != 0 ) {
sock_destroy( &info, SD_BOTH );
parser_response_init( response, req_method );
return ret_code;
}
// recv response
ret_code = http_RecvMessage( &info, response, req_method,
&timeout_secs, &http_error_code );
sock_destroy( &info, SD_BOTH ); //should shutdown completely
return ret_code;
}
/************************************************************************
* Function : http_Download
*
* Parameters :
* IN const char* url_str : String as a URL
* IN int timeout_secs : time out value
* OUT char** document : buffer to store the document extracted
* from the donloaded message.
* OUT int* doc_length : length of the extracted document
* OUT char* content_type : Type of content
*
* Description : Download the document message and extract the document
* from the message.
*
* Return : int;
* UPNP_E_SUCCESS;
* UPNP_E_INVALID_URL;
*
*
* Note :
************************************************************************/
int
http_Download( IN const char *url_str,
IN int timeout_secs,
OUT char **document,
OUT int *doc_length,
OUT char *content_type )
{
int ret_code;
uri_type url;
char *msg_start,
*entity_start,
*hoststr,
*temp;
http_parser_t response;
size_t msg_length,
hostlen;
memptr ctype;
size_t copy_len;
membuffer request;
char *urlPath = alloca( strlen( url_str ) + 1 );
//ret_code = parse_uri( (char*)url_str, strlen(url_str), &url );
DBGONLY( UpnpPrintf
( UPNP_INFO, HTTP, __FILE__, __LINE__, "DOWNLOAD URL : %s\n",
url_str );
)
ret_code =
http_FixStrUrl( ( char * )url_str, strlen( url_str ), &url );
if( ret_code != UPNP_E_SUCCESS ) {
return ret_code;
}
// make msg
membuffer_init( &request );
strcpy( urlPath, url_str );
hoststr = strstr( urlPath, "//" );
if( hoststr == NULL ) {
return UPNP_E_INVALID_URL;
}
hoststr += 2;
temp = strchr( hoststr, '/' );
if( temp == NULL ) {
return UPNP_E_INVALID_URL;
}
*temp = '\0';
hostlen = strlen( hoststr );
*temp = '/';
DBGONLY( UpnpPrintf
( UPNP_INFO, HTTP, __FILE__, __LINE__,
"HOSTNAME : %s Length : %d\n", hoststr, hostlen );
)
ret_code = http_MakeMessage( &request, 1, 1, "QsbcDCUc",
HTTPMETHOD_GET, url.pathquery.buff,
url.pathquery.size, "HOST: ", hoststr,
hostlen );
if( ret_code != 0 ) {
DBGONLY( UpnpPrintf
( UPNP_INFO, HTTP, __FILE__, __LINE__,
"HTTP Makemessage failed\n" );
)
membuffer_destroy( &request );
return ret_code;
}
DBGONLY( UpnpPrintf
( UPNP_INFO, HTTP, __FILE__, __LINE__,
"HTTP Buffer:\n %s\n----------END--------\n", request.buf );
)
// get doc msg
ret_code =
http_RequestAndResponse( &url, request.buf, request.length,
HTTPMETHOD_GET, timeout_secs, &response );
if( ret_code != 0 ) {
httpmsg_destroy( &response.msg );
membuffer_destroy( &request );
return ret_code;
}
DBGONLY( UpnpPrintf
( UPNP_INFO, HTTP, __FILE__, __LINE__, "Response\n" );
)
DBGONLY( print_http_headers( &response.msg );
)
// optional content-type
if( content_type ) {
if( httpmsg_find_hdr( &response.msg, HDR_CONTENT_TYPE, &ctype ) ==
NULL ) {
*content_type = '\0'; // no content-type
} else {
// safety
copy_len = ctype.length < LINE_SIZE - 1 ?
ctype.length : LINE_SIZE - 1;
memcpy( content_type, ctype.buf, copy_len );
content_type[copy_len] = '\0';
}
}
//
// extract doc from msg
//
if( ( *doc_length = ( int )response.msg.entity.length ) == 0 ) {
// 0-length msg
*document = NULL;
} else if( response.msg.status_code == HTTP_OK ) //LEAK_FIX_MK
{
// copy entity
entity_start = response.msg.entity.buf; // what we want
msg_length = response.msg.msg.length; // save for posterity
msg_start = membuffer_detach( &response.msg.msg ); // whole msg
// move entity to the start; copy null-terminator too
memmove( msg_start, entity_start, *doc_length + 1 );
// save mem for body only
*document = realloc( msg_start, *doc_length + 1 ); //LEAK_FIX_MK
//*document = Realloc( msg_start,msg_length, *doc_length + 1 );//LEAK_FIX_MK
// shrink can't fail
assert( ( int )msg_length > *doc_length );
assert( *document != NULL );
}
if( response.msg.status_code == HTTP_OK ) {
ret_code = 0; // success
} else {
// server sent error msg (not requested doc)
ret_code = response.msg.status_code;
}
httpmsg_destroy( &response.msg );
membuffer_destroy( &request );
return ret_code;
}
typedef struct HTTPPOSTHANDLE {
SOCKINFO sock_info;
int contentLength;
} http_post_handle_t;
/************************************************************************
* Function: MakePostMessage
*
* Parameters:
* const char *url_str ; String as a URL
* membuffer *request ; Buffer containing the request
* uri_type *url ; URI object containing the scheme, path
* query token, etc.
* int contentLength ; length of content
* const char *contentType ; Type of content
*
* Description: Makes the message for the HTTP POST message
*
* Returns:
* UPNP_E_INVALID_URL
* UPNP_E_INVALID_PARAM
* UPNP_E_SUCCESS
************************************************************************/
int
MakePostMessage( const char *url_str,
membuffer * request,
uri_type * url,
int contentLength,
const char *contentType )
{
int ret_code = 0;
char *urlPath = alloca( strlen( url_str ) + 1 );
int hostlen = 0;
char *hoststr,
*temp;
DBGONLY( UpnpPrintf( UPNP_INFO, HTTP, __FILE__, __LINE__,
"DOWNLOAD URL : %s\n", url_str );
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -