📄 dispatch.cpp
字号:
\*____________________________________________________________________________*/
class Dispatcher
{
private:
PIObject *pObject;
PIObject *pDefaultHost;
bool bOK;
int iKeepOpen;
int iKeepOpenCount;
int iKeepOpenTimeout;
const char *pPort;
/* ---
Fast keys
--- */
const char *pFKRecvTimeout;
const char *pFKKeepOpen;
const char *pFKPort;
const char *pFKKeySize;
public:
Dispatcher( PIObject *pTheObject, int, const char *[] )
:
pObject( pTheObject ),
pDefaultHost( 0 ),
bOK( false ),
iKeepOpen( 1 ),
iKeepOpenCount( 100 ),
iKeepOpenTimeout( 5 ),
pPort( 0 ),
pFKRecvTimeout(
PIDB_getFastKey( KEY_INT_RECVTIMEOUT, PIDBTYPE_OPAQUE ) ),
pFKKeepOpen( PIDB_getFastKey( KEY_INT_KEEPOPEN, PIDBTYPE_OPAQUE ) ),
pFKPort( PIDB_getFastKey( KEY_INT_SERVERPORT, PIDBTYPE_RFC822 ) ),
pFKKeySize( PIDB_getFastKey( KEY_HTTPS_KEYSIZE, PIDBTYPE_STRING ) )
{
assert( pObject );
if ( !pObject )
{ return; };
if ( HTTPCore_initServer( pObject ) )
{
return;
};
/* --- load up default virtual host object --- */
const char *pDefaultHostName = PIConfig_lookupValue(
PIObject_getConfigurationDB( pObject ),
KEY_CONF_DEFAULTHOST, 0, 0 );
if ( !pDefaultHostName )
{
CONFIG_ERR( pObject, "Dispatcher: 'DefaultHost' not defined" );
return;
};
PIDB *pDB = PIObject_getDB( pObject );
pDefaultHost = PIObject_loadFromLine(
pDB, PIObject_getConfigurationDB( pObject ), pDefaultHostName );
if ( !pDefaultHost )
{/* --- error set by PIObject_loadFromLine() --- */return; };
pPort = (const char *)PIDB_lookup( PIObject_getDB( pDefaultHost ),
PIDBTYPE_RFC822, pFKPort, PIDBFLAG_FASTKEY );
/* ---
Check for connection keep open, optional
--- */
const char *pTmp = PIConfig_lookupValue(
PIObject_getConfigurationDB( pObject ),
KEY_CONF_KEEPOPEN, 0, 0 );
if ( pTmp && !PIUtil_stricmp( pTmp, VALUE_OFF ) )
{ iKeepOpen = 0; };
/* ---
Check for keep open count, optional
--- */
pTmp = PIConfig_lookupValue(
PIObject_getConfigurationDB( pObject ),
KEY_CONF_KEEPOPENCOUNT, 0, 0 );
if ( pTmp ) { iKeepOpenCount = atoi( pTmp ); };
/* ---
Check for keep open timeout, optional
--- */
pTmp = PIConfig_lookupValue(
PIObject_getConfigurationDB( pObject ),
KEY_CONF_KEEPOPENTIMEOUT, 0, 0 );
if ( pTmp ) { iKeepOpenTimeout = atoi( pTmp ); };
bOK = true;
};
~Dispatcher()
{
PIObject_delete( pDefaultHost, 0, 0 );
HTTPCore_cleanupServer();
};
/* ---
Invoke all the steps on all the handlers
--- */
int HandleConnection( PIHTTP &tPIHTTP )
{
int iRet = HTTPCore_dispatch( &tPIHTTP, PH_INIT, PH_DESTROY );
return iRet;
};
/* ---
Invoke all the steps on all the handlers
--- */
inline int Execute( int iArgc, const char *ppArgv[] )
{
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 );
PIDB_add( pC, PIDBTYPE_OPAQUE, pFKKeepOpen, (void *)iKeepOpen,
PIDBFLAG_FASTKEY );
int iDoKeepOpen = 0;
int iDoKeepOpenCount = iKeepOpenCount;
int iRet;
PIHTTP tPIHTTP( pIO, PIObject_getDB( pDefaultHost ) );
/* --- set the port variable in host db if not yet done --- */
/* ( assume the server port won't change between connections) */
if (!pPort)
{
pPort = (const char *)PIDB_lookup( tPIHTTP.pConnectionDB,
PIDBTYPE_RFC822, pFKPort, PIDBFLAG_FASTKEY );
if (pPort)
{
const char *pKeySize = (const char *)PIDB_lookup( tPIHTTP.pConnectionDB,
PIDBTYPE_STRING, pFKKeySize, PIDBFLAG_FASTKEY );
int iDefaultPort = pKeySize ? HTTPS_DEFAULT_PORT : HTTP_DEFAULT_PORT;
if ( atoi(pPort) != iDefaultPort )
{
PIDB_replace( tPIHTTP.pHostDB, PIDBTYPE_RFC822, pFKPort,
(void *)pPort, PIDBFLAG_FASTKEY );
pPort = (const char *)PIDB_lookup( tPIHTTP.pHostDB,
PIDBTYPE_RFC822, pFKPort, PIDBFLAG_FASTKEY );
};
};
};
for(;;)
{
/* ---
Disallow more than the specified number of connection reuses
--- */
if ( !iDoKeepOpenCount )
{
PIDB_replace( pC, PIDBTYPE_OPAQUE, pFKKeepOpen, 0,
PIDBFLAG_FASTKEY );
}
else
{ iDoKeepOpenCount--; };
/* --- get ready for new request --- */
tPIHTTP.NewRequest();
iRet = HandleConnection( tPIHTTP );
/* --- make sure all data was flushed --- */
tPIHTTP.GetIOBuffer().Flush();
if ( iRet==PIAPI_COMPLETED )
{
/* ---
Look at what the headers told the browser would happen
--- */
iDoKeepOpen = (int)PIDB_lookup( pC, PIDBTYPE_OPAQUE,
pFKKeepOpen, PIDBFLAG_FASTKEY );
}
else
{
return iRet;
};
/* --- close connection ? --- */
if ( !iDoKeepOpen )
{
return iRet;
};
/* ---
Get the current timeout and set it low for poll on next
request
--- */
assert( pFKRecvTimeout );
int iTimeout = (int)PIDB_lookup( pC, PIDBTYPE_OPAQUE,
pFKRecvTimeout, PIDBFLAG_FASTKEY );
/* ---
NOTE: This keep open timeout should be moved to the
configuration
--- */
PIDB_replace( pC, PIDBTYPE_OPAQUE, pFKRecvTimeout,
(void *)5, PIDBFLAG_FASTKEY );
/* ---
If there're 2 bytes more data in the input queue ...
--- */
if ( tPIHTTP.GetIOBuffer().getBufferLen() == 2 )
{
/* ---
... fix browser bug with extra CR/LF
--- */
char pTmp[2];
tPIHTTP.GetIOBuffer().Read( (char *)pTmp, 2);
};
/* --- poll for new data --- */
if ( tPIHTTP.GetIOBuffer().PollBeforeRead()<= 0 )
{
/* --- record error conditions? --- */
iRet = PIAPI_COMPLETED;
break;
};
/* ---
Reset the recv timeout
--- */
PIDB_replace( pC, PIDBTYPE_OPAQUE, pFKRecvTimeout,
(void *)iTimeout, PIDBFLAG_FASTKEY );
};
return iRet; /* ---
NOTE: there are other return points in this fn.
--- */
};
inline int IsOK() { return bOK; };
};
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int Dispatcher_execute( PIObject *pObj,
int iArgc, const char *ppArgv[] )
{
if ( !pObj ) return PIAPI_ERROR;
return ((Dispatcher *)PIObject_getUserData(pObj))->Execute( iArgc,
ppArgv );
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int Dispatcher_onClassLoad( PIClass_LoadAction eLoad, void * )
{
switch( eLoad )
{
case STARTUP:
default:;
};
return PIAPI_COMPLETED;
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int Dispatcher_constructor( PIObject *pObj,
int iArgc, const char *ppArgv[] )
{
Dispatcher *pDisp = new Dispatcher( pObj, iArgc, ppArgv );
if (!( pDisp && pDisp->IsOK() ))
{
delete pDisp;
return PIAPI_ERROR;
};
if ( PIObject_setUserData( pObj, pDisp ) )
{
delete pDisp;
CONFIG_ERR( pObj, "Dispatcher_constructor: \
PIObject_setUserData() failed" );
return PIAPI_ERROR;
};
return PIAPI_COMPLETED;
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int Dispatcher_copyConstructor( PIObject *, int, const char *[] )
{
return PIAPI_ERROR;
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int Dispatcher_destructor( PIObject *pObj, int,
const char *[] )
{
delete (Dispatcher *)PIObject_getUserData( pObj );
return PIAPI_COMPLETED;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -