248 lines
8.8 KiB
C++
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;
|
|
}
|