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

248 lines
8.8 KiB
C++

#include <CLIPService.h>
#include <CLIPRequestObject.h>
#include <cdevMessage.h>
// *****************************************************************************
// * newCLIPService:
// * This function will be called by the cdevSystem object to create an
// * initial instance of the CLIPService.
// *****************************************************************************
extern "C" cdevService * newCLIPService (char * name, cdevSystem * system)
{
return new CLIPService(name, *system);
}
void NULLError (int, char *, cdevRequestObject *)
{
}
// *****************************************************************************
// * CLIPService::CLIPService :
// * This is the constructor for the CLIPService. It initializes the
// * underlying CLIPService by specifying that it is in the domain of
// * VIRTUAL.
// *****************************************************************************
CLIPService::CLIPService ( char * name, cdevSystem & system)
: cdevClientService("CLIP", name, system)
{
system.reportError(CDEV_SEVERITY_INFO, "CLIPService", NULL,
"Constructing a new CLIPService");
}
// *****************************************************************************
// * CLIPService::getRequestObject :
// * This is the interface that cdev objects will use to obtain a
// * CLIPRequestObject object. The CLIPRequestObject
// * represents a combined device and message pair that is associated
// * with the CLIPService.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *****************************************************************************
int CLIPService::getRequestObject ( char * device, char * message, cdevRequestObject * &req)
{
req = new CLIPRequestObject (device, message, system_);
return (req ? CDEV_SUCCESS : CDEV_ERROR);
}
// *****************************************************************************
// * CLIPService::connect :
// * This mechanism will establish a new connection with a server and will
// * will return a pointer to the ServerHandler. If the host and port are
// * specified in the arguments, then the method will attempt to connect
// * using those values without going through the CDEV Name Server.
// *
// * Note: This method will insert the ServerHandler into the connections
// * object and will install it in the Reactor.
// *****************************************************************************
ServerHandler * CLIPService::connect ( char * server, char * host, short port )
{
ServerHandler * handler = NULL;
// *********************************************************************
// * First attempt to locate the handler from the existing connections.
// *********************************************************************
if(server && *server && (handler = connections.find(server))==NULL)
{
int errCode = CDEV_SUCCESS;
char serverHost[255];
short serverPort;
int serverStatus;
int hostMatchesNS;
// *************************************************************
// * Initialize these values to reflect a server that is not
// * defined within the name server.
// *************************************************************
*serverHost = 0;
serverPort = 0;
serverStatus = 2;
hostMatchesNS = 0;
// *************************************************************
// * Raise the error threshold to reduce noise while the service
// * tries to resolve the location of the server.
// *************************************************************
system_.setThreshold(100);
// *************************************************************
// * In this implementation we will always attempt to resolve
// * the location of the server using the name server first, to
// * determine if monitoring can be installed later...
// *************************************************************
cdevData input;
cdevData output;
cdevRequestObject & rnsReq =
cdevRequestObject::attachRef("NameServer", "get");
// *****************************************************
// * Insert domain and name in the input request object
// * to be sent to the CDEV Name Server.
// *****************************************************
input.insert("name", server);
input.insert("domain", domain);
// *****************************************************
// * Query the Name Server to obtain the hostname and
// * port of the specified domain and server.
// *****************************************************
if(rnsReq.send(input, output)==CDEV_SUCCESS)
{
output.get("host", serverHost, 255);
output.get("port", &serverPort);
output.get("status", &serverStatus);
}
// *************************************************************
// * Restore the error threshold to a reasonable level.
// *************************************************************
system_.setThreshold(CDEV_SEVERITY_ERROR);
// *************************************************************
// * If the host and port have been specified, then use them
// * rather than going through the CDEV Name Server.
// *************************************************************
if(host!=NULL && *host && port>0)
{
if(strcmp(serverHost, host) && serverPort==port)
hostMatchesNS = 1;
strcpy(serverHost, host);
serverPort = port;
}
else {
if(*serverHost == 0 || serverPort<=0 || serverStatus!=0)
{
errCode = CDEV_ERROR;
// *********************************************
// * If the hostname could not be found, report
// * the error and set the return value to
// * CDEV_ERROR.
// *********************************************
outputError(CDEV_SEVERITY_ERROR,
"CLIPService::connect",
"Cannot find host for server \"%s\" in domain \"%s\"",
server, domain);
}
else hostMatchesNS = 1;
}
// *************************************************************
// * If the hostname was discovered, then the errCode should be
// * CDEV_SUCCESS. Attempt to connect to the server using the
// * cdevReactor mechanisms.
// *************************************************************
if(errCode==CDEV_SUCCESS)
{
cdevInetAddr addr;
addr.set (serverPort, serverHost);
handler = new ServerHandler(server, this);
if(handler->open(addr)!=0)
{
outputError(CDEV_SEVERITY_ERROR,
"CLIPService::connect",
"Failed to connect to %s on port %i",
serverHost,
serverPort);
delete handler;
handler = NULL;
}
else {
outputError(CDEV_SEVERITY_INFO,
"CLIPService::connect",
"Connected to %s on port %i",
serverHost,
serverPort);
connections.insert(handler);
// *********************************************
// * This calls the registerFd method of the
// * service which will cause the FD Changed
// * callbacks to be triggered.
// *********************************************
registerFd(handler->getHandle(), 1);
// *********************************************
// * Install a Name Server monitor to maintain
// * the status of the connection.
// * Note: If a monitor has already been
// * installed using this informations, then the
// * CDEV Name Server service should not create
// * a second monitor.
// *
// * Note: I am using the FifoQueue associated
// * with the specific server in order to
// * differentiate between the various servers.
// *********************************************
if(hostMatchesNS)
{
cdevData monData;
cdevCallback monCb(nameServerCallback, (void *)getCallbackArg(server));
cdevRequestObject & monReq = cdevRequestObject::attachRef("NameServer", "monitorOn");
monData.insert("name", server);
monData.insert("domain", domain);
monReq.sendCallback(monData, monCb);
}
// *********************************************
// * Here is where a "set ClientInfo" message
// * will be sent to the server to provide
// * descriptive information about the client.
// *********************************************
cdevData tagMap;
int * tags;
char ** ctags;
int ntags;
char * binary = NULL;
size_t binaryLen = 0;
cdevData::readTagTable(tags, ctags, ntags);
tagMap.insert(1, tags, ntags);
tagMap.insert(2, ctags, ntags);
delete tags;
delete ctags;
handler->setTagChangeFlag(0);
cdevMessageBinary packet(handler->getClientID(),
0, 0, 0, 0, CDEV_SERVER_OP, 0, 0,
NULL, "set ClientInfo",
&clientInfo.getClientData(),
NULL, &tagMap);
packet.streamOut(&binary, &binaryLen);
packet.detachData();
ServerInterface::enqueue(handler, binary, binaryLen);
}
}
}
return handler;
}