#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 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; idxconnect(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