📄 webserver.c
字号:
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 ************************************************************************/intCreateHTTPRangeResponseHeader( 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 ************************************************************************/intCheckOtherHTTPHeaders( 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 intprocess_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 // if( is_valid_alias( &gAliasDoc ) ) { alias_grab( alias ); alias_grabbed = TRUE; using_alias = get_alias( request_doc, alias, &finfo ); if( using_alias == TRUE ) { finfo.content_type = ixmlCloneDOMString( "text/xml" ); if( finfo.content_type == NULL ) { goto error_handler; } } } } 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 if( ( pVirtualDirCallback-> get_info( filename->buf, &finfo ) != UPNP_E_SUCCESS ) || finfo.is_directory ) { err_code = HTTP_NOT_FOUND; goto error_handler; } } // not readable if( !finfo.is_readable ) { err_code = HTTP_FORBIDDEN; goto error_handler; } // finally, get content type // if ( get_content_type(filename->buf, &content_type) != 0 ) //{ // goto error_handler; // } } } else if( !using_alias ) { if( gDocumentRootDir.length == 0 ) { goto error_handler; } // // get file name //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -