📄 httpreadwrite.c
字号:
*contentType = ctype.buf;
}
if( handle->response.position == POS_COMPLETE ) {
( *contentLength ) = 0;
} else if( handle->response.ent_position == ENTREAD_USING_CHUNKED ) {
( *contentLength ) = UPNP_USING_CHUNKED;
} else if( handle->response.ent_position == ENTREAD_USING_CLEN ) {
( *contentLength ) = handle->response.content_length;
} else if( handle->response.ent_position == ENTREAD_UNTIL_CLOSE ) {
( *contentLength ) = UPNP_UNTIL_CLOSE;
}
errorHandler:
( *Handle ) = handle;
membuffer_destroy( &request );
if( ret_code != UPNP_E_SUCCESS ) {
httpmsg_destroy( &handle->response.msg );
}
return ret_code;
}
/************************************************************************
* Function : http_SendStatusResponse
*
* Parameters :
* IN SOCKINFO *info : Socket information object
* IN int http_status_code : error code returned while making
* or sending the response message
* IN int request_major_version : request major version
* IN int request_minor_version : request minor version
*
* Description : Generate a response message for the status query and
* send the status response.
*
* Return : int;
* 0 -- success
* UPNP_E_OUTOF_MEMORY
* UPNP_E_SOCKET_WRITE
* UPNP_E_TIMEDOUT
*
* Note :
************************************************************************/
int
http_SendStatusResponse( IN SOCKINFO * info,
IN int http_status_code,
IN int request_major_version,
IN int request_minor_version )
{
int response_major,
response_minor;
membuffer membuf;
int ret;
int timeout;
http_CalcResponseVersion( request_major_version, request_minor_version,
&response_major, &response_minor );
membuffer_init( &membuf );
membuf.size_inc = 70;
ret = http_MakeMessage( &membuf, response_major, response_minor, "RSCB", http_status_code, // response start line
http_status_code ); // body
if( ret == 0 ) {
timeout = HTTP_DEFAULT_TIMEOUT;
ret = http_SendMessage( info, &timeout, "b",
membuf.buf, membuf.length );
}
membuffer_destroy( &membuf );
return ret;
}
/************************************************************************
* Function : http_MakeMessage
*
* Parameters :
* INOUT membuffer* buf : buffer with the contents of the
* message
* IN int http_major_version : HTTP major version
* IN int http_minor_version : HTTP minor version
* IN const char* fmt : Pattern format
* ... :
*
* Description : Generate an HTTP message based on the format that is
* specified in the input parameters.
*
* fmt types:
* 's': arg = const char* C_string
* 'b': arg1 = const char* buf; arg2 = size_t buf_length
* memory ptr
* 'c': (no args) appends CRLF "\r\n"
* 'd': arg = int number // appends decimal number
* 't': arg = time_t * gmt_time // appends time in RFC 1123 fmt
* 'D': (no args) appends HTTP DATE: header
* 'S': (no args) appends HTTP SERVER: header
* 'U': (no args) appends HTTP USER-AGENT: header
* 'C': (no args) appends a HTTP CONNECTION: close header
* depending on major,minor version
* 'N': arg1 = int content_length // content-length header
* 'Q': arg1 = http_method_t; arg2 = char* url;
* arg3 = int url_length // start line of request
* 'R': arg = int status_code // adds a response start line
* 'B': arg = int status_code
* appends content-length, content-type and HTML body for given code
* 'T': arg = char * content_type; format e.g: "text/html";
* content-type header
*
* Return : int;
* 0 - On Success
* UPNP_E_OUTOF_MEMORY
* UPNP_E_INVALID_URL;
*
* Note :
************************************************************************/
int
http_MakeMessage( INOUT membuffer * buf,
IN int http_major_version,
IN int http_minor_version,
IN const char *fmt,
... )
{
char c;
char *s = NULL;
int num;
size_t length;
time_t *loc_time;
time_t curr_time;
struct tm *date;
char *start_str,
*end_str;
int status_code;
const char *status_msg;
http_method_t method;
const char *method_str;
const char *url_str;
const char *temp_str;
uri_type url;
uri_type *uri_ptr;
int error_code = UPNP_E_OUTOF_MEMORY;
va_list argp;
char tempbuf[200];
const char *weekday_str = "Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat";
const char *month_str = "Jan\0Feb\0Mar\0Apr\0May\0Jun\0"
"Jul\0Aug\0Sep\0Oct\0Nov\0Dec";
va_start( argp, fmt );
while( ( c = *fmt++ ) != 0 ) {
if( c == 's' ) // C string
{
s = ( char * )va_arg( argp, char * );
assert( s );
//DBGONLY(UpnpPrintf(UPNP_ALL,HTTP,__FILE__,__LINE__,"Adding a string : %s\n", s);)
if( membuffer_append( buf, s, strlen( s ) ) != 0 ) {
goto error_handler;
}
} else if( c == 'K' ) // Add Chunky header
{
if( membuffer_append
( buf, "TRANSFER-ENCODING: chunked\r\n",
strlen( "Transfer-Encoding: chunked\r\n" ) ) != 0 ) {
goto error_handler;
}
} else if( c == 'G' ) // Add Range header
{
struct SendInstruction *RespInstr;
RespInstr =
( struct SendInstruction * )va_arg( argp,
struct SendInstruction
* );
assert( RespInstr );
// connection header
if( membuffer_append
( buf, RespInstr->RangeHeader,
strlen( RespInstr->RangeHeader ) ) != 0 ) {
goto error_handler;
}
} else if( c == 'b' ) // mem buffer
{
s = ( char * )va_arg( argp, char * );
//DBGONLY(UpnpPrintf(UPNP_ALL,HTTP,__FILE__,__LINE__,"Adding a char Buffer starting with: %c\n", s[0]);)
assert( s );
length = ( size_t ) va_arg( argp, size_t );
if( membuffer_append( buf, s, length ) != 0 ) {
goto error_handler;
}
}
else if( c == 'c' ) // crlf
{
if( membuffer_append( buf, "\r\n", 2 ) != 0 ) {
goto error_handler;
}
}
else if( c == 'd' ) // integer
{
num = ( int )va_arg( argp, int );
sprintf( tempbuf, "%d", num );
if( membuffer_append( buf, tempbuf, strlen( tempbuf ) ) != 0 ) {
goto error_handler;
}
}
else if( c == 't' || c == 'D' ) // date
{
if( c == 'D' ) {
// header
start_str = "DATE: ";
end_str = "\r\n";
curr_time = time( NULL );
date = gmtime( &curr_time );
} else {
// date value only
start_str = end_str = "";
loc_time = ( time_t * ) va_arg( argp, time_t * );
assert( loc_time );
date = gmtime( loc_time );
}
sprintf( tempbuf, "%s%s, %02d %s %d %02d:%02d:%02d GMT%s",
start_str,
&weekday_str[date->tm_wday * 4], date->tm_mday,
&month_str[date->tm_mon * 4], date->tm_year + 1900,
date->tm_hour, date->tm_min, date->tm_sec, end_str );
if( membuffer_append( buf, tempbuf, strlen( tempbuf ) ) != 0 ) {
goto error_handler;
}
}
else if( c == 'C' ) {
if( ( http_major_version > 1 ) ||
( http_major_version == 1 && http_minor_version == 1 )
) {
// connection header
if( membuffer_append_str( buf, "CONNECTION: close\r\n" ) !=
0 ) {
goto error_handler;
}
}
}
else if( c == 'N' ) {
// content-length header
num = ( int )va_arg( argp, int );
assert( num >= 0 );
if( http_MakeMessage
( buf, http_major_version, http_minor_version, "sdc",
"CONTENT-LENGTH: ", num ) != 0 ) {
goto error_handler;
}
}
else if( c == 'S' || c == 'U' ) {
// SERVER or USER-AGENT header
temp_str = ( c == 'S' ) ? "SERVER: " : "USER-AGENT: ";
get_sdk_info( tempbuf, 200 );
if( http_MakeMessage
( buf, http_major_version, http_minor_version, "ss",
temp_str, tempbuf ) != 0 ) {
goto error_handler;
}
}
else if( c == 'R' ) {
// response start line
// e.g.: 'HTTP/1.1 200 OK'
//
// code
status_code = ( int )va_arg( argp, int );
assert( status_code > 0 );
sprintf( tempbuf, "HTTP/%d.%d %d ",
http_major_version, http_minor_version, status_code );
// str
status_msg = http_get_code_text( status_code );
if( http_MakeMessage
( buf, http_major_version, http_minor_version, "ssc",
tempbuf, status_msg ) != 0 ) {
goto error_handler;
}
}
else if( c == 'B' ) {
// body of a simple reply
//
status_code = ( int )va_arg( argp, int );
sprintf( tempbuf, "%s%d %s%s",
"<html><body><h1>",
status_code, http_get_code_text( status_code ),
"</h1></body></html>" );
num = strlen( tempbuf );
if( http_MakeMessage( buf, http_major_version, http_minor_version, "NTcs", num, // content-length
"text/html", // content-type
tempbuf ) != 0 ) // body
{
goto error_handler;
}
}
else if( c == 'Q' ) {
// request start line
// GET /foo/bar.html HTTP/1.1\r\n
//
method = ( http_method_t ) va_arg( argp, http_method_t );
method_str = method_to_str( method );
url_str = ( const char * )va_arg( argp, const char * );
num = ( int )va_arg( argp, int ); // length of url_str
if( http_MakeMessage( buf, http_major_version, http_minor_version, "ssbsdsdc", method_str, // method
" ", url_str, num, // url
" HTTP/", http_major_version, ".",
http_minor_version ) != 0 ) {
goto error_handler;
}
}
else if( c == 'q' ) {
// request start line and HOST header
method = ( http_method_t ) va_arg( argp, http_method_t );
uri_ptr = ( uri_type * ) va_arg( argp, uri_type * );
assert( uri_ptr );
if( http_FixUrl( uri_ptr, &url ) != 0 ) {
error_code = UPNP_E_INVALID_URL;
printf("http_FixURL failed\n");
goto error_handler;
}
if( http_MakeMessage
( buf, http_major_version, http_minor_version, "Q" "sbc",
method, url.pathquery.buff, url.pathquery.size, "HOST: ",
url.hostport.text.buff, url.hostport.text.size ) != 0 ) {
goto error_handler;
}
}
else if( c == 'T' ) {
// content type header
temp_str = ( const char * )va_arg( argp, const char * ); // type/subtype format
if( http_MakeMessage
( buf, http_major_version, http_minor_version, "ssc",
"CONTENT-TYPE: ", temp_str ) != 0 ) {
goto error_handler;
}
}
else {
assert( 0 );
}
}
return 0;
error_handler:
va_end( argp );
membuffer_destroy( buf );
return error_code;
}
/************************************************************************
* Function : http_CalcResponseVersion
*
* Parameters :
* IN int request_major_vers : Request major version
* IN int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -