⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 siteroot.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        int iTmp;

		PIDB *pR = tPIHTTP.pResponseDB;
		PIDB *pQ = tPIHTTP.pRequestDB;

        /*
        ** Verify the content length and content type for
        ** sanity
        */
        const char *pContentLength = (const char *)
            PIDB_lookup( pQ, PIDBTYPE_RFC822, KEY_HTTP_CONTENTLENGTH, 0 );
        const char *pContentType = (const char *)
            PIDB_lookup( pQ, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE, 0 );
        int iContentLength = pContentLength ? atoi( pContentLength ) : 0;
        if ( iContentLength<=0 || !pContentType ||
            PIUtil_stricmp( pContentType, ADMIN_CONTENTTYPE ) )
            {
            HTTPCore_logError( &tPIHTTP, "%s", "SiteRoot: \
Bad body content headers or bad length or configuration file." );
            return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
            };
        /*
        ** Attempt to open the file
        */
        PIPLATFORM_FD tFd = PIFile_open( sConfigFileTmp, "wn" );
        if ( tFd == PIPLATFORM_FD_INVALID )
            {
            HTTPCore_logError( &tPIHTTP, "SiteRoot: \
Failed to open configuration temporary file '%s' for writing. Perhaps the \
configuration is being updated by two administrators at the same time. \
Configuration file upload failed.", 
                (const char *)sConfigFileTmp );
            SwallowInput( tPIHTTP.pBuffer, iContentLength );
            return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
            };

        /*
        ** Now read from the input buffer and write to the file
        */
        for(;;)
            {
            iTmp = (iContentLength<FILE_BUF_SIZE) ? iContentLength :
                FILE_BUF_SIZE;
            iTmp = PIIOBuffer_readToBuffer( tPIHTTP.pBuffer, szFileBuf, iTmp );
            switch( iTmp )
                {
                case 0:
                case -1:
                    /*
                    ** We didn't read sufficient data
                    */
                    HTTPCore_logError( &tPIHTTP, "SiteRoot: \
Failed to read the specificied 'Content-Length' of data from remote \
administration client. Temporary configuration file '%s' will be removed. \
Configuration file upload failed.",  (const char *)sConfigFileTmp );
                    iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
                    goto close_file;

                default:
                    /* good */
                    break;
                };

            assert( iTmp>0 );
            iContentLength -= iTmp;
            assert( iContentLength >= 0 );

            /*
            ** Write to the file
            */
            iTmp = PIFile_write( tFd, iTmp, szFileBuf );
            if ( iTmp )
                {
                /*
                ** Error
                */
                HTTPCore_logError( &tPIHTTP, "SiteRoot: \
Failed to write to temporary configuration file '%s'. File upload failed.",
                    (const char *)sConfigFileTmp );
                SwallowInput( tPIHTTP.pBuffer, iContentLength );
                iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
                goto close_file;
                };

            if ( !iContentLength )
                {
                iRet = PIAPI_COMPLETED;
                break;
                };
            };
        
close_file:
        /*
        ** The temporary file has been read - close it and consider
        ** making it the main configuration file
        */
        iTmp = PIFile_close( tFd );
        if ( iTmp!=PIAPI_COMPLETED )
            {
            HTTPCore_logError( &tPIHTTP, "SiteRoot: \
Failed to close temporary configuration file '%s'. Configuration file upload \
failed.", (const char *)sConfigFileTmp );
            iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
            };

        /*
        ** Attempt to load the new configuration
        */
        PIObject *pTmpObject = 0;
        if ( iRet!=INT_REDIRECT )
            {
            pTmpObject = LoadConfigurationFile( sConfigFileTmp, 1 );
  
            if ( !pTmpObject )
                {
                /*
                ** An error occurred, attempt to map the configuration
                ** file where the error will have been written
                */
                PIFInfo *pFInfo = 0;
                PIFMap *pMap = 0;
                const char *pFileMap = 0;
                int iLen = 0;

                pFInfo = PIFInfo_new( sConfigFileTmp );
                pMap = pFInfo ? PIFMap_new( pFInfo ) : 0 ;
                pFileMap = pMap ? (const char *)PIFMap_lock( pMap, &iLen ) : 0;
                if ( pFileMap )
                    {
                    HTTPCore_logError( &tPIHTTP, "SiteRoot: \
Failed to load new site configuration file '%s'. Detailed error information \
follows:\n%s", (const char *)sConfigFileTmp, pFileMap );
                    }
                else
                    {
                    HTTPCore_logError( &tPIHTTP, "SiteRoot: \
Failed to load new site configuration file '%s'.",
                        (const char *)sConfigFileTmp );
                    };

                if ( pMap ) { PIFMap_delete( pMap ); };
                if ( pFInfo ) { PIFInfo_delete( pFInfo ); };
                iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
                };
            };

        /*
        ** Send response to client?
        */
        if ( iRet!=INT_REDIRECT )
            {
            /*
            ** Send HTTP response to confirm that configuration has been
            ** accepted
            */
            /* --- start response --- */
            if (    HTTPCore_sendGeneralHeaders( &tPIHTTP ) ||
                    HTTPCore_sendEntityHeaders( &tPIHTTP, pR ) )
                {
                HTTPCore_logError( &tPIHTTP, "%s", "SiteRoot: Failed to send \
response headers for admin command." );
                iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
                };
            };

        /*
        ** Do we want to make this the configuration file?
        */
        if ( !tPIHTTP.iStatus || (tPIHTTP.iStatus>199 && tPIHTTP.iStatus<300))
            {
            /*
            ** Make this the new configuration.
            */
            iRet = remove( sConfigFile );
            assert( !iRet );

            iRet = rename( sConfigFileTmp, sConfigFile );
            assert( !iRet );

            pNewLogicObject = pTmpObject;
            if ( iInSiteCount )
                {
                /*
                ** There are threads currently executing the old logic
                ** object: let last thread out pick up the change.
                */
                assert( iInSiteCount>0 );
                pTmpObject = 0;
                }
            else
                {
                /*
                ** There are no threads executing the current logic
                ** object
                */
                pTmpObject = pLogicObject;
                pLogicObject = pNewLogicObject;
                pNewLogicObject = 0;
                };

            iRet = PIAPI_COMPLETED;
            }
        else
            {
            /*
            ** Nuke the temporary file
            */
            remove( sConfigFileTmp );
            };

        /*
        ** Delete any logic objects 
        */ 
        if ( pTmpObject )
            {
            PIObject_delete( pTmpObject, 0, 0 );
            };

        /*
        ** Done
        */
        return iRet;
        };

    /*
    ** Handle admin requests
    */
    int HandleAdminRequest( int iPhase, PIHTTP &tPIHTTP,
        const char *pAdminCommand )
        {
        /*
        ** Only handle the request is the current status is a
        ** non-error status
        */
        if (tPIHTTP.iStatus && (tPIHTTP.iStatus <200 || tPIHTTP.iStatus>299))
            {
            /* --- this is an error let something else handle it --- */
            return PIAPI_CONTINUE;
            };

        switch( iPhase )
            {
            case PH_INIT:
            case PH_HEADERS:
                assert( 0 );
                return PIAPI_COMPLETED;

            case PH_MAPPING:
                /*
                ** Set the physical path
                */
                PIDB_replace( tPIHTTP.pResponseDB, PIDBTYPE_STRING, 
                    KEY_INT_PATH, (void *)(const char *)sConfigFile, 0 );
				if (sRealm.Len())
					{
					PIDB_replace( tPIHTTP.pResponseDB, PIDBTYPE_STRING,
						KEY_INT_AUTHENTICATIONREALM, (void *)(const char *)sRealm, 0 );
					}
                return PIAPI_COMPLETED;

            case PH_CHECKPATH:
                return PIAPI_COMPLETED;

            case PH_CHECKAUTH:
		        /*
				** Do site request for this phase
				*/
				{
		        PIHTTP *pPIHTTP = &tPIHTTP;
				return PILogic_execute( pLogicObject, 1, (const char **)&pPIHTTP );
				}
            case PH_CHECKACCESS:
            case PH_CHECKTYPE:
                return PIAPI_COMPLETED;

            case PH_HANDLE:
                break;

            case PH_HOSTMAP:
            case PH_LOG:
            case PH_DESTROY:
                return PIAPI_CONTINUE;

            default:
                assert( 0 );
                return PIAPI_CONTINUE;
            };

        int iRet;
        if ( !PIUtil_stricmp( pAdminCommand, KEY_ADMIN_GETCONFIG ) )
            {
            PISync_lock( pMutex );
            iRet = SendConfigFile( tPIHTTP );
            PISync_unlock( pMutex );
            }
        else if ( !PIUtil_stricmp( pAdminCommand, KEY_ADMIN_SAVECONFIG ) )
            {
            PISync_lock( pMutex );
            iRet = GetConfigFile( tPIHTTP );
            PISync_unlock( pMutex );
            }
        else
            {
            HTTPCore_logError( &tPIHTTP, "SiteRoot: Unknown admin command \
'%s'.", pAdminCommand );
            iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
            };

        return iRet;
        };

    /*
    ** Handle requests for this site
    */
    int HandleSiteRequest( int iPhase, PIHTTP &tPIHTTP )
        {
again:
        PISync_lock( pMutex );
        if ( iPhase==PH_INIT && pNewLogicObject )
            {
            /*
            ** A new configuration is ready to be used, waiting for
            ** threads to stop executing objects within this 
            ** configuration.
            */
            assert( iInSiteCount>0 );
            PISync_unlock( pMutex );
            PIPlatform_sleep( 2000 );     /* high tech. solution */
            goto again;
            };
        assert( pLogicObject );
        iInSiteCount++;
        PISync_unlock( pMutex );

        /*
        ** Do site request for this phase
        */
        PIHTTP *pPIHTTP = &tPIHTTP;
        int iRet = PILogic_execute( pLogicObject, 1, (const char **)&pPIHTTP );

        PIObject *pTmpObject = 0;
        PISync_lock( pMutex );
        iInSiteCount--;
        if ( iPhase==PH_DESTROY && !iInSiteCount && pNewLogicObject )
            {
            /*
            ** No other threads are using the objects for this site.
            ** the new site may be used and the old one destroyed
            */
            pTmpObject = pLogicObject;
            pLogicObject = pNewLogicObject;
            pNewLogicObject = 0;
            };
        PISync_unlock( pMutex );

        /*
        ** Now we are outside the mutex we can delete the old logic
        ** object if a new one was copied over
        */
        if ( pTmpObject )
            {
            PIObject_delete( pTmpObject, 0, 0 );
            };

        return iRet;
        };

    /*
    ** The main function
    */
	int Handle( int iPhase, PIHTTP &tPIHTTP, PIIOBuffer &/* tBuffer */ )
		{
		int iRet;
		PIDB *pQ = tPIHTTP.pRequestDB;

		const char *pAdminCommand = (const char *)PIDB_lookup( pQ,
			PIDBTYPE_RFC822, pFKAdminCommand, PIDBFLAG_FASTKEY );

       	if ( pAdminCommand && strlen(pAdminCommand) )
           	{
           	/*
           	** This is an admin command
           	*/
           	iRet = HandleAdminRequest( iPhase, tPIHTTP, pAdminCommand );
			if (iRet == INT_REDIRECT)
				{
				PIDB_replace( pQ, PIDBTYPE_RFC822, pFKAdminCommand,
					NULL, PIDBFLAG_FASTKEY );
				}
#if 0
		cout << "Admin request: " << HTTPUtil_phaseNumberToName(iPhase)
			<< ", " << HTTPUtil_rcNumberToName(iRet)<< ", " << tPIHTTP.iStatus << endl;
#endif
            }
		else
			{
			iRet = HandleSiteRequest( iPhase, tPIHTTP );
#if 0
		cout << "Site request: " << HTTPUtil_phaseNumberToName(iPhase)
			<< ", " << HTTPUtil_rcNumberToName(iRet) << ", " << tPIHTTP.iStatus << endl;
#endif
			}

		return iRet;
        }
};

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int SiteRoot_constructor( PIObject *pObj,
	int iArgc, const char *ppArgv[] )
{
	return HandlerBaseSR_constructor( pObj, PI_NEW( SiteRoot( pObj,
		iArgc, ppArgv ) ) );
}

#if 0
/*___+++CNF_BEGIN+++___*/
	<Class>
		Name SiteRootClass
		Type LogicExtension
		Library SiteRoot
		OnClassLoad HandlerBaseSR_onClassLoad
		Constructor SiteRoot_constructor
		CopyConstructor HandlerBaseSR_copyConstructor
		Destructor HandlerBaseSR_destructor
		Execute HandlerBaseSR_execute
	</Class>

	<Object>
		Name SiteRoot
		Class SiteRootClass
	</Object>

/*___+++CNF_END+++___*/
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -