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

📄 psphandler.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				enum { BUF_SIZE=2100 }; // 2048 from PIIOBuf.h plus some bytes
				pData = (char *)PIUtil_malloc(BUF_SIZE);
				int iLen = 0;
				for( ; iRead<iContentLength && (iLen=PIIOBuffer_readToBuffer(pBuffer,pData,BUF_SIZE - 1))>0; ) {
					HTTPCore_logDebug( DBG_LOW, "PSP: Read %d bytes from client.", iLen );
					pData[iLen] = 0;
					sv_catpv(tmp, pData);
					iRead += iLen;
				}
				PIUtil_free( pData );

				if ( pContentType && !PIUtil_stricmp( pContentType, "application/x-www-form-urlencoded" )) {

					/* --- urldecode and add to Hash pspForm --- */
					eval_pv( SPLIT_HASH("pspForm"), FALSE );
					/* --- cleanup --- */
//					sv_clear(tmp);
//					sv_free(get_sv("pair", FALSE ));
//					sv_free(get_sv("name", FALSE ));
//					sv_free(get_sv("value", FALSE ));
					HTTPCore_logDebug( DBG_LOW,
						"PSP: %d bytes POST data of type '%s' added to form hash.",
						iRead, pContentType );
				} else {

					/* --- simple scalar pspPlain --- */
					HTTPCore_logDebug( DBG_LOW,
						"PSP: %d bytes POST data of type '%s' added to scalar variable.",
						iRead, pContentType );
				}
			}

		} else {

			const char *pQueryString = (const char *)PIDB_lookup( pQ, PIDBTYPE_STRING,
				pFKQueryString, PIDBFLAG_FASTKEY );
			if (pQueryString) {
				SV *tmp = get_sv("pspPlain", TRUE);
				sv_catpv(tmp, pQueryString);
				/* --- urldecode and add to Hash pspForm --- */
				eval_pv( SPLIT_HASH("pspQueryString"), FALSE );
				/* --- cleanup --- */
//				sv_clear(tmp);
//				sv_free(get_sv("pair", FALSE ));
//				sv_free(get_sv("name", FALSE ));
//				sv_free(get_sv("value", FALSE ));
				HTTPCore_logDebug( DBG_LOW,
					"PSP: QueryString from '%s' request added to form hash.", pMethod );
			};
		}

#undef SPLIT_HASH

		if (!get_cv("pspSetResponse", FALSE)) return PIAPI_COMPLETED;

		/* --- Invoke pspSetResponse() --- */
		char *args[] = { NULL };

		dSP;                            /* initialize stack pointer      */
		ENTER;                          /* everything created after here */
		SAVETMPS;                       /* ...is a temporary variable.   */
		PUSHMARK(SP);                   /* remember the stack pointer    */
		SV *ref = sv_setref_iv(newSViv(0), "const PIObjectPtr", (long)Object());
		XPUSHs(sv_2mortal(ref));
		SV *ref1 = sv_setref_iv(newSViv(0), "PIHTTPPtr", (long)pPIHTTP);
		XPUSHs(sv_2mortal(ref1));
		SV *ref2 = sv_setref_iv(newSViv(0), "PIIOBufferPtr", (long)pBuffer);
		XPUSHs(sv_2mortal(ref2));
		PUTBACK;                        /* make local stack pointer global */
		if ( call_pv("pspSetResponse", G_SCALAR) != 1  )      /* call the function             */
			{
			/* --- an error occurred --- */
			HTTPCore_logError( pPIHTTP, "PSP: \
'pspSetResponse()' returned wrong number of arguments in file %s.", pPath );
			return HTTPUtil_doHTTPError( pPIHTTP, ST_INTERNALERROR );			
			};
		SPAGAIN;                        /* refresh stack pointer         */
		int iRet = POPi;                /* pop the return value from stack */
		PUTBACK;
		FREETMPS;                       /* free that return value        */
		LEAVE;

		switch (iRet) {
			case PIAPI_ERROR:
				HTTPCore_logError( pPIHTTP, "PSP: \
'pspSetResponse()' returned with PIAPI_ERROR.");
				iRet = 1;
				break;

			case PIAPI_COMPLETED:
				{
					/* --- Read %pspResponse --- */
					if (reqHash) {
						hv_iterinit(reqHash);
						long iKeyLen;
						unsigned int iValLen;
						SV* sValue = hv_iternextsv(reqHash, (char **)&pKey, &iKeyLen);
						while (sValue) {
							char *pValue = SvPV(sValue, iValLen);
							PIDB_replace( pR, PIDBTYPE_RFC822, pKey, pValue, 0 );
							HTTPCore_logDebug( DBG_LOW,
								"PSP: Variable Response|RFC822|%s|%s written back to DB.",
								pKey, pValue );
							sValue = hv_iternextsv(reqHash, (char **)&pKey, &iKeyLen);
						};
					};
            
					/* --- Read %pspResponseStatus --- */
					SV* resStatus = get_sv("pspResponseStatus", FALSE);
					if (resStatus) {
						pPIHTTP->iStatus = SvIV(resStatus);
						HTTPCore_logDebug( DBG_LOW,
							"PSP: StatusCode %d written back to HTTP object.",
							pPIHTTP->iStatus );
					};
					break;
				}

			default:
				HTTPCore_logError( pPIHTTP,	"PSP: \
'pspSetResponse()' returned unknown returncode '%d'.", iRet );
				iRet = 1;
		};
		return iRet;
	};

	int OnLoad( PerlInterpreter *my_perl, PIHTTP *pPIHTTP, PIIOBuffer *pBuffer ) {

		PIDB *pQ = pPIHTTP->pRequestDB;
		PIDB *pR = pPIHTTP->pResponseDB;
		const char *pPath = (const char *)PIDB_lookup( pR, PIDBTYPE_STRING,
			pFKPath, PIDBFLAG_FASTKEY );

		/* --- Invoke pspLoad() --- */
		char *args[] = { NULL };

		PERL_SET_CONTEXT(my_perl);
		if (!get_cv("pspLoad", FALSE)) return PIAPI_COMPLETED;

		dSP;                            /* initialize stack pointer      */
		ENTER;                          /* everything created after here */
		SAVETMPS;                       /* ...is a temporary variable.   */
		PUSHMARK(SP);                   /* remember the stack pointer    */
		SV *ref = sv_setref_iv(newSViv(0), "const PIObjectPtr", (long)Object());
		XPUSHs(sv_2mortal(ref));
		PUTBACK;                        /* make local stack pointer global */
		if ( call_pv("pspLoad", G_SCALAR) != 1  )      /* call the function             */
			{
			/* --- an error occurred --- */
			HTTPCore_logError( pPIHTTP, "PSP: \
'pspLoad()' returned wrong number of arguments." );
			return PIAPI_ERROR;
			};
		SPAGAIN;                        /* refresh stack pointer         */
		int iRet = POPi;                /* pop the return value from stack */
		PUTBACK;
		FREETMPS;                       /* free that return value        */
		LEAVE;
		switch (iRet) {
			case PIAPI_ERROR:
				HTTPCore_logError( pPIHTTP, "PSP: \
'pspLoad()' returned with PIAPI_ERROR.");
				iRet = 1;
				break;
			case PIAPI_COMPLETED:
				break;
			default:
				HTTPCore_logError( pPIHTTP, "PSP: \
'pspLoad()' returned unknown returncode '%d'.", iRet);
				iRet = 1;
		};
		return iRet;
	};

	int OnUnload( PerlInterpreter *my_perl, const char *pPath ) {

		PIOStrStream os;
		os << "PSP: ";

		/* --- Invoke pspUnload() --- */
		char *args[] = { NULL };

		PERL_SET_CONTEXT(my_perl);
		if (!get_cv("pspUnload", FALSE)) return PIAPI_COMPLETED;

		dSP;                            /* initialize stack pointer      */
		ENTER;                          /* everything created after here */
		SAVETMPS;                       /* ...is a temporary variable.   */
		PUSHMARK(SP);                   /* remember the stack pointer    */
		SV *ref = sv_setref_iv(newSViv(0), "const PIObjectPtr", (long)Object());
		XPUSHs(sv_2mortal(ref));
		PUTBACK;                        /* make local stack pointer global */
		if ( call_pv("pspUnload", G_SCALAR) != 1  )      /* call the function             */
			{
			/* --- an error occurred --- */
			os << "'pspUnload()' returned wrong number of arguments.";
			CONFIG_ERR( Object(), os.str() );
			return PIAPI_ERROR;
			};
		SPAGAIN;                        /* refresh stack pointer         */
		int iRet = POPi;                /* pop the return value from stack */
		PUTBACK;
		FREETMPS;                       /* free that return value        */
		LEAVE;
		switch (iRet) {
			case PIAPI_ERROR:
				os << "'pspUnload()' returned with PIAPI_ERROR.";
				CONFIG_ERR( Object(), os.str() );
				iRet = 1;
				break;
			case PIAPI_COMPLETED:
				break;
			default:
				os << "'pspUnload()' returned returned unknown returncode '"
				<< iRet << "'.";
				CONFIG_ERR( Object(), os.str() );
				iRet = 1;
		};
		return iRet;
	};

protected:
int Parameter( const char *pVariable, const char *pValue,
	const char *pWhere )
	{
		assert( pVariable && pValue );
		PIOStrStream os;
		os << pWhere << "PSP: ";
		if ( !PIUtil_stricmp( KEY_CONF_DESTRUCTLEVEL, pVariable ) )
			{
			iDestructLevel = atoi( pValue );
			}
		else
			{
			os << "Unknown directive '" << pVariable <<	"'" << ends;
			CONFIG_ERR( Object(), os.str() );
			return 0;
			};
		
		return 1;
	};

public:
	PspHandler( PIObject *pObject, int iArgc, const char *ppArgv[] )
	:	HandlerBasePi3Perl( pObject ),
		pContextDB( PIDB_new( 0, "PSP_Context" ) ),
		pFKPath( PIDB_getFastKey( KEY_INT_PATH, PIDBTYPE_STRING ) ),
		pFKContentType( PIDB_getFastKey( KEY_HTTP_CONTENTTYPE, PIDBTYPE_RFC822 ) ),
		pFKContentLength( PIDB_getFastKey( KEY_HTTP_CONTENTLENGTH, PIDBTYPE_RFC822 ) ),
		pFKMethod( PIDB_getFastKey( KEY_HTTP_METHOD, PIDBTYPE_STRING ) ),
		pFKQueryString( PIDB_getFastKey( KEY_HTTP_QUERYSTRING, PIDBTYPE_STRING ) ),
		iDestructLevel( 0 ),
		pMutex ( PIPlatform_allocLocalMutex()) 
	{
	ReadParameters( iArgc, ppArgv );
	};

~PspHandler()
	{
	/* ---
	iterate through the Context DB and free context
	--- */
	const char *pKey;
	PerlInterpreter *pPerl;
	PIDBIterator *pIter;
	pIter = PIDB_getIterator( pContextDB, PIDBTYPE_OPAQUE, 0, 0 );
	if ( pIter ) {
		for( ; PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter )) {

			pPerl = (PerlInterpreter *)PIDBIterator_current( pIter, &pKey );
	
			PERL_SET_CONTEXT(pPerl);
			if (iDestructLevel == 1) {
			    perl_destruct(pPerl);
				perl_free(pPerl);
			};
		};
		PIDBIterator_delete( pIter );
	};

	PIDB_delete( pContextDB );
	};

int Handle( int iPhase, PIHTTP &tPIHTTP, PIIOBuffer &tBuffer )
	{
	if (iPhase != PH_HANDLE) return PIAPI_ERROR;

	PIDB *pR = tPIHTTP.pResponseDB;

	const char *pPath = (const char *)PIDB_lookup( pR, PIDBTYPE_STRING,
		pFKPath, PIDBFLAG_FASTKEY );

	int iNew = 0;
	PerlInterpreter *pPerl = getPerl(pPath, &iNew);
	if (!pPerl) {
		HTTPCore_logError( &tPIHTTP, "PSP: \
Fatal error, couldn't allocate Perl interpreter." );
		return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
	};

	/* --- transfer-encoding --- */
	int iFlags = (!PIHTTP_isChild( &tPIHTTP) && (int)PIDB_lookup( tPIHTTP.pRequestDB,
		PIDBTYPE_OPAQUE, KEY_HTTP_PROTOCOL, 0 ) == 3 ) ? PIIOBUF_CHUNKED : PIIOBUF_NONE;
	if ( iFlags & PIIOBUF_CHUNKED )
		{
		PIDB_replace( pR, PIDBTYPE_RFC822, KEY_HTTP_TRANSFERENCODING,
			(void *)KEY_HTTP_CHUNKED, 0 );
		};

	thePSPParser Parser = thePSPParser( pPath, pPerl, tPIHTTP, tBuffer, iFlags );
	int iRet = PIAPI_COMPLETED;

	PISync_lock( pMutex );
	if (Parser.exec()) iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
	if (Parser.getParsedLen()) {
		char szBuf[15];
		sprintf(szBuf,"%ul",Parser.getContentLen());
		PIDB_replace( pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTLENGTH, (void *)szBuf, 0 );
	};
	if ( iNew && OnLoad( pPerl, &tPIHTTP, &tBuffer )) iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
	if ( SetResponse( pPerl, &tPIHTTP, &tBuffer )) iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
	HTTPCore_sendGeneralHeaders(&tPIHTTP);
	HTTPCore_sendEntityHeaders(&tPIHTTP, pR);
	if ( iFlags & PIIOBUF_CHUNKED ) PIIOBuffer_flush( &tBuffer );
	Parser.prepare_next_pass();
	Parser.exec();
	PISync_unlock( pMutex );

	PIIOBuffer_flush( &tBuffer );
	return iRet;
	};

};


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

#if 0
/*___+++CNF_BEGIN+++___*/
	<Class>
		Name PSPClass
		Type LogicExtension
		Library Pi3Perl
		OnClassLoad HandlerBasePi3Perl_onClassLoad
		Constructor PSP_constructor
		CopyConstructor HandlerBasePi3Perl_copyConstructor
		Destructor HandlerBasePi3Perl_destructor
		Execute HandlerBasePi3Perl_execute
	</Class>

	<Object>
		Name PerlSrvPages
		Class PSPClass
	</Object>

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

⌨️ 快捷键说明

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