📄 webserver.c
字号:
StrTok( char **Src,
char *Del )
{
char *TmpPtr,
*RetPtr;
if( *Src != NULL ) {
RetPtr = *Src;
TmpPtr = strstr( *Src, Del );
if( TmpPtr != NULL ) {
*TmpPtr = '\0';
*Src = TmpPtr + strlen( Del );
} else
*Src = NULL;
return RetPtr;
}
return NULL;
}
/************************************************************************
* Function: GetNextRange
*
* Parameters:
* IN char ** SrcRangeStr ; string containing the token / range
* OUT int * FirstByte ; gets the first byte of the token
* OUT int * LastByte ; gets the last byte of the token
*
* Description: Returns a range of integers from a sring
*
* Returns: int ;
* always returns 1;
************************************************************************/
int
GetNextRange( char **SrcRangeStr,
int *FirstByte,
int *LastByte )
{
char *Ptr,
*Tok;
int i,
F = -1,
L = -1;
int Is_Suffix_byte_Range = 1;
if( *SrcRangeStr == NULL )
return -1;
Tok = StrTok( SrcRangeStr, "," );
if( ( Ptr = strstr( Tok, "-" ) ) == NULL )
return -1;
*Ptr = ' ';
sscanf( Tok, "%d%d", &F, &L );
if( F == -1 || L == -1 ) {
*Ptr = '-';
for( i = 0; i < ( int )strlen( Tok ); i++ ) {
if( Tok[i] == '-' ) {
break;
} else if( isdigit( Tok[i] ) ) {
Is_Suffix_byte_Range = 0;
break;
}
}
if( Is_Suffix_byte_Range ) {
*FirstByte = L;
*LastByte = F;
return 1;
}
}
*FirstByte = F;
*LastByte = L;
return 1;
}
/************************************************************************
* Function: CreateHTTPRangeResponseHeader
*
* Parameters:
* char * ByteRangeSpecifier ; String containing the range
* long FileLength ; Length of the file
* OUT struct SendInstruction * Instr ; SendInstruction object where the
* range operations will be stored
*
* Description: Fills in the Offset, read size and contents to send out
* as an HTTP Range Response
*
* Returns:
* HTTP_BAD_REQUEST
* UPNP_E_OUTOF_MEMORY
* HTTP_REQUEST_RANGE_NOT_SATISFIABLE
* HTTP_OK
************************************************************************/
int
CreateHTTPRangeResponseHeader( char *ByteRangeSpecifier,
long FileLength,
OUT struct SendInstruction *Instr )
{
int FirstByte,
LastByte;
char *RangeInput,
*Ptr;
Instr->IsRangeActive = 1;
Instr->ReadSendSize = FileLength;
if( !ByteRangeSpecifier )
return HTTP_BAD_REQUEST;
RangeInput = malloc( strlen( ByteRangeSpecifier ) + 1 );
if( !RangeInput )
return UPNP_E_OUTOF_MEMORY;
strcpy( RangeInput, ByteRangeSpecifier );
//CONTENT-RANGE: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT
if( StrStr( RangeInput, "bytes" ) == NULL ||
( Ptr = StrStr( RangeInput, "=" ) ) == NULL ) {
free( RangeInput );
Instr->IsRangeActive = 0;
return HTTP_BAD_REQUEST;
}
//Jump =
Ptr = Ptr + 1;
if( FileLength < 0 ) {
free( RangeInput );
return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
}
if( GetNextRange( &Ptr, &FirstByte, &LastByte ) != -1 ) {
if( FileLength < FirstByte ) {
free( RangeInput );
return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
}
if( FirstByte >= 0 && LastByte >= 0 && LastByte >= FirstByte ) {
if( LastByte >= FileLength )
LastByte = FileLength - 1;
Instr->RangeOffset = FirstByte;
Instr->ReadSendSize = LastByte - FirstByte + 1;
sprintf( Instr->RangeHeader, "CONTENT-RANGE: bytes %d-%d/%ld\r\n", FirstByte, LastByte, FileLength ); //Data between two range.
} else if( FirstByte >= 0 && LastByte == -1
&& FirstByte < FileLength ) {
Instr->RangeOffset = FirstByte;
Instr->ReadSendSize = FileLength - FirstByte;
sprintf( Instr->RangeHeader,
"CONTENT-RANGE: bytes %d-%ld/%ld\r\n", FirstByte,
FileLength - 1, FileLength );
} else if( FirstByte == -1 && LastByte > 0 ) {
if( LastByte >= FileLength ) {
Instr->RangeOffset = 0;
Instr->ReadSendSize = FileLength;
sprintf( Instr->RangeHeader,
"CONTENT-RANGE: bytes 0-%ld/%ld\r\n",
FileLength - 1, FileLength );
} else {
Instr->RangeOffset = FileLength - LastByte;
Instr->ReadSendSize = LastByte;
sprintf( Instr->RangeHeader,
"CONTENT-RANGE: bytes %ld-%ld/%ld\r\n",
FileLength - LastByte + 1, FileLength,
FileLength );
}
} else {
free( RangeInput );
return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
}
} else {
free( RangeInput );
return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
}
free( RangeInput );
return HTTP_OK;
}
/************************************************************************
* Function: CheckOtherHTTPHeaders
*
* Parameters:
* IN http_message_t * Req ; HTTP Request message
* OUT struct SendInstruction * RespInstr ; Send Instruction object to
* data for the response
* int FileSize ; Size of the file containing the request document
*
* Description: Get header id from the request parameter and take
* appropriate action based on the ids.
* as an HTTP Range Response
*
* Returns:
* HTTP_BAD_REQUEST
* UPNP_E_OUTOF_MEMORY
* HTTP_REQUEST_RANGE_NOT_SATISFIABLE
* HTTP_OK
************************************************************************/
int
CheckOtherHTTPHeaders( IN http_message_t * Req,
OUT struct SendInstruction *RespInstr,
int FileSize )
{
http_header_t *header;
ListNode *node;
//NNS: dlist_node* node;
int index,
RetCode = HTTP_OK;
char *TmpBuf;
TmpBuf = ( char * )malloc( LINE_SIZE );
if( !TmpBuf )
return UPNP_E_OUTOF_MEMORY;
node = ListHead( &Req->headers );
while( node != NULL ) {
header = ( http_header_t * ) node->item;
// find header type.
index = map_str_to_int( ( const char * )header->name.buf,
header->name.length, Http_Header_Names,
NUM_HTTP_HEADER_NAMES, FALSE );
if( header->value.length >= LINE_SIZE ) {
free( TmpBuf );
TmpBuf = ( char * )malloc( header->value.length + 1 );
if( !TmpBuf )
return UPNP_E_OUTOF_MEMORY;
}
memcpy( TmpBuf, header->value.buf, header->value.length );
TmpBuf[header->value.length] = '\0';
if( index >= 0 )
switch ( Http_Header_Names[index].id ) {
case HDR_TE: //Request
{
RespInstr->IsChunkActive = 1;
if( strlen( TmpBuf ) > strlen( "gzip" ) ) {
if( StrStr( TmpBuf, "trailers" ) != NULL ) { //means client will accept trailer
RespInstr->IsTrailers = 1;
}
}
}
break;
case HDR_CONTENT_LENGTH:
{
RespInstr->RecvWriteSize = atoi( TmpBuf );
break;
}
case HDR_RANGE:
if( ( RetCode = CreateHTTPRangeResponseHeader( TmpBuf,
FileSize,
RespInstr ) )
!= HTTP_OK ) {
free( TmpBuf );
return RetCode;
}
break;
default:
/*
TODO
*/
/*
header.value is the value.
*/
/*
case HDR_CONTENT_TYPE: //return 1;
case HDR_CONTENT_LANGUAGE://return 1;
case HDR_LOCATION: //return 1;
case HDR_CONTENT_LOCATION://return 1;
case HDR_ACCEPT: //return 1;
case HDR_ACCEPT_CHARSET://return 1;
case HDR_ACCEPT_LANGUAGE://return 1;
case HDR_USER_AGENT: break;//return 1;
*/
//Header check for encoding
/*
case HDR_ACCEPT_RANGE: //Server capability.
case HDR_CONTENT_RANGE://Response.
case HDR_IF_RANGE:
*/
//Header check for encoding
/*
case HDR_ACCEPT_ENCODING:
if(StrStr(TmpBuf, "identity"))
{
break;
}
else return -1;
case HDR_CONTENT_ENCODING:
case HDR_TRANSFER_ENCODING: //Response
*/
break;
}
node = ListNext( &Req->headers, node );
}
free( TmpBuf );
return RetCode;
}
/************************************************************************
* Function: process_request
*
* Parameters:
* IN http_message_t *req ; HTTP Request message
* OUT enum resp_type *rtype ; Tpye of response
* OUT membuffer *headers ;
* OUT membuffer *filename ; Get filename from request document
* OUT struct xml_alias_t *alias ; Xml alias document from the
* request document,
* OUT struct SendInstruction * RespInstr ; Send Instruction object
* where the response is set up.
*
* Description: Processes the request and returns the result in the OUT
* parameters
*
* Returns:
* HTTP_BAD_REQUEST
* UPNP_E_OUTOF_MEMORY
* HTTP_REQUEST_RANGE_NOT_SATISFIABLE
* HTTP_OK
************************************************************************/
static int
process_request( IN http_message_t * req,
OUT enum resp_type *rtype,
OUT membuffer * headers,
OUT membuffer * filename,
OUT struct xml_alias_t *alias,
OUT struct SendInstruction *RespInstr )
{
int code;
int err_code;
//membuffer content_type;
char *request_doc;
struct File_Info finfo;
xboolean using_alias;
xboolean using_virtual_dir;
uri_type *url;
char *temp_str;
int resp_major,
resp_minor;
xboolean alias_grabbed;
int dummy;
struct UpnpVirtualDirCallbacks *pVirtualDirCallback;
print_http_headers( req );
url = &req->uri;
assert( req->method == HTTPMETHOD_GET ||
req->method == HTTPMETHOD_HEAD
|| req->method == HTTPMETHOD_POST
|| req->method == HTTPMETHOD_SIMPLEGET );
// init
request_doc = NULL;
finfo.content_type = NULL;
//membuffer_init( &content_type );
alias_grabbed = FALSE;
err_code = HTTP_INTERNAL_SERVER_ERROR; // default error
using_virtual_dir = FALSE;
using_alias = FALSE;
http_CalcResponseVersion( req->major_version, req->minor_version,
&resp_major, &resp_minor );
//
// remove dots
//
request_doc = malloc( url->pathquery.size + 1 );
if( request_doc == NULL ) {
goto error_handler; // out of mem
}
memcpy( request_doc, url->pathquery.buff, url->pathquery.size );
request_doc[url->pathquery.size] = '\0';
dummy = url->pathquery.size;
remove_escaped_chars( request_doc, &dummy );
code = remove_dots( request_doc, url->pathquery.size );
if( code != 0 ) {
err_code = HTTP_FORBIDDEN;
goto error_handler;
}
if( *request_doc != '/' ) {
// no slash
err_code = HTTP_BAD_REQUEST;
goto error_handler;
}
if( isFileInVirtualDir( request_doc ) ) {
using_virtual_dir = TRUE;
RespInstr->IsVirtualFile = 1;
if( membuffer_assign_str( filename, request_doc ) != 0 ) {
goto error_handler;
}
} else {
//
// try using alias
//
#ifdef _ALIASDOC
if( is_valid_alias( &gAliasDoc ) ) {
alias_grab( alias );
alias_grabbed = TRUE;
using_alias = get_alias( request_doc, alias, &finfo );
#else
using_alias = getAliasFromDict( request_doc, alias, &finfo );
#endif
if( using_alias == TRUE ) {
alias_grabbed = TRUE;
finfo.content_type = ixmlCloneDOMString( "text/xml" );
if( finfo.content_type == NULL ) {
goto error_handler;
}
}
#ifdef _ALIASDOC
}
#endif
}
if( using_virtual_dir ) {
if( req->method != HTTPMETHOD_POST ) {
// get file info
pVirtualDirCallback = &virtualDirCallback;
if( pVirtualDirCallback->get_info( filename->buf, &finfo ) !=
0 ) {
err_code = HTTP_NOT_FOUND;
goto error_handler;
}
// try index.html if req is a dir
if( finfo.is_directory ) {
if( filename->buf[filename->length - 1] == '/' ) {
temp_str = "index.html";
} else {
temp_str = "/index.html";
}
if( membuffer_append_str( filename, temp_str ) != 0 ) {
goto error_handler;
}
// get info
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -