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

📄 fastcgi.cpp

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

			if ( eRecordState == RECORD )
				{
				/* ---
				Read fast cgi record
				--- */
				assert( iReadSoFar<iRecordLength );
				int iToRead = iRecordLength - iReadSoFar;
				// Can't read more than in the buffer at once
				if (iToRead > iLen - tHeader.paddingLength) {
					// Cut padding bytes
					iToRead = iLen - tHeader.paddingLength;
				};
				memcpy( &(pBuffer[iReadSoFar]), pData, iToRead );
				iReadSoFar += iToRead;
				if ( iReadSoFar<iRecordLength )
					{ /* --- read more into buffer --- */; continue; };

				/* ---
				Record fully read
				--- */
				};

			HTTPCore_logDebug( DBG_MED, "FastCGI: %s, Read header of type %d.",
				szIdent, (int)tHeader.type );
	
			/* ---
			Process this fcgi record
			--- */
			switch( tHeader.type )
				{
				case FCGI_STDERR:
					{
					/* ---
					Append to the stderr message
					--- */
					PIString sTmp( pBuffer, iRecordLength );
					sStdErr.Concatenate( sTmp );
					};
					break;

				case FCGI_STDOUT:
					if ( HandleFcgiStdout( tPIHTTP, pBuffer, iRecordLength,
						iVariablePos, iReadingVariables, szIdent )==-1)				
						{
						iExit = -1;
						};
					break;

				case FCGI_END_REQUEST:
					iExit = 0;
					break;

				case FCGI_GET_VALUES_RESULT:
					/* not  implemented */
				case FCGI_UNKNOWN_TYPE:
					/* not  implemented */
				default:
					iExit = -1;
				};

			/* ---
			Done with this record
			--- */
			PI_DELETE( [] pBuffer );

			/* ---
			Reset state to read next fcgi header
			--- */
			iReadSoFar = 0;
			eRecordState = HEADER;
			};

		HTTPCore_logDebug( DBG_LOW, "FastCGI: %s, done reading response.",
				szIdent );

		/* ---
		At this point the protocol headers should have been sent to the
		client and we should have been reading the data to send to the
		client
		--- */
		if ( iReadingVariables )
			{
			/* --- but I guess it didn't work out that way... --- */
			HTTPCore_logError( &tPIHTTP, "FastCGI: Failure to read \
proper fcgi STDOUT response from fcgi application '%s'.", szIdent );
			iExit = -1;
			};

		/* ---
		If the CGI application wrote stderr log it 
		Log stderr message
		--- */
		if ( sStdErr.Len()>0 )
			{
			HTTPCore_logError( &tPIHTTP, "FastCGI: Fast cgi \
application '%s' wrote STDERR output. Output follows:\n\
______________________________________________________________________________\
__\n%s\n\
______________________________________________________________________________\
__", szIdent, (const char *)sStdErr );
			iExit = -1;
			};

		return iExit;
		};

	/* -------------- +++++++++++++++++++++++++++++++ ------------------ *\

								Guts

	\* -------------- +++++++++++++++++++++++++++++++ ------------------ */
	/* ---
	GetFcgiConnection(), get a connection to the Fcgi application. This
	function can copy a new connection or reuse an existing one.

	For simplicity this function creates a new connection right now.
	--- */
	PIObject *GetFcgiConnection( PIHTTP &tPIHTTP, const PIString &sFcgiHost,
		int iFcgiPort )
		{
		(void)tPIHTTP;

		/* --- establish a connection to the remote Fcgi app. server --- */
		const char *ppConnectParameters[2];
		ppConnectParameters[0] = (const char *)sFcgiHost;
		ppConnectParameters[1] = (const char *)iFcgiPort;
		PIObject *pConn = PIObject_copy( pIO, 2, ppConnectParameters );

		return pConn;
		};
	
	/* ---
	ReleaseFcgiConnection(), release a connection to the fast cgi application,
	in the future this could be used to allow connection reuse.
	--- */
	void ReleaseFcgiConnection( PIObject *pConnection )
		{
		/* --- always destroy the connection --- */
		if ( pConnection )
			{ PIObject_delete( pConnection, 0, 0 ); };
		};

	/* ---
	Top level proxy server stuff
	--- */
	int DoFastCGI( PIHTTP &tPIHTTP, PIIOBuffer *pIOBuffer,
		const char *szIdent )
		{
		assert( pIO );

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

		/* ---
		Send Fcgi begin message
		--- */
		FCGI_BeginRequestBody tBody;
		tBody.roleB1 = ( FCGI_RESPONDER >> 8 ) & 0xff;
		tBody.roleB0 = ( FCGI_RESPONDER ) & 0xff;
		tBody.flags = 0;
		memset( tBody.reserved, 0, sizeof( tBody.reserved ) );
		if ( SendFcgiBody( pIOBuffer, &tBody, sizeof( tBody ),
			FCGI_BEGIN_REQUEST, 1 )==-1 )
			{
			/* --- error sending begin request --- */
			HTTPCore_logError( &tPIHTTP, "FastCGI: Error sending \
FCGI_BEGIN_REQUEST \
to fast cgi application '%s'.", szIdent );
			return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
			};

		/* ---
		Send Fcgi parameters,
		--- */
		char *pParamsBlock = PI_NEW( char[PARAM_BLOCK_SIZE] );
		int iParamsBlockSize = PARAM_BLOCK_SIZE;
		int iNumVariables = 0;
		int iOK = AddEnvironmentVariables( tPIHTTP, pParamsBlock,
			iParamsBlockSize, iNumVariables );
		int iToSend = PARAM_BLOCK_SIZE - iParamsBlockSize;
		assert( iToSend>0 );
		if ( iOK && iToSend )
			{
			iOK = ( SendFcgiBody( pIOBuffer, pParamsBlock,
				iToSend, FCGI_PARAMS, 1 )!=-1 );
			};
		PI_DELETE( [] pParamsBlock );
		if ( !iOK )
			{
			HTTPCore_logError( &tPIHTTP, "FastCGI: Error \
generating or sending \
FCGI_PARAMS to fast cgi application '%s'.", szIdent );
			return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
			};

		/* ---
		Determine whether or not there is any input to be sent to the
		fcgi application server.
		--- */
		const char *pContentLength = (const char *)PIDB_lookup( pQ,
			PIDBTYPE_RFC822, KEY_HTTP_CONTENTLENGTH, 0 );
		int iStdinLen = pContentLength ? atoi( pContentLength ) : 0;
		if ( iStdinLen>0 )
			{
			/* ---
			Generate header record
			--- */
			FCGI_Header tHeader;
			GenerateFcgiHeader( tHeader, FCGI_STDIN, 1, iStdinLen );

			/* ---
			Send header
			--- */
			if ( PIIOBuffer_write( pIOBuffer, (const char *)&tHeader,
				sizeof( tHeader ), PIIOBUF_NONE )!=sizeof( tHeader ) )
				{
				HTTPCore_logError( &tPIHTTP, "FastCGI: Error \
sending FCGI_STDIN header to fast cgi application '%s'.", szIdent );
				return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
				};

			/* ---
			Write iStdinLen bytes from browser buffer to the fcgi buffer.
			--- */
			if ( WriteBufferToBuffer( *pIOBuffer, *(tPIHTTP.pBuffer),
				iStdinLen ) )
				{
				/* --- error --- */
				HTTPCore_logError( &tPIHTTP, "FastCGI: Error \
sending %d bytes of STDIN from browser to fast \
cgi application '%s'.", iStdinLen, szIdent );
				return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
				};
			}
		else
			{
			/* ---
			Send an empty fcgi record
			--- */
			if ( SendFcgiBody( pIOBuffer, 0, 0, FCGI_STDIN, 1 )==-1 )
				{
				HTTPCore_logError( &tPIHTTP, "FastCGI: Error sending \
empty FCGI_STDIN \
to fast cgi application '%s'.", szIdent );
				return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
				};
			};

		/* ---
		Flush output to fcgi application
		--- */
		PIIOBuffer_flush( pIOBuffer );

		/* ---
		Read Fcgi stdout and stderr or Fcgi end request
		--- */
		if ( ReadFcgiResponse( tPIHTTP, pIOBuffer, szIdent )==-1 )
			{
			/* ---
			Error message already given 
			--- */
			return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
			};

		/* --- done --- */
		return PIAPI_COMPLETED;
		};

	/* -------------- +++++++++++++++++++++++++++++++ ------------------ *\

						Standard Handle Function

	\* -------------- +++++++++++++++++++++++++++++++ ------------------ */
	int Handle( int iPhase, PIHTTP &tPIHTTP, PIIOBuffer &/* tBuffer */ )
		{
		if ( iPhase!=PH_HANDLE )
			{ return PIAPI_ERROR; };

		assert( pIO );

		const char *pPath = (const char *)PIDB_lookup( tPIHTTP.pResponseDB,
			PIDBTYPE_STRING, KEY_INT_PATH, 0 );

		/* ---
		Check if the filename matches
		--- */
		if ( sFile!=PIString::Empty() )
			{
			if ( !pPath )
				{ return PIAPI_CONTINUE; };
			PIFInfo *pFInfo = HTTPCore_getCachedFile( pPath );
			int iPathMatches = ( sFile==PIFInfo_getName( pFInfo ) );
			HTTPCore_releaseCachedFile( pFInfo );
			if ( !iPathMatches )
				{ return PIAPI_CONTINUE; };
			};

		/* ---
		If this is a real file then attempt to read the host and port
		information from it
		--- */
		PIString sFcgiHost( sHost );
		int iFcgiPort = iPort;
		PIFInfo *pFInfo = HTTPCore_getCachedFile( pPath );
		if ( pFInfo && PIFInfo_exists( pFInfo ) )
			{
			if (	!PIFInfo_isRegular( pFInfo ) ||
					!PIFInfo_isReadable( pFInfo ) )
				{
				HTTPCore_logError( &tPIHTTP, "FastCGI: Fast CGI information \
file '%s' is not readable.", PIFInfo_getPath( pFInfo ) );
				HTTPCore_releaseCachedFile( pFInfo );
				return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
				};
			HTTPCore_releaseCachedFile( pFInfo );
			
			/* ---
			Read host and port information 
			--- */
			ifstream ifs( pPath );
			if ( !ifs.good() || ifs.eof() )
				{
				HTTPCore_logError( &tPIHTTP, "FastCGI: Error opening \
fast CGI information file '%s'.", pPath );
				return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
				};
			enum { BUF_SIZE=1023 };
			char szBuf[BUF_SIZE+1];
			szBuf[BUF_SIZE] = '\0';
			*szBuf = '\0';
			/* XXX, buffer overrun risk, be careful with lengths! */
			ifs >> szBuf;
			sFcgiHost = szBuf;
			*szBuf = '\0';
			ifs >> szBuf;
			iFcgiPort = atoi( szBuf );
			if ( sFcgiHost==PIString::Empty() || iFcgiPort<=0 )
				{
				HTTPCore_logError( &tPIHTTP, "FastCGI: Bad \
host:port pair (%s:%d) from fast CGI information file '%s'.", 
					(const char *)sFcgiHost, iFcgiPort, pPath );
				return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
				};
			}
		else
			{
			HTTPCore_releaseCachedFile( pFInfo );
			};

		/* ---
		Make identification string for error messages and logging
		-- */
		PIString sIdent( "host:port=" );
		sIdent.Concatenate( sFcgiHost );
		enum { SMALL_BUF=63 };
		char szSmall[SMALL_BUF+1];
		sprintf( szSmall, ":%d", iFcgiPort );
		sIdent.Concatenate( szSmall );

		/* ---
		Get Connection Object
		--- */
		PIObject *pIOObject = GetFcgiConnection( tPIHTTP,
			sFcgiHost, iFcgiPort );

		if ( !pIOObject )
			{
			HTTPCore_logError( &tPIHTTP, "FastCGI: Failed to \
establish connection \
to fast cgi application '%s'.", (const char *)sIdent );
			return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
			};

		/* --- 
		Make buffer object
		--- */
		PIIOBuffer *pIOBuffer = PIIOBuffer_new( pIOObject );

		int iRet = DoFastCGI( tPIHTTP, pIOBuffer, sIdent );

		PIIOBuffer_delete( pIOBuffer );
		ReleaseFcgiConnection( pIOObject );

		return iRet;
		};
};

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

#if 0
/*___+++CNF_BEGIN+++___*/
	<Class>
		Name FastCGIClass
		Type LogicExtension
		Library Fcgi
		OnClassLoad HandlerBaseFcgi_onClassLoad
		Constructor FastCGI_constructor
		CopyConstructor HandlerBaseFcgi_copyConstructor
		Destructor HandlerBaseFcgi_destructor
		Execute HandlerBaseFcgi_execute
	</Class>

	<Object>
		Name FastCGI
		Class FastCGIClass
	</Object>
/*___+++CNF_END+++___*/
#endif

⌨️ 快捷键说明

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