📄 tcpipsck.cpp
字号:
Example:
<PRE>
<Object>
Name DefaultTCPIPIOObject
Class TCPIPIOClass
BindHost localhost
BindPort 80
Type Passive
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 TCPIPSocket 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 server 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,
"%sTCPIPIO: '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,
"%sTCPIPIO: Could not open file: '%s'.%s",
pWhere, pValue, szLockFileMsg );
return 0;
};
if ( ifs.good() )
{
ifs >> szBuf;
};
if ( !*szBuf )
{
PILog_addMessage( pDB, pConfigDB, PILOG_ERROR,
"%sTCPIPIO: 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,
"TCPIPIO%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,
"%sTCPIPIO: Bad flag in list of flags '%s'", pWhere,
pValue );
return 0;
};
}
else
{
PILog_addMessage( pDB, pConfigDB, PILOG_ERROR,
"%sTCPIPIO: 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( TCPIPSocketData *pData, PIObject *pChildSocket );
int InitSocketFromConfiguration( PIObject *pThis,
TCPIPSocketData *pProtoType );
};
/*____________________________________________________________________________*\
** Data structure associated with the instances of TCPIPSocket objects
\*____________________________________________________________________________*/
class TCPIPSocketData
{
public:
/* --- generic stuff --- */
PIObject *pObject;
int iPrototype;
int iOK;
/* --- socket stuff --- */
int iSize;
struct sockaddr_in tAddr;
int iSocket;
/* --- other stuff --- */
const TCPIPSocketData *pParentData; /* NULL for parent sockets */
MainSocketData *pMainSocketData; /* NULL for child sockets */
/* ---
Constructor
--- */
TCPIPSocketData(
PIObject *pTheObject,
int iArgc,
const char *ppArgv[] )
:
pObject( pTheObject ),
iPrototype( 1 ),
iOK( 0 ),
iSize( sizeof( struct sockaddr_in ) ),
iSocket( SOCKET_ERROR ),
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
--- */
TCPIPSocketData(
PIObject *pTheObject,
const TCPIPSocketData *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, "TCPIPSocketDB" );
PIObject_setDB( pObject, pDB );
};
iOK = 1;
};
~TCPIPSocketData()
{
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,
TCPIPSocketData *pProtoTypeTCPIPObject )
{
PIDB *pTheDB;
PIConfig *pDB;
pTheDB = PIObject_getDB( pThis );
pDB = PIObject_getConfigurationDB( pThis );
if ( !pTheDB || !pDB )
{ return PIAPI_ABORT; };
/*
**
*/
if ( !iServer )
{
pProtoTypeTCPIPObject->pMainSocketData = this;
return Internal_initActiveSocket( pThis );
};
/*
** Check for errors
*/
if ( iPort<0 )
{
PILog_addMessage( pTheDB, pDB, PILOG_ERROR,
"TCPIPIO: Invalid bind port." );
}
else if ( !pHost )
{
PILog_addMessage( pTheDB, pDB, PILOG_ERROR,
"TCPIPIO: Invalid bind host." );
}
else
{
/* --- OK --- */
pProtoTypeTCPIPObject->pMainSocketData = this;
if ( iServer )
{
return Internal_initPassiveSocket( pThis, pProtoTypeTCPIPObject );
};
};
/* --- something failed --- */
return PIAPI_ABORT;
}
/*____________________________________________________________________________*\
*
Function: Internal_initActiveSocket
Synopsis:
Description:
\*____________________________________________________________________________*/
int Internal_initActiveSocket( PIObject * )
{
return PIAPI_COMPLETED;
}
/*____________________________________________________________________________*\
*
Function: Internal_initPassiveSocket
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -