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

📄 fastcgi.cpp

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

	~FastCGI()
		{
		for( DblListIterator i( lVariables ); !i.BadIndex(); i++ )
			{ Pi3Expression_delete( (Pi3Expression *)i.Current() ); };
		PIObject_delete( pIO, 0, 0 );
		};

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

							Utilities

	\* -------------- +++++++++++++++++++++++++++++++ ------------------ */
	/* ---
	Write environment variables (params) into the supplied block.

	Returns 1 on success, 0 on failure.
	--- */
	int AddEnvironmentVariables(
			PIHTTP &tPIHTTP,
			char *pBlock,
			int &iBlockSize,
			int &iNumberOfVariables )
		{
		for( DblListIterator i( lVariables ); !i.BadIndex(); i++ )
			{
			Pi3Expression *pExpr = (Pi3Expression *)i.Current();
			assert( pExpr );

			int iWritten = Pi3Expression_write( pExpr, &tPIHTTP, this, pBlock,
				iBlockSize );
			if ( iWritten==-1 )
				{
				return 0;
				}
			/*
			** Only add non empty variable patterns
			*/
			else if ( iWritten > 0 )
				{
				/* ---
				Check first, before looking at contents.
				--- */
				if ( iWritten>=iBlockSize )
					{
					*pBlock = '\0';
					return 0;
					};

				/* --- buffer for lengths --- */
				unsigned char szLengths[8];
				int iLengthPos=0;

				/* --- get index of '=' --- */
				int i=0;
				for( ; i<iWritten && pBlock[i]!='='; i++ );
				int iNameLen = i;
				if ( i<iWritten ) { i++; };
				int iValueLen = iWritten - i;

				/* --- i is index of first character of value in pBlock --- */

				/* --- lengths --- */
				if ( iNameLen < 0x80 )
					{ szLengths[iLengthPos++] = iNameLen; }
				else
					{
					iNameLen &= 0xFFFFFFFF;
					szLengths[iLengthPos++] = ( iNameLen >> 24 ) | 0x80;
					szLengths[iLengthPos++] = ( iNameLen >> 16 );
					szLengths[iLengthPos++] = ( iNameLen >> 8 );
					};
				if ( iValueLen < 0x80 )
					{ szLengths[iLengthPos++] = iValueLen; }
				else
					{
					iValueLen &= 0xFFFFFFFF;
					szLengths[iLengthPos++] = ( iValueLen >> 24 ) | 0x80;
					szLengths[iLengthPos++] = ( iValueLen >> 16 );
					szLengths[iLengthPos++] = ( iValueLen >> 8 );
					};

				/* ---
				Check again because we've expanded the size
				--- */
				if ( iWritten>=iBlockSize )
					{
					*pBlock = '\0';
					return 0;
					};
			
				iWritten = iLengthPos + iNameLen + iValueLen;

				/* --- sanity --- */
				assert( ((iWritten==(iNameLen+iValueLen))==i) ||
						((iWritten>(iNameLen+iValueLen))&&(i<iWritten)) );

				memmove(
					&(pBlock[iWritten-iValueLen]),
					&(pBlock[i]),
					iValueLen );
				memmove(
					&(pBlock[(iWritten-iValueLen)-iNameLen]),
					pBlock,
					iNameLen );
				memcpy( pBlock, szLengths, iLengthPos );

				pBlock = &( pBlock[iWritten] );
				iBlockSize -= iWritten;

				iNumberOfVariables++;
				};
			};

		return 1;
		};

	/* ---
	Write output from one buffer into another.
	iReadLen gives number of bytes to transfer, must be > 0

	Returns 0 on success.
	--- */
	int WriteBufferToBuffer( PIIOBuffer &tInBuffer, PIIOBuffer &tOutBuffer,
		int iReadLen )
		{
		assert( iReadLen>0 );
		if ( iReadLen<=0 )
			{ return 0; };
		enum { BUF_SIZE=4096 };
		char szBuffer[BUF_SIZE];
		int iAttemptToRead = (iReadLen >= BUF_SIZE) ? BUF_SIZE : iReadLen;

		int iLen;
		iLen = PIIOBuffer_readToBuffer( &tInBuffer, szBuffer, iAttemptToRead );
		while( iLen>0 )
			{
			if ( PIIOBuffer_write( &tOutBuffer, szBuffer, iLen,
				PIIOBUF_NONE )<=0 )
				{ return -1; };

			iAttemptToRead -= iLen;
			if ( !iAttemptToRead )
				{ return 0; };

			iLen = PIIOBuffer_readToBuffer( &tInBuffer, szBuffer,
				iAttemptToRead );
			};

		/* ---
		Done
		--- */
		return iLen;
		};

	/* ---
	Initialize a fast CGI header record
	--- */
	void GenerateFcgiHeader( FCGI_Header &tHeader, int iType, 
		int iRequestId, int iContentLength )
		{
		tHeader.version = FCGI_VERSION_1;
		tHeader.type = iType;
		tHeader.requestIdB1 = (iRequestId >> 8 ) & 0xff;
		tHeader.requestIdB0 = (iRequestId ) & 0xff;
		tHeader.contentLengthB1 = (iContentLength >> 8 ) & 0xff;
		tHeader.contentLengthB0 = (iContentLength ) & 0xff;
		tHeader.paddingLength = 0;
		};

	/* ---
	Wrap a Fcgi body in a record and send it into the specified
	IO buffer object.

	Returns 0 on success, -1 on failure.
	--- */
	int SendFcgiBody( PIIOBuffer *pIOBuffer, void *pBody, int iBodyLength,
		int iType, int iRequestId )
		{
		assert( pIOBuffer );

		/* ---
		Generate header record
		--- */
		FCGI_Header tHeader;
		GenerateFcgiHeader( tHeader, iType, iRequestId, iBodyLength );

		/* ---
		Send header
		--- */
		if ( PIIOBuffer_write( pIOBuffer, (const char *)&tHeader,
			sizeof( tHeader ), PIIOBUF_NONE )!=sizeof( tHeader ) )
			{
			return -1;
			};

		/* ---
		Send body and flush
		--- */
		if ( iBodyLength>0 && PIIOBuffer_write( pIOBuffer, (const char *)pBody,
			iBodyLength, PIIOBUF_NONE )!=iBodyLength )
			{
			return -1;
			};

		return 0;	/* --- OK --- */
		};

	/* ---
	Correct response variables just before they're sent
	--- */
	void CorrectResponseVariables( PIHTTP &tPIHTTP )
		{
		/* --- disable keep alive --- */
		PIDB_replace( tPIHTTP.pConnectionDB, PIDBTYPE_OPAQUE, 
			KEY_INT_KEEPOPEN, (void *)0, 0 );

		/* --- set response status code --- */
		tPIHTTP.iStatus = ST_OK;
		};

	/* ---
	Handle stdout from an FCGI application server

	Return 0 on success, -1 on error.
	--- */
	int HandleFcgiStdout(
			PIHTTP &tPIHTTP,
			char *pData,
			int iDataLength,
			int &iVariablePos,			/* --- note pass by reference --- */
			int &iReadingVariables, 	/* --- note pass by reference --- */
			const char *szIdent )
	{
	assert( pData );

	if ( iReadingVariables )
		{
		/* ---
		reading CGI response headers
		--- */
		assert( iVariablePos<iDataLength );

		/* --- get index of EOL (\r\n) --- */
		int iEOL = 0;
		for( ;
			(iEOL<iDataLength) &&
			(pData[iEOL]!='\r') &&
			(pData[iEOL+1]!='\n');
			iEOL++ );

		if ( iEOL==iDataLength )
			{
			/* --- end of variables --- */
			iReadingVariables = 0;
			}
		else
			{

			/* ---
			EOL reached read in the variable.
			--- */
			assert( iEOL<=iDataLength );
			if ( iEOL )
				{
				/* ---
				Seperate variable from value
				--- */
				int i=0;
				for( ; i<iEOL && pData[i]!=':'; i++);	/* scan to ':' */
				/* ---
				real rfc822 variable, value pair
				--- */
				if ( i < iEOL - 3 /* : x\0 */)
					{
					pData[iEOL] = '\0';
					pData[i]='\0';	
					const char *pVariable = pData;
					if ( i<iEOL ) { i++; };
					for( ; i<iEOL && isspace(pData[i]); i++);/* scan to !ws */
					const char *pValue = &(pData[i]);
		
					/* ---
					Place variable value pair in response DB
					--- */
					assert( pVariable );
					assert( *pVariable );
					assert( pValue );
					PIDB_replace( tPIHTTP.pResponseDB, PIDBTYPE_RFC822, pVariable,
						(void *)pValue, 0 );

					/* --- reset variable buffer --- */
					iEOL+=2;		/* --- increment to next character ---  */
					assert( iEOL<=iDataLength );
					iVariablePos += iEOL;
					iReadingVariables = iVariablePos<iDataLength;
					/* ---
					Recurse to read the rest of the buffer if there's more
					--- */
					iDataLength -= iEOL;
					pData = &(pData[iEOL]);
					}
				else
					{
					iReadingVariables = 0;
					};
				}
			else
				{
				/* --- end of variables --- */
				if ( iVariablePos )
					{
					iDataLength -= 2;
					pData = &(pData[2]);
					};
				iReadingVariables = 0;
				};
			};

		/* ---
		Recurse to read more headers
		--- */
		if ( iDataLength && iReadingVariables )
			{
			return HandleFcgiStdout( tPIHTTP, pData, iDataLength,
					iVariablePos, iReadingVariables, szIdent );
			};
		};

	if (!iReadingVariables )
		{
		/* ---
		End of the stdout variables 
		start the http response
		--- */
		PIDB *pR = tPIHTTP.pResponseDB;
		CorrectResponseVariables( tPIHTTP );
		if (	HTTPCore_sendGeneralHeaders( &tPIHTTP ) ||
				HTTPCore_sendEntityHeaders( &tPIHTTP, pR ) )
			{
			HTTPCore_logError( &tPIHTTP, "FastCGI: Failed \
to start HTTP response from fast cgi application '%s'.", szIdent );
			return -1;
			};

		/* ---
		reading CGI response data
		Just ship it straight back to the client browser.
		--- */
		int iRet = 1;
		if ( iDataLength )
			{
			iRet = PIIOBuffer_write( tPIHTTP.pBuffer, pData, iDataLength,
				PIIOBUF_NONE );
			};
			if ( iRet<=0 )
			{
			HTTPCore_logError( &tPIHTTP, "FastCGI: Error sending \
response to browser from fast cgi application '%s'.", szIdent );
			return -1;
			};
		};

	return 0;		/* --- OK --- */
	};

	/* ---
	Read a Fcgi response.

	returns 0 on success, -1 on failure.
	--- */
	int ReadFcgiResponse( PIHTTP &tPIHTTP, PIIOBuffer *pIOBuffer,
		const char *szIdent )
		{
		PIString sStdErr;		/* for stderr responses */
		const char *pData;		/* pointer to current data block */
		FCGI_Header tHeader;	/* for reading FCGI headers */
		int iReadSoFar = 0;		/* offset into record or data */
		int iRecordLength;		/* length of current fcgi record */
		char *pBuffer = 0;		/* buffer for record data */
		int iExit = 1;			/* exit code or 1 for no exit */
		int iVariablePos=0;	/* current pos in HTTP vars */
		int iReadingVariables = 1;
								/* initially reading variables */
		enum { HEADER=1, RECORD } eRecordState = HEADER;
		int iLen;				/* length of data read from fcgi */
		for( ; (pData = PIIOBuffer_read( pIOBuffer, &iLen ))!=0 &&
			iExit == 1; )
			{
			HTTPCore_logDebug( DBG_LOW, "FastCGI: %s, Read %d bytes from fcgi.",
				szIdent, iLen );
	
			if ( eRecordState == HEADER )
				{
				/* ---
				Read fast cgi header
				--- */
				assert( iReadSoFar<(int)sizeof( FCGI_Header ) );
				int iToRead = sizeof( FCGI_Header ) - iReadSoFar;
				if ( iToRead>iLen )
					{ iToRead = iLen; };
				memcpy( &(((char *)&tHeader)[iReadSoFar]), pData, iToRead );
				iReadSoFar += iToRead;
				if ( iReadSoFar<(int)sizeof( FCGI_Header ) )
					{ /* --- read more into buffer --- */; continue; };

				/* ---
				Reset buffer pointers 
				--- */
				pData = &(pData[iToRead]);
				iLen -= (int)sizeof( FCGI_Header );
				iReadSoFar = 0;
				eRecordState = RECORD;

				/* ---
				prepare for record data
				--- */
				iRecordLength = ( tHeader.contentLengthB1 << 8 ) +
						tHeader.contentLengthB0;
				pBuffer = PI_NEW( char[iRecordLength] );

⌨️ 快捷键说明

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