404 lines
15 KiB
C++
Executable File
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
|