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

📄 udpipsck.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		AcceptTimeout -1
		RecvTimeout 30
		SendTimeout 60 
		PeerAddressVariable "STRING:RemoteAddr"
		PeerHostNameVariable "STRING:RemoteHost"
		LocalAddressVariable "STRING:LocalAddr"
		ServerPortVariable "RFC822:ServerPort"
		Flags "OwnDB|SetLocalAddress|SetPeerAddress|DNSReverseLookup"
	</Object>

	</PRE>
/*___+++HTMLDOC_END+++___*/
#endif

/*____________________________________________________________________________*\
** Data structure associated with the instances of prototype UDPIPSocket object
\*____________________________________________________________________________*/
class MainSocketData
{
private:
	PIDB *pDB;
	PIConfig *pConfigDB;

	/* --- internal methods --- */
	int FlagNamesToNumber( const char *pFlags )
		{
		assert( pFlags );
		if ( !pFlags )
			{ return 0; };
		int iFlags = 0;
		for(;;)
			{
			/* --- skip leading space --- */
			for( ; *pFlags && (isspace(*pFlags)); pFlags++ );
			const char *pFlag = pFlags;
			int i=0;
			for( ; pFlags[i] && !(isspace(pFlags[i])) && pFlags[i]!='|'; i++ );
			
			/* --- deal with this flag --- */
			if ( !PIUtil_strncmpi( pFlag, VALUE_FLAG_OWNDB, i ))
				{ iFlags |= FLG_OWNDB; }
			else if ( !PIUtil_strncmpi( pFlag, VALUE_FLAG_SETREMOTEADDRESS, i ))
				{ iFlags |= FLG_SETREMOTEADDRESS; }
			else if ( !PIUtil_strncmpi( pFlag, VALUE_FLAG_DNSREVERSELOOKUP, i ))
				{ iFlags |= FLG_DNSREVERSELOOKUP; }
			else if ( !PIUtil_strncmpi( pFlag, VALUE_FLAG_SETLOCALADDRESS, i ))
				{ iFlags |= FLG_SETLOCALADDRESS; }
			else
				{ iFlags |= FLG_ERROR; };

			/* -- check for end of string --- */
			if ( pFlags[i] )
				{
				/* --- another flag --- */
				pFlags=&(pFlags[++i]);
				}
			else
				{ break; };
			};
		return iFlags;
		};

public:
	int iServer;				/* active or passive, 0 = passive */
	int iPort;
	char *pHost;
	int iAcceptTimeout;
	int iRecvTimeout;
	int iSendTimeout;
	DBInfo *pPeerAddressVariable;	/* variable used to store remote IP */
	DBInfo *pPeerHostVariable;		/* variable used to store remote Host */ 
	DBInfo *pLocalAddressVariable;	/* variable used to store local IP */ 
	DBInfo *pServerPortVariable;	/* variable used to store local port */ 
	int iFlags;
	char *pFAcceptLockFile;		/* lockfile name */
	int iFAcceptLockFD;			/* lockfile descriptor */

protected:
	int Parameter( const char *pVariable, const char *pValue,
		const char *pWhere )
		{
		assert( pVariable && pValue );
		if ( !pVariable || !pValue )
			{ return 0; };
		if ( !PIUtil_stricmp( KEY_CONF_TYPE, pVariable ) )
			{
			iServer = !PIUtil_stricmp( pValue, VALUE_PASSIVE );
			}
		else if ( !PIUtil_stricmp( KEY_CONF_BINDPORT, pVariable ) )
			{
			iPort = atoi( pValue );
			}
		else if ( !PIUtil_stricmp( KEY_CONF_BINDHOST, pVariable ) )
			{
			pHost = PIUtil_strdup( pValue );
			}
		else if ( !PIUtil_stricmp( KEY_CONF_ACCEPTTIMEOUT, pVariable ) )
			{
			iAcceptTimeout = atoi( pValue );
			}
		else if ( !PIUtil_stricmp( KEY_CONF_SENDTIMEOUT, pVariable ) )
			{
			iSendTimeout = atoi( pValue );
			}
		else if ( !PIUtil_stricmp( KEY_CONF_RECVTIMEOUT, pVariable ) )
			{
			iRecvTimeout = atoi( pValue );
			}
		else if ( !PIUtil_stricmp( KEY_CONF_ACCEPTTIMEOUT, pVariable ) )
			{
			iAcceptTimeout = atoi( pValue );
			}
		else if ( !PIUtil_stricmp( KEY_CONF_PEERADDRESSVARIABLE, pVariable ) )
			{
			pPeerAddressVariable = new DBInfo( pValue );
			}
		else if ( !PIUtil_stricmp( KEY_CONF_PEERHOSTNAMEVARIABLE, pVariable ) )
			{
			pPeerHostVariable = new DBInfo( pValue );
			}
		else if ( !PIUtil_stricmp( KEY_CONF_LOCALADDRESSVARIABLE, pVariable ) )
			{
			pLocalAddressVariable = new DBInfo( pValue );
			}
		else if ( !PIUtil_stricmp( KEY_CONF_SERVERPORTVARIABLE, pVariable ) )
			{
			pServerPortVariable = new DBInfo( pValue );
			}

		else if ( !PIUtil_stricmp( KEY_CONF_ACCEPTLOCKFILE, pVariable ) )
			{
/* --- lockfile synchronization is UNIX specific --- */
#if POSIX
			/* --- check this hasn't already been done --- */
			if ( iFAcceptLockFD!=-1 )
				{
				PILog_addMessage( pDB, pConfigDB, PILOG_ERROR,
					"%sUDPIPIO: 'AcceptLockFile' specified more than once.",
					pWhere );
				return 0;
				};
			
			/* --- get the name of the lockfile --- */	
			/* NOTE: There is some risk of overwrite here if file specified by
			** UNIXDaemon is too long. Fortunately this is under our control
			** not under a remote users control.
			*/
			enum { BUF_SIZE=511 };
			char szBuf[BUF_SIZE+1];
			*szBuf = '\0';
			ifstream ifs( pValue );
			if ( ifs.bad() )
				{
				PILog_addMessage( pDB, pConfigDB, PILOG_ERROR,
					"%sUDPIPIO: Could not open file: '%s'.%s",
					pWhere, pValue, szLockFileMsg );
				return 0;
				};
			if ( ifs.good() )
				{
				ifs >> szBuf;
				};	
			if ( !*szBuf )
				{
				PILog_addMessage( pDB, pConfigDB, PILOG_ERROR,
					"%sUDPIPIO: Could not read lock file name from file:\
 '%s'.", pWhere, pValue );
				return 0;
				};

			pFAcceptLockFile = PIUtil_strdup( szBuf );

			/* --- attempt to open a descriptor to the lockfile --- */
			iFAcceptLockFD = ::open( pFAcceptLockFile, O_RDWR );
			if ( iFAcceptLockFD==-1 )
				{
				PILog_addMessage( pDB, pConfigDB, PILOG_ERROR,
					"UDPIPIO%s: Error opening lockfile: '%s' errno: %d.",
					pWhere, pFAcceptLockFile, errno );

				return 0;
				};
#endif	/* lockfile synchronization is UNIX specific */
			}
		else if ( !PIUtil_stricmp( KEY_CONF_FLAGS, pVariable ) )
			{
			iFlags |= FlagNamesToNumber( pValue );
			if ( iFlags & FLG_ERROR )
				{
				PILog_addMessage( pDB, pConfigDB, PILOG_ERROR,
					"%sUDPIPIO: Bad flag in list of flags '%s'", pWhere,
					pValue );
				return 0;
				};
			}
		else
			{
			PILog_addMessage( pDB, pConfigDB, PILOG_ERROR,
				"%sUDPIPIO: Unknown parameter '%s'", pWhere, pVariable );
			return 0;
			};

		return 1;
		};

public:
	static int ParameterFn( void *pData, const char *pVar, const char *pVal,
		const char *pWhere )
		{
		assert( pData );
		return ((MainSocketData *)pData)->Parameter( pVar, pVal, pWhere );
		};

	/* ---
	This pointer is here because a thread could be terminated just when it
	was waiting on a connection to be accepted. The new IO object
	would not be deleted because the pointer has not been returned
	to whomever would use it. Therefore the main IO object sets this
	pointer to a new IO object just before polling, and resets it
	to 0 just after, so that if the thread and main parent object
	is deleted without the poll returning, then the new IO object would
	still be deleted.
	--- */
	PIObject *pAcceptingIOObject;
	
	MainSocketData( PIDB *pTheDB, PIConfig *pTheConfigDB )
		:
			pDB( pTheDB ),
			pConfigDB( pTheConfigDB ),
			iServer( 0 ),
			iPort( 0 ),
			pHost( 0 ),
			iAcceptTimeout( DEFAULT_TIMEOUT ),
			iRecvTimeout( DEFAULT_TIMEOUT ),
			iSendTimeout( DEFAULT_TIMEOUT ),
			pPeerAddressVariable( 0 ),
			pPeerHostVariable( 0 ),
			pLocalAddressVariable( 0 ),
			pServerPortVariable( 0 ),
			iFlags( 0 ),
			pFAcceptLockFile( 0 ),
			iFAcceptLockFD( -1 ),
			pAcceptingIOObject( 0 )
		{};

	~MainSocketData()
		{
		PIUtil_free( pHost ); 
		delete pPeerAddressVariable; 
		delete pPeerHostVariable; 
		delete pLocalAddressVariable; 
		delete pServerPortVariable;
		PIUtil_free( pFAcceptLockFile ); 

		/* --- close lockfile descriptor --- */
#	if POSIX
		if ( iFAcceptLockFD!=-1 )
			{ ::close( iFAcceptLockFD ); };
		iFAcceptLockFD = -1;
#	endif

		if ( pAcceptingIOObject )
			{ PIObject_delete( pAcceptingIOObject, 0, 0 ); };
		};

	int Accept( UDPIPSocketData *pData, PIObject *pChildSocket );
	int InitSocketFromConfiguration( PIObject *pThis,
		UDPIPSocketData *pProtoType );
};

/*____________________________________________________________________________*\
** Data structure associated with the instances of UDPIPSocket objects
\*____________________________________________________________________________*/
class UDPIPSocketData
{
public:
	/* --- generic stuff --- */
	PIObject *pObject;
	int iPrototype;
	int iOK;

	/* --- socket stuff --- */
	int iSize;
	struct sockaddr_in tAddr;
	int iSocket;

    /* --- buffer for received data --- */
    int iReceivedLen;
    char szReceived[MAX_PACKET_SIZE];

	/* --- other stuff --- */
	const UDPIPSocketData *pParentData;		/* NULL for parent sockets */
	MainSocketData *pMainSocketData;		/* NULL for child sockets */

	/* ---
	Constructor
	--- */
	UDPIPSocketData(
		PIObject *pTheObject,
		int iArgc,
		const char *ppArgv[] )
	:
		pObject( pTheObject ),
		iPrototype( 1 ),	
		iOK( 0 ),
		iSize( sizeof( struct sockaddr_in ) ),
		iSocket( SOCKET_ERROR ),
        iReceivedLen( 0 ),
		pParentData( 0 ),
		pMainSocketData( 0 )
		{
		PIDB *pTheDB;
		PIConfig *pDB;
		MainSocketData *pConfig;

		pTheDB = PIObject_getDB( pObject );
		pDB = PIObject_getConfigurationDB( pObject );
		if ( !pTheDB || !pDB )
			{ return; };
		pConfig = new MainSocketData( pTheDB, pDB );
		if (  !pConfig )
			{ return; };

		if ( !PIObject_readParameters( pObject, iArgc, ppArgv,
			MainSocketData::ParameterFn, pConfig ) )
			{ return; };

		if ( pConfig->InitSocketFromConfiguration( pTheObject, this ) )
			{ return; };
		iOK = 1;
		};

	/* ---
	Copy constructor 
	--- */
	UDPIPSocketData(
		PIObject *pTheObject,
		const UDPIPSocketData *pTheParentData,
		int /* iArgc */,
		const char * /* ppArgv */ [] )
	:
		pObject( pTheObject ),
		iPrototype( 0 ),	
		iOK( 0 ),
		iSize( sizeof( struct sockaddr_in ) ),
		iSocket( SOCKET_ERROR ),
		pParentData( pTheParentData ),
		pMainSocketData( pTheParentData->pMainSocketData )
		{
		PIObject_setUserData( pTheObject, this );
		assert( pMainSocketData );
		
		PIDB *pParentDB = PIObject_getDB( pObject );
		PIDB *pDB = pParentDB;

		/* --- should this object have its own DB ? --- */
		if ( pMainSocketData->iFlags & FLG_OWNDB )
			{
			pDB = PIDB_new( 0, "UDPIPSocketDB" );
			PIObject_setDB( pObject, pDB );
			};

		iOK = 1;
		};

	~UDPIPSocketData()
		{
		if ( iSocket!=-1 )
			{
			::shutdown( iSocket, 2 );
			::closesocket( iSocket );
			};
		if ( iPrototype )
			{
			delete pMainSocketData;
			}
		else
			{
			PIDB_delete( PIObject_getDB( pObject ) );
			};

		/* ---
		this object does not have to delete its DB object even
		if it created it, because that happens automatically
		--- */
		};

	inline int IsOK()		{ return iOK; };
};

#define CONFIG_ERR(pThis, msg)	\
	{ PILog_addMessage( PIObject_getDB(pThis), \
	PIObject_getConfigurationDB(pThis), PILOG_ERROR, (msg) ); }

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int MainSocketData::InitSocketFromConfiguration( PIObject *pThis,
	UDPIPSocketData *pProtoTypeUDPIPObject )
{
	PIDB *pTheDB;
	PIConfig *pDB;

	pTheDB = PIObject_getDB( pThis );
	pDB = PIObject_getConfigurationDB( pThis );
	if ( !pTheDB || !pDB )
		{ return PIAPI_ABORT; };

	/*
	**
	*/
	if ( !iServer )
		{
		pProtoTypeUDPIPObject->pMainSocketData = this;
		return Internal_initActiveSocket( pThis );
		};

	/*
	** Check for errors
	*/
	if ( iPort<0 )
		{
		PILog_addMessage( pTheDB, pDB, PILOG_ERROR,	
			"UDPIPIO: Invalid bind port." );
		}
	else if ( !pHost )
		{
		PILog_addMessage( pTheDB, pDB, PILOG_ERROR,
			"UDPIPIO: Invalid bind host." );
		}
	else
		{
		/* --- OK --- */
		pProtoTypeUDPIPObject->pMainSocketData = this;

		if ( iServer )
			{
			return Internal_initPassiveSocket( pThis, pProtoTypeUDPIPObject );
			};
		};
	
	/* --- something failed --- */
	return PIAPI_ABORT;
}

/*____________________________________________________________________________*\
 *
 Function:		 Internal_initActiveSocket
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int Internal_initActiveSocket( PIObject * )
{
	return PIAPI_COMPLETED;
}

/*____________________________________________________________________________*\
 *
 Function:		 Internal_initPassiveSocket
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int Internal_initPassiveSocket( PIObject *pThis, UDPIPSocketData *pData )
{
	/* automatic variables */
	int iOne=1;

	assert( pData );

⌨️ 快捷键说明

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