cdev-1.7.2n
This commit is contained in:
97
extensions/cdevGenericServer/cdevClient/Makefile
Executable file
97
extensions/cdevGenericServer/cdevClient/Makefile
Executable file
@@ -0,0 +1,97 @@
|
||||
ARCH = OS
|
||||
SHOBJ = YES
|
||||
|
||||
include ../include/makeinclude/Makefile.$(ARCH)
|
||||
|
||||
APPNAME = "CDEV Generic Client Engine"
|
||||
TEMPLINKS = cdevPacket.cc\
|
||||
cdevMessageBinary.cc\
|
||||
cdevMessage.cc\
|
||||
cdevContextMap.cc\
|
||||
SignalManager.cc\
|
||||
cdevAddr.cc\
|
||||
cdevEventHandler.cc\
|
||||
cdevHandleSet.cc\
|
||||
cdevReactor.cc\
|
||||
cdevSocket.cc\
|
||||
cdevSocketAcceptor.cc\
|
||||
cdevSocketConnector.cc\
|
||||
cdevSocketDatagram.cc\
|
||||
cdevSocketStream.cc\
|
||||
cdevStreamNode.cc\
|
||||
cdevStreamQueue.cc\
|
||||
cdevTime.cc\
|
||||
fifo.cc
|
||||
|
||||
CLIENT_OBJS = $(OBJDIR)/cdevClientService.o\
|
||||
$(OBJDIR)/cdevClientRequestObject.o\
|
||||
$(OBJDIR)/ServerInterface.o\
|
||||
$(OBJDIR)/ServerHandler.o
|
||||
|
||||
COMMON_OBJS = $(OBJDIR)/cdevPacket.o\
|
||||
$(OBJDIR)/cdevMessageBinary.o\
|
||||
$(OBJDIR)/cdevMessage.o\
|
||||
$(OBJDIR)/cdevContextMap.o\
|
||||
$(OBJDIR)/SignalManager.o\
|
||||
$(OBJDIR)/fifo.o
|
||||
|
||||
ACE_OBJS = $(OBJDIR)/cdevAddr.o\
|
||||
$(OBJDIR)/cdevEventHandler.o\
|
||||
$(OBJDIR)/cdevHandleSet.o\
|
||||
$(OBJDIR)/cdevReactor.o\
|
||||
$(OBJDIR)/cdevSocket.o\
|
||||
$(OBJDIR)/cdevSocketAcceptor.o\
|
||||
$(OBJDIR)/cdevSocketConnector.o\
|
||||
$(OBJDIR)/cdevSocketDatagram.o\
|
||||
$(OBJDIR)/cdevSocketStream.o\
|
||||
$(OBJDIR)/cdevStreamNode.o\
|
||||
$(OBJDIR)/cdevStreamQueue.o\
|
||||
$(OBJDIR)/cdevTime.o
|
||||
|
||||
OBJS = $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS)
|
||||
|
||||
# ******************************************************************************
|
||||
# * The BINARIES definition names all of the binary files that should be deleted
|
||||
# * whenever "make clean" is executed.
|
||||
# ******************************************************************************
|
||||
BINARIES = $(CDEVLIB)/libcdevClient.$(SHARED_EXT) \
|
||||
$(CDEVLIB)/libcdevClient.a
|
||||
|
||||
ifeq ($(SHOBJ),YES)
|
||||
TARGETS = $(TEMPLINKS) $(CDEVLIB)/libcdevClient.$(SHARED_EXT)
|
||||
else
|
||||
TARGETS = $(TEMPLINKS) $(CDEVLIB)/libcdevClient.a
|
||||
endif
|
||||
|
||||
targets : $(TARGETS)
|
||||
|
||||
$(TEMPLINKS) :
|
||||
@cp $^ $@
|
||||
|
||||
$(CDEVLIB)/libcdevClient.a : $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS)
|
||||
$(LINK.a) $@ $^
|
||||
@$(RANLIB) $@ > /dev/null
|
||||
@cp $@ $(CDEVLIB)
|
||||
|
||||
$(CDEVLIB)/libcdevClient.$(SHARED_EXT) : $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS)
|
||||
$(LINK.so) -o $@ $^ $(NETLIBS)
|
||||
@cp $@ $(CDEVLIB)
|
||||
|
||||
cdevMessage.cc : ../cdevPacket/cdevMessage.cc
|
||||
cdevMessageBinary.cc : ../cdevPacket/cdevMessageBinary.cc
|
||||
cdevPacket.cc : ../cdevPacket/cdevPacket.cc
|
||||
cdevContextMap.cc : ../cdevContextMap/cdevContextMap.cc
|
||||
SignalManager.cc : ../common/SignalManager.cc
|
||||
cdevAddr.cc : ../cdevReactor/cdevAddr.cc
|
||||
cdevEventHandler.cc : ../cdevReactor/cdevEventHandler.cc
|
||||
cdevHandleSet.cc : ../cdevReactor/cdevHandleSet.cc
|
||||
cdevReactor.cc : ../cdevReactor/cdevReactor.cc
|
||||
cdevSocket.cc : ../cdevReactor/cdevSocket.cc
|
||||
cdevSocketAcceptor.cc : ../cdevReactor/cdevSocketAcceptor.cc
|
||||
cdevSocketConnector.cc : ../cdevReactor/cdevSocketConnector.cc
|
||||
cdevSocketDatagram.cc : ../cdevReactor/cdevSocketDatagram.cc
|
||||
cdevSocketStream.cc : ../cdevReactor/cdevSocketStream.cc
|
||||
cdevStreamNode.cc : ../cdevReactor/cdevStreamNode.cc
|
||||
cdevStreamQueue.cc : ../cdevReactor/cdevStreamQueue.cc
|
||||
cdevTime.cc : ../cdevReactor/cdevTime.cc
|
||||
fifo.cc : ../common/fifo.cc
|
||||
139
extensions/cdevGenericServer/cdevClient/NMakefile.mak
Normal file
139
extensions/cdevGenericServer/cdevClient/NMakefile.mak
Normal file
@@ -0,0 +1,139 @@
|
||||
.SUFFIXES: .cc .obj
|
||||
|
||||
APPNAME = CDEV Generic Client Engine
|
||||
ARCH = WINNT-4.0
|
||||
|
||||
TEMPLINKS = cdevPacket.cc\
|
||||
cdevMessageBinary.cc\
|
||||
cdevMessage.cc\
|
||||
cdevContextMap.cc\
|
||||
SignalManager.cc\
|
||||
cdevAddr.cc\
|
||||
cdevEventHandler.cc\
|
||||
cdevHandleSet.cc\
|
||||
cdevReactor.cc\
|
||||
cdevSocket.cc\
|
||||
cdevSocketAcceptor.cc\
|
||||
cdevSocketConnector.cc\
|
||||
cdevSocketDatagram.cc\
|
||||
cdevSocketStream.cc\
|
||||
cdevStreamNode.cc\
|
||||
cdevStreamQueue.cc\
|
||||
cdevTime.cc\
|
||||
fifo.cc
|
||||
|
||||
BINARIES = $(CDEVLIB)\cdevClient.dll \
|
||||
$(CDEVLIB)\cdevClient.lib \
|
||||
$(TEMPLINKS)
|
||||
|
||||
include ..\include\makeinclude\Makefile.WINNT-4.0
|
||||
|
||||
CLIENT_OBJS = $(OBJDIR)\cdevClientService.obj\
|
||||
$(OBJDIR)\cdevClientRequestObject.obj\
|
||||
$(OBJDIR)\ServerInterface.obj\
|
||||
$(OBJDIR)\ServerHandler.obj
|
||||
|
||||
COMMON_OBJS = $(OBJDIR)\cdevPacket.obj\
|
||||
$(OBJDIR)\cdevMessageBinary.obj\
|
||||
$(OBJDIR)\cdevMessage.obj\
|
||||
$(OBJDIR)\cdevContextMap.obj\
|
||||
$(OBJDIR)\SignalManager.obj\
|
||||
$(OBJDIR)\fifo.obj
|
||||
|
||||
ACE_OBJS = $(OBJDIR)\cdevAddr.obj\
|
||||
$(OBJDIR)\cdevEventHandler.obj\
|
||||
$(OBJDIR)\cdevHandleSet.obj\
|
||||
$(OBJDIR)\cdevReactor.obj\
|
||||
$(OBJDIR)\cdevSocket.obj\
|
||||
$(OBJDIR)\cdevSocketAcceptor.obj\
|
||||
$(OBJDIR)\cdevSocketConnector.obj\
|
||||
$(OBJDIR)\cdevSocketDatagram.obj\
|
||||
$(OBJDIR)\cdevSocketStream.obj\
|
||||
$(OBJDIR)\cdevStreamNode.obj\
|
||||
$(OBJDIR)\cdevStreamQueue.obj\
|
||||
$(OBJDIR)\cdevTime.obj
|
||||
|
||||
OBJS = $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS)
|
||||
|
||||
CXXEXTRA = /D "_CDEV_REACTOR_EXPORTS_=1" /D "_GENERIC_SERVER_EXPORTS_=1"
|
||||
|
||||
!IF "$(SHOBJ)" == "YES"
|
||||
TARGETS = $(TEMPLINKS) $(CDEVLIB)\cdevClient.dll
|
||||
!ELSE
|
||||
TARGETS = $(TEMPLINKS) $(CDEVLIB)\cdevClient.lib
|
||||
!ENDIF
|
||||
|
||||
targets : $(TARGETS)
|
||||
@erase $(TEMPLINKS)
|
||||
|
||||
$(CDEVLIB)\cdevClient.lib : $(OBJS)
|
||||
@echo ^ ^ ^ =^> Linking $(@F)
|
||||
-@if exist $@ erase $@
|
||||
-@if not exist $(@D) mkdir $(@D)
|
||||
@$(LIB32) $(CDEVLIB)\cdev.lib\
|
||||
$(LINK_LIB_FLAGS) /out:$@ $(OBJS)
|
||||
@echo ^ ^ ^ ^ ^ ^ Done...
|
||||
|
||||
$(CDEVLIB)\cdevClient.dll : $(OBJS)
|
||||
@echo ^ ^ ^ =^> Linking $(@F)
|
||||
-@if exist $@ erase $@
|
||||
-@if not exist $(@D) mkdir $(@D)
|
||||
@$(LIB32) $(CDEVLIB)\cdev.lib\
|
||||
$(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $(OBJS)
|
||||
@echo ^ ^ ^ ^ ^ ^ Done...
|
||||
|
||||
cdevMessage.cc : ..\cdevPacket\cdevMessage.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevMessageBinary.cc : ..\cdevPacket\cdevMessageBinary.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevPacket.cc : ..\cdevPacket\cdevPacket.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevContextMap.cc : ..\cdevContextMap\cdevContextMap.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
SignalManager.cc : ..\common\SignalManager.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevAddr.cc : ..\cdevReactor\cdevAddr.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevEventHandler.cc : ..\cdevReactor\cdevEventHandler.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevHandleSet.cc : ..\cdevReactor\cdevHandleSet.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevReactor.cc : ..\cdevReactor\cdevReactor.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevSocket.cc : ..\cdevReactor\cdevSocket.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevSocketAcceptor.cc : ..\cdevReactor\cdevSocketAcceptor.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevSocketConnector.cc : ..\cdevReactor\cdevSocketConnector.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevSocketDatagram.cc : ..\cdevReactor\cdevSocketDatagram.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevSocketStream.cc : ..\cdevReactor\cdevSocketStream.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevStreamNode.cc : ..\cdevReactor\cdevStreamNode.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevStreamQueue.cc : ..\cdevReactor\cdevStreamQueue.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevTime.cc : ..\cdevReactor\cdevTime.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
fifo.cc : ..\common\fifo.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
|
||||
526
extensions/cdevGenericServer/cdevClient/ServerHandler.cc
Executable file
526
extensions/cdevGenericServer/cdevClient/ServerHandler.cc
Executable file
@@ -0,0 +1,526 @@
|
||||
#include <cdevClock.h>
|
||||
#include <ServerInterface.h>
|
||||
#include <xdrClass.h>
|
||||
#include <SignalManager.h>
|
||||
#include <clipMagicNumber.h>
|
||||
|
||||
#define _CDEV_CONNECTION_RETRIES 5
|
||||
|
||||
SignalManager ServerHandler::signalManager;
|
||||
int ServerHandler::signalManagerInit = 0;
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandlerCallbackNode:
|
||||
// * This is a node of a linked list that isolates the ServerHandlerCallback
|
||||
// * object from inadverntently being corrupted by being placed in more
|
||||
// * than one ServerHandler object.
|
||||
// *
|
||||
// * The ALLOCATION_COUNT of 128 forces the allocation of blocks that are
|
||||
// * close to 1 kilobyte in size.
|
||||
// *****************************************************************************
|
||||
class ServerHandlerCallbackNode
|
||||
{
|
||||
friend class ServerHandler;
|
||||
private:
|
||||
static ServerHandlerCallbackNode * freeList_;
|
||||
ServerHandlerCallbackNode * next;
|
||||
ServerHandlerCallback * callback;
|
||||
enum { ALLOCATION_COUNT=128 };
|
||||
|
||||
ServerHandlerCallbackNode ( void );
|
||||
public:
|
||||
ServerHandlerCallbackNode ( ServerHandlerCallback * Callback );
|
||||
~ServerHandlerCallbackNode( void );
|
||||
void * operator new ( size_t );
|
||||
void operator delete ( void * ptr );
|
||||
};
|
||||
|
||||
ServerHandlerCallbackNode * ServerHandlerCallbackNode::freeList_;
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandler::ServerHandler
|
||||
// * Default constructor for the ServerHandler class
|
||||
// *****************************************************************************
|
||||
ServerHandler::ServerHandler ( char * Server, ServerInterface * Interface )
|
||||
: SocketReader(CLIP_MAGIC_NUMBER), SocketWriter(CLIP_MAGIC_NUMBER),
|
||||
queue(*(Interface->getQueue(Server))), serverface(Interface), callbacks(NULL),
|
||||
enqueuedPackets(0), enqueuedBytes(0), clientID(-1), contextID(-1),
|
||||
tagChanged(1), serverQuitFlag(0)
|
||||
{
|
||||
strncpy(server, Server, 256);
|
||||
server[255] = 0;
|
||||
hostName[0] = 0;
|
||||
clientID = getNextClientID();
|
||||
|
||||
if(!signalManagerInit) signalManager.installDefaults();
|
||||
|
||||
// *********************************************************************
|
||||
// * If any data exists in the queue for this server, walk through each
|
||||
// * entry and determine if it is valid - if so, reenqueue it,
|
||||
// * otherwise, delete it.
|
||||
// *********************************************************************
|
||||
if(!queue.empty())
|
||||
{
|
||||
FifoQueue tempQueue;
|
||||
char * binary;
|
||||
size_t len;
|
||||
while(queue.dequeue(&binary, &len)==0)
|
||||
{
|
||||
if(serverface->isPacketValid(binary, len))
|
||||
{
|
||||
tempQueue.enqueue(binary, len);
|
||||
}
|
||||
else delete binary;
|
||||
}
|
||||
while(tempQueue.dequeue(&binary, &len)==0)
|
||||
{
|
||||
enqueue(binary, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandler::outputError :
|
||||
// * This mechanism is used to report errors to the system.
|
||||
// *****************************************************************************
|
||||
int ServerHandler::outputError(int severity, char *name, char *formatString, ...)
|
||||
{
|
||||
va_list argp;
|
||||
static char msg[1024];
|
||||
|
||||
va_start (argp, formatString);
|
||||
vsprintf (msg, formatString, argp);
|
||||
va_end (argp);
|
||||
|
||||
return serverface->outputError(severity, name, msg);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * open:
|
||||
// * Established a connection with the host specified by remote_sap
|
||||
// *****************************************************************************
|
||||
int ServerHandler::open ( const cdevAddr & addr )
|
||||
{
|
||||
int result = 0;
|
||||
int count = 0;
|
||||
|
||||
result = stream.connect (addr);
|
||||
|
||||
if (result != -1)
|
||||
{
|
||||
if((result = serverface->Reactor.registerHandler(this, READ_MASK|WRITE_MASK|EXCEPT_MASK))==-1)
|
||||
{
|
||||
handleClose();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ~ServerHandler:
|
||||
// * Default destructor for the ServerHandler object.
|
||||
// *****************************************************************************
|
||||
ServerHandler::~ServerHandler (void)
|
||||
{
|
||||
ServerHandlerCallbackNode * cb = callbacks;
|
||||
|
||||
// *********************************************************************
|
||||
// * Write a -1 as the packetLength to the connection in order to
|
||||
// * terminate.
|
||||
// *********************************************************************
|
||||
if(stream.getHandle()>0 && serverQuitFlag==0)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
void (*action)(int) = signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
writeGoodbye();
|
||||
|
||||
#ifndef _WIN32
|
||||
signal(SIGPIPE, action);
|
||||
#endif
|
||||
}
|
||||
|
||||
// *********************************************************************
|
||||
// * Contact all of the objects that rely on the existance of this
|
||||
// * class.
|
||||
// *********************************************************************
|
||||
while(cb!=NULL)
|
||||
{
|
||||
ServerHandlerCallbackNode * oldCB = cb;
|
||||
cb = cb->next;
|
||||
oldCB->callback->executeServerHandlerCallback(this);
|
||||
delete oldCB;
|
||||
}
|
||||
|
||||
// *********************************************************************
|
||||
// * Perform standard shutdown steps.
|
||||
// *********************************************************************
|
||||
if(reactor) reactor->extractHandler(this);
|
||||
handleClose();
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandler::getHostName:
|
||||
// * This function returns the name of the remote host.
|
||||
// *****************************************************************************
|
||||
char * ServerHandler::getHostName( void )
|
||||
{
|
||||
if(*hostName==0)
|
||||
{
|
||||
cdevInetAddr addr;
|
||||
if(stream.getRemoteAddress (addr)==0)
|
||||
{
|
||||
const char * ptr=addr.getHostName();
|
||||
if(ptr) strncpy (hostName, ptr, MAXHOSTNAMELEN+1);
|
||||
}
|
||||
}
|
||||
return hostName;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandler::getName :
|
||||
// * Allows the caller to obtain the name of the class.
|
||||
// *****************************************************************************
|
||||
char * ServerHandler::getName (void) const
|
||||
{
|
||||
return "ServerHandler";
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandler::getHandle
|
||||
// * Allows the caller to obtain the file identifier of the socket.
|
||||
// *****************************************************************************
|
||||
int ServerHandler::getHandle (void) const
|
||||
{
|
||||
return stream.getHandle();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandler::getServer:
|
||||
// * Allows the caller to obtain the name of the connected server.
|
||||
// *****************************************************************************
|
||||
char * ServerHandler::getServer (void) const
|
||||
{
|
||||
return (char *)server;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * handleClose:
|
||||
// * Closes the stream.
|
||||
// *****************************************************************************
|
||||
int ServerHandler::handleClose (void)
|
||||
{
|
||||
serverface->disconnect(server);
|
||||
stream.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * handleInput :
|
||||
// * This function is called when data is ready to be read from a connected
|
||||
// * socket. This function will read the data from the socket, and will then
|
||||
// * submit the buffer to the ServerInterface class for processing.
|
||||
// *****************************************************************************
|
||||
int ServerHandler::handleInput (void)
|
||||
{
|
||||
int retval = 0;
|
||||
char * buf = NULL;
|
||||
size_t len = 0;
|
||||
int result = 1;
|
||||
|
||||
// *****************************************************************************
|
||||
// * Record oriented semantics dictate that the length of the transmission
|
||||
// * always preceeds the actual data. Therefore, read the length of the
|
||||
// * transmission into the len variable.
|
||||
// *****************************************************************************
|
||||
while(result>0)
|
||||
{
|
||||
result = read(&buf, (int *)&len);
|
||||
|
||||
switch(result)
|
||||
{
|
||||
// *************************************************************
|
||||
// * A return value of SHUTDOWN_CODE indicates that a negative
|
||||
// * one was provided as the packet length - indicating a
|
||||
// * shutdown...
|
||||
// *************************************************************
|
||||
case SHUTDOWN_CODE:
|
||||
outputError(CDEV_SEVERITY_INFO, (char *)getName(),
|
||||
"Connection to %s terminated by client", getHostName());
|
||||
retval = -1;
|
||||
break;
|
||||
|
||||
// *************************************************************
|
||||
// * A return value of -1 indicates an error occured while
|
||||
// * reading from the socket. A value of -1 is returned to
|
||||
// * shutdown the socket and remove it from the reactor.
|
||||
// *************************************************************
|
||||
case -1:
|
||||
outputError(CDEV_SEVERITY_WARN, (char *)getName(),
|
||||
"Error reading from connection to client %s", getHostName());
|
||||
retval = -1;
|
||||
break;
|
||||
|
||||
// *************************************************************
|
||||
// * A return value of 0 means that no data was ready to be
|
||||
// * retrieved from the socket.
|
||||
// *************************************************************
|
||||
case 0:
|
||||
break;
|
||||
|
||||
// *************************************************************
|
||||
// * Any other value returned from the socket represents the
|
||||
// * number of bytes actually read into the local Session object.
|
||||
// *************************************************************
|
||||
default:
|
||||
serverface->enqueue(ServerInterface::COMPLETED, this, buf, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * Return the value specified by retval.
|
||||
// *****************************************************************************
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * handleOutput :
|
||||
// * This function is called when data is ready to be transmitted to a
|
||||
// * connected socket. This function will read the data from the queue,
|
||||
// * translate it to XDR, and then transmit it to the client.
|
||||
// *****************************************************************************
|
||||
int ServerHandler::handleOutput ( void )
|
||||
{
|
||||
int retval = 0;
|
||||
char * buf = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
// *****************************************************************************
|
||||
// * Attempt to transmit or continue transmitting the data. Note, the peek
|
||||
// * method is used to attempt to writeEnqueue a data item without actually
|
||||
// * removing it from the outbound queue. If the item can be writeEnqueued,
|
||||
// * then the dequeue method is called to remove it from the queue...
|
||||
// * This method is repeated until the output buffer is fully populated.
|
||||
// *****************************************************************************
|
||||
if(!writing() && dequeue(&buf, &len)==0)
|
||||
{
|
||||
int full = 0;
|
||||
while(!full)
|
||||
{
|
||||
if(!(full = writeEnqueue(buf, len)))
|
||||
{
|
||||
delete buf;
|
||||
full = dequeue(&buf, &len);
|
||||
}
|
||||
else undequeue(buf, len);
|
||||
}
|
||||
if(writeContinue()<0) retval = -1;
|
||||
}
|
||||
else if(writing())
|
||||
{
|
||||
if(writeContinue()<0) retval = -1;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * Display an error message if the transmission failed.
|
||||
// *****************************************************************************
|
||||
if(retval!=0)
|
||||
{
|
||||
outputError(CDEV_SEVERITY_WARN, (char *)getName(),
|
||||
"Error transmitting to %s", getHostName());
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * If there are no further messages in the outbound queue and the
|
||||
// * ACE_Event_Handler has finished servicing the current message, turn off the
|
||||
// * WRITE_MASK for this ACE_Event_Handler.
|
||||
// *****************************************************************************
|
||||
if(empty() && !writing())
|
||||
{
|
||||
setMask(READ_MASK|EXCEPT_MASK);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * Return the value specified by retval.
|
||||
// *****************************************************************************
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * handleExcept :
|
||||
// * This function is called when out of band data has been received from
|
||||
// * the server. It will terminate the connection with the server.
|
||||
// *****************************************************************************
|
||||
int ServerHandler::handleExcept ( void )
|
||||
{
|
||||
stream.close();
|
||||
serverQuitFlag=1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * registerServerCallback :
|
||||
// * This method is called to add a ServerHandlerCallback object to the list
|
||||
// * of objects that the ServerHandler will notify when it is destroyed...
|
||||
// * This notification process protects objects that use this class for
|
||||
// * communications from using a pointer to a ServerHandler that has been
|
||||
// * deleted.
|
||||
// *****************************************************************************
|
||||
void ServerHandler::registerServerCallback(ServerHandlerCallback * cb)
|
||||
{
|
||||
ServerHandlerCallbackNode *cbPrev=NULL, *cbNext=callbacks;
|
||||
|
||||
while(cbNext!=NULL && cbNext->callback!=cb)
|
||||
{
|
||||
cbPrev = cbNext;
|
||||
cbNext = cbNext->next;
|
||||
}
|
||||
if(cbNext==NULL)
|
||||
{
|
||||
if(cbPrev==NULL) callbacks = new ServerHandlerCallbackNode(cb);
|
||||
else cbPrev->next = new ServerHandlerCallbackNode(cb);
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * unregisterServerCallback :
|
||||
// * This method is used to remove a ServerHandlerCallback object from the
|
||||
// * list of objects that will be notified when the ServerHandler object
|
||||
// * is destroyed.
|
||||
// *****************************************************************************
|
||||
void ServerHandler::unregisterServerCallback (ServerHandlerCallback * cb)
|
||||
{
|
||||
ServerHandlerCallbackNode *cbPrev=NULL, *cbNext=callbacks;
|
||||
|
||||
while(cbNext!=NULL && cbNext->callback!=cb)
|
||||
{
|
||||
cbPrev = cbNext;
|
||||
cbNext = cbNext->next;
|
||||
}
|
||||
if(cbNext->callback==cb)
|
||||
{
|
||||
if(cbPrev==NULL) callbacks = cbNext->next;
|
||||
else cbPrev->next = cbNext->next;
|
||||
delete cbNext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * enqueue :
|
||||
// * This method places an object into the embedded FifoQueue and will force
|
||||
// * a flush of the socket if it reaches the high water mark.
|
||||
// *****************************************************************************
|
||||
void ServerHandler::enqueue (char * buf, size_t len)
|
||||
{
|
||||
enqueuedPackets++;
|
||||
enqueuedBytes+=len;
|
||||
queue.enqueue(buf, len);
|
||||
if(enqueuedPackets>100 || enqueuedBytes>16000)
|
||||
{
|
||||
serverface->flush(getHandle());
|
||||
enqueuedPackets=0;
|
||||
enqueuedBytes=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandler::getNextClientID :
|
||||
// * This method allows the caller to retrieve a unique clientID to be
|
||||
// * assigned to a client. The nextClientID value is automatically
|
||||
// * incremented.
|
||||
// *****************************************************************************
|
||||
short ServerHandler::getNextClientID ( void )
|
||||
{
|
||||
static short nextClientID = 0;
|
||||
|
||||
nextClientID++;
|
||||
if(nextClientID<=0) nextClientID = 1;
|
||||
return nextClientID;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandlerCallbackNode::ServerHandlerCallbackNode :
|
||||
// * Default constructor for the ServerHandlerCallbackNode class.
|
||||
// *****************************************************************************
|
||||
ServerHandlerCallbackNode::ServerHandlerCallbackNode ( void )
|
||||
: callback(NULL), next(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandlerCallbackNode::ServerHandlerCallbackNode :
|
||||
// * Parameterized constructor for the ServerHandlerCallbackNode class.
|
||||
// *****************************************************************************
|
||||
ServerHandlerCallbackNode::ServerHandlerCallbackNode( ServerHandlerCallback * Callback )
|
||||
: callback(Callback), next(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandlerCallbackNode::~ServerHandlerCallbackNode :
|
||||
// * Destructor for the ServerHandlerCallbackNode class.
|
||||
// *****************************************************************************
|
||||
ServerHandlerCallbackNode::~ServerHandlerCallbackNode( void )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandlerCallbackNode::operator new :
|
||||
// * Gets a ServerHandlerCallbackNode instance from the freelist.
|
||||
// *****************************************************************************
|
||||
void * ServerHandlerCallbackNode::operator new ( size_t )
|
||||
{
|
||||
ServerHandlerCallbackNode * result = NULL;
|
||||
|
||||
if(freeList_==NULL)
|
||||
{
|
||||
freeList_ = ::new ServerHandlerCallbackNode[ALLOCATION_COUNT];
|
||||
for(int i=0; i<ALLOCATION_COUNT; i++)
|
||||
{
|
||||
freeList_[i].next =
|
||||
(i<(ALLOCATION_COUNT-1))?&freeList_[i+1]:(ServerHandlerCallbackNode *)NULL;
|
||||
}
|
||||
}
|
||||
if(freeList_!=NULL)
|
||||
{
|
||||
result = freeList_;
|
||||
freeList_ = result->next;
|
||||
result->next = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandlerCallbackNode::operator delete :
|
||||
// * Returns a ServerHandlerCallbackNode instance to the freelist.
|
||||
// *****************************************************************************
|
||||
void ServerHandlerCallbackNode::operator delete ( void * ptr )
|
||||
{
|
||||
ServerHandlerCallbackNode * node = (ServerHandlerCallbackNode *)ptr;
|
||||
if(node != NULL)
|
||||
{
|
||||
node->next = freeList_;
|
||||
freeList_ = node;
|
||||
}
|
||||
}
|
||||
|
||||
97
extensions/cdevGenericServer/cdevClient/ServerHandler.h
Executable file
97
extensions/cdevGenericServer/cdevClient/ServerHandler.h
Executable file
@@ -0,0 +1,97 @@
|
||||
#if !defined (_SERVER_HANDLER_H_)
|
||||
#define _SERVER_HANDLER_H_
|
||||
|
||||
// *****************************************************************************
|
||||
// * SIG_PIPE_HANDLED:
|
||||
// * This definition tells the SocketWriter class not to independently
|
||||
// * handle the SIGPIPE signal.
|
||||
// *****************************************************************************
|
||||
#define SIG_PIPE_HANDLED 1
|
||||
|
||||
#include "cdevEventHandler.h"
|
||||
#include "cdevAddr.h"
|
||||
#include "cdevSocketConnector.h"
|
||||
#include "cdevReactor.h"
|
||||
|
||||
#include "SocketUtil.h"
|
||||
#include "fifo.h"
|
||||
|
||||
class ServerInterface;
|
||||
class ServerHandlerCallbackNode;
|
||||
class SignalManager;
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandlerCallback :
|
||||
// * This class is used by other classes to register to be informed when the
|
||||
// * ServerHandler is destroyed.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API ServerHandlerCallback
|
||||
{
|
||||
public:
|
||||
ServerHandlerCallback ( void ) {}
|
||||
virtual ~ServerHandlerCallback ( void ) {}
|
||||
virtual void executeServerHandlerCallback (class ServerHandler * handler) = 0;
|
||||
};
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerHandler:
|
||||
// * This class provides the mechanisms that will be used to service the
|
||||
// * requests of a client.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API ServerHandler : public cdevEventHandler,
|
||||
public SocketReader,
|
||||
public SocketWriter
|
||||
{
|
||||
protected:
|
||||
static SignalManager signalManager;
|
||||
static int signalManagerInit;
|
||||
|
||||
char hostName [MAXHOSTNAMELEN + 1];
|
||||
char server [256];
|
||||
FifoQueue & queue;
|
||||
cdevSocketConnector stream;
|
||||
ServerInterface * serverface;
|
||||
ServerHandlerCallbackNode * callbacks;
|
||||
size_t enqueuedPackets;
|
||||
size_t enqueuedBytes;
|
||||
short clientID;
|
||||
int contextID;
|
||||
int tagChanged;
|
||||
int serverQuitFlag;
|
||||
|
||||
public:
|
||||
ServerHandler (char * Server, ServerInterface * Interface);
|
||||
~ServerHandler (void);
|
||||
virtual int outputError (int severity, char *name, char *formatString, ...);
|
||||
|
||||
virtual int open (const cdevAddr &addr);
|
||||
|
||||
char * getHostName (void);
|
||||
char * getName (void) const;
|
||||
virtual int getHandle (void) const;
|
||||
virtual char * getServer (void) const;
|
||||
|
||||
virtual int handleClose (void);
|
||||
virtual int handleInput (void);
|
||||
virtual int handleOutput (void);
|
||||
virtual int handleExcept (void);
|
||||
|
||||
virtual void registerServerCallback (ServerHandlerCallback *);
|
||||
virtual void unregisterServerCallback (ServerHandlerCallback *);
|
||||
|
||||
void enqueue (char * buf, size_t len);
|
||||
void undequeue (char * buf, size_t len) { queue.undequeue(buf, len); }
|
||||
int dequeue (char **buf, size_t *len) { return queue.dequeue(buf, len); }
|
||||
int empty (void) { return queue.empty(); }
|
||||
|
||||
static short getNextClientID ( void );
|
||||
short getClientID ( void ) { return clientID; }
|
||||
void setClientID ( short ClientID ) { clientID=ClientID; }
|
||||
int getContextID ( void ) { return contextID; }
|
||||
void setContextID ( int ContextID ) { contextID = ContextID; }
|
||||
int getTagChangeFlag ( void ) { return tagChanged; }
|
||||
void setTagChangeFlag ( int flag ) { tagChanged = flag; }
|
||||
};
|
||||
|
||||
#endif /* _SERVER_HANDLER_H_ */
|
||||
506
extensions/cdevGenericServer/cdevClient/ServerInterface.cc
Executable file
506
extensions/cdevGenericServer/cdevClient/ServerInterface.cc
Executable file
@@ -0,0 +1,506 @@
|
||||
#include "cdevClock.h"
|
||||
#include "ServerInterface.h"
|
||||
|
||||
cdevReactor ServerInterface::Reactor;
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerConnectionList::ServerConnectionList :
|
||||
// * Constructor for the list of active connections that is being managed
|
||||
// * by the ServerHandler.
|
||||
// *****************************************************************************
|
||||
ServerConnectionList::ServerConnectionList ( void )
|
||||
{
|
||||
maxItems = ALLOCATION_COUNT;
|
||||
items = (ServerHandler **)malloc(maxItems*sizeof(ServerHandler *));
|
||||
memset(items, 0, maxItems*sizeof(ServerHandler *));
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerConnectionList::~ServerConnectionList :
|
||||
// * Destructor for the list of active connections that is being managed
|
||||
// * by the ServerHandler.
|
||||
// *****************************************************************************
|
||||
ServerConnectionList::~ServerConnectionList ( void )
|
||||
{
|
||||
free (items);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerConnectionList::find :
|
||||
// * Locates a ServerHandler object that is associated with the specified
|
||||
// * server name.
|
||||
// *****************************************************************************
|
||||
ServerHandler * ServerConnectionList::find ( char * server )
|
||||
{
|
||||
int i;
|
||||
for(i=0;
|
||||
i<maxItems &&
|
||||
items[i]!=NULL &&
|
||||
strcmp(server, items[i]->getServer());
|
||||
i++);
|
||||
return (i<maxItems && items[i]!=NULL)?items[i]:(ServerHandler *)NULL;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerConnectionList::insert :
|
||||
// * Inserts the new ServerHandler object specified by handler into the
|
||||
// * server connection list if it does not already exist there...
|
||||
// *****************************************************************************
|
||||
int ServerConnectionList::insert ( ServerHandler * handler )
|
||||
{
|
||||
int result = -1;
|
||||
if(handler!=NULL)
|
||||
{
|
||||
int i;
|
||||
char * server = handler->getServer();
|
||||
for(i=0;
|
||||
i<maxItems &&
|
||||
items[i]!=NULL &&
|
||||
items[i]!=handler &&
|
||||
strcmp(server, items[i]->getServer());
|
||||
i++);
|
||||
|
||||
if(i>=maxItems)
|
||||
{
|
||||
items = (ServerHandler **) realloc(items, 2*maxItems*sizeof(ServerHandler *));
|
||||
memset(&items[maxItems], 0, maxItems*sizeof(ServerHandler *));
|
||||
maxItems*=2;
|
||||
}
|
||||
|
||||
if(items[i]==NULL)
|
||||
{
|
||||
items[i] = handler;
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerConnectionList::remove :
|
||||
// * Removes the ServerHandler object specified by handler if it exists in
|
||||
// * list.
|
||||
// *****************************************************************************
|
||||
int ServerConnectionList::remove ( ServerHandler * handler )
|
||||
{
|
||||
int result = -1;
|
||||
if(handler!=NULL)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<maxItems && items[i]!=NULL && items[i]!=handler; i++);
|
||||
if(i<maxItems && items[i]==handler)
|
||||
{
|
||||
items[i] = NULL;
|
||||
if(i<maxItems-1) memmove(&items[i], &items[i+1], (maxItems-(i+1))*sizeof(ServerHandler *));
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerConnectionList::remove :
|
||||
// * locates and removes the ServerHandler specified by server and returns
|
||||
// * a pointer to the handler that was removed.
|
||||
// *****************************************************************************
|
||||
ServerHandler * ServerConnectionList::remove ( char * server )
|
||||
{
|
||||
ServerHandler * handler = find(server);
|
||||
if(handler!=NULL) remove(handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerInterface::ServerInterface :
|
||||
// * This is the constructor for the ServerInterface class. This class
|
||||
// * will establish and maintain a collection of connections to cdevServers.
|
||||
// *****************************************************************************
|
||||
ServerInterface::ServerInterface ( void )
|
||||
: connections(),
|
||||
connectionQueues(),
|
||||
defaultServer(NULL),
|
||||
defaultServerHandler(NULL),
|
||||
maxFd(32)
|
||||
{
|
||||
fdList = (int *)malloc( sizeof(int)*maxFd);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerInterface::~ServerInterface :
|
||||
// * This is the destructor for the class. It is responsible for releasing
|
||||
// * any memory that might have been previously allocated to the class.
|
||||
// *****************************************************************************
|
||||
ServerInterface::~ServerInterface ( void )
|
||||
{
|
||||
if(defaultServer) delete defaultServer;
|
||||
free (fdList);
|
||||
|
||||
// *********************************************************************
|
||||
// * Remove each of the ServerHandlers from the list and delete them.
|
||||
// * This will remove them from the global reactor and will terminate
|
||||
// * the connections.
|
||||
// *
|
||||
// * Note: When deleting a ServerHandler - it submits a FAILED_TO_SEND
|
||||
// * message for each of the packets that it could not send. Because
|
||||
// * destroying this class implies that the cdevService is being
|
||||
// * destroyed also, this class will simply delete each of the packets
|
||||
// * and will not forward any other information.
|
||||
// *********************************************************************
|
||||
ServerHandler * handler;
|
||||
char * buf;
|
||||
size_t len;
|
||||
while((handler = connections[0])!=NULL)
|
||||
{
|
||||
while(handler->dequeue(&buf, &len)==0) delete buf;
|
||||
connections.remove(handler);
|
||||
delete handler;
|
||||
}
|
||||
|
||||
// *********************************************************************
|
||||
// * Iterate through the queues associated with servers and remove
|
||||
// * all messages that have not been transmitted.
|
||||
// *********************************************************************
|
||||
StringHashIterator iter(&connectionQueues);
|
||||
iter.first();
|
||||
while((buf = iter.key())!=NULL)
|
||||
{
|
||||
FifoQueue * queue = (FifoQueue *)iter.data();
|
||||
connectionQueues.remove(buf);
|
||||
while(queue->dequeue(&buf, &len)==0) delete buf;
|
||||
delete queue;
|
||||
iter.first();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerInterface::getDefault :
|
||||
// * This method allows the caller to obtain a pointer to the name of the
|
||||
// * default server.
|
||||
// *****************************************************************************
|
||||
char * ServerInterface::getDefault ( void )
|
||||
{
|
||||
return defaultServer;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerInterface::setDefault :
|
||||
// * This method allows the caller to set the name of the default server.
|
||||
// *****************************************************************************
|
||||
void ServerInterface::setDefault ( char * Default )
|
||||
{
|
||||
if(defaultServer!=NULL)
|
||||
{
|
||||
delete defaultServer;
|
||||
defaultServer = NULL;
|
||||
defaultServerHandler = NULL;
|
||||
}
|
||||
if(Default!=NULL && *Default)
|
||||
{
|
||||
defaultServer = strdup(Default);
|
||||
defaultServerHandler = connect(defaultServer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerInterface::connect :
|
||||
// * This is a stub method that should be overridden by the developer in
|
||||
// * a child class.
|
||||
// *****************************************************************************
|
||||
ServerHandler * ServerInterface::connect ( char *, char *, unsigned short )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerInterface::disconnect :
|
||||
// * This is a stub method that should be overridden by the developer in
|
||||
// * a child class.
|
||||
// *****************************************************************************
|
||||
ServerHandler * ServerInterface::disconnect ( char * )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerInterface::enqueue :
|
||||
// * This enqueue mechanism is called by the client if they have already
|
||||
// * identified the server that they wish to communicate with and have
|
||||
// * obtained a pointer to its ServerHandler object.
|
||||
// *
|
||||
// * If the specified server handler is NULL then the message will be
|
||||
// * submitted to the default server.
|
||||
// *****************************************************************************
|
||||
int ServerInterface::enqueue( ServerHandler * handler, char * binary, size_t binaryLen )
|
||||
{
|
||||
int result;
|
||||
|
||||
if(handler!=NULL || (handler=defaultServerHandler)!=NULL ||
|
||||
(defaultServer!=NULL && (handler=(defaultServerHandler=connect(defaultServer)))!=NULL))
|
||||
{
|
||||
handler->enqueue(binary, binaryLen);
|
||||
result = CDEV_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
outputError(CDEV_SEVERITY_ERROR,
|
||||
"ServerInterface::enqueue",
|
||||
"No default server has been specified");
|
||||
result = CDEV_ERROR;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerInterface::getQueue :
|
||||
// * This method allows the caller to obtain a pointer to the FifoQueue
|
||||
// * associated with a specific server. This queue is then attached to
|
||||
// * the ServerHandler that is connected to that server.
|
||||
// *****************************************************************************
|
||||
FifoQueue * ServerInterface::getQueue ( char * server )
|
||||
{
|
||||
FifoQueue * queue = (FifoQueue *)connectionQueues.find(server);
|
||||
if(queue==NULL)
|
||||
{
|
||||
queue=new FifoQueue;
|
||||
connectionQueues.insert(server, (void *)queue);
|
||||
}
|
||||
return queue;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerInterface::isPacketValid :
|
||||
// * This method is called by the ServerHandler after it has been restarted.
|
||||
// * If the ServerHandler inherits packets that are already in the queue, it
|
||||
// * will call this method for each pcket in order to determine if they are
|
||||
// * valid. If the packets are no longer valid (i.e., there is no longer
|
||||
// * a cdevTransObj associated with them, they will be deleted. Otherwise,
|
||||
// * they will be submitted to the server.
|
||||
// *
|
||||
// * Because this functionality will be handled in a derived class, this
|
||||
// * method will always return 1 to indicate that the packet is valid.
|
||||
// *****************************************************************************
|
||||
int ServerInterface::isPacketValid ( char * binary, size_t binaryLen )
|
||||
{
|
||||
return (binary!=NULL && binaryLen>0)?1:0;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerInterface::getFd :
|
||||
// * This mechanism is used to obtain a list of the file descriptors that
|
||||
// * are used by the ServerInterface. These file descriptors may then be
|
||||
// * used for polling.
|
||||
// *****************************************************************************
|
||||
int ServerInterface::getFd (int * &fd, int &numFd )
|
||||
{
|
||||
int idx = 0;
|
||||
|
||||
numFd = 0;
|
||||
|
||||
while(connections[idx]!=NULL)
|
||||
{
|
||||
if((numFd+1)>maxFd)
|
||||
{
|
||||
maxFd*=2;
|
||||
fdList = (int *)realloc(fdList, maxFd*sizeof(int));
|
||||
}
|
||||
fdList[numFd++] = connections[idx++]->getHandle();
|
||||
}
|
||||
|
||||
if(numFd) fd = fdList;
|
||||
else fd = NULL;
|
||||
|
||||
return CDEV_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerInterface::flush :
|
||||
// * This mechanism is used to flush all outbound buffers to their respective
|
||||
// * servers.
|
||||
// *****************************************************************************
|
||||
int ServerInterface::flush ( void )
|
||||
{
|
||||
// *********************************************************************
|
||||
// * First - determine if there is any outbound data that needs to be
|
||||
// * processed. Walk through the connectionQueue objects - which exist
|
||||
// * even if the connection has been lost - and count up the number of
|
||||
// * queues that are not empty.
|
||||
// *********************************************************************
|
||||
StringHashIterator iter(&connectionQueues);
|
||||
FifoQueue * queue = NULL;
|
||||
int needsFlush = 0;
|
||||
|
||||
// *********************************************************************
|
||||
// * Invoke a brief reactor.checkHandlers in order to cause any
|
||||
// * dead ServerHandlers to be removed from the Reactor. Then
|
||||
// * attempt to reattach to any ServerHandlers that have
|
||||
// * outbound data.
|
||||
// *********************************************************************
|
||||
char * server;
|
||||
Reactor.checkHandlers();
|
||||
|
||||
for(iter.first(); (server=iter.key())!=NULL; iter++)
|
||||
{
|
||||
queue = (FifoQueue *)iter.data();
|
||||
if(queue && !queue->empty())
|
||||
{
|
||||
needsFlush++;
|
||||
connect(server);
|
||||
}
|
||||
}
|
||||
|
||||
// *********************************************************************
|
||||
// * At this point he needsFlush variable will be non-zero if any of
|
||||
// * the queues contain outbound data. The remainder of this code
|
||||
// * only needs to be performed if this is the case.
|
||||
// *********************************************************************
|
||||
if(needsFlush)
|
||||
{
|
||||
// *************************************************************
|
||||
// * Provide a maximum timeout value of 5 seconds. If the system
|
||||
// * cannot be flushed in that amount of time - then an error or
|
||||
// * a hang must exist on the other side.
|
||||
// *************************************************************
|
||||
cdevTimeValue t(5.0);
|
||||
cdevClock timer;
|
||||
timer.schedule(NULL, t);
|
||||
|
||||
// *************************************************************
|
||||
// * While there are sockets that have outbound data AND the
|
||||
// * timer has not expired - process events.
|
||||
// *************************************************************
|
||||
int idx = 0;
|
||||
while(needsFlush && !timer.expired())
|
||||
{
|
||||
needsFlush = 0;
|
||||
for(idx=0; connections[idx]!=NULL; idx++)
|
||||
{
|
||||
if(!connections[idx]->empty())
|
||||
{
|
||||
connections[idx]->setMask(cdevEventHandler::WRITE_MASK|cdevEventHandler::EXCEPT_MASK);
|
||||
needsFlush++;
|
||||
}
|
||||
else connections[idx]->setMask(cdevEventHandler::READ_MASK|cdevEventHandler::EXCEPT_MASK);
|
||||
}
|
||||
if(needsFlush) Reactor.handleEvents(1.0, cdevReactor::UNTIL_EVENT);
|
||||
}
|
||||
|
||||
// *********************************************************************
|
||||
// * Walk through all of the ServerHandlers and restore them to
|
||||
// * READ_MASK mode.
|
||||
// *********************************************************************
|
||||
if(needsFlush)
|
||||
{
|
||||
for(idx=0; connections[idx]!=NULL; idx++)
|
||||
{
|
||||
connections[idx]->setMask(cdevEventHandler::READ_MASK|cdevEventHandler::EXCEPT_MASK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CDEV_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerInterface::flush :
|
||||
// * This mechanism is used to flush all outbound buffers to their respective
|
||||
// * servers.
|
||||
// *****************************************************************************
|
||||
int ServerInterface::flush ( int fd )
|
||||
{
|
||||
// *********************************************************************
|
||||
// * Walk through each item and locate the handler that needs to be
|
||||
// * flushed. If the connection is located, then handle events until
|
||||
// * it is empty.
|
||||
// *********************************************************************
|
||||
int i;
|
||||
for(i=0; connections[i]!=NULL && connections[i]->getHandle()!=fd; i++);
|
||||
if(connections[i]!=NULL)
|
||||
{
|
||||
cdevTimeValue t(5.0);
|
||||
cdevClock timer;
|
||||
timer.schedule(NULL, t);
|
||||
|
||||
connections[i]->setMask(cdevEventHandler::WRITE_MASK|cdevEventHandler::EXCEPT_MASK);
|
||||
while(connections[i]!=NULL && !connections[i]->empty() && !timer.expired())
|
||||
{
|
||||
Reactor.handleEvents(1.0, cdevReactor::UNTIL_EVENT);
|
||||
}
|
||||
// *************************************************************
|
||||
// * If an error occurs during the write, the ServerHandler may
|
||||
// * have been deleted - therefore, check to ensure that the
|
||||
// * connection is valid prior to restoring its mask.
|
||||
// *************************************************************
|
||||
if(connections[i]!=NULL)
|
||||
{
|
||||
connections[i]->setMask(cdevEventHandler::READ_MASK|cdevEventHandler::EXCEPT_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
return CDEV_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerInterface::pend :
|
||||
// * Pends for the specified period of time. The int parameter is not used
|
||||
// * in this implementation. In later designs it may be used to allow the
|
||||
// * interface to pend on a specific file descriptor.
|
||||
// *****************************************************************************
|
||||
int ServerInterface::pend ( double seconds, int )
|
||||
{
|
||||
// *********************************************************************
|
||||
// * Test to determine if there are any ServerHandlers in operation.
|
||||
// *********************************************************************
|
||||
if(connections[0]!=NULL)
|
||||
{
|
||||
// *************************************************************
|
||||
// * Flush outbound requests if necessary.
|
||||
// *************************************************************
|
||||
flush();
|
||||
|
||||
// *************************************************************
|
||||
// * Handle events for the specified period.
|
||||
// *************************************************************
|
||||
Reactor.handleEvents(seconds);
|
||||
}
|
||||
|
||||
return CDEV_SUCCESS;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * ServerInterface::poll :
|
||||
// * This method polls the cdevReactor to see if any events are ready to be
|
||||
// * processed on any of the sockets. If events are ready, then they are
|
||||
// * processed immediately - otherwise, the function returns immediately.
|
||||
// *****************************************************************************
|
||||
int ServerInterface::poll ( void )
|
||||
{
|
||||
// *********************************************************************
|
||||
// * Test to determine if there are any ServerHandlers in operation.
|
||||
// *********************************************************************
|
||||
if(connections[0]!=NULL)
|
||||
{
|
||||
// *************************************************************
|
||||
// * Flush outbound requests if necessary.
|
||||
// *************************************************************
|
||||
flush();
|
||||
|
||||
// *************************************************************
|
||||
// * Handle events for 0 seconds - effectively polling.
|
||||
// *************************************************************
|
||||
Reactor.handleEvents(0.0001, cdevReactor::UNTIL_EVENT);
|
||||
}
|
||||
|
||||
return CDEV_SUCCESS;
|
||||
}
|
||||
71
extensions/cdevGenericServer/cdevClient/ServerInterface.h
Executable file
71
extensions/cdevGenericServer/cdevClient/ServerInterface.h
Executable file
@@ -0,0 +1,71 @@
|
||||
#ifndef _SERVER_INTERFACE_H_
|
||||
#define _SERVER_INTERFACE_H_
|
||||
|
||||
#include "cdevErrCode.h"
|
||||
#include "ServerHandler.h"
|
||||
#include "ErrorReporter.h"
|
||||
#include "StringHash.h"
|
||||
#include "fifo.h"
|
||||
#include "cdevReactor.h"
|
||||
#include "cdevEventHandler.h"
|
||||
#include "cdevAddr.h"
|
||||
|
||||
class GENERIC_SERVER_API ServerConnectionList
|
||||
{
|
||||
private:
|
||||
enum { ALLOCATION_COUNT = 32 };
|
||||
ServerHandler ** items;
|
||||
int maxItems;
|
||||
|
||||
public:
|
||||
ServerConnectionList ( void );
|
||||
virtual ~ServerConnectionList ( void );
|
||||
|
||||
ServerHandler * find ( char * server );
|
||||
int insert ( ServerHandler * handler );
|
||||
int remove ( ServerHandler * handler );
|
||||
ServerHandler * remove ( char * server );
|
||||
|
||||
ServerHandler * operator [] ( int idx )
|
||||
{ return (idx<maxItems)?items[idx]:(ServerHandler *)NULL; }
|
||||
};
|
||||
|
||||
|
||||
class GENERIC_SERVER_API ServerInterface : public ErrorReporter
|
||||
{
|
||||
protected:
|
||||
ServerConnectionList connections;
|
||||
StringHash connectionQueues;
|
||||
char * defaultServer;
|
||||
ServerHandler * defaultServerHandler;
|
||||
int maxFd;
|
||||
int * fdList;
|
||||
|
||||
public:
|
||||
enum { FAILED_TO_SEND = -1, COMPLETED = 0};
|
||||
|
||||
static cdevReactor Reactor;
|
||||
|
||||
ServerInterface ( void );
|
||||
~ServerInterface ( void );
|
||||
|
||||
virtual char * getDefault ( void );
|
||||
virtual void setDefault ( char * Default );
|
||||
|
||||
virtual ServerHandler * connect ( char * server, char * host=NULL, unsigned short port=0 );
|
||||
virtual ServerHandler * disconnect ( char * server );
|
||||
|
||||
int enqueue ( ServerHandler * handler, char * binary, size_t binaryLen );
|
||||
FifoQueue * getQueue ( char * server );
|
||||
virtual int enqueue ( int status, ServerHandler * handler, char * binary, size_t binaryLen ) = 0;
|
||||
virtual int isPacketValid ( char * binary, size_t binaryLen );
|
||||
|
||||
virtual int getFd ( int * &fd, int &numFd );
|
||||
virtual int flush ( void );
|
||||
int flush ( int fd );
|
||||
virtual int poll ( void );
|
||||
virtual int pend ( double seconds, int fd = -1 );
|
||||
};
|
||||
|
||||
|
||||
#endif /* _SERVER_INTERFACE_H_ */
|
||||
432
extensions/cdevGenericServer/cdevClient/cdevClientRequestObject.cc
Executable file
432
extensions/cdevGenericServer/cdevClient/cdevClientRequestObject.cc
Executable file
@@ -0,0 +1,432 @@
|
||||
#include <ctype.h>
|
||||
#include <cdevDirectory.h>
|
||||
#include <cdevClientRequestObject.h>
|
||||
#include <cdevClock.h>
|
||||
#include <cdevTranObj.h>
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientRequestObject::cdevClientRequestObject :
|
||||
// * This constructor initializes the internals of a device/message
|
||||
// * pair associated with a cdevClientService based service.
|
||||
// *
|
||||
// * Returns nothing.
|
||||
// *
|
||||
// * Remember it is the responsibility of the requestObject to ensure
|
||||
// * that the message is not laden with extraneous spaces.
|
||||
// *****************************************************************************
|
||||
cdevClientRequestObject::cdevClientRequestObject ( char * device, char * msg, cdevSystem & system)
|
||||
: cdevRequestObject(device, msg, system),
|
||||
syncCallback(defaultCallback, (void *)&sendStatus),
|
||||
handler(NULL), contextID(-1)
|
||||
{
|
||||
char message[256];
|
||||
char * ptr;
|
||||
|
||||
*server = 0;
|
||||
*DDL_server = 0;
|
||||
|
||||
// *********************************************************************
|
||||
// * Remove any extra spaces from the message.
|
||||
// * Copy user supplied msg to a message buffer to allow
|
||||
// * modification in this routine since the user supplied
|
||||
// * msg could be a constant string
|
||||
// *********************************************************************
|
||||
strncpy (message, msg, sizeof (message) - 1);
|
||||
message[255] = 0;
|
||||
|
||||
for(ptr=message; *ptr!=0; ptr++)
|
||||
{
|
||||
if(isspace(*ptr))
|
||||
{
|
||||
char * nextChar;
|
||||
|
||||
for(nextChar=ptr+1; isspace(*nextChar) && *nextChar!=0; nextChar++);
|
||||
if(nextChar!=ptr+1) strcpy(ptr+1, nextChar);
|
||||
*ptr=' ';
|
||||
}
|
||||
}
|
||||
|
||||
// *********************************************************************
|
||||
// * Remove all trailing spaces from the message.
|
||||
// *********************************************************************
|
||||
for(ptr = message+(strlen(message)-1); ptr>=message && isspace(*ptr); ptr--)
|
||||
{
|
||||
*ptr=0;
|
||||
}
|
||||
// *********************************************************************
|
||||
// * Determine the commandCode from the message string.
|
||||
// *********************************************************************
|
||||
if(!strncmp(message, "get ", 4)) commandCode = GET_COMMAND;
|
||||
else if(!strncmp(message, "set ", 4)) commandCode = SET_COMMAND;
|
||||
else if(!strncmp(message, "monitorOn ", 10)) commandCode = MONITOR_ON_COMMAND;
|
||||
else if(!strncmp(message, "monitorOff ", 11)) commandCode = MONITOR_OFF_COMMAND;
|
||||
else commandCode = OTHER_COMMAND;
|
||||
|
||||
// *********************************************************************
|
||||
// * Determine the messageCode from the message string.
|
||||
// *********************************************************************
|
||||
if(!strcmp(message, "get servers")) messageCode = GET_SERVERS_MESSAGE;
|
||||
else if(!strcmp(message, "get default")) messageCode = GET_DEFAULT_MESSAGE;
|
||||
else if(!strcmp(message, "set default")) messageCode = SET_DEFAULT_MESSAGE;
|
||||
else if(!strcmp(message, "disconnect")) messageCode = DISCONNECT_MESSAGE;
|
||||
else if(!strcmp(message, "get ClientInfo")) messageCode = GET_CLIENTINFO_MESSAGE;
|
||||
else if(!strcmp(message, "get ServerInfo")) messageCode = GET_SERVERINFO_MESSAGE;
|
||||
else messageCode = OTHER_MESSAGE;
|
||||
|
||||
// *********************************************************************
|
||||
// * Attempt to read the server name from the DDL file.
|
||||
// *********************************************************************
|
||||
cdevData output;
|
||||
|
||||
sprintf (DDL_server, "resolveServiceData %s %s", device, message);
|
||||
if((system.nameServer()).send(DDL_server, NULL, &output)==CDEV_SUCCESS)
|
||||
{
|
||||
*DDL_server = 0;
|
||||
output.get ("server", DDL_server, 256);
|
||||
}
|
||||
else *DDL_server = 0;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientRequestObject::~cdevClientRequestObject:
|
||||
// * This is the destructor for the object. It will free any memory that it
|
||||
// * has allocated and remove itself from its associated ServerHandler
|
||||
// * callback.
|
||||
// *****************************************************************************
|
||||
cdevClientRequestObject::~cdevClientRequestObject ( void )
|
||||
{
|
||||
if(handler!=NULL) handler->unregisterServerCallback(this);
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientRequestObject::getState :
|
||||
// * Returns the connection state of the cdevClientRequestObject.
|
||||
// *****************************************************************************
|
||||
int cdevClientRequestObject::getState ( void )
|
||||
{
|
||||
ServerHandler * Handler = NULL;
|
||||
return (getServerHandler(&Handler)==CDEV_SUCCESS)?CDEV_STATE_NOTCONNECTED:CDEV_STATE_CONNECTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientRequestObject::className :
|
||||
// * Obtains the name of this class as a string.
|
||||
// *****************************************************************************
|
||||
const char * cdevClientRequestObject::className ( void ) const
|
||||
{
|
||||
return "cdevClientRequestObject";
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientRequestObject::setContext :
|
||||
// * This method is called to set the context of the request object. The
|
||||
// * first step in this process is to determine if the caller has specified
|
||||
// * a server in the context. If so, the server name should be set to that
|
||||
// * value. Next call the setContext method of the underlying
|
||||
// * cdevRequestObject...
|
||||
// *****************************************************************************
|
||||
int cdevClientRequestObject::setContext (cdevData& cxt)
|
||||
{
|
||||
cdevClientService * svc = (cdevClientService *)service_;
|
||||
int result = CDEV_SUCCESS;
|
||||
int newContextID = 0;
|
||||
|
||||
if((newContextID = svc->contexts.insert(cxt))!=contextID)
|
||||
{
|
||||
ServerHandler * Handler = NULL;
|
||||
|
||||
if(handler!=NULL) handler->unregisterServerCallback(this);
|
||||
|
||||
contextID = newContextID;
|
||||
*server = 0;
|
||||
handler = NULL;
|
||||
|
||||
cxt.get ("server", server, 256);
|
||||
getServerHandler(&Handler);
|
||||
|
||||
result = cdevRequestObject::setContext(cxt);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientRequestObject::sendNoBlock :
|
||||
// * This function allows the caller to submit an asynchronous message to the
|
||||
// * server for processing.
|
||||
// *****************************************************************************
|
||||
int cdevClientRequestObject::sendNoBlock (cdevData & in, cdevData & out)
|
||||
{ return sendNoBlock(&in, &out); }
|
||||
int cdevClientRequestObject::sendNoBlock (cdevData * in, cdevData & out)
|
||||
{ return sendNoBlock(in, &out); }
|
||||
int cdevClientRequestObject::sendNoBlock (cdevData & in, cdevData * out)
|
||||
{ return sendNoBlock(&in, out); }
|
||||
int cdevClientRequestObject::sendNoBlock (cdevData * in, cdevData * out)
|
||||
{
|
||||
cdevClientService * svc = (cdevClientService *)service_;
|
||||
cdevTranObj * xobj = new cdevTranObj(&system_, this, out, &svc->syncCallback);
|
||||
ServerHandler * Handler = NULL;
|
||||
int status = CDEV_SUCCESS;
|
||||
|
||||
xobj->disableDeleteCbk();
|
||||
|
||||
if((status=getServerHandler(&Handler))==CDEV_SUCCESS)
|
||||
{
|
||||
status = svc->enqueue(Handler, in, *xobj);
|
||||
}
|
||||
else delete xobj;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientRequestObject::sendCallback :
|
||||
// * This function allows the caller to submit an asynchronous message to the
|
||||
// * server for processing.
|
||||
// *****************************************************************************
|
||||
int cdevClientRequestObject::sendCallback (cdevData & in, cdevCallback & callback)
|
||||
{ return sendCallback(&in, callback); }
|
||||
int cdevClientRequestObject::sendCallback (cdevData * in, cdevCallback & callback)
|
||||
{
|
||||
cdevCallback * cb = new cdevCallback(callback);
|
||||
cdevClientService * svc = (cdevClientService *)service_;
|
||||
cdevTranObj * xobj = new cdevTranObj(&system_, this, NULL, cb);
|
||||
ServerHandler * Handler = NULL;
|
||||
int status = CDEV_SUCCESS;
|
||||
|
||||
xobj->enableDeleteCbk();
|
||||
|
||||
if((status=getServerHandler(&Handler))==CDEV_SUCCESS)
|
||||
{
|
||||
status = svc->enqueue(Handler, in, *xobj);
|
||||
}
|
||||
else delete xobj;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientRequestObject::send :
|
||||
// * The send interface is used to provide synchronous I/O with the service.
|
||||
// *
|
||||
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
|
||||
// *****************************************************************************
|
||||
int cdevClientRequestObject::send ( cdevData & in, cdevData & out )
|
||||
{ return send(&in, &out); }
|
||||
int cdevClientRequestObject::send ( cdevData * in, cdevData & out )
|
||||
{ return send(in, &out); }
|
||||
int cdevClientRequestObject::send ( cdevData & in, cdevData * out )
|
||||
{ return send(&in, out); }
|
||||
int cdevClientRequestObject::send ( cdevData * in, cdevData * out )
|
||||
{
|
||||
int status = CDEV_SUCCESS;
|
||||
cdevClientService * svc = (cdevClientService *)service_;
|
||||
cdevTranObj * xobj = new cdevTranObj(&system_, this, out, &syncCallback);
|
||||
ServerHandler * Handler;
|
||||
|
||||
sendStatus.completionCode = 0;
|
||||
sendStatus.finished = 0;
|
||||
xobj->disableDeleteCbk();
|
||||
|
||||
if((status=getServerHandler(&Handler))==CDEV_SUCCESS)
|
||||
{
|
||||
if((status = svc->enqueue(Handler, in, *xobj))==CDEV_SUCCESS)
|
||||
{
|
||||
// *****************************************************
|
||||
// * I used to wait for a response here only if the outbound
|
||||
// * cdevData object was non-null. However, that provided
|
||||
// * unexpected behavior to the client. Now I wait whether
|
||||
// * output data is expected or not.
|
||||
// *****************************************************
|
||||
cdevTimeValue t(waitPeriod());
|
||||
cdevClock timer;
|
||||
timer.schedule(NULL,t);
|
||||
|
||||
// *****************************************************
|
||||
// * WAITING WITH system_.pend():
|
||||
// * Previously I was using system_.pend() to process
|
||||
// * events while waiting for the service to respond.
|
||||
// * This resulted in a lock-up when the connection
|
||||
// * could not be established or if the connection
|
||||
// * collapsed while in use.
|
||||
// *
|
||||
// * WAITING WITH system_.poll():
|
||||
// * When in a heavy inbound traffic situation, the
|
||||
// * calls from other services will trample all over
|
||||
// * the inbound data coming from the server.
|
||||
// * This results in unreliable delivery and processing
|
||||
// * of messages from the server.
|
||||
// *
|
||||
// * WAITING WITH service_.poll():
|
||||
// * So far so good.
|
||||
// *****************************************************
|
||||
|
||||
while(!sendStatus.finished && !timer.expired()) service_->poll();
|
||||
if (!sendStatus.finished)
|
||||
{
|
||||
svc->cancel(*xobj);
|
||||
status = CDEV_ERROR;
|
||||
system_.reportError(
|
||||
CDEV_SEVERITY_ERROR,
|
||||
"cdevRequestObject",
|
||||
this,
|
||||
"Server failed to respond after %.1f seconds",
|
||||
(float)waitPeriod());
|
||||
}
|
||||
else
|
||||
{
|
||||
status = sendStatus.completionCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
else delete xobj;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientRequestObject::defaultCallback :
|
||||
// * This is the callback function that is used by the object to
|
||||
// * receive callbacks for send operations.
|
||||
// *****************************************************************************
|
||||
void cdevClientRequestObject::defaultCallback (int status, void * user, cdevRequestObject &, cdevData &)
|
||||
{
|
||||
SendStatus * result = (SendStatus *)user;
|
||||
|
||||
if(result)
|
||||
{
|
||||
result->completionCode = status;
|
||||
result->finished = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientRequestObject::executeServerHandlerCallback :
|
||||
// * The requestObject registers itself with the ServerHandler when it
|
||||
// * attaches to it... If the Serverhandler is destroyed, it will
|
||||
// * call this method on all of the registered request objects in order
|
||||
// * to notify them that it is going away. This allows the request
|
||||
// * object to clear the pointer to the ServerHandler.
|
||||
// *****************************************************************************
|
||||
void cdevClientRequestObject::executeServerHandlerCallback (ServerHandler * Handler)
|
||||
{
|
||||
if(Handler==handler)
|
||||
{
|
||||
/*
|
||||
* system_.reportError(CDEV_SEVERITY_INFO, "cdevRequestObject",
|
||||
* this, "Connection to %s broken for %s:%s",
|
||||
* Handler->get_server(), device().name(), message());
|
||||
*/
|
||||
handler=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientRequestObject::getServerHandler :
|
||||
// * This method is used to obtain the ServerHandler for this request
|
||||
// * object...
|
||||
// *
|
||||
// * The following rules will be followed:
|
||||
// *
|
||||
// * 1) If a server has been specified in the context, then that
|
||||
// * server will be used.
|
||||
// *
|
||||
// * - otherwise -
|
||||
// *
|
||||
// * 2) If a server has been specified in the service data of the
|
||||
// * DDL file, then that server will be used.
|
||||
// *
|
||||
// * - otherwise -
|
||||
// *
|
||||
// * 3) The default server as specified at the cdevClientService will
|
||||
// * be used.
|
||||
// *****************************************************************************
|
||||
int cdevClientRequestObject::getServerHandler (ServerHandler ** Handler)
|
||||
{
|
||||
cdevClientService * svc = (cdevClientService *)service_;
|
||||
int result = CDEV_SUCCESS;
|
||||
|
||||
*Handler = NULL;
|
||||
|
||||
if (*server==0 && *DDL_server!=0) strcpy(server, DDL_server);
|
||||
if (*server!=0 && handler==NULL)
|
||||
{
|
||||
if((*Handler = svc->connect(server))==NULL) result = CDEV_ERROR;
|
||||
else
|
||||
{
|
||||
handler = *Handler;
|
||||
handler->registerServerCallback(this);
|
||||
}
|
||||
}
|
||||
else *Handler = handler;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientRequestObject::isRequestRestartable :
|
||||
// * This method allows the caller to determine if the request object
|
||||
// * is restartable. If a server goes down and then a new server comes
|
||||
// * up in its place, this method will be called for each request object
|
||||
// * that has an outstanding request that has not been serviced.
|
||||
// * If the isRequestRestartable method returns 1, the request will be
|
||||
// * sent to the new server - otherwise, the request will be terminated.
|
||||
// *****************************************************************************
|
||||
int cdevClientRequestObject::isRequestRestartable ( void )
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
switch(getCommandCode())
|
||||
{
|
||||
case GET_COMMAND:
|
||||
case MONITOR_ON_COMMAND:
|
||||
result = 1;
|
||||
break;
|
||||
|
||||
case SET_COMMAND:
|
||||
case MONITOR_OFF_COMMAND:
|
||||
default:
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientRequestObject::getContextID :
|
||||
// * This method will retrieve the identifier of the context that is
|
||||
// * currently in use by this object.
|
||||
// *****************************************************************************
|
||||
int cdevClientRequestObject::getContextID ( void )
|
||||
{
|
||||
return contextID;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * getCommandCode :
|
||||
// * This method will return the current value of the commandCode variable.
|
||||
// * This variable is used to identify the VERB that is utilized by this
|
||||
// * cdevClientRequestObject. The default set of verbs are "get", "set",
|
||||
// * "monitorOn", and "monitorOff".
|
||||
// *****************************************************************************
|
||||
int cdevClientRequestObject::getCommandCode ( void ) { return commandCode; }
|
||||
|
||||
// *****************************************************************************
|
||||
// * getMessageCode :
|
||||
// * This method will return the current value of the messageCode variable.
|
||||
// * This variable is used to identify the message that is utilized by this
|
||||
// * cdevClientRequestObject. The default set of supported messages are
|
||||
// * "get servers", "get default", "set default", and "disconnect".
|
||||
// *****************************************************************************
|
||||
int cdevClientRequestObject::getMessageCode ( void ) { return messageCode; }
|
||||
|
||||
223
extensions/cdevGenericServer/cdevClient/cdevClientRequestObject.h
Executable file
223
extensions/cdevGenericServer/cdevClient/cdevClientRequestObject.h
Executable file
@@ -0,0 +1,223 @@
|
||||
#if !defined (_CDEV_CLIENT_REQUEST_OBJECT_H_)
|
||||
#define _CDEV_CLIENT_REQUEST_OBJECT_H_
|
||||
|
||||
#include <cdevGroup.h>
|
||||
#include <cdevErrCode.h>
|
||||
#include <cdevClientService.h>
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientRequestObject:
|
||||
// * The cdevClientRequestObject class provides the interface for sending
|
||||
// * messages to a server. All device/message commands are routed
|
||||
// * through a cdevClientRequestObject either directly or indirectly.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API cdevClientRequestObject : public cdevRequestObject, public ServerHandlerCallback
|
||||
{
|
||||
protected:
|
||||
typedef struct
|
||||
{
|
||||
int completionCode;
|
||||
int finished;
|
||||
} SendStatus;
|
||||
|
||||
SendStatus sendStatus;
|
||||
char server [256];
|
||||
char DDL_server[256];
|
||||
cdevCallback syncCallback;
|
||||
ServerHandler * handler;
|
||||
int contextID;
|
||||
|
||||
int commandCode;
|
||||
int messageCode;
|
||||
|
||||
public:
|
||||
// *********************************************************************
|
||||
// * These enumerated type are used to identify the basic four commands
|
||||
// * that might be represented by a cdevClientRequestObject... By using
|
||||
// * these identifiers the cdevService does not have to perform a
|
||||
// * string compare in order to identify the nature of the request
|
||||
// * object.
|
||||
// *
|
||||
// * At construction the cdevClientRequestObject will set the
|
||||
// * commandCode to contain the correct value, the developer may
|
||||
// * override this setting in the constructor for an inherited class.
|
||||
// *
|
||||
// * Enumerated list extensions created by developers should begin at
|
||||
// * value cdevClientRequestObject::MONITOR_OFF_COMMAND+1.
|
||||
// *
|
||||
// * The current setting of the commandCode may be obtained by calling
|
||||
// * the getCommandCode method of the class.
|
||||
// *********************************************************************
|
||||
enum {OTHER_COMMAND = 0,
|
||||
GET_COMMAND,
|
||||
SET_COMMAND,
|
||||
MONITOR_ON_COMMAND,
|
||||
MONITOR_OFF_COMMAND};
|
||||
|
||||
// *********************************************************************
|
||||
// * These enumerated type are used to identify the messages that are
|
||||
// * intrinisicly supported by the cdevService... By using
|
||||
// * these identifiers the cdevService does not have to perform a
|
||||
// * string compare in order to identify the nature of the request
|
||||
// * object.
|
||||
// *
|
||||
// * At construction the cdevClientRequestObject will set the
|
||||
// * messageCode to contain the correct value, the developer may
|
||||
// * override this setting in the constructor for an inherited class.
|
||||
// *
|
||||
// * Enumerated list extensions created by developers should begin at
|
||||
// * value cdevClientRequestObject::SET_DEFAULT_MESSAGE+1
|
||||
// *
|
||||
// * The current setting of the commandCode may be obtained by calling
|
||||
// * the getMessageCode method of the class.
|
||||
// *********************************************************************
|
||||
enum {OTHER_MESSAGE = 0,
|
||||
GET_SERVERS_MESSAGE,
|
||||
GET_DEFAULT_MESSAGE,
|
||||
SET_DEFAULT_MESSAGE,
|
||||
DISCONNECT_MESSAGE,
|
||||
GET_CLIENTINFO_MESSAGE,
|
||||
GET_SERVERINFO_MESSAGE};
|
||||
|
||||
cdevClientRequestObject ( char * device, char * message,
|
||||
cdevSystem & system = cdevSystem::defaultSystem());
|
||||
|
||||
virtual ~cdevClientRequestObject ( void );
|
||||
|
||||
// *********************************************************************
|
||||
// * cdevClientRequestObject::getState :
|
||||
// * Returns the connection state of the cdevClientRequestObject.
|
||||
// *********************************************************************
|
||||
virtual int getState ( void );
|
||||
|
||||
// *********************************************************************
|
||||
// * cdevClientRequestObject::setContext :
|
||||
// * This mechanism is used to specify the default server that will
|
||||
// * be used for the request.
|
||||
// *********************************************************************
|
||||
virtual int setContext ( cdevData & ctx);
|
||||
|
||||
// *********************************************************************
|
||||
// * cdevClientRequestObject::send :
|
||||
// * The send interface is used to provide synchronous I/O with the
|
||||
// * service.
|
||||
// *
|
||||
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
|
||||
// *********************************************************************
|
||||
virtual int send ( cdevData & in, cdevData & out );
|
||||
virtual int send ( cdevData * in, cdevData & out );
|
||||
virtual int send ( cdevData & in, cdevData * out );
|
||||
virtual int send ( cdevData * in, cdevData * out );
|
||||
|
||||
// *********************************************************************
|
||||
// * cdevClientRequestObject::sendNoBlock :
|
||||
// * The sendNoBlock interface is used in conjunction with cdevGroup
|
||||
// * or cdevSystem to execute a series of operations. During the
|
||||
// * early implementation of this product, these functions will be
|
||||
// * linked directly to the send call.
|
||||
// *
|
||||
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
|
||||
// *********************************************************************
|
||||
virtual int sendNoBlock (cdevData & in, cdevData & out);
|
||||
virtual int sendNoBlock (cdevData * in, cdevData & out);
|
||||
virtual int sendNoBlock (cdevData & in, cdevData * out);
|
||||
virtual int sendNoBlock (cdevData * in, cdevData * out);
|
||||
|
||||
// *********************************************************************
|
||||
// * cdevClientRequestObject::sendCallback :
|
||||
// * The sendCallback interface provides asynchronous communications
|
||||
// * with the server. During the early implementation of this
|
||||
// * product, these functions will be linked directly to the send
|
||||
// * call.
|
||||
// *
|
||||
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
|
||||
// *********************************************************************
|
||||
virtual int sendCallback (cdevData & in, cdevCallback & callback);
|
||||
virtual int sendCallback (cdevData * in, cdevCallback & callback);
|
||||
|
||||
virtual const char * className ( void ) const;
|
||||
|
||||
// *********************************************************************
|
||||
// * cdevClientRequestObject::deafultCallback :
|
||||
// * This is the callback function that is used by the object to
|
||||
// * receive callbacks for send operations.
|
||||
// *********************************************************************
|
||||
static void defaultCallback (int status, void * user, cdevRequestObject &, cdevData &);
|
||||
|
||||
// *********************************************************************
|
||||
// * The requestObject registers itself with the ServerHandler when it
|
||||
// * attaches to it... If the Serverhandler is destroyed, it will
|
||||
// * call this method on all of the registered request objects in order
|
||||
// * to notify them that it is going away. This allows the request
|
||||
// * object to clear the pointer to the ServerHandler.
|
||||
// *********************************************************************
|
||||
virtual void executeServerHandlerCallback (ServerHandler * Handler);
|
||||
|
||||
// *********************************************************************
|
||||
// * This method is used to obtain the ServerHandler for this request
|
||||
// * object...
|
||||
// *
|
||||
// * The following rules will be followed:
|
||||
// * 1) If a server has been specified in the context, then that
|
||||
// * server will be used.
|
||||
// *
|
||||
// * - otherwise -
|
||||
// *
|
||||
// * 2) If a server has been specified in the service data of the
|
||||
// * DDL file, then that server will be used.
|
||||
// *
|
||||
// * - otherwise -
|
||||
// *
|
||||
// * 3) The default server as specified at the cdevClientService will
|
||||
// * be used.
|
||||
// *********************************************************************
|
||||
virtual int getServerHandler (ServerHandler ** Handler);
|
||||
|
||||
// *********************************************************************
|
||||
// * This method allows the caller to determine if the request object
|
||||
// * is restartable. If a server goes down and then a new server comes
|
||||
// * up in its place, this method will be called for each request object
|
||||
// * that has an outstanding request that has not been serviced.
|
||||
// * If the isRequestRestartable method returns 1, the request will be
|
||||
// * sent to the new server - otherwise, the request will be terminated.
|
||||
// *********************************************************************
|
||||
virtual int isRequestRestartable ( void );
|
||||
|
||||
// *********************************************************************
|
||||
// * getContextID :
|
||||
// * This method will retrieve the identifier of the context that
|
||||
// * is currently in use by this object.
|
||||
// *********************************************************************
|
||||
int getContextID ( void );
|
||||
|
||||
// *********************************************************************
|
||||
// * getCommandCode :
|
||||
// * This method will return the current value of the commandCode
|
||||
// * variable. This variable is used to identify the VERB that is
|
||||
// * utilized by this cdevRequestObject. The default set of verbs
|
||||
// * are "get", "set", "monitorOn", and "monitorOff".
|
||||
// *********************************************************************
|
||||
int getCommandCode ( void );
|
||||
|
||||
// *********************************************************************
|
||||
// * getMessageCode :
|
||||
// * This method will return the current value of the messageCode
|
||||
// * variable. This variable is used to identify the message that is
|
||||
// * utilized by this cdevRequestObject. The default set of
|
||||
// * supported messages are "get servers", "get default",
|
||||
// * "set default", and "disconnect".
|
||||
// *********************************************************************
|
||||
int getMessageCode ( void );
|
||||
|
||||
|
||||
// *********************************************************************
|
||||
// * waitPeriod :
|
||||
// * This method returns a double that indicates the maximum amount
|
||||
// * of time that the service should wait for a synchronous result to
|
||||
// * be returned.
|
||||
// *********************************************************************
|
||||
virtual double waitPeriod ( void ) { return 10.0; }
|
||||
};
|
||||
|
||||
|
||||
#endif /* _CDEV_CLIENT_REQUEST_OBJECT_H_ */
|
||||
1219
extensions/cdevGenericServer/cdevClient/cdevClientService.cc
Executable file
1219
extensions/cdevGenericServer/cdevClient/cdevClientService.cc
Executable file
File diff suppressed because it is too large
Load Diff
140
extensions/cdevGenericServer/cdevClient/cdevClientService.h
Executable file
140
extensions/cdevGenericServer/cdevClient/cdevClientService.h
Executable file
@@ -0,0 +1,140 @@
|
||||
#if !defined (_CDEV_CLIENT_SERVICE_H_)
|
||||
#define _CDEV_CLIENT_SERVICE_H_
|
||||
|
||||
#include <cdevService.h>
|
||||
#include <cdevRequestObject.h>
|
||||
#include <cdevTranObj.h>
|
||||
#include <ServerInterface.h>
|
||||
#include <AddressIndex.h>
|
||||
#include <cdevContextMap.h>
|
||||
#include <ClientInfo.h>
|
||||
#include <cdevGenericServerTags.h>
|
||||
#include <StringHash.h>
|
||||
|
||||
// *****************************************************************************
|
||||
// * class NSCallbackArg :
|
||||
// * This class is provided as a technique for allowing the name server
|
||||
// * to differentiate when making monitorOn requests between two servers that
|
||||
// * use the same service.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API NSCallbackArg
|
||||
{
|
||||
friend class cdevClientService;
|
||||
|
||||
private:
|
||||
char * server;
|
||||
cdevClientService * service;
|
||||
|
||||
NSCallbackArg ( char * Server, cdevClientService * Service )
|
||||
: server(strdup(Server)), service(Service)
|
||||
{
|
||||
}
|
||||
|
||||
~NSCallbackArg ( void )
|
||||
{
|
||||
if(server) delete server;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevClientService:
|
||||
// * This is class provides the mechanisms that the cdev system will use
|
||||
// * to communicate with the model service.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API cdevClientService : public cdevService,
|
||||
public ServerInterface,
|
||||
public cdevTagTableCallback
|
||||
{
|
||||
friend class cdevClientRequestObject;
|
||||
friend class cdevClientTransaction;
|
||||
|
||||
public:
|
||||
enum { ServiceTagBase=511 };
|
||||
|
||||
static int ServerTag;
|
||||
static int HostTag;
|
||||
static int PortTag;
|
||||
|
||||
cdevClientService ( char * domain, char * name, cdevSystem & system = cdevSystem::defaultSystem());
|
||||
static void defaultCallback (int, void *, cdevRequestObject &, cdevData &);
|
||||
static void nameServerCallback(int, void *, cdevRequestObject &, cdevData &);
|
||||
virtual int outputError (int severity, char *name, char *formatString, ...);
|
||||
ServerHandler * connect ( char * server, char * host=NULL, unsigned short port = 0);
|
||||
ServerHandler * disconnect ( char * server );
|
||||
|
||||
int flush ( void );
|
||||
int pend ( double seconds, int fd = -1 );
|
||||
int getFd ( int * &fd, int & numFd );
|
||||
|
||||
int poll ( void );
|
||||
int pend ( int fd = -1 );
|
||||
int getNameServer ( cdevDevice * &ns );
|
||||
int getRequestObject ( char * device, char * message, cdevRequestObject * &req);
|
||||
|
||||
int enqueue ( char * server, cdevData * in, cdevTranObj & xobj );
|
||||
int enqueue ( ServerHandler * handler, cdevData * in, cdevTranObj & xobj );
|
||||
int enqueue ( ServerHandler * handler, class cdevClientTransaction &, unsigned);
|
||||
int cancel ( cdevTranObj & xobj );
|
||||
int enqueue ( int status, ServerHandler * handler, char * binary, size_t binaryLen );
|
||||
int isPacketValid ( char * binary, size_t binaryLen );
|
||||
void callback ( int newTag, char * newName );
|
||||
char * getDomain ( void ) const { return domain; }
|
||||
|
||||
protected:
|
||||
virtual ~cdevClientService ( void );
|
||||
virtual void fireCallback ( int status, cdevTranObj &xobj, cdevData *resultData, int partialTransaction = 0 );
|
||||
virtual int processLocal ( cdevData * in, cdevTranObj & xobj );
|
||||
|
||||
char * domain;
|
||||
AddressIndex transactions;
|
||||
cdevCallback syncCallback;
|
||||
cdevContextMap contexts;
|
||||
int quitFlag;
|
||||
StringHash nsCallbackArgs;
|
||||
static ClientInfo clientInfo;
|
||||
static cdevGenericServerTagDef tags;
|
||||
|
||||
NSCallbackArg * getCallbackArg ( char * server );
|
||||
};
|
||||
|
||||
class GENERIC_SERVER_API cdevClientTransaction
|
||||
{
|
||||
private:
|
||||
// *********************************************************************
|
||||
// * Free list data elements and private array constructor.
|
||||
// *********************************************************************
|
||||
enum {ALLOCATION_COUNT = 16 };
|
||||
static cdevClientTransaction * freeList_;
|
||||
cdevClientTransaction * freeListNext_;
|
||||
cdevClientTransaction ( void );
|
||||
|
||||
public:
|
||||
// *********************************************************************
|
||||
// * Public free list interface.
|
||||
// *********************************************************************
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * ptr );
|
||||
|
||||
char server[256];
|
||||
cdevTranObj * xobj;
|
||||
int permanent;
|
||||
int statusCode;
|
||||
|
||||
// *********************************************************************
|
||||
// * Data elements used for restartable transactions.
|
||||
// *********************************************************************
|
||||
int restartable;
|
||||
int contextID;
|
||||
cdevData * userData;
|
||||
|
||||
cdevClientTransaction ( cdevTranObj & XObj, ServerHandler &handler,
|
||||
int Restartable=0, cdevData *data=NULL,
|
||||
unsigned ContextID=0 );
|
||||
virtual ~cdevClientTransaction ( void );
|
||||
void reconnect (char * host=NULL, unsigned short port=0, unsigned key=0);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* _CDEV_CLIENT_SERVICE_H_ */
|
||||
Reference in New Issue
Block a user