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

📄 bscproxy.cpp

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

		(void)tPIHTTP;

		/* ---
		## NOTE ##, connection reuse is not used right now, later, a mutex
		should protect access to a list of connection resources and an 
		existing connection with the same protocol, host and port tuple
		should be returned if available

		Right now a new connection is created every time around.
		--- */

		/* --- only support HTTP proxies right now --- */
		if ( PIUtil_stricmp( pProtocol, "http" ) )
			{ return 0; };
		
		/* --- establish a connection to the remote server --- */
		const char *ppConnectParameters[2];
		ppConnectParameters[0] = pHost;
		ppConnectParameters[1] = (const char *)iPort;
		PIObject *pConn = PIObject_copy( pIO, 2, ppConnectParameters );
		return pConn;
		};
	
	/* ---
	ReleaseProxyConnection(), if we are managing a pool of connections then
	return this connection to the pool if necessary, the flag bDelete, can
	be set to indicate that headers are some other means have indicated that
	this connection should not be kept open
	--- */
	void ReleaseProxyConnection( PIObject *pConnection, int bDestroy )
		{
		(void)bDestroy;

		/* --- pool not implemented, always delete connection --- */
		if ( pConnection )
			{ PIObject_delete( pConnection, 0, 0 ); };
		};

	/* ---
	Attempts to satisfy a request by using cached data
		returns:
			0 indicates request not satisfied
			1 indicates request satisified from cache
			-1 indicates error
	--- */
	int HandleFromCachedData( PIHTTP &tPIHTTP, const PIString &sMetaFileName )
		{
		PIDB *pR = tPIHTTP.pResponseDB;
		PIDB *pQ = tPIHTTP.pRequestDB;

		PIFInfo *pFInfo = HTTPCore_getCachedFile( sMetaFileName );

		if ( !pFInfo || !PIFInfo_exists( pFInfo ) )
			{
			return 0;
			};

		int iRet = !( PIFInfo_getSize( pFInfo ) > 0 );

		CacheRecord tRecord;

		/* --- get filemap object --- */
		const char *pMap = 0;
		if ( !iRet )
			{
			int iLen;
			PIFMap *pFileMap = PIFMap_new( pFInfo );
			if ( pFileMap )
				{
				pMap = (const char *)PIFMap_lock( pFileMap, &iLen );
				if ( !pMap )
					{
					iRet = -1;
					}
				else
					{
					if ( iLen>=((int)sizeof( CacheRecord )) )
						{
						memcpy( &tRecord, pMap, sizeof( CacheRecord ) );
						}	
					else
						{
						iRet = -1;
						};
					};
				PIFMap_delete( pFileMap );
				};
			};
	
		HTTPCore_releaseCachedFile( pFInfo );	

		/* ---
		Report errors from getting the cache record
		--- */
		if ( iRet )
			{
			HTTPCore_logError( &tPIHTTP, "BscProxy: Could not get \
cache meta file with path '%s'.", (const char *)sMetaFileName );
			return -1;
			};

		/* --- now get the data file --- */
		pFInfo = HTTPCore_getCachedFile( tRecord.szFileName );
		if ( !pFInfo )
			{
			HTTPCore_logError( &tPIHTTP, "BscProxy: Could not open \
cache data file with path '%s'.", tRecord.szFileName );
			};

		/* --- add headers --- */
		Pi3String *pTmp = Pi3String_new( 0 );
		PIPlatform_beforeUnsafeBlock();
		struct tm *pTms = gmtime( &( tRecord.tLastModified ) );
		if ( pTms )
			{
			HTTPUtil_rFC822Time( pTms, pTmp );
			};

		PIPlatform_afterUnsafeBlock();
		PIString sTmp = Pi3String_getPtr( pTmp );
		Pi3String_delete( pTmp );
		if ( sTmp.Len() )
			{ PIDB_add( pR, PIDBTYPE_RFC822, KEY_HTTP_LASTMODIFIED,
				(void *)(const char *)sTmp, 0 );
			};
		
		if ( *( tRecord.szContentType ) )
			{ PIDB_add( pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE,
				tRecord.szContentType, 0 );
			};

		if ( *( tRecord.szContentEncoding ) )
			{ PIDB_add( pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTENCODING,
				tRecord.szContentEncoding, 0 );
			};

		enum { BUF_SIZE=63 };
		char szBuf[BUF_SIZE+1];
		sprintf( szBuf, "%ld", (long)PIFInfo_getSize( pFInfo ) );
		PIDB_add( pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTLENGTH, szBuf, 0 );

		tPIHTTP.iStatus = ST_OK;

		/* ---
		Start response
		--- */
		/* --- start response --- */
		if (	HTTPCore_sendGeneralHeaders( &tPIHTTP ) ||
				HTTPCore_sendEntityHeaders( &tPIHTTP, pR ) )
			{
			HTTPCore_releaseCachedFile( pFInfo );	
			HTTPCore_logError( &tPIHTTP, "BscProxy: Error sending \
response headers for cached data file '%s'.", tRecord.szFileName );
			return -1;
			};

		/* ---
		Send data 
		--- */
		int iMethod = (int)PIDB_lookup( pQ, PIDBTYPE_OPAQUE,
			KEY_HTTP_METHOD, 0 );
		switch( iMethod )
			{
			case MD_GET:
				HTTPUtil_sendFile( tPIHTTP.pBuffer, pFInfo, PIIOBUF_NONE, 0 );
				break;
		
			case MD_HEAD:
				break;

			default:
				assert( 0 );
				HTTPCore_releaseCachedFile( pFInfo );	
				return -1;
			};

		HTTPCore_releaseCachedFile( pFInfo );	

		/* --- sent --- */
		return 1;
		};

	/* ---
	Create cache record
		returns:
			1, file created
			0, file already exists
			-1, error 
	--- */
	int CreateCacheRecord( PIHTTP &tPIHTTP, const PIString &sMetaFileName,
			const PIString &sFileName )
		{
		PIDB *pR = tPIHTTP.pResponseDB;

		CacheRecord tRecord;

		/* --- get file meta data --- */
		const char *pCT = (const char *)PIDB_lookup( pR, PIDBTYPE_RFC822,
			KEY_HTTP_CONTENTTYPE, 0 );
		const char *pCE = (const char *)PIDB_lookup( pR, PIDBTYPE_RFC822,
			KEY_HTTP_CONTENTENCODING, 0 );
		const char *pLM = (const char *)PIDB_lookup( pR, PIDBTYPE_RFC822,
			KEY_HTTP_LASTMODIFIED, 0 );
		const char *pDate = (const char *)PIDB_lookup( pR, PIDBTYPE_RFC822,
			KEY_HTTP_DATE, 0 );

		/* --- localize the last modified time to this servers time --- */
		struct tm tLM;
		time_t tLocalLM;
		time_t tT;
		time( &tT );
		if ( pLM && HTTPUtil_readTime( pLM, &tLM ) )
			{
			time_t tFile = mktime( &tLM );
			struct tm tDate;
			if ( pDate && HTTPUtil_readTime( pDate, &tDate ) )
				{
				/* --- server sent its time, calculate localized LM time --- */
				time_t tRemoteTime = mktime( &tDate );
				tLocalLM = tFile + ( tT - tRemoteTime );
				}
			else
				{
				/* --- server didn't send its time, trust the LM date --- */
				tLocalLM = tFile;
				};

			/* --- increment LM time by 1 second to avoid sync. problems --- */
			tLocalLM++;
			}
		else
			{ tLocalLM = (time_t)-1; };

		/* --- set record data --- */
		if ( pCT )
			{ strncpy( tRecord.szContentType, pCT, FIELD_LENGTH ); };
		if ( pCE )
			{ strncpy( tRecord.szContentEncoding, pCE, FIELD_LENGTH ); };
		tRecord.tLastModified = tLocalLM;
		strncpy( tRecord.szFileName, sFileName, CACHE_PATH_LENGTH );
		tRecord.szFileName[CACHE_PATH_LENGTH] = '\0';

		/* --- attempt to create file --- */
		PIPLATFORM_FD tFd = PIFile_open( sMetaFileName, "wn" );
		if ( tFd==PIPLATFORM_FD_INVALID )
			{
#if 0
/* 
** NOTE: In this case delete all files to allow them to be created cleanly
** next time
*/
			/* --- meta file created, another process/thread got there --- */
			return 0;
#endif
			remove( sMetaFileName );
			return -1;
			};
		int iRet = PIFile_write( tFd, sizeof( tRecord ), &tRecord );
		if ( iRet )
			{
			/* --- could not write file --- */
			remove( sMetaFileName );
/////// XXXX Fd LATER
			return -1;
			};

/////// XXXX Fd LATER
		/* --- cache file created --- */
		return 1;
		};

	/* ---
	Write output from one buffer into another. Transfer data until no more
	data can be read.
	Returns 0 on success.
	--- */
	int WriteBufferToBuffer( PIIOBuffer &tInBuffer, PIIOBuffer &tOutBuffer )
		{
		int iLen;
		const char *pBuffer = PIIOBuffer_read( &tInBuffer, &iLen );
		while( pBuffer )
			{
			int iRet = PIIOBuffer_write( &tOutBuffer, pBuffer, iLen,
				PIIOBUF_NOBUFFER );
			switch( iRet )
				{
				case 0: return 0;
				case -1: return -1;
				default:
					assert( iRet>0 );
				};
			pBuffer = PIIOBuffer_read( &tInBuffer, &iLen );
			};
		return 0;
		};

	/* ---
	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_NOBUFFER )
				<=0 )
				{ return -1; };
			iAttemptToRead -= iLen;
			if ( !iAttemptToRead )
				{ return 0; };

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

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

	/* ---
	Top level proxy server stuff
	--- */
	int DoProxy( PIHTTP &tPIHTTP )
		{
		assert( pIO );

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

		/* --- get the hostname, port and protocol --- */
		const char *pHost = (const char *)PIDB_lookup( pQ, PIDBTYPE_STRING,
			KEY_HTTP_PROXYHOST, 0 );
		const char *pPort = (const char *)PIDB_lookup( pQ, PIDBTYPE_STRING,
			KEY_HTTP_PROXYPORT, 0 );
		int iPort = ( pPort && *pPort ) ? atoi( pPort ) : HTTP_DEFAULT_PORT;
		const char *pProto = (const char *)PIDB_lookup( pQ, PIDBTYPE_STRING,
			KEY_HTTP_PROXYPROTOCOL, 0 );
		if ( !pHost || !pProto || iPort<0 )
			{
			/* --- this is an error --- */
			HTTPCore_logError( &tPIHTTP, "BasicProxy: Invalid host '%s', \
port '%d' or protocol '%s'.", pHost ? pHost : "", iPort, pProto ? pProto : "" );
			return HTTPUtil_doHTTPError( &tPIHTTP, ST_BADREQUEST );
			};

		/* ---
		Check if the current host corresponds to a host in the allow list
		--- */
		int iFound = 0;
		if ( !lAllowHosts.Size() )
			{ iFound = 1; }
		else
			{
			for( DblListIterator iAllowHosts( lAllowHosts );
				!iAllowHosts.BadIndex(); iAllowHosts++ )

⌨️ 快捷键说明

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