Files
cdev-1.7.2n/extensions/cdevGenericServer/cdevServer/cdevServerTools.cc
2022-12-13 12:44:04 +01:00

404 lines
15 KiB
C++
Executable File

#include "cdevServerTools.h"
// ****************************************************************************
// cdevSimpleTimer::cdevSimpleTimer :
// Constructor.
// ****************************************************************************
cdevSimpleTimer::cdevSimpleTimer ( cdevReactor & Reactor, double Rate)
{
setTimeoutRate(Rate);
if(Reactor.registerTimer (this) == -1)
{
outputError ( CDEV_SEVERITY_SEVERE, "cdevSimpleTimer",
"Unable to register timer with cdevReactor");
}
}
// ****************************************************************************
// cdevSimpleTimer::~cdevSimpleTimer :
// Destructor.
// ****************************************************************************
cdevSimpleTimer::~cdevSimpleTimer ( void )
{
if(reactor) reactor->extractHandler(this);
handleClose();
}
// ****************************************************************************
// cdevSimpleTimer::handle_timeout :
// Called when the timer expires.
// ****************************************************************************
int cdevSimpleTimer::handleTimeout(void)
{
return execute();
}
// *****************************************************************************
// * cdevNameServerManager::cdevNameServerManager :
// * This method will read the CDEV_NAME_SERVER environment variable to
// * obtain a list of one or more cdev name servers that should be notified
// * that this server is operational. The class will create a
// * cdevNameServerHandler event handler to manage the connection to each of
// * the specified name servers. If a connection is lost to one of the
// * name servers, the cdevNameServerManager will attempt periodically to
// * reconnect to the specific name server.
// *****************************************************************************
cdevNameServerManager::cdevNameServerManager ( cdevReactor & Reactor,
char * DomainName,
char * ServerName,
unsigned short ServerPort )
: domainName(strdup(DomainName)),
serverName(strdup(ServerName)),
serverPort(ServerPort),
nameServerList(NULL),
nameServerHandlers(NULL),
nameServerCnt(0)
{
// *********************************************************************
// * Prior to establishing any connections, the class must first install
// * all of the necessary data into the serverInfo and updateInfo
// * objects.
// *********************************************************************
char * userName = getenv("USER");
char hostname[255];
struct hostent * hostPtr;
struct timeval tv;
gettimeofday (&tv);
gethostname(hostname, 255);
hostPtr = gethostbyname(hostname);
serverInfo.insert ("name", serverName);
serverInfo.insert ("domain", domainName);
serverInfo.insert ("host", (char *)hostPtr->h_name);
serverInfo.insert ("owner", userName?userName:(char *)"UNKNOWN");
serverInfo.insert ("time", (long)tv.tv_sec);
serverInfo.insert ("port", (long)serverPort);
serverInfo.insert ("pid", getpid ());
updateInfo.insert ("name", serverName);
updateInfo.insert ("domain", domainName);
// *********************************************************************
// * First obtain a list of name servers from the CDEV_NAME_SERVER
// * environment variable. If this list is empty, then report an
// * error once and then never call the handler again.
// *********************************************************************
char * nsList = getenv("CDEV_NAME_SERVER");
int idx;
int length;
if(nsList!=NULL)
{
char * nsPtr = nsList;
char * endPtr = nsList;
// *************************************************************
// * Determine the number of name servers that have been
// * defined in the CDEV_NAME_SERVER environment variable.
// *************************************************************
while(*nsPtr==':' && *nsPtr!=0) nsPtr++;
if(*nsPtr!=0)
{
nameServerCnt = 1;
while(nsPtr!=NULL && *nsPtr!=0)
{
if((nsPtr = strchr(nsPtr, ':'))!=NULL)
{
while(*(++nsPtr)==':' && *nsPtr!=0);
if(*nsPtr!=0) nameServerCnt++;
}
}
}
// *************************************************************
// * Copy each of the defined cdev name server host names into
// * the nameServerList.
// *************************************************************
if(nameServerCnt>0)
{
nameServerList = new char *[nameServerCnt];
nameServerHandlers = new cdevNameServerHandler *[nameServerCnt];
for(nsPtr = nsList, idx=0; idx<nameServerCnt && *nsPtr!=0; idx++)
{
while(*nsPtr==':' && *nsPtr!=0) nsPtr++;
for(endPtr=nsPtr; *endPtr && *endPtr!=':'; endPtr++);
length = endPtr-nsPtr;
nameServerList[idx] = new char[length+1];
strncpy(nameServerList[idx], nsPtr, length);
nameServerList[idx][length] = 0;
nsPtr = endPtr;
}
}
}
// *********************************************************************
// * If no cdev name servers have been defined in the cdev name server
// * list, print a warning message.
// ********************************************************************
if(nameServerCnt<=0)
{
outputError(CDEV_SEVERITY_WARN, "CDEV Name Server Manager",
"\n%s\n%s\n%s",
" => No name servers have been specified in the CDEV_NAME_SERVER",
" => environment variable.",
" => This server WILL NOT be registered with any name servers...");
}
// *********************************************************************
// * Otherwise, set all of the cdevNameServerHandler pointers to NULL
// * so that they will be connected when the execute timeout method
// * is called.
// *********************************************************************
else {
for(idx=0; idx<nameServerCnt; idx++)
{
nameServerHandlers[idx] = NULL;
}
}
// *********************************************************************
// * Register this class with the cdevReactor so that it will be called
// * every thirty seconds. If any of the cdevNameServerHandlers have
// * become disconnected, it will attempt to reestablish the connection
// * at that time.
// *********************************************************************
setTimeoutRate(15.0);
Reactor.registerTimer(this);
handleTimeout();
}
// *****************************************************************************
// * cdevNameServerManager::~cdevNameServerManager :
// * This is the destructor for the cdevNameServerManager class. When called
// * it will remove and delete any cdevNameServerHandlers that have been
// * registered with the cdevReactor.
// *****************************************************************************
cdevNameServerManager::~cdevNameServerManager ( void )
{
int idx;
for(idx = 0; idx<nameServerCnt; idx++)
{
if(nameServerHandlers[idx]!=0) delete nameServerHandlers[idx];
if(nameServerList[idx]!=NULL) delete nameServerList[idx];
}
if(nameServerList!=NULL) delete nameServerList;
if(nameServerHandlers!=NULL) delete nameServerHandlers;
if(domainName!=NULL) delete domainName;
if(serverName!=NULL) delete serverName;
}
// *****************************************************************************
// * cdevNameServerManager::handleTimeout :
// * This method will be called every thirty seconds to make sure that all
// * connections to the cdev name servers are established. If a
// * cdevNameServerHandler has become disconnected, this method will attempt
// * to reconnect to the specified handler.
// *****************************************************************************
int cdevNameServerManager::handleTimeout ( void )
{
int idx;
for(idx=0; idx<nameServerCnt; idx++)
{
if(nameServerHandlers[idx]==NULL &&
nameServerList[idx]!=NULL)
{
int error = 0;
rsvcClient * client = new rsvcClient;
rsvcUdpClient * udpClient = new rsvcUdpClient;
if(client->connect(nameServerList[idx], RSVC_SERVER_PORT, 2.0)!=RSVC_SUCCESS)
{
outputError ( CDEV_SEVERITY_ERROR, "CDEV Name Server Manager",
"Failed to connect to name server on host %s",
nameServerList[idx]);
error = -1;
}
else if(udpClient->connect(nameServerList[idx], RSVC_SERVER_PORT+1024)!=RSVC_SUCCESS)
{
outputError ( CDEV_SEVERITY_ERROR, "CDEV Name Server Manager",
"Failed to open UDP port to name server on host %s",
nameServerList[idx]);
error = -1;
}
else if(client->insertValue ("cdevServers", serverInfo, rsvcCallback, nameServerList[idx], 1)!=RSVC_SUCCESS)
{
outputError ( CDEV_SEVERITY_ERROR, "CDEV Name Server Manager",
"Error transmitting to name server on host %s",
nameServerList[idx]);
error = -1;
}
if(!error) nameServerHandlers[idx] = new cdevNameServerHandler(*this, *reactor, idx, client, udpClient);
else {
client->disconnect();
udpClient->disconnect();
delete client;
delete udpClient;
}
}
}
return 0;
}
// *****************************************************************************
// * cdevNameServerManager::unregisterHandler:
// * This method is called whenever a cdevNameServerHandler needs to
// * unregister itself from the cdevNameServerManager. The handlers index
// * will be set to 0 and the connection will be reestablished the next time
// * the handleTimeout method is called.
// *****************************************************************************
void cdevNameServerManager::unregisterHandler ( size_t index )
{
if(index < nameServerCnt) nameServerHandlers[index] = NULL;
}
// *****************************************************************************
// * cdevNameServerManager::rsvcCallback :
// * This is the method that is called when the register server method
// * is executed.
// *****************************************************************************
void cdevNameServerManager::rsvcCallback (int status, void* arg, rsvcData* /* data */)
{
char * nameServer = (char *)arg;
if (status != RSVC_SUCCESS)
{
#ifndef _WIN32
fprintf(stderr, "CDEV Name Server Manager Error: %s %s\n",
"Failed to register with name server on host",
nameServer?nameServer:"UNKNOWN");
#endif
}
}
// *****************************************************************************
// * cdevNameServerHandler::cdevNameServerHandler :
// * This is the constructor for the cdevNameServerHandler class. It is
// * called by the cdevNameServerManager when a new cdevNameServerHandler
// * must be created to communicate with a name server. The connected
// * rsvcClient and rsvcUdpClient objects are provided to the class.
// ******************************************************************************
cdevNameServerHandler::cdevNameServerHandler ( cdevNameServerManager & Manager,
cdevReactor & Reactor,
int index,
rsvcClient * tcpClient,
rsvcUdpClient * udpClient )
: nameServerTCP(tcpClient), nameServerUDP(udpClient),
nameServerIndex(index), nameServerManager(Manager)
{
setTimeoutRate(5.0);
setMask(WRITE_MASK);
Reactor.registerHandler(this, WRITE_MASK);
Reactor.registerTimer (this);
}
// *****************************************************************************
// * cdevNameServerHandler::~cdevNameServerHandler :
// * This is the destructor for the class. this method is responsible for
// * disconnecting and closing the tcp and udp client connections and
// * sending notification to the cdevNameServerManager that it is
// * terminating.
// *****************************************************************************
cdevNameServerHandler::~cdevNameServerHandler ( void )
{
nameServerTCP->disconnect();
nameServerUDP->disconnect();
delete nameServerTCP;
delete nameServerUDP;
if(reactor) reactor->extractHandler(this);
nameServerManager.unregisterHandler(nameServerIndex);
}
// *****************************************************************************
// * cdevNameServerHandler::handleInput :
// * This method is called whenever data is ready to be read from the
// * nameServerTCP rsvcClient connection.
// *****************************************************************************
int cdevNameServerHandler::handleInput ( void )
{
return (nameServerTCP->pendIO()==RSVC_IOERROR)?-1:0;
}
// *****************************************************************************
// * cdevNameServerHandler::handleOutput :
// * This method is called whenever data is ready to be written to the
// * nameServerTCP rsvcClient connection.
// *****************************************************************************
int cdevNameServerHandler::handleOutput ( void )
{
setMask(READ_MASK);
return (nameServerTCP->pendIO()==RSVC_IOERROR)?-1:0;
}
// *****************************************************************************
// * cdevNameServerHandler::handleTimeout :
// * This method is called every five seconds to allow the object to emit
// * a UDP packet to the name server to notify it that the server is alive.
// *****************************************************************************
int cdevNameServerHandler::handleTimeout ( void )
{
if(nameServerUDP->update(*nameServerManager.getUpdateInfo())!=RSVC_SUCCESS)
{
outputError(CDEV_SEVERITY_ERROR, "CDEV Name Server Handler",
"Failed to update name server on host %s",
nameServerManager.getHostName(nameServerIndex));
}
return 0;
}
// *****************************************************************************
// * cdevNameServerHandler::getHandle :
// * This method allows the caller to obtain the file handle that is being
// * used by the nameServerTCP rsvcClient connection. This handle is used
// * by the cdevReactor to detect when an event has occured.
// *****************************************************************************
int cdevNameServerHandler::getHandle ( void ) const
{
return nameServerTCP->getFd();
}
#ifndef DONT_SUPPORT_CDEV_CALLS
// *********************************************************************
// * cdevSystemHandler::cdevSystemHandler :
// * This is the constructor for the cdevSystemHandler object.
// *********************************************************************
cdevSystemHandler::cdevSystemHandler (cdevReactor & Reactor,
double pollRate,
cdevSystem & System)
: cdevSimpleTimer(Reactor, pollRate), system(System)
{
execute();
}
#endif
#ifndef DONT_SUPPORT_CDEV_CALLS
// *********************************************************************
// * cdevSystemHandler::~cdevSystemHandler :
// * This is the destructor for the cdevSystemHandler object.
// *********************************************************************
cdevSystemHandler::~cdevSystemHandler (void)
{
}
#endif
#ifndef DONT_SUPPORT_CDEV_CALLS
// *********************************************************************
// * cdevSystemHandler::execute :
// * This is the method that is executed when the specified timer
// * expires.
// *********************************************************************
int cdevSystemHandler::execute (void)
{
system.poll();
return 0;
}
#endif