📄 server.cpp
字号:
/////////////////////////////////////////////////////////////////////////////// Copyright (c) 2000 Intel Corporation// All rights reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are met://// * Redistributions of source code must retain the above copyright notice,// this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above copyright notice,// this list of conditions and the following disclaimer in the documentation// and/or other materials provided with the distribution.// * Neither name of Intel Corporation nor the names of its contributors// may be used to endorse or promote products derived from this software// without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE./////////////////////////////////////////////////////////////////////////////// $Revision: 1.1.1.4 $// $Date: 2001/06/15 00:22:15 $// readwrite.cpp#include "../../inc/tools/config.h"#ifdef INTERNAL_WEB_SERVER#if EXCLUDE_WEB_SERVER == 0#include <stdio.h>#include <string.h>#include <sys/stat.h>#include <genlib/util/util.h>#include <genlib/util/xstring.h>#include <genlib/util/dbllist.h>#include <genlib/net/http/statuscodes.h>#include <genlib/net/http/parseutil.h>#include <genlib/net/http/readwrite.h>#include <genlib/net/http/server.h>#include <genlib/http_client/http_client.h>#include <unistd.h>#include <pthread.h>#define SVRERR_FILE_NOT_FOUND -2#define SVRERR_BAD_FORMAT -3CREATE_NEW_EXCEPTION_TYPE( HttpServerException, BasicException, "HttpServerException" )//////////////////////////////////////////struct AliasedEntity{ xstring alias; xstring contentType; xstring contentSubtype; time_t modifiedTime; HttpEntity* entity; int count; bool stopServing;};//////////////////////////////////////////////CREATE_NEW_EXCEPTION_TYPE( AliasedListException, BasicException, "AliasedListException" )//////////////////////////////////////////////class AliasedEntityList{public: enum { E_SUCCESS = 0, E_NOT_FOUND = -2, E_DUPLICATE = -3, E_CANT_ADD = -5 };public: // throws OutOfMemoryException AliasedEntityList(); virtual ~AliasedEntityList(); // adds the specified aliased entity to the list // // NOTE: 'entity' will be owned by the list // throws: // OutOfMemoryException void addEntity( IN const char* alias, IN HttpEntity* entity, OUT xstring& actualAlias ); // returns entity and its attributes // // throws: // AliasListException.E_NOT_FOUND void grabEntity( IN const char* alias, OUT HttpEntity** entity, OUT xstring& contentType, OUT xstring& contentSubtype, OUT time_t& lastModifiedTime ); // releases entity denoted by the alias // // stopServing: if true, future requests will return NOT FOUND // // throws: // AliasListException.E_NOT_FOUND void releaseEntity( IN const char* alias, bool stopServing = false ); // returns true if the aliased entity is in the list bool isAliasPresent( IN const char* alias );private: // returns NULL if list node associated with alias is not found dblListNode* find( IN const char* alias );private: dblList aliasList; // = list<AliasedEntity> pthread_mutex_t mutex;};// *******************************************************// module vars //////////////// root directory of http server; must not have '/' at the endstatic xstring gRootDocumentDir;static bool gServerActive = false; // serve requests only when activestatic AliasedEntityList gAliasList;////////////////////////////////////////////////////////////////////////static void Free_AliasedEntity( void* al_ent ){ AliasedEntity* ae = (AliasedEntity *)al_ent; assert( ae != NULL ); assert( ae->entity != NULL ); DBG( UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__, "Deleting aliased entity %s\n", ae->alias.c_str()); ) delete ae->entity; delete ae;}//////////////////////////////////////////////static bool Compare_AliasedEntity( void *entityA, void* entityB ){ AliasedEntity *a = (AliasedEntity*) entityA; AliasedEntity *b = (AliasedEntity*) entityB; //DBG( // printf("Compare alias: a = %s, b = %s\n", // a->alias.c_str(), b->alias.c_str() ); //) return a->alias == b->alias;}////////////////////////////////////////// 1) adds leading '/' to entityName if it is absent// 2) returns index of extension in string after the dot// index = -1 if no extension foundstatic int GetExtensionIndex( INOUT xstring& entityName ){ const char *ptr; const char *dot_ptr; const char *save_dot_ptr; int extensionIndex; // doc name starts after last '/' ptr = strrchr( entityName.c_str(), '/' ); if ( ptr == NULL ) { // no '/'; insert one at start entityName.insert( '/', 0 ); ptr = entityName.c_str(); } // precond: ptr points to last '/' assert( *ptr == '/' ); // // look for last '.' // dot_ptr = ptr; save_dot_ptr = NULL; // scan left-to-right so that a dot before '/' is // not detected accidentally while ( true ) { dot_ptr = strchr( dot_ptr, '.' ); if ( dot_ptr == NULL ) { break; } save_dot_ptr = dot_ptr; dot_ptr++; // skip dot } if ( save_dot_ptr == NULL ) { // dot is not present extensionIndex = -1; } else { // determine index of dot in string extensionIndex = save_dot_ptr - entityName.c_str(); } return extensionIndex;}struct FileExtensionType{ char* ext; char* type; char* subtype;};static char* AudioStr = "audio";static char* VideoStr = "video";static char* ImageStr = "image";static char* ApplicationStr = "application";static char* TextStr = "text";#define NUM_MEDIA_TYPES 36static FileExtensionType MediaTypeList[ NUM_MEDIA_TYPES ] ={ { "aif", AudioStr, "x-aiff" }, { "au", AudioStr, "basic" }, { "avi", VideoStr, "msvideo" }, { "bmp", ImageStr, "x-MS-bmp"}, { "gif", ImageStr, "gif" }, { "htm", TextStr, "html" }, { "html", TextStr, "html" }, { "jar", ApplicationStr, "java-archive" }, { "jpeg", ImageStr, "jpeg" }, { "jpg", ImageStr, "jpeg" }, { "jpe", ImageStr, "jpeg" }, { "jfif", ImageStr, "jpeg" }, { "mid", AudioStr, "midi" }, { "midi", AudioStr, "midi" }, { "mp3", AudioStr, "mp3" }, { "mpeg", VideoStr, "mpeg" }, { "mpg", VideoStr, "mpeg" }, { "mpv", VideoStr, "mpeg" }, { "mpe", VideoStr, "mpeg" }, { "mov", VideoStr, "quicktime" }, { "pdf", ApplicationStr, "pdf" }, { "pjp", ImageStr, "jpeg" }, { "pjpeg",ImageStr, "jpeg" }, { "png", ImageStr, "png" }, { "qt", VideoStr, "quicktime" }, { "ram", AudioStr, "x-pn-realaudio" }, { "rmi", AudioStr, "mid" }, { "rmm", AudioStr, "x-pn-realaudio" }, { "shtml",TextStr, "html" }, { "tar", ApplicationStr, "tar" }, { "text", TextStr, "plain" }, { "txt", TextStr, "plain" }, { "wav", AudioStr, "wav" }, { "xml", TextStr, "xml" }, { "xsl", TextStr, "xml" }, { "zip", ApplicationStr, "zip" },};static int SearchExtension( IN const char* fileExtension, IN FileExtensionType* table, IN int size ){ int top, mid, bot; int cmp; top = 0; bot = size - 1; while ( top <= bot ) { mid = ( top + bot ) / 2; cmp = strcasecmp( fileExtension, table[mid].ext ); if ( cmp > 0 ) { top = mid + 1; // look below mid } else if ( cmp < 0 ) { bot = mid - 1; // look above mid } else // cmp == 0 { return mid; // match } } return -1;}// if fileExtension not found, type is application/octet-streamstatic void GetMediaType( IN const char* fileExtension, OUT xstring& contentType, OUT xstring& contentSubtype ){ int index; index = SearchExtension( fileExtension, MediaTypeList, NUM_MEDIA_TYPES ); if ( index == -1 ) { contentType = ApplicationStr; contentType = "octet-stream"; } else { FileExtensionType* ext; assert( index >= 0 && index < NUM_MEDIA_TYPES ); ext = &MediaTypeList[index]; contentType = ext->type; contentSubtype = ext->subtype; }}////////////////////////////////////////// AliasedEntityList////////////////////////////////////////AliasedEntityList::AliasedEntityList() : aliasList( Free_AliasedEntity, Compare_AliasedEntity ){ if ( pthread_mutex_init(&mutex, NULL) != 0 ) { throw OutOfMemoryException( "AliasedEntityList::AliasedEntityList()" ); }}////////////////////////////////////////AliasedEntityList::~AliasedEntityList(){ while ( pthread_mutex_destroy(&mutex) == EBUSY ) { // highly unlikely -- but still possible to return EBUSY sleep( 1 ); }}////////////////////////////////////////void AliasedEntityList::addEntity( IN const char* alias, IN HttpEntity* entity, OUT xstring& actualAlias ){ dblListNode *node; AliasedEntity* ae; int eCode = 0; int dot_index; xstring contentType, contentSubtype; assert( alias != NULL ); assert( entity != NULL ); pthread_mutex_lock( &mutex ); try { ae = new AliasedEntity; if ( ae == NULL ) { throw -5; // no mem } actualAlias = alias; dot_index = GetExtensionIndex( actualAlias ); node = find( actualAlias.c_str() ); if ( node != NULL ) { // duplicate alias // add id to make it unique // allocated entity -- to -- integer string char buf[50]; sprintf( buf, "-%u", (unsigned)ae ); if ( dot_index == -1 ) { actualAlias += buf; // no dot; append } else { actualAlias.insert( buf, dot_index );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -