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

📄 stressclient.cpp

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

	/* ---
	path and query string.
	--- */
	for(; i<iLineLen && pLine[i]!='?' && !(isspace(pLine[i])); i++);
	*ppPath = pLine;

	if ( pLine[i]=='?' )
		{ 
		pLine[i++] = '\0';
		*ppQueryString = &(pLine[i]);
		for(; i<iLineLen && !(isspace(pLine[i])); i++);
		}
	else
		{ *ppQueryString = ""; };

	if ( i==iLineLen ) { return INT_CONTINUE; };
	pLine[i++]='\0';
	for(; i<iLineLen && (isspace(pLine[i])); i++);
	pLine = &( pLine[i] ); iLineLen -= i; i=0; 

	/* ---
	pLine now points at the component following the URL path and
	query string.
	--- */

	/* ---
	protocol is last component on the line, skip components until the last
	--- */
	for(;;)
		{
		for(; i<iLineLen && !(isspace(pLine[i])); i++);
		*ppProtocol = pLine;
		for(; i<iLineLen && (isspace(pLine[i])); i++);
		if ( i==iLineLen ) { return INT_CONTINUE; }; /* this should be true */

		/* --- I guess not --- */
		pLine = &( pLine[i] ); iLineLen -= i; i=0;
		};

	/* -- OK --- */
	return INT_CONTINUE;
}


/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int StressClient::ReadRequestLine( PIDB *pDB, const char *pLine )
	{
	const char *pMethod = 0;
	const char *pProxyProtocol = 0;
	const char *pProxyHost = 0;
	int iProxyHostLen = 0;
	const char *pProxyPort = 0;
	int iProxyPortLen = 0;
	const char *pURI = 0;
	const char *pQueryString = 0;
	const char *pProtocol = 0;

	int iStatus = SplitRequestLine(
		(char *)pLine, 
		strlen(pLine),
		&pMethod,
		&pProxyProtocol,
		&pProxyHost,
		&iProxyHostLen,
		&pProxyPort,
		&iProxyPortLen,
		&pURI,
		&pQueryString,
		&pProtocol
		);
		
	if ( iStatus ) { return iStatus; };

	if ( !pMethod || !pURI || !pQueryString || !pProtocol )
		{ return ST_BADREQUEST; };

	/* --- store these headers --- */
	PIDB_add( pDB, PIDBTYPE_STRING, KEY_HTTP_METHOD, (void *)pMethod, 0 );
	PIDB_add( pDB, PIDBTYPE_STRING, KEY_HTTP_URI, (void *)pURI, 0 );
	PIDB_add( pDB, PIDBTYPE_STRING, KEY_HTTP_QUERYSTRING, (void *)pQueryString, 0 );
	PIDB_add( pDB, PIDBTYPE_STRING, KEY_HTTP_PROTOCOL, (void *)pProtocol, 0 );

	/* --- Is this a proxy request? --- */
	if ( pProxyProtocol )
		{
		PIDB_add( pDB, PIDBTYPE_STRING, KEY_HTTP_PROXYPROTOCOL,
			(void *)pProxyProtocol, 0 );
		PIString sProxyHost( pProxyHost, iProxyHostLen );
		PIDB_add( pDB, PIDBTYPE_STRING, KEY_HTTP_PROXYHOST,
			(void *)(const char *)sProxyHost, 0 );
		PIString sProxyPort( pProxyPort, iProxyPortLen );
		PIDB_add( pDB, PIDBTYPE_STRING, KEY_HTTP_PROXYPORT,
			(void *)(const char *)sProxyPort, 0 );
		};

	/* ---
	Convert method and status into internal numeric form	
	--- */
	int iMethod = MD_UNKNOWN;
	int iProtocol = PR_UNKNOWN;
	if ( !PIUtil_stricmp( pMethod, MD_NAME_GET ) )
		{ iMethod = MD_GET; }
	else if ( !PIUtil_stricmp( pMethod, MD_NAME_POST ) )
		{ iMethod = MD_POST; }
	else if ( !PIUtil_stricmp( pMethod, MD_NAME_HEAD ) )
		{ iMethod = MD_HEAD; }
	else if ( !PIUtil_stricmp( pMethod, MD_NAME_PUT ) )
		{ iMethod = MD_PUT; }
	else if ( !PIUtil_stricmp( pMethod, MD_NAME_DELETE ) )
		{ iMethod = MD_DELETE; }
	else if ( !PIUtil_stricmp( pMethod, MD_NAME_OPTIONS ) )
		{ iMethod = MD_OPTIONS; }
	else if ( !PIUtil_stricmp( pMethod, MD_NAME_TRACE ) )
		{ iMethod = MD_TRACE; };

	if ( *pProtocol )
		{
		/* --- any protocol is not HTTP/0.9 --- */
		if ( !PIUtil_stricmp( pProtocol, PR_NAME_HTTP10 ) )
			{ iProtocol = PR_HTTP10; }
		else if ( !PIUtil_stricmp( pProtocol, PR_NAME_HTTP11 ) )
			{ iProtocol = PR_HTTP11; };
		}
	else
		{ iProtocol = PR_HTTP09; };

	/* --- Do we support this method and protocol ? --- */
	if ( iMethod == MD_UNKNOWN ) { return ST_NOTIMPLEMENTED; };
	if ( iProtocol == PR_UNKNOWN ) { iProtocol = PR_HTTP10; };

	/* --- Do we support the method for version < HTTP/1.1 ? --- */
	if ((iProtocol != PR_HTTP11) && (iMethod > MD_HEAD))
		{ return ST_BADREQUEST; }; // maybe better ST_NOTIMPLEMENTED?
	
	/* --- set the numeric method and protocol --- */
	PIDB_add( pDB, PIDBTYPE_OPAQUE, KEY_HTTP_METHOD, (void *)iMethod, 0 );
	PIDB_add( pDB, PIDBTYPE_OPAQUE, KEY_HTTP_PROTOCOL, (void *)iProtocol, 0 );

	return iStatus;
	}


/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int StressClient::ReadFileMask( const char *pValue, int iStatus )
{

	PIFInfo *pInfo = PIFInfo_new( pValue );

	PIString sFilePath = PIFInfo_getPathRoot( pInfo );
	PIString sFileMask = PIFInfo_getName( pInfo );

	if ( sFileMask && sFilePath )
		{
		PIFInfo *pDir = HTTPCore_getCachedFile( (const char *)sFilePath );
		if ( pDir && PIFInfo_isDirectory( pDir ) )
			{

			PIFInfo *pFile = PIFInfo_getFirstFileInDirectory( pDir );
			enum { BUFSIZE=15 };
			char szBuf[BUFSIZE+1];
		
			while( pFile )
				{
	
				/* ---
				Check file is allowed, if mask pattern matches
				then include this file
				--- */
				if ( PIFInfo_isReadable( pFile ) )
					{

					/* ---
					Get filename
					--- */
					PIString sFileName( PIFInfo_getName( pFile ) );

					if ( HTTPUtil_regexMatch( sFileMask, sFileMask.Len(),
						sFileName, sFileName.Len() ))
						{
						sprintf( szBuf, "%lu", iCurrentTest++ );
						PIString sTestFile = sFilePath;
						sTestFile.Concatenate( PIPlatform_getDirectorySeparator());
						sTestFile.Concatenate( sFileName );
						PIDB *pDB = PIDB_new( pTestcaseDB, szBuf );
						PIDB_add( pDB, PIDBTYPE_STRING, KEY_INT_TESTFILE,
							(void *)(const char *)sTestFile, 0 );
						PIDB_add( pDB, PIDBTYPE_OPAQUE, KEY_INT_STATUS,
							(void *)iStatus, 0 );
						};
					};

				if ( !PIFInfo_getNextFileInDirectory( pFile ) )
					{ PIFInfo_delete( pFile ); pFile = 0; };

				}; //while
			HTTPCore_releaseCachedFile( pDir );
			};
		};
	return PIAPI_COMPLETED;
}


/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int StressClient::Parameter( const char *pVariable, const char *pValue,
		const char *pWhere )
	{
	assert( pVariable && pValue );
	PIOStrStream os;
	os << pWhere << "StressClient: ";

	if ( !PIUtil_stricmp( KEY_CONF_USERAGENT, pVariable ) )
		{
		sUserAgent = (const char *)DeQuote( pValue );
		}
	else if ( !PIUtil_stricmp( KEY_CONF_PROTOCOL, pVariable ) )
		{
		iProtocol = (!PIUtil_stricmp((const char *)DeQuote( pValue ),
			"HTTP/1.1")) ? PR_HTTP11 : PR_HTTP10;
		}
	else if ( !PIUtil_stricmp( KEY_CONF_VIRTUALHOST, pVariable ) )
		{
		sVirtualHost = (const char *)DeQuote( pValue );
		}
	else if ( !PIUtil_stricmp( KEY_CONF_KEEPOPEN, pVariable ) )
		{
		iKeepAlive = !PIUtil_stricmp((const char *)DeQuote( pValue ), "On");
		}
	else if ( !PIUtil_stricmp( KEY_CONF_KEEPOPENTIMEOUT, pVariable ) )
		{
		iAliveTimeout = atoi((const char *)DeQuote( pValue ));
		}
	else if ( !PIUtil_stricmp( KEY_CONF_KEEPOPENCOUNT, pVariable ) )
		{
		iKeepOpenCount = atoi((const char *)DeQuote( pValue ));
		}
	else if ( !PIUtil_stricmp( KEY_CONF_RANDOM, pVariable ) )
		{
		iRandom = !PIUtil_stricmp((const char *)DeQuote( pValue ), "On");
		}
	else if ( !PIUtil_stricmp( KEY_CONF_FILEMASK, pVariable ) )
		{
		StringTokenizer tTokens( (const char *)DeQuote( pValue ),":" );
		int iStatus = tTokens.NumTokens() > 1 ? atoi( tTokens.GetToken( 1 ) ) : 200;
		ReadFileMask( (const char *)tTokens.GetToken( 0 ), iStatus );
		}
	else if ( !PIUtil_stricmp( KEY_CONF_TESTFILE, pVariable ) )
		{
		enum { BUFSIZE=15 };
		char szBuf[BUFSIZE+1];
		sprintf( szBuf, "%lu", iCurrentTest++ );
		StringTokenizer tTokens( (const char *)DeQuote( pValue ), ":" );
		PIDB *pDB = PIDB_new( pTestcaseDB, szBuf );
		PIDB_add( pDB, PIDBTYPE_STRING, KEY_INT_TESTFILE,
			(void *)(const char *)tTokens.GetToken( 0 ), 0 );
		int iStatus = tTokens.NumTokens() > 1 ? atoi( tTokens.GetToken( 1 ) ) : 200;
		PIDB_add( pDB, PIDBTYPE_OPAQUE, KEY_INT_STATUS, (void *)iStatus, 0 );
		}
	else if ( !PIUtil_stricmp( KEY_CONF_TESTCASE, pVariable ) )
		{
		enum { BUFSIZE=15 };
		char szBuf[BUFSIZE+1];
		sprintf( szBuf, "%lu", iCurrentTest++ );
		PIDB *pDB = PIDB_new( pTestcaseDB, szBuf );
		StringTokenizer tTokens( (const char *)DeQuote( pValue ), ":" );

		if ( !ReadRequestLine( pDB,	(const char *)tTokens.GetToken( 0 ) ) == INT_CONTINUE )
			{
			// ErrorMsg!
			iOK = 0;
			}
		else
			{
			int iStatus = tTokens.NumTokens() > 1 ? atoi( tTokens.GetToken( 1 ) ) : 200;
			PIDB_add( pDB, PIDBTYPE_OPAQUE, KEY_INT_STATUS,
				(void *)iStatus, 0 );
			};
		}
	else if ( !PIUtil_stricmp( KEY_CONF_LOGFILE, pVariable ) )
		{
		sLogfile = (const char *)DeQuote( pValue );
		}
	else if ( !PIUtil_stricmp( KEY_CONF_OPENMODE, pVariable ) )
		{
		sOpenMode = (const char *)DeQuote( pValue );
		}
	else
		{
		os << "Unknown directive '" << pVariable <<
			"'" << ends;
		CONFIG_ERR( Object(), os.str() );
		return 0;
		};

	return 1;
	};

int hex2int(char *s)
{
	int iRes = 0;
	for (unsigned int i=0;i<strlen(s);i++)
		{
		s[i] = toupper(s[i]);
		iRes <<= 4;
		iRes += (s[i]<'A') ? s[i]-48 : s[i]-55;
		}
	return iRes;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int StressClient::Execute( int iArgc, const char *ppArgv[] )
{
	PI_MARK;

	if ( iArgc<1 ) { return PIAPI_ERROR; };
	PIObject *pIO = (PIObject *)*ppArgv;
	if ( !pIO )	{ return PIAPI_ERROR; };

	/* ---
	Get the DB from the IO object to monitor the KeepOpen flag
	--- */
	PIDB *pC = PIObject_getDB( pIO );
	int iRet;
	int iTimeout;

	PIIOBuffer *pBuffer = PIIOBuffer_new( pIO );
	if ( !pBuffer ) return PIAPI_ERROR;

	if ( iKeepAlive ) {
		assert( pFKRecvTimeout );
		iTimeout = (int)PIDB_lookup( pC, PIDBTYPE_OPAQUE,
			pFKRecvTimeout, PIDBFLAG_FASTKEY );

		PIDB_replace( pC, PIDBTYPE_OPAQUE, pFKRecvTimeout,
			(void *)iAliveTimeout, PIDBFLAG_FASTKEY );
	};

	if (iRandom) srand( (unsigned)time( NULL ) );

    int iDoKeepOpen = iKeepAlive;
	int iDoKeepOpenCount = iKeepOpenCount;
	int iServerProtocol = PR_HTTP11;
	const char *pKeepOpen = 0;
    PIDB *pR = PIDB_new( 0, "R" );

	for(;;)
		{
		/* ---
		Disallow more than the specified number of connection reuses
		--- */
		if ( !iDoKeepOpenCount )
			iDoKeepOpen = 0;
		else
			iDoKeepOpenCount--;

		/* ---
		Get the testcase from DB
		--- */
		if ( !pTestcaseDB ) break;
		enum { BUFSIZE=16 };
		char szBuf[BUFSIZE+1];
		if ( iRandom )
			{
			iCurrentTest = rand() % (iMaxTest + 1);
			}
		else
			{
			if (iCurrentTest > iMaxTest ) { iCurrentTest = 0; };
			}
		sprintf( szBuf, "%lu", iCurrentTest );
		PIDB *pQ = (PIDB *)PIDB_lookup( pTestcaseDB, PIDBTYPE_TREE, szBuf, 0 );
		if ( !pQ ) return PIAPI_ERROR;

		/* --- get ready for new request --- */
		const char *pPath = (const char *)PIDB_lookup( pQ, PIDBTYPE_STRING,
			pFKTestfile, PIDBFLAG_FASTKEY );

		iRet = pPath ? SendRequestFile( pBuffer, pPath )
		             : SendRequestDB( pBuffer, pC, pQ, iDoKeepOpen );

	    /* --- send the whole thing on its way --- */
		PIIOBuffer_flush( pBuffer );
		iRet = PIIOBuffer_pollBeforeRead( pBuffer );
		if (iRet < 0)
			{
			cout << "PIIOBuffer_pollBeforeRead failed" <<
				endl << "Testcase: " << iCurrentTest << endl;
			goto exit_handle;
			}

	    /*
		** Read the response
	    */
		iRet = HTTPCore_readHeaders( pBuffer, pR, RH_RESPONSE );
		if ( iRet )
			{
			cout << "HTTPCore_readHeaders failed: " << iRet <<
				endl << "Testcase: " << iCurrentTest << endl;
	        goto exit_handle;
		    };
    
		/* ---
	    Check out status line from remote server

⌨️ 快捷键说明

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