Files
2022-12-13 12:44:04 +01:00

249 lines
8.1 KiB
C++
Executable File

#include <cdevDevice.h>
#include <cdevRequestObject.h>
#include <cdevCollection.h>
#include <cdevCollectionRequest.h>
#include "cdevGateway.h"
GatewayServer *gatewayServer;
// *****************************************************************************
// * GatewayServer::GatewayServer :
// * This is the constructor for the gateway server. It initializes the
// * underlying cdevServer object and sets the nextCollectionInt variable
// * to zero.
// *
// * The constructor will also extract all of the file descriptors from the
// * cdevSystem object and will create a GatewayHandler for each of them...
// * The fdChangedCallback method will be register with the cdevSystem to
// * ensure that these GatewayHandlers will be regularly updated/removed
// * as they become connected and disconnected.
// *****************************************************************************
GatewayServer::GatewayServer ( char * domain, char * server, unsigned short port, double pulse )
: cdevServer(domain, server, port, pulse), nextCollectionInt(0)
{
int fdBufSize = 256;
int * fdBuf = NULL;
// *********************************************************************
// * Get the list of all file descriptors that are in use by the
// * cdevSystem class.
// *********************************************************************
do {
fdBuf = new int[fdBufSize];
if(cdevSystem::defaultSystem().getFd(fdBuf, fdBufSize)!=CDEV_SUCCESS)
{
delete fdBuf;
fdBufSize *= 2;
fdBuf = NULL;
}
} while (fdBuf==NULL);
// *********************************************************************
// * Create a GatewayHandler to manage each of the file descriptors
// * that was provided by the cdevSystem class, and register them with
// * the Reactor.
// *********************************************************************
for(int i=0; i<fdBufSize; i++)
{
GatewayHandler * hdlr;
hdlr = new GatewayHandler(cdevSystem::defaultSystem(), fdBuf[i]);
Reactor.registerHandler(hdlr, cdevEventHandler::READ_MASK);
}
// *********************************************************************
// * Install the static fdChangedCallback method to be called each time
// * one of the cdevSystem's file descriptors is added or deleted.
// *********************************************************************
cdevSystem::defaultSystem().addFdChangedCallback(fdChangedCallback, this);
// *********************************************************************
// * Delete the temporary file descriptor buffer before returning.
// *********************************************************************
delete fdBuf;
}
// *****************************************************************************
// * GatewayServer::~GatewayServer :
// * This is the virtual destructor for the cdevGateway class. It does
// * nothing except serve as a placeholder to ensure that the delete
// * mechanism calls the most senior object.
// *****************************************************************************
GatewayServer::~GatewayServer ( void )
{
}
// *****************************************************************************
// * GatewayServer::fdChangedCallback :
// * This method will be called by CDEV anytime one of the file descriptors
// * associated with the cdevSystem is added or deleted. This method may
// * then add or delete the file descriptor from the Reactor object.
// *****************************************************************************
void GatewayServer::fdChangedCallback (int fd, int opened, void * arg )
{
GatewayServer * server = (GatewayServer *)arg;
if(opened)
{
GatewayHandler * hdlr;
hdlr = new GatewayHandler(cdevSystem::defaultSystem(), fd);
server->Reactor.registerHandler(hdlr, cdevEventHandler::READ_MASK);
}
else server->Reactor.removeHandler(fd);
}
// *****************************************************************************
// * GatewayServer::handleTimeout :
// * This is the handleTimeout method. It is called by the cdevReactor
// * periodically to make sure that all events are being handled.
// *****************************************************************************
int GatewayServer::handleTimeout ( void )
{
cdevSystem::defaultSystem().pend(0.001);
return 0;
}
// *****************************************************************************
// * GatewayServer::processMessages :
// * This is the processMessages method. It receives the inbound requests
// * from the clients and then calls CDEV to process the requests.
// *****************************************************************************
void GatewayServer::processMessages ( void )
{
int data_handled = 0;
cdevMessage * request;
while(dequeue(request)==0)
{
if(!strcmp(request->getMessage(), "register") ||
!strcmp(request->getMessage(), "unregister"))
{
enqueue(request);
delete (request);
}
else
{
int result (CDEV_SUCCESS);
cdevCallback cb (gatewayCallback, request);
int deviceCount (request->getDeviceCount());
char ** deviceList = request->getDeviceList();
char * message = request->getMessage();
cdevData * context = request->getContext();
cdevData * dataOut = request->getData();
cdevRequestObject * req = NULL;
if(deviceCount<=0 || deviceList==NULL || message==NULL)
{
result = CDEV_ERROR;
}
else
{
if(deviceCount==1)
{
req = cdevRequestObject::attachPtr(deviceList[0], message);
}
else {
char name[32];
sprintf(name, "~Collection%i", nextCollectionInt++);
cdevCollection *col = cdevCollection::attachPtr(name);
col->add(deviceCount, deviceList);
req = col->getRequestObject(message);
}
if(context) req->setContext(*context);
result = req->sendCallback(dataOut, cb);
if(result==CDEV_SUCCESS) data_handled++;
}
if(result != CDEV_SUCCESS)
{
request->setCompletionCode(result);
enqueue(request);
delete request;
}
}
// *********************************************************************
// * Note: The developer MUST do a pend at this point in order to
// * have the file descriptors updated... However, the wait time can be
// * very, very short.
// *********************************************************************
if(data_handled) cdevSystem::defaultSystem().pend(0.000001);
}
}
// *****************************************************************************
// * GatewayServer::gatewayCallback :
// * This is the callback function that is called each time a request has
// * been processed by CDEV. The cdevMessage that was used to make the
// * request is stored in the userarg parameter and this method will pass
// * the result to the cdevGateway for processing.
// *
// * When the isTransactionDone flag is set to TRUE, this method will
// * delete the cdevMessage object.
// *****************************************************************************
void GatewayServer::gatewayCallback ( int status, void *userarg, cdevRequestObject &, cdevData &data)
{
cdevMessage * message = (cdevMessage *)userarg;
message->setCompletionCode(status);
message->setData(&data, 1);
message->setOperationCode(cdevCallback::isTransactionDone()?1:0);
gatewayServer->enqueue(message);
message->setData(NULL);
if(cdevCallback::isTransactionDone()) delete message;
}
int main(int argc, char ** argv)
{
char serverName[255];
int serverPort = 9573;
int mismatch = 0;
strcpy(serverName, "Gateway1");
for(int i=1; i<argc && !mismatch; i++)
{
char * ptr;
switch(*argv[i])
{
case 's':
if((ptr = strchr(argv[i], '='))!=NULL && *(++ptr))
{
strcpy(serverName, ptr);
}
else mismatch = 1;
break;
case 'p':
if((ptr = strchr(argv[i], '='))!=NULL && *(++ptr))
{
if((serverPort = atoi(ptr))==0)
{
mismatch = 1;
}
}
else mismatch = 1;
break;
default:
mismatch = 1;
break;
}
}
if(mismatch)
{
fprintf(stderr, "%s <s=server name> <p=server port>\\n", argv[0]);
}
else
{
gatewayServer = new GatewayServer("GATEWAY", serverName, serverPort, 60);
gatewayServer->runServer();
}
return mismatch?-1:0;
}