cdev-1.7.2n
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
#include "ClientAcceptor.h"
|
||||
#include "ClientHandler.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// * ClientAcceptor:
|
||||
// * Default constructor for the ClientAcceptor class
|
||||
// *****************************************************************************
|
||||
ClientAcceptor::ClientAcceptor (cdevSessionManager & s)
|
||||
: server(s)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ClientAcceptor::~ClientAcceptor:
|
||||
// * Destructor for the ClientAcceptor class
|
||||
// *****************************************************************************
|
||||
ClientAcceptor::~ClientAcceptor (void)
|
||||
{
|
||||
if(reactor) reactor->extractHandler(this);
|
||||
handleClose();
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * open:
|
||||
// * Initializes the listening socket
|
||||
// *****************************************************************************
|
||||
int ClientAcceptor::open (const cdevInetAddr &addr)
|
||||
{
|
||||
int result = -1;
|
||||
if (this->acceptor.open (addr, TRUE) == -1)
|
||||
{
|
||||
outputError(CDEV_SEVERITY_SEVERE, (char *)getName(),
|
||||
"Failed to open listening port");
|
||||
}
|
||||
else if (acceptor.setFlags (O_NONBLOCK) == -1)
|
||||
{
|
||||
outputError(CDEV_SEVERITY_ERROR, (char *)getName(),
|
||||
"Could not enable non-blocking I/O");
|
||||
}
|
||||
else result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * getHandle:
|
||||
// * Returns the device descriptor of the listening socket
|
||||
// *****************************************************************************
|
||||
int ClientAcceptor::getHandle (void) const
|
||||
{
|
||||
return acceptor.getHandle ();
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * handleInput:
|
||||
// * Accepts a connection on a listening socket and then creates a
|
||||
// * ClientHandler class to manage the connection.
|
||||
// *****************************************************************************
|
||||
int ClientAcceptor::handleInput (void)
|
||||
{
|
||||
cdevInetAddr addr;
|
||||
ClientHandler *svc_handler = new ClientHandler(server);
|
||||
if (acceptor.accept (*svc_handler, &addr) != -1)
|
||||
{
|
||||
svc_handler->open(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputError(CDEV_SEVERITY_ERROR, (char *)getName(),
|
||||
"Failed to accept connection");
|
||||
}
|
||||
// *********************************************************************
|
||||
// * Always return 0... Otherwise, the accepting socket will
|
||||
// * be destroyed and a crippled server is all that will remain.
|
||||
// *********************************************************************
|
||||
return 0;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * handleClose:
|
||||
// * Closes the listening socket
|
||||
// *****************************************************************************
|
||||
int ClientAcceptor::handleClose (void)
|
||||
{
|
||||
acceptor.close ();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#if !defined (_CLIENT_ACCEPTOR_H)
|
||||
#define _CLIENT_ACCEPTOR_H
|
||||
|
||||
#include "cdevSessionManager.h"
|
||||
|
||||
#include "cdevSocketAcceptor.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// * class ClientAcceptor:
|
||||
// * This class provdies the cdevEventHandler that accepts connections through
|
||||
// * the reactor on the listening port. Once accepted, these new connections
|
||||
// * are serviced by the ClientHandler.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API ClientAcceptor : public cdevEventHandler, public ErrorReporter
|
||||
{
|
||||
friend class ClientHandler;
|
||||
public:
|
||||
ClientAcceptor (cdevSessionManager &s);
|
||||
~ClientAcceptor (void);
|
||||
|
||||
const char *getName (void) { return "ClientAcceptor"; }
|
||||
int getLocalAddress (cdevAddr &addr) { return acceptor.getLocalAddress(addr); }
|
||||
int open (const cdevInetAddr &addr);
|
||||
|
||||
virtual int getHandle (void) const;
|
||||
virtual int handleInput (void);
|
||||
virtual int handleClose (void);
|
||||
|
||||
private:
|
||||
cdevSocketAcceptor acceptor;
|
||||
cdevSessionManager & server;
|
||||
};
|
||||
|
||||
#endif
|
||||
+268
@@ -0,0 +1,268 @@
|
||||
#include "ClientHandler.h"
|
||||
#include "ClientAcceptor.h"
|
||||
#include <clipMagicNumber.h>
|
||||
|
||||
// *****************************************************************************
|
||||
// * ClientHandler:
|
||||
// * Default constructor for the ClientHandler class
|
||||
// *****************************************************************************
|
||||
ClientHandler::ClientHandler (cdevSessionManager & s)
|
||||
: server(s), queue(NULL), clientQuitFlag(0),
|
||||
SocketReader(CLIP_MAGIC_NUMBER), SocketWriter(CLIP_MAGIC_NUMBER),
|
||||
packetsSent(0), packetsRecv(0)
|
||||
{
|
||||
hostName[0] = 0;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * ClientHandler::getHostName:
|
||||
// * This function returns the name of the remote host.
|
||||
// *****************************************************************************
|
||||
char * ClientHandler::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;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * open:
|
||||
// * Initializes the new socket and adds this ClientHandler class to
|
||||
// * the reactor
|
||||
// *****************************************************************************
|
||||
int ClientHandler::open (class ClientAcceptor * )
|
||||
{
|
||||
cdevInetAddr addr;
|
||||
int result = 0;
|
||||
|
||||
if (stream.getRemoteAddress (addr) == -1)
|
||||
{
|
||||
outputError(CDEV_SEVERITY_SEVERE, (char *)getName(),
|
||||
"Couldn't get local address");
|
||||
result = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (server.Reactor.registerHandler (this, READ_MASK|WRITE_MASK|EXCEPT_MASK)!=0)
|
||||
{
|
||||
outputError(CDEV_SEVERITY_SEVERE, (char *)getName(),
|
||||
"Cannot register handler with reactor");
|
||||
result = -1;
|
||||
}
|
||||
else {
|
||||
// *****************************************************
|
||||
// * Get the socket number and use it to identify the
|
||||
// * socket within the cdevSessionManager.
|
||||
// *****************************************************
|
||||
int handle = getHandle();
|
||||
if((queue = server.findSocket(handle))!=NULL)
|
||||
{
|
||||
server.removeSocket(handle);
|
||||
}
|
||||
queue = server.addSocket(handle);
|
||||
|
||||
outputError(CDEV_SEVERITY_INFO, (char *)getName(),
|
||||
"Establishing connection to %s on socket %i",
|
||||
getHostName(), handle);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * getHandle:
|
||||
// * Returns the device descriptor for the underlying socket
|
||||
// *****************************************************************************
|
||||
int ClientHandler::getHandle (void) const
|
||||
{
|
||||
return stream.getHandle ();
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * ~ClientHandler:
|
||||
// * Destructor for the ClientHandler object
|
||||
// *****************************************************************************
|
||||
ClientHandler::~ClientHandler (void)
|
||||
{
|
||||
if(stream.getHandle()>0 && clientQuitFlag==0) writeGoodbye();
|
||||
if(reactor) reactor->extractHandler(this);
|
||||
handleClose();
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * handleClose:
|
||||
// * Removes the object from the reactor class and then deletes it.
|
||||
// *****************************************************************************
|
||||
int ClientHandler::handleClose (void)
|
||||
{
|
||||
outputError(CDEV_SEVERITY_INFO, (char *)getName(),
|
||||
"Terminating connection to %s on socket %i",
|
||||
getHostName(), queue?queue->getSocketID():0);
|
||||
|
||||
stream.close();
|
||||
if(queue)
|
||||
{
|
||||
server.removeSocket(queue->getSocketID());
|
||||
queue = NULL;
|
||||
}
|
||||
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 processIncomingPacket function for processing.
|
||||
// *****************************************************************************
|
||||
int ClientHandler::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)
|
||||
{
|
||||
if(buf==NULL) result = read(&buf, (int *)&len);
|
||||
else result = readNextPacket(&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 buffer object.
|
||||
// *************************************************************
|
||||
default:
|
||||
server.enqueue(getHandle(), buf, len);
|
||||
packetsSent++;
|
||||
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 ClientHandler::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() && queue!=NULL && queue->peek(&buf, &len)==0)
|
||||
{
|
||||
int full = 0;
|
||||
while(!full)
|
||||
{
|
||||
full = writeEnqueue(buf, len);
|
||||
if(!full)
|
||||
{
|
||||
queue->dequeue(&buf, &len);
|
||||
delete buf;
|
||||
buf = NULL;
|
||||
len = 0;
|
||||
if(queue->peek(&buf, &len)!=0) full=-1;
|
||||
packetsRecv++;
|
||||
}
|
||||
}
|
||||
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(retval!=0 || ((queue==NULL || queue->empty()) && !writing()))
|
||||
{
|
||||
setMask(READ_MASK|EXCEPT_MASK);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * Return the value specified by retval.
|
||||
// *****************************************************************************
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * ClientHandler::handleExcept :
|
||||
// * This function is called when out of band data is ready to be received
|
||||
// * from the socket.
|
||||
// *****************************************************************************
|
||||
int ClientHandler::handleExcept(void)
|
||||
{
|
||||
clientQuitFlag=1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
#if !defined (_CLIENT_HANDLER_H)
|
||||
#define _CLIENT_HANDLER_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cdevSessionManager.h"
|
||||
#include "SocketUtil.h"
|
||||
|
||||
#include "cdevSocketStream.h"
|
||||
|
||||
class GENERIC_SERVER_API ClientHandler : public cdevEventHandler, public SocketReader, public SocketWriter
|
||||
{
|
||||
public:
|
||||
ClientHandler (cdevSessionManager & s);
|
||||
~ClientHandler (void);
|
||||
|
||||
char * getHostName (void);
|
||||
const char * getName (void) { return "ClientHandler"; }
|
||||
virtual int open (class ClientAcceptor * acc);
|
||||
virtual int getHandle (void) const;
|
||||
operator cdevSocketStream & (void) { return stream; }
|
||||
|
||||
virtual int handleClose (void);
|
||||
virtual int handleInput (void);
|
||||
virtual int handleOutput (void);
|
||||
virtual int handleExcept (void);
|
||||
|
||||
size_t getPacketsSent (void) { return packetsSent; }
|
||||
size_t getPacketsRecv (void) { return packetsRecv; }
|
||||
|
||||
protected:
|
||||
char hostName[MAXHOSTNAMELEN + 1];
|
||||
cdevSocketStream stream;
|
||||
cdevSessionManager & server;
|
||||
SocketSession * queue;
|
||||
int clientQuitFlag;
|
||||
size_t packetsSent;
|
||||
size_t packetsRecv;
|
||||
};
|
||||
|
||||
#endif /* _CLIENT_HANDLER_H */
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
ARCH = OS
|
||||
SHOBJ = YES
|
||||
|
||||
include ../include/makeinclude/Makefile.$(ARCH)
|
||||
|
||||
APPNAME = "CDEV Generic Server Engine"
|
||||
CXXINCLUDES = -I../include/ace $(ACEINCLUDES)
|
||||
TEMPLINKS = cdevPacket.cc\
|
||||
cdevMessageBinary.cc\
|
||||
cdevMessage.cc\
|
||||
cdevContextMap.cc\
|
||||
cdevTagMap.cc\
|
||||
cdevMonitorTable.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\
|
||||
IntHash.cc
|
||||
|
||||
SERVER_OBJS = $(OBJDIR)/cdevServer.o\
|
||||
$(OBJDIR)/cdevServerTools.o\
|
||||
$(OBJDIR)/cdevSessionManager.o\
|
||||
$(OBJDIR)/ClientHandler.o\
|
||||
$(OBJDIR)/ClientAcceptor.o\
|
||||
$(OBJDIR)/cdevTagMap.o\
|
||||
$(OBJDIR)/cdevMonitorTable.o
|
||||
|
||||
COMMON_OBJS = $(OBJDIR)/cdevPacket.o\
|
||||
$(OBJDIR)/cdevMessageBinary.o\
|
||||
$(OBJDIR)/cdevMessage.o\
|
||||
$(OBJDIR)/cdevContextMap.o\
|
||||
$(OBJDIR)/SignalManager.o\
|
||||
$(OBJDIR)/fifo.o\
|
||||
$(OBJDIR)/IntHash.cc
|
||||
|
||||
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
|
||||
|
||||
# ******************************************************************************
|
||||
# * The BINARIES definition names all of the binary files that should be deleted
|
||||
# * whenever "make clean" is executed.
|
||||
# ******************************************************************************
|
||||
BINARIES = $(BASELIB)/libcdevServer.$(SHARED_EXT) \
|
||||
$(BASELIB)/libcdevServer.a
|
||||
|
||||
ifeq ($(SHOBJ),YES)
|
||||
TARGETS = $(TEMPLINKS) $(BASELIB)/libcdevServer.$(SHARED_EXT)
|
||||
else
|
||||
TARGETS = $(TEMPLINKS) $(BASELIB)/libcdevServer.a
|
||||
endif
|
||||
|
||||
targets : $(TARGETS)
|
||||
|
||||
$(TEMPLINKS) :
|
||||
@cp $^ $@
|
||||
|
||||
$(BASELIB)/libcdevServer.a : $(SERVER_OBJS) $(COMMON_OBJS) $(ACE_OBJS)
|
||||
$(LINK.a) $@ $^
|
||||
@$(RANLIB) $@ > /dev/null
|
||||
@cp $@ $(CDEVLIB)
|
||||
|
||||
$(BASELIB)/libcdevServer.$(SHARED_EXT) : $(SERVER_OBJS) $(COMMON_OBJS) $(ACE_OBJS)
|
||||
$(LINK.so) -o $@ $^ $(NETLIBS)
|
||||
@cp $@ $(CDEVLIB)
|
||||
|
||||
cdevPacket.cc : ../cdevPacket/cdevPacket.cc
|
||||
cdevMessageBinary.cc : ../cdevPacket/cdevMessageBinary.cc
|
||||
cdevMessage.cc : ../cdevPacket/cdevMessage.cc
|
||||
cdevContextMap.cc : ../cdevContextMap/cdevContextMap.cc
|
||||
cdevTagMap.cc : ../cdevTagMap/cdevTagMap.cc
|
||||
cdevMonitorTable.cc : ../cdevMonitorTable/cdevMonitorTable.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
|
||||
IntHash.cc : ../common/IntHash.cc
|
||||
@@ -0,0 +1,149 @@
|
||||
.SUFFIXES: .cc .obj
|
||||
|
||||
APPNAME = CDEV Generic Server Engine
|
||||
ARCH = WINNT-4.0
|
||||
|
||||
TEMPLINKS = cdevPacket.cc\
|
||||
cdevMessageBinary.cc\
|
||||
cdevMessage.cc\
|
||||
cdevContextMap.cc\
|
||||
cdevTagMap.cc\
|
||||
cdevMonitorTable.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)\cdevServer.dll \
|
||||
$(CDEVLIB)\cdevServer.lib \
|
||||
$(TEMPLINKS)
|
||||
|
||||
include ..\include\makeinclude\Makefile.WINNT-4.0
|
||||
|
||||
SERVER_OBJS = $(OBJDIR)\cdevServer.obj\
|
||||
$(OBJDIR)\cdevServerTools.obj\
|
||||
$(OBJDIR)\cdevSessionManager.obj\
|
||||
$(OBJDIR)\ClientHandler.obj\
|
||||
$(OBJDIR)\ClientAcceptor.obj\
|
||||
$(OBJDIR)\cdevTagMap.obj\
|
||||
$(OBJDIR)\cdevMonitorTable.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 = $(SERVER_OBJS) $(COMMON_OBJS) $(ACE_OBJS)
|
||||
|
||||
CXXEXTRA = /D "_CDEV_REACTOR_EXPORTS_=1" /D "_GENERIC_SERVER_EXPORTS_=1"
|
||||
|
||||
!IF "$(SHOBJ)" == "YES"
|
||||
TARGETS = $(TEMPLINKS) $(CDEVLIB)\cdevServer.dll
|
||||
!ELSE
|
||||
TARGETS = $(TEMPLINKS) $(CDEVLIB)\cdevServer.lib
|
||||
!ENDIF
|
||||
|
||||
targets : $(TARGETS)
|
||||
@erase $(TEMPLINKS)
|
||||
|
||||
$(CDEVLIB)\cdevServer.lib : $(OBJS)
|
||||
@echo ^ ^ ^ =^> Linking $(@F)
|
||||
-@if exist $@ erase $@
|
||||
-@if not exist $(@D) mkdir $(@D)
|
||||
@$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\rsvc.lib\
|
||||
$(LINK_LIB_FLAGS) /out:$@ $(OBJS)
|
||||
@echo ^ ^ ^ ^ ^ ^ Done...
|
||||
|
||||
$(CDEVLIB)\cdevServer.dll : $(OBJS)
|
||||
@echo ^ ^ ^ =^> Linking $(@F)
|
||||
-@if exist $@ erase $@
|
||||
-@if not exist $(@D) mkdir $(@D)
|
||||
@$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\rsvc.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)
|
||||
|
||||
cdevTagMap.cc : ..\cdevTagMap\cdevTagMap.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
cdevMonitorTable.cc : ..\cdevMonitorTable\cdevMonitorTable.cc
|
||||
-@$(CREATE_LINK)
|
||||
|
||||
|
||||
+692
@@ -0,0 +1,692 @@
|
||||
#include "cdevServer.h"
|
||||
#include "ClientAcceptor.h"
|
||||
#include "ClientHandler.h"
|
||||
|
||||
sig_atomic_t cdevServer::Finished = 0;
|
||||
SignalManager cdevServer::SigManager;
|
||||
cdevGenericServerTagDef cdevServer::tags;
|
||||
|
||||
// *****************************************************************************
|
||||
// * This function is an interrupt handler that will be executed whenever the
|
||||
// * program receives a SIGINT. When called it will set the finished flag to 1
|
||||
// * and trigger the termination of the program.
|
||||
// *****************************************************************************
|
||||
static void SIGINT_handler (int signo)
|
||||
{
|
||||
cdevServer::Finished = 1;
|
||||
signal(signo, SIGINT_handler);
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::cdevServer :
|
||||
// * This is the constructor for the class. It will post the listening
|
||||
// * socket, establish registration with the name server and record all
|
||||
// * other pertinent information.
|
||||
// *****************************************************************************
|
||||
cdevServer::cdevServer (char * DomainName, char * ServerName, unsigned short Port, double Rate)
|
||||
: cdevSessionManager(),
|
||||
serverName (NULL),
|
||||
acceptor (NULL),
|
||||
timer (NULL),
|
||||
status (UNINITIALIZED),
|
||||
serverInfo (NULL)
|
||||
{
|
||||
// *********************************************************************
|
||||
// * Register the import method for the cdevMessage class with the
|
||||
// * cdevPacket class.
|
||||
// *********************************************************************
|
||||
cdevPacket::registerImportMethod(cdevMessage::CDEV_PACKET_VERSION,
|
||||
cdevMessage::import);
|
||||
|
||||
startServer(DomainName, ServerName, Port, Rate, 0);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::cdevServer :
|
||||
// * This is the do nothing constructor for the class.
|
||||
// *****************************************************************************
|
||||
cdevServer::cdevServer ( void )
|
||||
: cdevSessionManager (),
|
||||
serverName (NULL),
|
||||
acceptor (NULL),
|
||||
timer (NULL),
|
||||
status (UNINITIALIZED),
|
||||
serverInfo (NULL)
|
||||
{
|
||||
// *********************************************************************
|
||||
// * Register the import method for the cdevMessage class with the
|
||||
// * cdevPacket class.
|
||||
// *********************************************************************
|
||||
cdevPacket::registerImportMethod(cdevMessage::CDEV_PACKET_VERSION,
|
||||
cdevMessage::import);
|
||||
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::~cdevServer :
|
||||
// * This is the destructor for the object. It will close all listening
|
||||
// * sockets and will delete all allocated items.
|
||||
// *****************************************************************************
|
||||
cdevServer::~cdevServer ( void )
|
||||
{
|
||||
outputError ( CDEV_SEVERITY_INFO, "CDEV Server",
|
||||
"Server %s is Terminating...",
|
||||
serverName);
|
||||
|
||||
Reactor.extractHandler(this);
|
||||
|
||||
if(timer!=NULL) delete timer;
|
||||
if(serverName!=NULL) delete serverName;
|
||||
if(acceptor!=NULL) delete acceptor;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::startServer :
|
||||
// * This method will initialize a cdevServer within a given name, will
|
||||
// * register it within the CDEV Name Server and will commence listening
|
||||
// * for connections on the specified port.
|
||||
// *****************************************************************************
|
||||
int cdevServer::startServer (char * DomainName, char * ServerName, unsigned short Port, double Rate, int searchForPort)
|
||||
{
|
||||
if(acceptor!=NULL)
|
||||
{
|
||||
delete acceptor;
|
||||
acceptor=NULL;
|
||||
}
|
||||
if(timer)
|
||||
{
|
||||
delete timer;
|
||||
timer=NULL;
|
||||
}
|
||||
if(serverName)
|
||||
{
|
||||
delete serverName;
|
||||
serverName = NULL;
|
||||
}
|
||||
if(serverInfo)
|
||||
{
|
||||
delete serverInfo;
|
||||
serverInfo = NULL;
|
||||
}
|
||||
|
||||
Reactor.extractHandler(this);
|
||||
|
||||
setTimeoutRate(Rate);
|
||||
serverName = strdup(ServerName);
|
||||
status = UNINITIALIZED;
|
||||
acceptor = new ClientAcceptor(*this);
|
||||
|
||||
// *********************************************************************
|
||||
// * Attempt to open the acceptor to receive new connections.
|
||||
// *********************************************************************
|
||||
if(searchForPort) Port = 0;
|
||||
cdevInetAddr addr(Port);
|
||||
int initialized=!(acceptor->open(addr));
|
||||
|
||||
// *********************************************************************
|
||||
// * Call getLocalAddress to retrieve the actual port number that was
|
||||
// * opened. This value will differ from the specified port if...
|
||||
// * 1) the user specified 0 for the port number -or-
|
||||
// * 2) the user set the searchForPort flag to non-zero.
|
||||
// *********************************************************************
|
||||
if(acceptor->getLocalAddress(addr)==0) Port = addr.getPortNum();
|
||||
else Port = (unsigned short)-1;
|
||||
|
||||
// *********************************************************************
|
||||
// * ServerInfo must be created after the port has been searched for
|
||||
// * and found. Otherwise, the server will report the original port
|
||||
// * number rather than the actual port number.
|
||||
// *********************************************************************
|
||||
serverInfo = new ServerInfo(DomainName, ServerName, Port);
|
||||
|
||||
if(initialized)
|
||||
{
|
||||
// *************************************************************
|
||||
// * Register the acceptor with the Reactor.
|
||||
// *************************************************************
|
||||
if(Reactor.registerHandler(acceptor, READ_MASK)!=-1)
|
||||
{
|
||||
// *****************************************************
|
||||
// * Register this event handler with the Reactor.
|
||||
// *****************************************************
|
||||
if(Reactor.registerHandler(this, READ_MASK)!=-1)
|
||||
{
|
||||
// *********************************************
|
||||
// * Schedule the periodic timer if it is
|
||||
// * greater than 0.
|
||||
// *********************************************
|
||||
if(Rate <= 0.0 ||
|
||||
Reactor.registerTimer(this)!=-1)
|
||||
{
|
||||
// *************************************
|
||||
// * Install a name server timer to
|
||||
// * continuously register this server
|
||||
// * with the Name Server.
|
||||
// *************************************
|
||||
timer = new cdevNameServerManager(Reactor, DomainName, ServerName, Port);
|
||||
outputError (CDEV_SEVERITY_INFO, "CDEV Server",
|
||||
"Server %s is operational and servicing requests...",
|
||||
serverName);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputError ( CDEV_SEVERITY_SEVERE, "CDEV Server",
|
||||
"Server %s - Unable to register server timer with cdevReactor",
|
||||
serverName);
|
||||
status = CANT_REGISTER_TIMER;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
outputError ( CDEV_SEVERITY_SEVERE, "CDEV Server",
|
||||
"Server %s - Unable to register server handler with cdevReactor",
|
||||
serverName);
|
||||
status = CANT_REGISTER_SERVER;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
outputError (CDEV_SEVERITY_SEVERE, "CDEV Server",
|
||||
"Server %s - Unable to register listening service with cdevReactor",
|
||||
serverName);
|
||||
status = CANT_REGISTER_LISTENER;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
outputError ( CDEV_SEVERITY_SEVERE, "CDEV Server",
|
||||
"Server %s - Unable to open listening socket",
|
||||
serverName);
|
||||
status = CANT_OPEN_SOCKET;
|
||||
}
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case CANT_REGISTER_TIMER:
|
||||
Reactor.extractHandler(this);
|
||||
|
||||
case CANT_REGISTER_SERVER:
|
||||
Reactor.extractHandler(acceptor);
|
||||
|
||||
case CANT_REGISTER_LISTENER:
|
||||
case CANT_OPEN_SOCKET:
|
||||
delete acceptor;
|
||||
acceptor = NULL;
|
||||
break;
|
||||
|
||||
case SUCCESS:
|
||||
default:
|
||||
status = SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// * cdevServer::runServer :
|
||||
// * This method is called to simultaneously execute all servers that
|
||||
// * reside in the system.
|
||||
// ***************************************************************************
|
||||
void cdevServer::runServer ( void )
|
||||
{
|
||||
SigManager.installDefaults();
|
||||
SigManager.installHandler (SIGINT, SIGINT_handler);
|
||||
while (!Finished) Reactor.handleEvents ();
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::registerClient :
|
||||
// * This is the cdevMessage specific method that is used to send a
|
||||
// * "register" message to the server.
|
||||
// *****************************************************************************
|
||||
void cdevServer::registerClient ( short localID )
|
||||
{
|
||||
cdevMessage message(localID,0,0,0,0,0,0,0,NULL,"register");
|
||||
cdevPacketBinary * packet = new cdevPacketBinary;
|
||||
char * binary;
|
||||
size_t binaryLen;
|
||||
|
||||
message.streamOut (&binary, &binaryLen);
|
||||
packet->attachData(binary, binaryLen);
|
||||
inbound.enqueue (packet);
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::unregisterClient :
|
||||
// * This is the cdevMessage specific method that is used to send an
|
||||
// * "unregister" message to the server.
|
||||
// *****************************************************************************
|
||||
void cdevServer::unregisterClient ( short localID )
|
||||
{
|
||||
cdevMessage message(localID,0,0,0,0,0,0,0,NULL,"unregister");
|
||||
cdevPacketBinary * packet = new cdevPacketBinary;
|
||||
char * binary;
|
||||
size_t binaryLen;
|
||||
|
||||
message.streamOut (&binary, &binaryLen);
|
||||
packet->attachData(binary, binaryLen);
|
||||
inbound.enqueue (packet);
|
||||
trigger.insertEvent();
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::newClientSession :
|
||||
// * This method allows the caller to create a new ClientSession object. The
|
||||
// * ClientSession object functions primarily as a pointer to the queue that
|
||||
// * holds packets destined for a specific client, however, the developer
|
||||
// * can create a subclass of the ClientSession that may be used to associate
|
||||
// * additional, client specific information to the structure.
|
||||
// *
|
||||
// * The CLIPClientSession class allows the developer to associate a context
|
||||
// * with the clientID.
|
||||
// *****************************************************************************
|
||||
ClientSession * cdevServer::newClientSession ( int SocketID, int ClientID, int LocalID )
|
||||
{
|
||||
return new CLIPClientSession (SocketID, ClientID, LocalID);
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::newSocketSession :
|
||||
// * This method allows the caller to create a new SocketSession object. The
|
||||
// * SocketSession object functions primarily as a pointer to the queue that
|
||||
// * holds packets destined for a specific socket, however, the developer
|
||||
// * can create a subclass of the SocketSession that may be used to associate
|
||||
// * additional, socket specific information to the structure.
|
||||
// *
|
||||
// * The CLIPSocketSession class allows the developer to associate a
|
||||
// * context map and a tag table with the socket number.
|
||||
// *****************************************************************************
|
||||
SocketSession * cdevServer::newSocketSession ( int SocketID )
|
||||
{
|
||||
if(serverInfo) serverInfo->clientCnt++;
|
||||
|
||||
return new CLIPSocketSession (SocketID);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::deleteSocketSession :
|
||||
// * This method is called to delete an existing socket session.
|
||||
// *****************************************************************************
|
||||
void cdevServer::deleteSocketSession ( SocketSession *socket )
|
||||
{
|
||||
if(socket)
|
||||
{
|
||||
if(serverInfo)
|
||||
{
|
||||
if(serverInfo->clientCnt>0) serverInfo->clientCnt--;
|
||||
else serverInfo->clientCnt=0;
|
||||
}
|
||||
|
||||
sockets.remove(socket->getSocketID());
|
||||
delete socket;
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::dequeue :
|
||||
// * This method provides a mechanism for the cdevServer object to only
|
||||
// * dequeue packets that are of the type cdevMessage.
|
||||
// *****************************************************************************
|
||||
int cdevServer::dequeue ( cdevMessage * &message )
|
||||
{
|
||||
cdevPacket * packet = NULL;
|
||||
|
||||
while(packet==NULL && cdevSessionManager::dequeue(packet)==0)
|
||||
{
|
||||
if(packet->getVersion()!=cdevMessage::CDEV_PACKET_VERSION)
|
||||
{
|
||||
delete packet;
|
||||
packet = NULL;
|
||||
}
|
||||
else if(((cdevMessage *)packet)->getOperationCode()==CDEV_SERVER_OP)
|
||||
{
|
||||
processLocal((cdevMessage * &)packet);
|
||||
delete packet;
|
||||
packet = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
message = (cdevMessage *)packet;
|
||||
return message==NULL?-1:0;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::processLocal :
|
||||
// * This method is called to process requests that are being transmitted
|
||||
// * directly to the cdev Generic Server Engine to set or retrieve statistics
|
||||
// * about the operation of the server or its clients.
|
||||
// *****************************************************************************
|
||||
void cdevServer::processLocal ( cdevMessage * & message )
|
||||
{
|
||||
CLIPClientSession * client = NULL;
|
||||
CLIPSocketSession * socket = NULL;
|
||||
|
||||
if((client = (CLIPClientSession *)findLocalClient(message->getClientID()))!=NULL)
|
||||
{
|
||||
socket = (CLIPSocketSession *)findSocket(client->getSocketID());
|
||||
}
|
||||
if(!strcmp(message->getMessage(), "set ClientInfo"))
|
||||
{
|
||||
cdevData * data = message->getData();
|
||||
if(data && socket) socket->updateClientInfo(*data);
|
||||
}
|
||||
else if(!strcmp(message->getMessage(), "get ServerInfo"))
|
||||
{
|
||||
if(serverInfo)
|
||||
{
|
||||
message->setOperationCode(CDEV_NORMAL_OP);
|
||||
message->setData(&serverInfo->getServerData(), 1);
|
||||
}
|
||||
else {
|
||||
message->setOperationCode(CDEV_NORMAL_OP);
|
||||
message->setCompletionCode(-1);
|
||||
}
|
||||
enqueue(message);
|
||||
}
|
||||
else if(!strcmp(message->getMessage(), "get ClientInfo"))
|
||||
{
|
||||
IntHashIterator iter(&sockets);
|
||||
ClientHandler * handler = NULL;
|
||||
int socketCnt = 0;
|
||||
int index = 0;
|
||||
cdevData result;
|
||||
|
||||
iter.first();
|
||||
while(iter.data()!=NULL)
|
||||
{
|
||||
iter++;
|
||||
socketCnt++;
|
||||
}
|
||||
if(socketCnt)
|
||||
{
|
||||
char ** username = new char *[socketCnt];
|
||||
char ** group = new char *[socketCnt];
|
||||
unsigned * uid = new unsigned [socketCnt];
|
||||
unsigned * gid = new unsigned [socketCnt];
|
||||
unsigned * pid = new unsigned [socketCnt];
|
||||
char ** program = new char *[socketCnt];
|
||||
char ** commandline = new char *[socketCnt];
|
||||
unsigned * starttime = new unsigned [socketCnt];
|
||||
unsigned * connecttime = new unsigned [socketCnt];
|
||||
char ** host = new char *[socketCnt];
|
||||
char ** os = new char *[socketCnt];
|
||||
char ** osrelease = new char *[socketCnt];
|
||||
char ** osversion = new char *[socketCnt];
|
||||
char ** machine = new char *[socketCnt];
|
||||
char ** shell = new char *[socketCnt];
|
||||
unsigned * socketNum = new unsigned[socketCnt];
|
||||
unsigned * sendPktCnt = new unsigned[socketCnt];
|
||||
unsigned * recvPktCnt = new unsigned[socketCnt];
|
||||
|
||||
iter.first();
|
||||
while(index<socketCnt && (socket = (CLIPSocketSession *)iter.data())!=NULL)
|
||||
{
|
||||
username[index] = socket->getUsername();
|
||||
group[index] = socket->getGroup();
|
||||
uid[index] = socket->getUid();
|
||||
gid[index] = socket->getGid();
|
||||
pid[index] = socket->getPid();
|
||||
program[index] = socket->getProgram();
|
||||
commandline[index] = socket->getCommandLine();
|
||||
starttime[index] = (unsigned)socket->getStartTime();
|
||||
connecttime[index] = (unsigned)socket->getConnectTime();
|
||||
host[index] = socket->getHost();
|
||||
os[index] = socket->getOs();
|
||||
osrelease[index] = socket->getOsRelease();
|
||||
osversion[index] = socket->getOsVersion();
|
||||
machine[index] = socket->getMachine();
|
||||
shell[index] = socket->getShell();
|
||||
socketNum[index] = socket->getSocketID();
|
||||
if(Reactor.getHandler(socketNum[index], (cdevEventHandler *&)handler)==0)
|
||||
{
|
||||
sendPktCnt[index] = handler->getPacketsSent();
|
||||
recvPktCnt[index] = handler->getPacketsRecv();
|
||||
}
|
||||
else {
|
||||
sendPktCnt[index] = 0;
|
||||
recvPktCnt[index] = 0;
|
||||
}
|
||||
index++;
|
||||
iter++;
|
||||
}
|
||||
|
||||
result.insert("username", username, socketCnt); delete username;
|
||||
result.insert("group", group, socketCnt); delete group;
|
||||
result.insert("uid", uid, socketCnt); delete uid;
|
||||
result.insert("gid", gid, socketCnt); delete gid;
|
||||
result.insert("pid", pid, socketCnt); delete pid;
|
||||
result.insert("program", program, socketCnt); delete program;
|
||||
result.insert("commandline", commandline, socketCnt); delete commandline;
|
||||
result.insert("starttime", starttime, socketCnt); delete starttime;
|
||||
result.insert("connecttime", connecttime, socketCnt); delete connecttime;
|
||||
result.insert("host", host, socketCnt); delete host;
|
||||
result.insert("os", os, socketCnt); delete os;
|
||||
result.insert("osrelease", osrelease, socketCnt); delete osrelease;
|
||||
result.insert("osversion", osversion, socketCnt); delete osversion;
|
||||
result.insert("machine", machine, socketCnt); delete machine;
|
||||
result.insert("shell", shell, socketCnt); delete shell;
|
||||
result.insert("socket", socketNum, socketCnt); delete socketNum;
|
||||
result.insert("sendPktCnt", sendPktCnt, socketCnt); delete sendPktCnt;
|
||||
result.insert("recvPktCnt", recvPktCnt, socketCnt); delete recvPktCnt;
|
||||
}
|
||||
message->setOperationCode(CDEV_NORMAL_OP);
|
||||
message->setData(&result, 1);
|
||||
enqueue(message);
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::decodePacket :
|
||||
// * This method is used to perform preprocessing on a newly dequeued binary
|
||||
// * packet before it is provided to the caller. This method allows the
|
||||
// * developer to perform special preparations on the packet before providing
|
||||
// * it to the caller.
|
||||
// *****************************************************************************
|
||||
cdevPacket * cdevServer::decodePacket( cdevPacketBinary * input )
|
||||
{
|
||||
cdevPacket * packet = NULL;
|
||||
|
||||
if(input!=NULL)
|
||||
{
|
||||
short version;
|
||||
input->getVersion(version);
|
||||
switch (version)
|
||||
{
|
||||
// *****************************************************
|
||||
// * If it is a cdevMessage object, I want to call the
|
||||
// * cdevMessage specific decodePacket method.
|
||||
// *****************************************************
|
||||
case cdevMessage::CDEV_PACKET_VERSION:
|
||||
packet = decodePacket ((cdevMessage *)cdevPacket::import(*input));
|
||||
break;
|
||||
|
||||
// *****************************************************
|
||||
// * Use the cdevSessionManager::decodePacket method
|
||||
// * to handle any other type of packet.
|
||||
// *****************************************************
|
||||
default:
|
||||
packet = cdevSessionManager::decodePacket(input);
|
||||
break;
|
||||
}
|
||||
if(serverInfo) serverInfo->recvPktCnt++;
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::decodePacket :
|
||||
// * This decodePacket method is designed specifically to preprocess the
|
||||
// * data associated with a cdevMessage object.
|
||||
// *****************************************************************************
|
||||
cdevPacket * cdevServer::decodePacket (cdevMessage * message )
|
||||
{
|
||||
CLIPClientSession * client = NULL;
|
||||
CLIPSocketSession * socket = NULL;
|
||||
|
||||
if(message!=NULL &&
|
||||
(client = (CLIPClientSession *)findLocalClient(message->getClientID()))!=NULL &&
|
||||
(socket = (CLIPSocketSession *)findSocket(client->getSocketID()))!=NULL)
|
||||
{
|
||||
// *************************************************************
|
||||
// * If a tagMap has been provided... use it to update
|
||||
// * the tagMap stored in the SocketSession object.
|
||||
// *************************************************************
|
||||
if(message->getTagMap()!=NULL)
|
||||
{
|
||||
socket->TagMap().updateTagMap(*message->getTagMap());
|
||||
message->setTagMap(NULL);
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
// * Pass the data and context objects through the tag map to
|
||||
// * convert their tags from the remote integers to the local
|
||||
// * integers.
|
||||
// *************************************************************
|
||||
if(message->getData()!=NULL)
|
||||
socket->TagMap().remoteToLocal(*message->getData());
|
||||
if(message->getContext()!=NULL)
|
||||
socket->TagMap().remoteToLocal(*message->getContext());
|
||||
|
||||
// *************************************************************
|
||||
// * If a context has been provided by the client side
|
||||
// * of the connection - perform the following steps...
|
||||
// *
|
||||
// * 1) Add the context to the cdevContextMap for this
|
||||
// * socketID if it does not already exist, and
|
||||
// * obtain the index that identifies the new
|
||||
// * context.
|
||||
// *
|
||||
// * 2) Delete the context from within the message.
|
||||
// *
|
||||
// * 3) Set the context within the message to the
|
||||
// * current context that is specified in the
|
||||
// * ClientSession object.
|
||||
// *
|
||||
// * 4) Set the saveContext flag in the message to
|
||||
// * prevent its inadvertant destruction when the
|
||||
// * message is deleted.
|
||||
// *************************************************************
|
||||
if(message->getContext()!=NULL)
|
||||
{
|
||||
cdevData * lastContext = client->getContext();
|
||||
if(lastContext==NULL || *lastContext!=*message->getContext())
|
||||
{
|
||||
int contextID = socket->ContextMap().insert(*message->getContext());
|
||||
client->setContext(socket->ContextMap().find(contextID));
|
||||
}
|
||||
}
|
||||
message->setContext(client->getContext(), 1);
|
||||
|
||||
// *************************************************************
|
||||
// * Toggle the local and foreign data indices.
|
||||
// *************************************************************
|
||||
unsigned int index = message->getForeignDataIndex();
|
||||
message->setForeignDataIndex(message->getLocalDataIndex());
|
||||
message->setLocalDataIndex (index);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::encodePacket :
|
||||
// * This method is used to perform postprocessing on a packet that has been
|
||||
// * enqueued to be sent to a client. This method allows the developer to
|
||||
// * perform special preparations on the packet before providing it to the
|
||||
// * client.
|
||||
// *****************************************************************************
|
||||
cdevPacketBinary * cdevServer::encodePacket ( cdevPacket * input )
|
||||
{
|
||||
cdevPacketBinary * packet = NULL;
|
||||
|
||||
if(input!=NULL)
|
||||
{
|
||||
switch(input->getVersion())
|
||||
{
|
||||
case cdevMessage::CDEV_PACKET_VERSION:
|
||||
packet = encodePacket ((cdevMessage *)input);
|
||||
break;
|
||||
|
||||
default:
|
||||
packet = cdevSessionManager::encodePacket(input);
|
||||
break;
|
||||
}
|
||||
if(serverInfo) serverInfo->sendPktCnt++;
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::encodePacket :
|
||||
// * This encodePacket method is designed specifically to postprocess the
|
||||
// * data associated with a cdevMessage object.
|
||||
// *****************************************************************************
|
||||
cdevPacketBinary * cdevServer::encodePacket (cdevMessage * message )
|
||||
{
|
||||
cdevPacketBinary * result = NULL;
|
||||
CLIPClientSession * client = NULL;
|
||||
CLIPSocketSession * socket = NULL;
|
||||
|
||||
if(message!=NULL &&
|
||||
message->getClientID()>0 &&
|
||||
message->getTransIndex()>0 &&
|
||||
(client = (CLIPClientSession *)findLocalClient(message->getClientID()))!=NULL &&
|
||||
(socket = (CLIPSocketSession *)findSocket(client->getSocketID()))!=NULL)
|
||||
{
|
||||
char * binary = NULL;
|
||||
size_t binaryLen = 0;
|
||||
static cdevMessage outBound;
|
||||
|
||||
// *************************************************************
|
||||
// * Remap the data to its foreign design.
|
||||
// *************************************************************
|
||||
if(message->getData()!=NULL)
|
||||
socket->TagMap().localToRemote(*message->getData());
|
||||
|
||||
// *************************************************************
|
||||
// * Transfer the critical data items into the class. Note that
|
||||
// * we are not returning the deviceList, message, context,
|
||||
// * cancelTransIndex, or operationCode with the return packet.
|
||||
// *
|
||||
// * Also note that the cdevData object is marked as permanent
|
||||
// * and is using a pointer to the same cdevData object that is
|
||||
// * in the message object.
|
||||
// *************************************************************
|
||||
outBound.clear();
|
||||
outBound.setClientID (client->getClientID()&0xFFFF);
|
||||
outBound.setTransIndex (message->getTransIndex());
|
||||
outBound.setLocalDataIndex (message->getForeignDataIndex());
|
||||
outBound.setForeignDataIndex (message->getLocalDataIndex());
|
||||
outBound.setOperationCode (message->getOperationCode());
|
||||
outBound.setCompletionCode (message->getCompletionCode());
|
||||
outBound.setData (message->getData(), 1);
|
||||
|
||||
// *************************************************************
|
||||
// * Create a binary stream from the cdevMessage object and then
|
||||
// * place it into the outbound queue system.
|
||||
// *************************************************************
|
||||
outBound.streamOut(&binary, &binaryLen);
|
||||
outBound.clear ();
|
||||
|
||||
result = new cdevPacketBinary;
|
||||
result->attachData(binary, binaryLen);
|
||||
|
||||
// *************************************************************
|
||||
// * Remap the data to its local design.
|
||||
// *************************************************************
|
||||
if(message->getData()!=NULL)
|
||||
socket->TagMap().remoteToLocal(*message->getData());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
#if !defined (_CDEV_SERVER_H_)
|
||||
#define _CDEV_SERVER_H_
|
||||
|
||||
#include "SignalManager.h"
|
||||
#include "cdevServerTools.h"
|
||||
#include "cdevMessage.h"
|
||||
#include "cdevContextMap.h"
|
||||
#include "cdevTagMap.h"
|
||||
#include "ClientInfo.h"
|
||||
#include "ServerInfo.h"
|
||||
#include "cdevGenericServerTags.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// * class CLIPClientSession :
|
||||
// *
|
||||
// * This class also allows the server to associate certain data with a
|
||||
// * specific client...
|
||||
// *
|
||||
// * context: This is a pointer to the most recently used context from the
|
||||
// * cdevContextMap.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API CLIPClientSession : public ClientSession
|
||||
{
|
||||
private:
|
||||
cdevData *context;
|
||||
|
||||
public:
|
||||
CLIPClientSession ( int SocketID, int ClientID, int LocalID )
|
||||
: ClientSession(SocketID, ClientID, LocalID),
|
||||
context(NULL)
|
||||
{
|
||||
}
|
||||
virtual ~CLIPClientSession ( void ) { }
|
||||
cdevData * getContext ( void ) { return context; }
|
||||
void setContext ( cdevData * cxt ) { context = cxt; }
|
||||
};
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * class CLIPSocketSession :
|
||||
// *
|
||||
// * This class allows the developer to associate additional information with
|
||||
// * a particular socket...
|
||||
// *
|
||||
// * contextMap : a table of cdevData contexts that can be retrieved by index
|
||||
// *
|
||||
// * tagMap : the table for mapping cdevData tags from the remote system
|
||||
// * to the tag table associated with this system.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API CLIPSocketSession : public SocketSession, public ClientInfoStruct
|
||||
{
|
||||
private:
|
||||
cdevContextMap contextMap;
|
||||
cdevTagMap tagMap;
|
||||
|
||||
public:
|
||||
CLIPSocketSession ( int SocketID )
|
||||
: SocketSession ( SocketID )
|
||||
{
|
||||
}
|
||||
virtual ~CLIPSocketSession ( void ) { }
|
||||
cdevContextMap & ContextMap ( void ) { return contextMap; }
|
||||
cdevTagMap & TagMap ( void ) { return tagMap; }
|
||||
};
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer :
|
||||
// * This is the cdevServer class. It is responsible for establishing a
|
||||
// * listening socket, and then responding to all incoming and outgoing
|
||||
// * messages.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API cdevServer : public cdevSessionManager
|
||||
{
|
||||
public:
|
||||
typedef enum { SUCCESS = 0,
|
||||
UNINITIALIZED,
|
||||
CANT_OPEN_SOCKET,
|
||||
CANT_REGISTER_LISTENER,
|
||||
CANT_REGISTER_SERVER,
|
||||
CANT_REGISTER_TIMER
|
||||
} ServerInitStatus;
|
||||
|
||||
protected:
|
||||
char * serverName;
|
||||
class ClientAcceptor * acceptor;
|
||||
cdevNameServerManager * timer;
|
||||
ServerInitStatus status;
|
||||
ServerInfo * serverInfo;
|
||||
|
||||
public:
|
||||
static cdevGenericServerTagDef tags;
|
||||
static SignalManager SigManager;
|
||||
static sig_atomic_t Finished;
|
||||
|
||||
static void runServer (void);
|
||||
|
||||
cdevServer (char * DomainName, char * ServerName, unsigned short Port, double Rate);
|
||||
cdevServer (void);
|
||||
virtual ~cdevServer (void);
|
||||
int startServer (char * DomainName, char * ServerName, unsigned short Port, double Rate, int searchForPort=0);
|
||||
|
||||
virtual void registerClient ( short localID );
|
||||
virtual void unregisterClient ( short localID );
|
||||
|
||||
virtual ClientSession * newClientSession ( int SocketID, int ClientID, int LocalID );
|
||||
virtual SocketSession * newSocketSession ( int SocketID );
|
||||
virtual void deleteSocketSession ( SocketSession *socket );
|
||||
|
||||
virtual int dequeue (cdevMessage * &message);
|
||||
void processLocal (cdevMessage * &message);
|
||||
virtual cdevPacket * decodePacket (cdevPacketBinary * input);
|
||||
virtual cdevPacket * decodePacket (cdevMessage * message);
|
||||
virtual cdevPacketBinary * encodePacket (cdevPacket * input);
|
||||
virtual cdevPacketBinary * encodePacket (cdevMessage * message);
|
||||
virtual int operational (void) { return (status==0)?1:0; }
|
||||
virtual ServerInitStatus getInitStatus(void) { return status; }
|
||||
};
|
||||
|
||||
#endif /* _CDEV_SERVER_H_ */
|
||||
+403
@@ -0,0 +1,403 @@
|
||||
#include "cdevServerTools.h"
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// cdevSimpleTimer::cdevSimpleTimer :
|
||||
// Constructor.
|
||||
// ****************************************************************************
|
||||
cdevSimpleTimer::cdevSimpleTimer ( cdevReactor & Reactor, double Rate)
|
||||
{
|
||||
setTimeoutRate(Rate);
|
||||
if(Reactor.registerTimer (this) == -1)
|
||||
{
|
||||
outputError ( CDEV_SEVERITY_SEVERE, "cdevSimpleTimer",
|
||||
"Unable to register timer with cdevReactor");
|
||||
}
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// cdevSimpleTimer::~cdevSimpleTimer :
|
||||
// Destructor.
|
||||
// ****************************************************************************
|
||||
cdevSimpleTimer::~cdevSimpleTimer ( void )
|
||||
{
|
||||
if(reactor) reactor->extractHandler(this);
|
||||
handleClose();
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// cdevSimpleTimer::handle_timeout :
|
||||
// Called when the timer expires.
|
||||
// ****************************************************************************
|
||||
int cdevSimpleTimer::handleTimeout(void)
|
||||
{
|
||||
return execute();
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevNameServerManager::cdevNameServerManager :
|
||||
// * This method will read the CDEV_NAME_SERVER environment variable to
|
||||
// * obtain a list of one or more cdev name servers that should be notified
|
||||
// * that this server is operational. The class will create a
|
||||
// * cdevNameServerHandler event handler to manage the connection to each of
|
||||
// * the specified name servers. If a connection is lost to one of the
|
||||
// * name servers, the cdevNameServerManager will attempt periodically to
|
||||
// * reconnect to the specific name server.
|
||||
// *****************************************************************************
|
||||
cdevNameServerManager::cdevNameServerManager ( cdevReactor & Reactor,
|
||||
char * DomainName,
|
||||
char * ServerName,
|
||||
unsigned short ServerPort )
|
||||
: domainName(strdup(DomainName)),
|
||||
serverName(strdup(ServerName)),
|
||||
serverPort(ServerPort),
|
||||
nameServerList(NULL),
|
||||
nameServerHandlers(NULL),
|
||||
nameServerCnt(0)
|
||||
{
|
||||
// *********************************************************************
|
||||
// * Prior to establishing any connections, the class must first install
|
||||
// * all of the necessary data into the serverInfo and updateInfo
|
||||
// * objects.
|
||||
// *********************************************************************
|
||||
char * userName = getenv("USER");
|
||||
char hostname[255];
|
||||
struct hostent * hostPtr;
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday (&tv);
|
||||
gethostname(hostname, 255);
|
||||
hostPtr = gethostbyname(hostname);
|
||||
|
||||
serverInfo.insert ("name", serverName);
|
||||
serverInfo.insert ("domain", domainName);
|
||||
serverInfo.insert ("host", (char *)hostPtr->h_name);
|
||||
serverInfo.insert ("owner", userName?userName:(char *)"UNKNOWN");
|
||||
serverInfo.insert ("time", (long)tv.tv_sec);
|
||||
serverInfo.insert ("port", (long)serverPort);
|
||||
serverInfo.insert ("pid", getpid ());
|
||||
updateInfo.insert ("name", serverName);
|
||||
updateInfo.insert ("domain", domainName);
|
||||
|
||||
// *********************************************************************
|
||||
// * First obtain a list of name servers from the CDEV_NAME_SERVER
|
||||
// * environment variable. If this list is empty, then report an
|
||||
// * error once and then never call the handler again.
|
||||
// *********************************************************************
|
||||
char * nsList = getenv("CDEV_NAME_SERVER");
|
||||
int idx;
|
||||
int length;
|
||||
|
||||
if(nsList!=NULL)
|
||||
{
|
||||
char * nsPtr = nsList;
|
||||
char * endPtr = nsList;
|
||||
|
||||
// *************************************************************
|
||||
// * Determine the number of name servers that have been
|
||||
// * defined in the CDEV_NAME_SERVER environment variable.
|
||||
// *************************************************************
|
||||
while(*nsPtr==':' && *nsPtr!=0) nsPtr++;
|
||||
if(*nsPtr!=0)
|
||||
{
|
||||
nameServerCnt = 1;
|
||||
while(nsPtr!=NULL && *nsPtr!=0)
|
||||
{
|
||||
if((nsPtr = strchr(nsPtr, ':'))!=NULL)
|
||||
{
|
||||
while(*(++nsPtr)==':' && *nsPtr!=0);
|
||||
if(*nsPtr!=0) nameServerCnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
// * Copy each of the defined cdev name server host names into
|
||||
// * the nameServerList.
|
||||
// *************************************************************
|
||||
if(nameServerCnt>0)
|
||||
{
|
||||
nameServerList = new char *[nameServerCnt];
|
||||
nameServerHandlers = new cdevNameServerHandler *[nameServerCnt];
|
||||
|
||||
for(nsPtr = nsList, idx=0; idx<nameServerCnt && *nsPtr!=0; idx++)
|
||||
{
|
||||
while(*nsPtr==':' && *nsPtr!=0) nsPtr++;
|
||||
for(endPtr=nsPtr; *endPtr && *endPtr!=':'; endPtr++);
|
||||
length = endPtr-nsPtr;
|
||||
|
||||
nameServerList[idx] = new char[length+1];
|
||||
strncpy(nameServerList[idx], nsPtr, length);
|
||||
nameServerList[idx][length] = 0;
|
||||
nsPtr = endPtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *********************************************************************
|
||||
// * If no cdev name servers have been defined in the cdev name server
|
||||
// * list, print a warning message.
|
||||
// ********************************************************************
|
||||
if(nameServerCnt<=0)
|
||||
{
|
||||
outputError(CDEV_SEVERITY_WARN, "CDEV Name Server Manager",
|
||||
"\n%s\n%s\n%s",
|
||||
" => No name servers have been specified in the CDEV_NAME_SERVER",
|
||||
" => environment variable.",
|
||||
" => This server WILL NOT be registered with any name servers...");
|
||||
}
|
||||
// *********************************************************************
|
||||
// * Otherwise, set all of the cdevNameServerHandler pointers to NULL
|
||||
// * so that they will be connected when the execute timeout method
|
||||
// * is called.
|
||||
// *********************************************************************
|
||||
else {
|
||||
for(idx=0; idx<nameServerCnt; idx++)
|
||||
{
|
||||
nameServerHandlers[idx] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// *********************************************************************
|
||||
// * Register this class with the cdevReactor so that it will be called
|
||||
// * every thirty seconds. If any of the cdevNameServerHandlers have
|
||||
// * become disconnected, it will attempt to reestablish the connection
|
||||
// * at that time.
|
||||
// *********************************************************************
|
||||
setTimeoutRate(15.0);
|
||||
Reactor.registerTimer(this);
|
||||
handleTimeout();
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevNameServerManager::~cdevNameServerManager :
|
||||
// * This is the destructor for the cdevNameServerManager class. When called
|
||||
// * it will remove and delete any cdevNameServerHandlers that have been
|
||||
// * registered with the cdevReactor.
|
||||
// *****************************************************************************
|
||||
cdevNameServerManager::~cdevNameServerManager ( void )
|
||||
{
|
||||
int idx;
|
||||
|
||||
for(idx = 0; idx<nameServerCnt; idx++)
|
||||
{
|
||||
if(nameServerHandlers[idx]!=0) delete nameServerHandlers[idx];
|
||||
if(nameServerList[idx]!=NULL) delete nameServerList[idx];
|
||||
}
|
||||
if(nameServerList!=NULL) delete nameServerList;
|
||||
if(nameServerHandlers!=NULL) delete nameServerHandlers;
|
||||
if(domainName!=NULL) delete domainName;
|
||||
if(serverName!=NULL) delete serverName;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevNameServerManager::handleTimeout :
|
||||
// * This method will be called every thirty seconds to make sure that all
|
||||
// * connections to the cdev name servers are established. If a
|
||||
// * cdevNameServerHandler has become disconnected, this method will attempt
|
||||
// * to reconnect to the specified handler.
|
||||
// *****************************************************************************
|
||||
int cdevNameServerManager::handleTimeout ( void )
|
||||
{
|
||||
int idx;
|
||||
for(idx=0; idx<nameServerCnt; idx++)
|
||||
{
|
||||
if(nameServerHandlers[idx]==NULL &&
|
||||
nameServerList[idx]!=NULL)
|
||||
{
|
||||
int error = 0;
|
||||
rsvcClient * client = new rsvcClient;
|
||||
rsvcUdpClient * udpClient = new rsvcUdpClient;
|
||||
if(client->connect(nameServerList[idx], RSVC_SERVER_PORT, 2.0)!=RSVC_SUCCESS)
|
||||
{
|
||||
outputError ( CDEV_SEVERITY_ERROR, "CDEV Name Server Manager",
|
||||
"Failed to connect to name server on host %s",
|
||||
nameServerList[idx]);
|
||||
error = -1;
|
||||
}
|
||||
else if(udpClient->connect(nameServerList[idx], RSVC_SERVER_PORT+1024)!=RSVC_SUCCESS)
|
||||
{
|
||||
outputError ( CDEV_SEVERITY_ERROR, "CDEV Name Server Manager",
|
||||
"Failed to open UDP port to name server on host %s",
|
||||
nameServerList[idx]);
|
||||
error = -1;
|
||||
}
|
||||
else if(client->insertValue ("cdevServers", serverInfo, rsvcCallback, nameServerList[idx], 1)!=RSVC_SUCCESS)
|
||||
{
|
||||
outputError ( CDEV_SEVERITY_ERROR, "CDEV Name Server Manager",
|
||||
"Error transmitting to name server on host %s",
|
||||
nameServerList[idx]);
|
||||
error = -1;
|
||||
}
|
||||
|
||||
if(!error) nameServerHandlers[idx] = new cdevNameServerHandler(*this, *reactor, idx, client, udpClient);
|
||||
else {
|
||||
client->disconnect();
|
||||
udpClient->disconnect();
|
||||
delete client;
|
||||
delete udpClient;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevNameServerManager::unregisterHandler:
|
||||
// * This method is called whenever a cdevNameServerHandler needs to
|
||||
// * unregister itself from the cdevNameServerManager. The handlers index
|
||||
// * will be set to 0 and the connection will be reestablished the next time
|
||||
// * the handleTimeout method is called.
|
||||
// *****************************************************************************
|
||||
void cdevNameServerManager::unregisterHandler ( size_t index )
|
||||
{
|
||||
if(index < nameServerCnt) nameServerHandlers[index] = NULL;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevNameServerManager::rsvcCallback :
|
||||
// * This is the method that is called when the register server method
|
||||
// * is executed.
|
||||
// *****************************************************************************
|
||||
void cdevNameServerManager::rsvcCallback (int status, void* arg, rsvcData* /* data */)
|
||||
{
|
||||
char * nameServer = (char *)arg;
|
||||
|
||||
if (status != RSVC_SUCCESS)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
fprintf(stderr, "CDEV Name Server Manager Error: %s %s\n",
|
||||
"Failed to register with name server on host",
|
||||
nameServer?nameServer:"UNKNOWN");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevNameServerHandler::cdevNameServerHandler :
|
||||
// * This is the constructor for the cdevNameServerHandler class. It is
|
||||
// * called by the cdevNameServerManager when a new cdevNameServerHandler
|
||||
// * must be created to communicate with a name server. The connected
|
||||
// * rsvcClient and rsvcUdpClient objects are provided to the class.
|
||||
// ******************************************************************************
|
||||
cdevNameServerHandler::cdevNameServerHandler ( cdevNameServerManager & Manager,
|
||||
cdevReactor & Reactor,
|
||||
int index,
|
||||
rsvcClient * tcpClient,
|
||||
rsvcUdpClient * udpClient )
|
||||
: nameServerTCP(tcpClient), nameServerUDP(udpClient),
|
||||
nameServerIndex(index), nameServerManager(Manager)
|
||||
{
|
||||
setTimeoutRate(5.0);
|
||||
setMask(WRITE_MASK);
|
||||
Reactor.registerHandler(this, WRITE_MASK);
|
||||
Reactor.registerTimer (this);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevNameServerHandler::~cdevNameServerHandler :
|
||||
// * This is the destructor for the class. this method is responsible for
|
||||
// * disconnecting and closing the tcp and udp client connections and
|
||||
// * sending notification to the cdevNameServerManager that it is
|
||||
// * terminating.
|
||||
// *****************************************************************************
|
||||
cdevNameServerHandler::~cdevNameServerHandler ( void )
|
||||
{
|
||||
nameServerTCP->disconnect();
|
||||
nameServerUDP->disconnect();
|
||||
delete nameServerTCP;
|
||||
delete nameServerUDP;
|
||||
if(reactor) reactor->extractHandler(this);
|
||||
nameServerManager.unregisterHandler(nameServerIndex);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevNameServerHandler::handleInput :
|
||||
// * This method is called whenever data is ready to be read from the
|
||||
// * nameServerTCP rsvcClient connection.
|
||||
// *****************************************************************************
|
||||
int cdevNameServerHandler::handleInput ( void )
|
||||
{
|
||||
return (nameServerTCP->pendIO()==RSVC_IOERROR)?-1:0;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevNameServerHandler::handleOutput :
|
||||
// * This method is called whenever data is ready to be written to the
|
||||
// * nameServerTCP rsvcClient connection.
|
||||
// *****************************************************************************
|
||||
int cdevNameServerHandler::handleOutput ( void )
|
||||
{
|
||||
setMask(READ_MASK);
|
||||
return (nameServerTCP->pendIO()==RSVC_IOERROR)?-1:0;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevNameServerHandler::handleTimeout :
|
||||
// * This method is called every five seconds to allow the object to emit
|
||||
// * a UDP packet to the name server to notify it that the server is alive.
|
||||
// *****************************************************************************
|
||||
int cdevNameServerHandler::handleTimeout ( void )
|
||||
{
|
||||
if(nameServerUDP->update(*nameServerManager.getUpdateInfo())!=RSVC_SUCCESS)
|
||||
{
|
||||
outputError(CDEV_SEVERITY_ERROR, "CDEV Name Server Handler",
|
||||
"Failed to update name server on host %s",
|
||||
nameServerManager.getHostName(nameServerIndex));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevNameServerHandler::getHandle :
|
||||
// * This method allows the caller to obtain the file handle that is being
|
||||
// * used by the nameServerTCP rsvcClient connection. This handle is used
|
||||
// * by the cdevReactor to detect when an event has occured.
|
||||
// *****************************************************************************
|
||||
int cdevNameServerHandler::getHandle ( void ) const
|
||||
{
|
||||
return nameServerTCP->getFd();
|
||||
}
|
||||
|
||||
|
||||
#ifndef DONT_SUPPORT_CDEV_CALLS
|
||||
// *********************************************************************
|
||||
// * cdevSystemHandler::cdevSystemHandler :
|
||||
// * This is the constructor for the cdevSystemHandler object.
|
||||
// *********************************************************************
|
||||
cdevSystemHandler::cdevSystemHandler (cdevReactor & Reactor,
|
||||
double pollRate,
|
||||
cdevSystem & System)
|
||||
: cdevSimpleTimer(Reactor, pollRate), system(System)
|
||||
{
|
||||
execute();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef DONT_SUPPORT_CDEV_CALLS
|
||||
// *********************************************************************
|
||||
// * cdevSystemHandler::~cdevSystemHandler :
|
||||
// * This is the destructor for the cdevSystemHandler object.
|
||||
// *********************************************************************
|
||||
cdevSystemHandler::~cdevSystemHandler (void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef DONT_SUPPORT_CDEV_CALLS
|
||||
// *********************************************************************
|
||||
// * cdevSystemHandler::execute :
|
||||
// * This is the method that is executed when the specified timer
|
||||
// * expires.
|
||||
// *********************************************************************
|
||||
int cdevSystemHandler::execute (void)
|
||||
{
|
||||
system.poll();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
#if !defined (_CDEV_SERVER_TOOLS_H_)
|
||||
#define _CDEV_SERVER_TOOLS_H_
|
||||
|
||||
#ifndef DONT_SUPPORT_CDEV_CALLS
|
||||
#include "cdevSystemEventHandler.h"
|
||||
#endif
|
||||
|
||||
#include "cdevSessionManager.h"
|
||||
#include "cdevMessage.h"
|
||||
#include "rsvcClient.h"
|
||||
#include "rsvcUdpClient.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// * This is the cdevSimpleTimer class. The user specifies a function, a rate
|
||||
// * and a void * data pointer. The ACE_Reactor will then call the function
|
||||
// * each time the period of time expires.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API cdevSimpleTimer : public cdevEventHandler, public ErrorReporter
|
||||
{
|
||||
public:
|
||||
cdevSimpleTimer ( cdevReactor & Reactor, double Rate = 1.0 );
|
||||
~cdevSimpleTimer ( void );
|
||||
virtual int handleTimeout (void);
|
||||
virtual int execute (void) = 0;
|
||||
};
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * class cdevNameServerManager:
|
||||
// * This class will extract the list of cdev Name Servers from the
|
||||
// * CDEV_NAME_SERVER environment variable and will create a collection
|
||||
// * of cdevNameServerHandler objects that will manage the connections
|
||||
// * to them. These cdevNameServerHandler objects will register the
|
||||
// * server with the name server and will send updates every five seconds.
|
||||
// * If the connection to the specific name server is lost, the
|
||||
// * cdevNameServer handler will call the unregisterHandler method to
|
||||
// * terminate the connection and before being deleted. This object
|
||||
// * will then attempt to reestablish the connection periodically.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API cdevNameServerManager : public cdevEventHandler, public ErrorReporter
|
||||
{
|
||||
protected:
|
||||
char ** nameServerList;
|
||||
class cdevNameServerHandler ** nameServerHandlers;
|
||||
size_t nameServerCnt;
|
||||
rsvcData serverInfo;
|
||||
rsvcData updateInfo;
|
||||
char * serverName;
|
||||
char * domainName;
|
||||
unsigned short serverPort;
|
||||
|
||||
public:
|
||||
cdevNameServerManager ( cdevReactor & Reactor, char * DomainName, char * ServerName, unsigned short port);
|
||||
~cdevNameServerManager ( void );
|
||||
|
||||
static void rsvcCallback (int status, void* arg, rsvcData* data);
|
||||
|
||||
virtual int handleTimeout ( void );
|
||||
void unregisterHandler ( size_t index );
|
||||
rsvcData * getServerInfo ( void ) { return &serverInfo; }
|
||||
rsvcData * getUpdateInfo ( void ) { return &updateInfo; }
|
||||
char * getHostName ( size_t index ) { return (index<nameServerCnt)?nameServerList[index]:(char *)"UNKNOWN"; }
|
||||
};
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * class cdevNameServerHandler :
|
||||
// * This class will establish a connection with a specific cdev Name
|
||||
// * Server and will send period updates to let the name server know that
|
||||
// * the process is still alive and operational. If the handler loses its
|
||||
// * connection to the name server, it will notify the cdevNameServerManager
|
||||
// * prior to being deleted. The cdevNameServer manager will then attempt
|
||||
// * to recreate the connection at a later time.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API cdevNameServerHandler : public cdevEventHandler, public ErrorReporter
|
||||
{
|
||||
protected:
|
||||
int nameServerIndex;
|
||||
rsvcClient * nameServerTCP;
|
||||
rsvcUdpClient * nameServerUDP;
|
||||
cdevNameServerManager & nameServerManager;
|
||||
|
||||
public:
|
||||
cdevNameServerHandler ( cdevNameServerManager & Manager, cdevReactor & Reactor, int index, rsvcClient *tcp, rsvcUdpClient *udp );
|
||||
~cdevNameServerHandler ( void );
|
||||
virtual int handleInput ( void );
|
||||
virtual int handleOutput ( void );
|
||||
virtual int handleTimeout ( void );
|
||||
virtual int getHandle ( void ) const;
|
||||
};
|
||||
|
||||
|
||||
#ifndef DONT_SUPPORT_CDEV_CALLS
|
||||
// *********************************************************************
|
||||
// * class cdevSystemHandler:
|
||||
// * This class causes the specified cdevReactor to periodically
|
||||
// * poll the cdevSystem for activity (by default 5 times per second).
|
||||
// *********************************************************************
|
||||
class GENERIC_SERVER_API cdevSystemHandler : public cdevSimpleTimer
|
||||
{
|
||||
protected:
|
||||
cdevSystem & system;
|
||||
|
||||
public:
|
||||
cdevSystemHandler (cdevReactor & Reactor,
|
||||
double pollRate = 0.2,
|
||||
cdevSystem & System = cdevSystem::defaultSystem());
|
||||
virtual ~cdevSystemHandler ( void );
|
||||
int execute ( void );
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _CDEV_SERVER_TOOLS_H_ */
|
||||
@@ -0,0 +1,635 @@
|
||||
#include <cdevSessionManager.h>
|
||||
|
||||
cdevReactor cdevSessionManager::Reactor;
|
||||
IntHash cdevSessionManager::localIdx;
|
||||
|
||||
// *****************************************************************************
|
||||
// * ClientSession::ClientSession :
|
||||
// * This method serves only to initialize the internals of the class.
|
||||
// *****************************************************************************
|
||||
ClientSession::ClientSession ( int SocketID, int ClientID, int LocalID )
|
||||
: socketID(SocketID), clientID(ClientID), localID(LocalID)
|
||||
{
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * ClientSession::~ClientSession :
|
||||
// * This method deletes all unprocessed binary packets that are stored
|
||||
// * within the queue.
|
||||
// *****************************************************************************
|
||||
ClientSession::~ClientSession ( void )
|
||||
{
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * SocketSession::SocketSession :
|
||||
// * This is the constructor for the SocketSession object, it serves only
|
||||
// * to initialize internal variables.
|
||||
// *****************************************************************************
|
||||
SocketSession::SocketSession( int SocketID )
|
||||
: FifoQueue(), socketID(SocketID)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * SocketSession::~SocketSession :
|
||||
// * This method deletes all unprocessed binary packets that are stored
|
||||
// * within the queue.
|
||||
// *****************************************************************************
|
||||
SocketSession::~SocketSession ( void )
|
||||
{
|
||||
char * binary;
|
||||
size_t binaryLen;
|
||||
|
||||
while(dequeue(&binary, &binaryLen)==0) delete binary;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::~cdevSessionManager :
|
||||
// * This method deletes all entries from the client and socket queues
|
||||
// * and then deletes all queue objects...
|
||||
// *****************************************************************************
|
||||
cdevSessionManager::~cdevSessionManager ( void )
|
||||
{
|
||||
int socketID;
|
||||
int clientID;
|
||||
IntHashIterator clientIter(&clients);
|
||||
IntHashIterator socketIter(&sockets);
|
||||
ClientSession * clientPtr;
|
||||
SocketSession * socketPtr;
|
||||
cdevPacketBinary * packet;
|
||||
|
||||
while((packet = (cdevPacketBinary *)inbound.dequeue())!=NULL)
|
||||
{
|
||||
delete packet;
|
||||
}
|
||||
|
||||
clientIter.first();
|
||||
while((clientPtr=(ClientSession *)clientIter.data())!=NULL)
|
||||
{
|
||||
clientID = clientPtr->getClientID();
|
||||
clientIter++;
|
||||
removeClient(clientID, 0);
|
||||
}
|
||||
|
||||
socketIter.first();
|
||||
while((socketPtr=(SocketSession *)socketIter.data())!=NULL)
|
||||
{
|
||||
socketID = socketIter.key();
|
||||
socketIter++;
|
||||
removeSocket(socketID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::newClientSession :
|
||||
// * This method allows the caller to create a new ClientSession object. The
|
||||
// * ClientSession object functions primarily as a pointer to the queue that
|
||||
// * holds packets destined for a specific client, however, the developer
|
||||
// * can create a subclass of the ClientSession that may be used to associate
|
||||
// * additional, client specific information to the structure.
|
||||
// *****************************************************************************
|
||||
ClientSession * cdevSessionManager::newClientSession ( int SocketID, int ClientID, int LocalID )
|
||||
{
|
||||
return new ClientSession (SocketID, ClientID, LocalID);
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::newSocketSession :
|
||||
// * This method allows the caller to create a new SocketSession object. The
|
||||
// * SocketSession object functions primarily as a pointer to the queue that
|
||||
// * holds packets destined for a specific socket, however, the developer
|
||||
// * can create a subclass of the SocketSession that may be used to associate
|
||||
// * additional, socket specific information to the structure.
|
||||
// *****************************************************************************
|
||||
SocketSession * cdevSessionManager::newSocketSession ( int SocketID )
|
||||
{
|
||||
return new SocketSession (SocketID);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::deleteSocketSession :
|
||||
// * This method is called to delete a SocketSession object.
|
||||
// *****************************************************************************
|
||||
void cdevSessionManager::deleteSocketSession ( SocketSession *socket )
|
||||
{
|
||||
if(socket)
|
||||
{
|
||||
sockets.remove(socket->getSocketID());
|
||||
delete socket;
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::findLocalClient :
|
||||
// * This method allows the caller to locate a ClientSession using the local
|
||||
// * client identifier that is assigned by the cdevSessionManager class.
|
||||
// *****************************************************************************
|
||||
ClientSession * cdevSessionManager::findLocalClient( short localID )
|
||||
{
|
||||
return (ClientSession *)localIdx.find(localID);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::findClient :
|
||||
// * This method allows the caller to locate a ClientSession using its
|
||||
// * clientID.
|
||||
// *****************************************************************************
|
||||
ClientSession * cdevSessionManager::findClient( int clientID )
|
||||
{
|
||||
return (ClientSession *)clients.find(clientID);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::findSocket :
|
||||
// * This method allows the caller to locate a SocketSession using its
|
||||
// * socketID.
|
||||
// *****************************************************************************
|
||||
SocketSession * cdevSessionManager::findSocket( int socketID )
|
||||
{
|
||||
return (SocketSession *)sockets.find(socketID);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::addClient :
|
||||
// * This method allows the caller to add a new clientID and construct a
|
||||
// * ClientSession object for it.
|
||||
// *
|
||||
// * The socketID must have already been registered using the addSocket
|
||||
// * method. If the clientID already exists or if an error occurs NULL will
|
||||
// * be returned.
|
||||
// *****************************************************************************
|
||||
ClientSession * cdevSessionManager::addClient( int socketID, int clientID )
|
||||
{
|
||||
ClientSession * session = NULL;
|
||||
|
||||
if(findSocket(socketID)!=NULL && findClient(clientID)==NULL)
|
||||
{
|
||||
short localID = getNextLocalID();
|
||||
if(localID>0 &&
|
||||
(session = newClientSession(socketID, clientID, localID))!=NULL)
|
||||
{
|
||||
clients.insert (clientID, session);
|
||||
localIdx.insert((int)localID, session);
|
||||
}
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::addSocket :
|
||||
// * This method allows the caller to add a new socketID and construct a
|
||||
// * SocketSession object to service it.
|
||||
// *
|
||||
// * This function will fail if the socketID has already been registered...
|
||||
// * On failure this method will return NULL.
|
||||
// *****************************************************************************
|
||||
SocketSession * cdevSessionManager::addSocket ( int socketID )
|
||||
{
|
||||
SocketSession * session = NULL;
|
||||
if(findSocket(socketID)==NULL &&
|
||||
(session = newSocketSession(socketID))!=NULL)
|
||||
{
|
||||
sockets.insert(socketID, session);
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::removeClient :
|
||||
// * This method will remove the specified clientID from the clients list
|
||||
// * and will delete the associated ClientSession object.
|
||||
// *****************************************************************************
|
||||
void cdevSessionManager::removeClient ( int clientID, int unregisterFlag)
|
||||
{
|
||||
ClientSession * session;
|
||||
|
||||
if((session = (ClientSession *)clients.find(clientID))!=NULL)
|
||||
{
|
||||
// *****************************************************
|
||||
// * Submit an unregister command to notify the server
|
||||
// *****************************************************
|
||||
if(unregisterFlag) unregisterClient(session->getLocalID());
|
||||
|
||||
localIdx.remove((int)session->getLocalID());
|
||||
clients.remove (clientID);
|
||||
delete session;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::removeSocket :
|
||||
// * This method will remove the specified socketID from the sockets list
|
||||
// * and will delete the associated SocketSession object. It will then
|
||||
// * ascend the clients list and will remove all ClientSessions that are
|
||||
// * associated with the socketID.
|
||||
// *****************************************************************************
|
||||
void cdevSessionManager::removeSocket ( int socketID )
|
||||
{
|
||||
cdevEventHandler * handler = NULL;
|
||||
SocketSession * socket;
|
||||
ClientSession * client;
|
||||
int clientID;
|
||||
|
||||
if(Reactor.getHandler(socketID, handler)==0 && handler!=NULL)
|
||||
{
|
||||
delete handler;
|
||||
}
|
||||
|
||||
if((socket = (SocketSession *)sockets.find(socketID))!=NULL)
|
||||
{
|
||||
IntHashIterator clientIter(&clients);
|
||||
clientIter.first();
|
||||
while((client=(ClientSession *)clientIter.data())!=NULL)
|
||||
{
|
||||
if(client->getSocketID()==socketID)
|
||||
{
|
||||
clientID = client->getClientID();
|
||||
clientIter++;
|
||||
removeClient(clientID);
|
||||
}
|
||||
else clientIter++;
|
||||
}
|
||||
|
||||
deleteSocketSession(socket);
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::getNextLocalID :
|
||||
// * This method allows the caller to retrieve a unique localID to be
|
||||
// * assigned to a client. The nextLocalID value is automatically
|
||||
// * incremented.
|
||||
// *****************************************************************************
|
||||
short cdevSessionManager::getNextLocalID ( void )
|
||||
{
|
||||
static short nextLocalID = 0;
|
||||
short startingPoint = nextLocalID;
|
||||
ClientSession *session = NULL;
|
||||
|
||||
if(nextLocalID>=32767) nextLocalID = 1;
|
||||
else nextLocalID++;
|
||||
|
||||
startingPoint = nextLocalID;
|
||||
|
||||
do {
|
||||
session=(ClientSession *)localIdx.find((int)nextLocalID);
|
||||
if(session!=NULL)
|
||||
{
|
||||
if(nextLocalID>=32767) nextLocalID = 1;
|
||||
else nextLocalID++;
|
||||
}
|
||||
} while(session!=NULL && nextLocalID!=startingPoint);
|
||||
|
||||
return session==NULL?nextLocalID:-1;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::enqueue :
|
||||
// * This method is used to enqueue a binary packet into the inbound
|
||||
// * fifoQueue. This method is called by the client handler objects.
|
||||
// *
|
||||
// * The binary data item becomes the property of the queue and should not
|
||||
// * be accessed later by the caller.
|
||||
// *****************************************************************************
|
||||
int cdevSessionManager::enqueue( int socketID, char * binary, unsigned binaryLen )
|
||||
{
|
||||
int result = -1;
|
||||
SocketSession * socket = NULL;
|
||||
ClientSession * client = NULL;
|
||||
cdevPacketBinary * packet = new cdevPacketBinary;
|
||||
|
||||
// *********************************************************************
|
||||
// * Make sure its a valid packet.
|
||||
// *********************************************************************
|
||||
if(packet->streamIn(binary, binaryLen)==0)
|
||||
{
|
||||
// *************************************************************
|
||||
// * Add the socketID if it does not already exist.
|
||||
// *************************************************************
|
||||
if((socket = findSocket(socketID))==NULL)
|
||||
{
|
||||
socket = addSocket(socketID);
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
// * Combine the (short)clientID and the (short)socketID to
|
||||
// * create a unique identifier for this client.
|
||||
// *
|
||||
// * < HIGH WORD > < LOW WORD >
|
||||
// * SSSSSSSS CCCCCCCCC
|
||||
// *************************************************************
|
||||
short packetClientID;
|
||||
int clientID;
|
||||
|
||||
packet->getClientID(packetClientID);
|
||||
clientID = ((socketID<<16)|packetClientID);
|
||||
|
||||
// *************************************************************
|
||||
// * Add a clientID if it does not already exist.
|
||||
// *************************************************************
|
||||
if((client = findClient(clientID))==NULL &&
|
||||
(client = addClient(socketID, clientID))!=NULL)
|
||||
{
|
||||
registerClient ( client->getLocalID() );
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
// * This would only fail if the clientID had already been used
|
||||
// * by another socket.
|
||||
// *************************************************************
|
||||
if(client!=NULL && client->getSocketID()==socketID)
|
||||
{
|
||||
result = 0;
|
||||
|
||||
// *****************************************************
|
||||
// * At this point everything necessary is known to
|
||||
// * submit the packet for processing...
|
||||
// *****************************************************
|
||||
|
||||
// *****************************************************
|
||||
// * Set the clientID to the localClientID to be used
|
||||
// * by the server side of the connection.
|
||||
// *****************************************************
|
||||
packet->setClientID(client->getLocalID());
|
||||
|
||||
// *****************************************************
|
||||
// * Enqueue the packet and set the pointer to NULL to
|
||||
// * prevent its later deletion.
|
||||
// *****************************************************
|
||||
inbound.enqueue((void *)packet);
|
||||
packet = NULL;
|
||||
}
|
||||
}
|
||||
if(packet!=NULL) delete packet;
|
||||
|
||||
// *********************************************************************
|
||||
// * If a packet was successfully added to the inbound queue and the
|
||||
// * queue is not empty , then add an event to the FDTrigger to cause
|
||||
// * the handle_input mechanism to be called.
|
||||
// *********************************************************************
|
||||
if(result==0 && !inbound.empty()) trigger.insertEvent();
|
||||
|
||||
// *********************************************************************
|
||||
// * Due to the new design of the SocketUtil class, the binary should
|
||||
// * never be deleted.
|
||||
// *********************************************************************
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::enqueue :
|
||||
// * This method is used to enqueue a cdevPacket packet into an outbound
|
||||
// * queue. The method will first identify the target client and place the
|
||||
// * packet into its queue... then it will identify the socket and place the
|
||||
// * packet into its queue.
|
||||
// *
|
||||
// * This method will return -1 if either the socket or the client is
|
||||
// * undefined.
|
||||
// *
|
||||
// * The packet remains the property of the caller who must delete it.
|
||||
// *****************************************************************************
|
||||
int cdevSessionManager::enqueue ( cdevPacket * input )
|
||||
{
|
||||
cdevPacketBinary * packet = encodePacket(input);
|
||||
ClientSession * client = NULL;
|
||||
SocketSession * socket = NULL;
|
||||
int result = -1;
|
||||
|
||||
// *********************************************************************
|
||||
// * Note that this condition makes sure that a queue exists for both
|
||||
// * the client ID and the socketID. If both of these conditions are
|
||||
// * met, then it checks to ensure that the socket has not been overrun
|
||||
// * with data (500 or more packets).
|
||||
// *********************************************************************
|
||||
if(packet!=NULL &&
|
||||
input->getClientID()>0 &&
|
||||
(client = findLocalClient(input->getClientID()))!=NULL &&
|
||||
(socket = findSocket(client->getSocketID()))!=NULL)
|
||||
{
|
||||
cdevEventHandler * handler = NULL;
|
||||
Reactor.getHandler(client->getSocketID(), handler);
|
||||
|
||||
// *************************************************************
|
||||
// * Attempt to flush the handler if more than 500 packets
|
||||
// * have already been inserted.
|
||||
// *************************************************************
|
||||
if(handler && socket->getCount()>=500)
|
||||
{
|
||||
outputError(CDEV_SEVERITY_WARN, "CDEV Server",
|
||||
"Forcing flush of socket %i to prevent overflow...",
|
||||
client->getSocketID());
|
||||
|
||||
// *****************************************************
|
||||
// * Call handleOutput to cause the handler to attempt
|
||||
// * to write its contents.
|
||||
// *****************************************************
|
||||
if(handler->handleOutput()<0)
|
||||
{
|
||||
Reactor.removeHandler(handler);
|
||||
handler = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(handler && socket->getCount()<500)
|
||||
{
|
||||
char * binary = NULL;
|
||||
size_t binaryLen = 0;
|
||||
|
||||
// *****************************************************
|
||||
// * Create a binary stream from the cdevPacketBinary
|
||||
// * object and then use the detachData method to
|
||||
// * prevent the buffer from being deleted when the
|
||||
// * cdevPacketBinary is destroyed.
|
||||
// *****************************************************
|
||||
packet->streamOut(&binary, &binaryLen);
|
||||
packet->detachData();
|
||||
|
||||
// *****************************************************
|
||||
// * Populate the cdevServerBinary object with the data
|
||||
// * that was extracted from the cdevPacketBinary object
|
||||
// *****************************************************
|
||||
socket->enqueue(binary, binaryLen);
|
||||
|
||||
// *****************************************************
|
||||
// * Set the event mask for the outbound socket to read/
|
||||
// * write to force it to attempt to write to the socket
|
||||
// * until data is transmitted.
|
||||
// *****************************************************
|
||||
if(handler) handler->setMask(READ_MASK|WRITE_MASK);
|
||||
|
||||
result = 0;
|
||||
}
|
||||
else if(handler)
|
||||
{
|
||||
outputError ( CDEV_SEVERITY_ERROR, "CDEV Server",
|
||||
"Dropping packet to socket %i : queue is full...",
|
||||
client->getSocketID());
|
||||
}
|
||||
}
|
||||
|
||||
// *********************************************************************
|
||||
// * Delete the cdevPacketBinary if it was generated.
|
||||
// *********************************************************************
|
||||
if(packet) delete packet;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::dequeue :
|
||||
// * This method is used to by the server engine to extract a message from
|
||||
// * the inbound queue. Once the packet has been enqueue it will be sent to
|
||||
// * the decodePacket method which will perform any preprocessing that the
|
||||
// * developer may deem necessary before returning the packet to the caller.
|
||||
// *
|
||||
// * The cdevPacket object becomes the property of the caller and must
|
||||
// * be deleted when it is no longer needed.
|
||||
// *****************************************************************************
|
||||
int cdevSessionManager::dequeue ( cdevPacket * &packet )
|
||||
{
|
||||
cdevPacketBinary * binary = NULL;
|
||||
packet = NULL;
|
||||
|
||||
// *********************************************************************
|
||||
// * Conitnue this loop unitl a valid packet has been extracted, or
|
||||
// * until there are no more binary packets left in the queue.
|
||||
// *********************************************************************
|
||||
do {
|
||||
// *************************************************************
|
||||
// * Attempt to dequeue the cdevPacketBinary from the queue...
|
||||
// * If it is not NULL, then begin processing.
|
||||
// *************************************************************
|
||||
if((binary = (cdevPacketBinary *)inbound.dequeue())!=NULL)
|
||||
{
|
||||
// *****************************************************
|
||||
// * Call the decodePacket mechanism... This will use
|
||||
// * the factory mechanisms of the cdevPacket class to
|
||||
// * import the data and then will complete any required
|
||||
// * preprocessing...
|
||||
// *****************************************************
|
||||
packet = decodePacket(binary);
|
||||
|
||||
// *****************************************************
|
||||
// * Delete the binary as it is no longer needed.
|
||||
// *****************************************************
|
||||
delete binary;
|
||||
}
|
||||
} while(binary!=NULL && packet==NULL);
|
||||
|
||||
// *********************************************************************
|
||||
// * Return 0 if a cdevPacket was successfully dequeued, otherwise,
|
||||
// * return -1.
|
||||
// *********************************************************************
|
||||
return packet?0:-1;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevServer::decodePacket :
|
||||
// * This method is used to perform preprocessing on a newly dequeued binary
|
||||
// * packet before it is provided to the caller. This method allows the
|
||||
// * developer to perform special preparations on the packet before providing
|
||||
// * it to the caller.
|
||||
// *****************************************************************************
|
||||
cdevPacket * cdevSessionManager::decodePacket (cdevPacketBinary * input)
|
||||
{
|
||||
return input?cdevPacket::import(*input):(cdevPacket *)NULL;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::encodePacket :
|
||||
// * This method is used to perform postprocessing on a packet that has been
|
||||
// * enqueued to be sent to a client. This method allows the developer to
|
||||
// * perform special preparations on the packet before providing it to the
|
||||
// * client.
|
||||
// *****************************************************************************
|
||||
cdevPacketBinary * cdevSessionManager::encodePacket ( cdevPacket * input )
|
||||
{
|
||||
cdevPacketBinary *result;
|
||||
|
||||
if(input)
|
||||
{
|
||||
char * binary;
|
||||
size_t binaryLen;
|
||||
input->streamOut(&binary, &binaryLen);
|
||||
if(binary && binaryLen)
|
||||
{
|
||||
result = new cdevPacketBinary;
|
||||
result->attachData(binary, binaryLen);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::getHandle :
|
||||
// * This method is used to obtain a copy of the file handle that is used
|
||||
// * to poll for events. In this case it will be the read file descriptor
|
||||
// * of the FD_Trigger object.
|
||||
// *****************************************************************************
|
||||
int cdevSessionManager::getHandle ( void ) const
|
||||
{
|
||||
return trigger.readfd();
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSessionManager::handleInput :
|
||||
// * This method is called whenever there is a read event pending on the
|
||||
// * FD_Trigger object.
|
||||
// *****************************************************************************
|
||||
int cdevSessionManager::handleInput ( void )
|
||||
{
|
||||
processMessages();
|
||||
if(inbound.empty()) trigger.purge();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// cdevSessionManager::handleClose :
|
||||
// Shuts down the timer - this will result in the destruction of the
|
||||
// * cdevSessionManager object.
|
||||
// ****************************************************************************
|
||||
int cdevSessionManager::handleClose(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// * cdevSessionManager::handleTimeout :
|
||||
// * Called when the timer expires... This method serves only to call the
|
||||
// * processMessages function.
|
||||
// ****************************************************************************
|
||||
int cdevSessionManager::handleTimeout(void)
|
||||
{
|
||||
processMessages();
|
||||
if(inbound.empty()) trigger.purge();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// * cdevServer::processMessages :
|
||||
// * This is a simple stand-in function that retrieves a message from the
|
||||
// * queue and then immediately returns it to the outbound queue. This
|
||||
// * function should be overloaded by the developers mechanism for
|
||||
// * processing messages.
|
||||
// ***************************************************************************
|
||||
void cdevSessionManager::processMessages ( void )
|
||||
{
|
||||
cdevPacket * packet;
|
||||
|
||||
while(dequeue(packet)==0)
|
||||
{
|
||||
enqueue(packet);
|
||||
delete packet;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
#if !defined (_CDEV_SESSION_MANAGER_H_)
|
||||
#define _CDEV_SESSION_MANAGER_H_
|
||||
|
||||
#include "cdevReactor.h"
|
||||
#include "cdevEventHandler.h"
|
||||
#include "cdevAddr.h"
|
||||
#include "cdevSocketStream.h"
|
||||
|
||||
#include "ErrorReporter.h"
|
||||
#include "FD_Trigger.h"
|
||||
#include "fifo.h"
|
||||
#include "IntHash.h"
|
||||
#include "cdevPacket.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// * class ClientSession :
|
||||
// *
|
||||
// * The ClientSession allows the server to associate certain data
|
||||
// * with a specific client...
|
||||
// *
|
||||
// * The ClientSession object may be sub-classed later in order to allow the
|
||||
// * developer to attach additional information to a particular client id.
|
||||
// *
|
||||
// * localID : This is the short integer that uniquely identifies the
|
||||
// * client on the server side of the connection.
|
||||
// *
|
||||
// * clientID : This is an integer that uniquely identifies the client
|
||||
// * within the context of the socket... That is to say...
|
||||
// *
|
||||
// * The high-order short integer is the socketID - AND -
|
||||
// * the low-order short integer is a clientID that uniquely
|
||||
// * identifies the client on the client side of the connection.
|
||||
// *
|
||||
// * Even though both the clientID and the localID uniquely
|
||||
// * identify the client... both are maintained in order to
|
||||
// * perform bi-directional routing of packets between multiple
|
||||
// * repeaters.
|
||||
// *
|
||||
// * socketID : This is the socket number that the client is attached on.
|
||||
// *
|
||||
// * context: This is a pointer to the most recently used context from the
|
||||
// * cdevContextMap.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API ClientSession
|
||||
{
|
||||
private:
|
||||
short localID;
|
||||
int clientID;
|
||||
int socketID;
|
||||
|
||||
public:
|
||||
ClientSession ( int SocketID, int ClientID, int LocalID );
|
||||
virtual ~ClientSession ( void );
|
||||
int getSocketID ( void ) { return socketID; }
|
||||
void setSocketID ( int SocketID ) { socketID = SocketID; }
|
||||
int getClientID ( void ) { return clientID; }
|
||||
void setClientID ( int ClientID ) { clientID = ClientID; }
|
||||
short getLocalID ( void ) { return localID; }
|
||||
void setLocalID ( short LocalID ) { localID = LocalID; }
|
||||
};
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * class SocketSession :
|
||||
// * This class is a queue that will feed to a specific socket in that is
|
||||
// * connected to a remote client. The class contains the following variables.
|
||||
// *
|
||||
// * The SocketSession object may be sub-classed later in order to allow the
|
||||
// * developer to attach additional information to a particular socket.
|
||||
// *
|
||||
// * socketID : the integer identifier of the socket
|
||||
// *
|
||||
// * contextMap : a table of cdevData contexts that can be retrieved by index
|
||||
// *
|
||||
// * tagMap : the table for mapping cdevData tags from the remote system
|
||||
// * to the tag table associated with this system.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API SocketSession : public FifoQueue
|
||||
{
|
||||
private:
|
||||
int socketID;
|
||||
|
||||
public:
|
||||
SocketSession ( int SocketID );
|
||||
virtual ~SocketSession ( void );
|
||||
int getSocketID ( void ) { return socketID; }
|
||||
void setSocketID ( int SocketID ) { socketID = SocketID; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * class cdevSessionManager:
|
||||
// * The cdevSessionManager class is used to manage the queues that are
|
||||
// * associated with the operation of a server. It maintains the following
|
||||
// * variables.
|
||||
// *
|
||||
// * Reactor : This is the cdevReactor that will be used to manage the client
|
||||
// * connections.
|
||||
// *
|
||||
// * localIdx : This is the next available local index. This value will be
|
||||
// * used to populate the localID variable in each ClientSession.
|
||||
// *
|
||||
// *
|
||||
// * trigger : This is the file descriptor mechanism that is used to
|
||||
// * notify the cdevEventHandler mechanisms when a packet
|
||||
// * is available to be dequeued.
|
||||
// *
|
||||
// * rate : This is the rate at which the handleTimeout mechanism will
|
||||
// * be periodically called in order to process time oriented
|
||||
// * events.
|
||||
// *
|
||||
// * inbound : This is the inbound message queue. Since all messages will
|
||||
// * go to the same method to be processed, they can be enqueued
|
||||
// * in the same queue for storage.
|
||||
// *
|
||||
// * clients : This is a hash table that contains the queues for each
|
||||
// * client that is attached to the server. Since multiple
|
||||
// * clients can be routed through the same socket, these
|
||||
// * classes are used to determine which socket to send the
|
||||
// * outbound message to.
|
||||
// *
|
||||
// * sockets : This is the hash table that contains the queues for each
|
||||
// * socket. After the cdevSessionManager determines the clientID
|
||||
// * associated with an outbound message, that value will be used
|
||||
// * to locate the SocketSession - where the outbound message will
|
||||
// * be enqueued.
|
||||
// *****************************************************************************
|
||||
class GENERIC_SERVER_API cdevSessionManager : public ErrorReporter, public cdevEventHandler
|
||||
{
|
||||
public:
|
||||
static cdevReactor Reactor;
|
||||
|
||||
protected:
|
||||
static IntHash localIdx;
|
||||
|
||||
FD_Trigger trigger;
|
||||
FifoQueue inbound;
|
||||
IntHash clients;
|
||||
IntHash sockets;
|
||||
|
||||
public:
|
||||
cdevSessionManager ( void ) {}
|
||||
virtual ~cdevSessionManager ( void );
|
||||
|
||||
static short getNextLocalID ( void );
|
||||
|
||||
// *********************************************************************
|
||||
// * These mechanisms are used to obtain new ClientSession and
|
||||
// * SocketSession objects. This design allows the developer to affix
|
||||
// * addition socket specific or client specific components to his
|
||||
// * classes later in order to have an easily accessable data point.
|
||||
// *********************************************************************
|
||||
virtual ClientSession * newClientSession ( int SocketID, int ClientID, int LocalID );
|
||||
virtual SocketSession * newSocketSession ( int SocketID );
|
||||
virtual void deleteSocketSession ( SocketSession * session );
|
||||
// *********************************************************************
|
||||
// * These mechanisms are used to add, locate and remove client and
|
||||
// * socket sessions.
|
||||
// *********************************************************************
|
||||
virtual ClientSession * findLocalClient ( short localID );
|
||||
virtual ClientSession * findClient ( int clientID );
|
||||
virtual SocketSession * findSocket ( int socketID );
|
||||
virtual ClientSession * addClient ( int socketID, int clientID );
|
||||
virtual SocketSession * addSocket ( int socketID );
|
||||
virtual void removeClient ( int clientID, int unregisterFlag=1);
|
||||
virtual void removeSocket ( int socketID );
|
||||
|
||||
// *********************************************************************
|
||||
// * This mechanism is used by the ClientHandler class to enqueue binary
|
||||
// * information incoming from the socket.
|
||||
// *********************************************************************
|
||||
virtual int enqueue ( int socketID, char * binary, unsigned binaryLen );
|
||||
|
||||
// *********************************************************************
|
||||
// * This method is used by the developer to send a packet to a specific
|
||||
// * client. The client is specified by the clientID in the cdevPacket.
|
||||
// *********************************************************************
|
||||
virtual int enqueue ( cdevPacket * packet );
|
||||
|
||||
// *********************************************************************
|
||||
// * This method is used by the developer to extract a packet from the
|
||||
// * inbound queue for processing.
|
||||
// *********************************************************************
|
||||
int dequeue ( cdevPacket * &packet );
|
||||
|
||||
// *********************************************************************
|
||||
// * This method is used by the developer to dequeue, process and then
|
||||
// * enqueue messages to a client.
|
||||
// *********************************************************************
|
||||
virtual void processMessages ( void );
|
||||
|
||||
// *********************************************************************
|
||||
// * This method formats packets when they are being enqueued or
|
||||
// * dequeued.
|
||||
// *********************************************************************
|
||||
virtual cdevPacket * decodePacket (cdevPacketBinary * input);
|
||||
virtual cdevPacketBinary * encodePacket (cdevPacket * input);
|
||||
|
||||
// *********************************************************************
|
||||
// * These are the ACE_Event_Handler methods that are called whenever
|
||||
// * a timeout, input or output event occur.
|
||||
// *********************************************************************
|
||||
virtual int getHandle (void) const;
|
||||
virtual int handleInput (void);
|
||||
virtual int handleClose (void);
|
||||
virtual int handleTimeout (void);
|
||||
|
||||
// *********************************************************************
|
||||
// * These are developer defined functions which are used to announce
|
||||
// * the creation of a new client or the destruction of an existing
|
||||
// * client to the main processing loop.
|
||||
// *
|
||||
// * Typically, they will only enqueue a message in the server specific
|
||||
// * packet format that specifies either "register" or "unregister" and
|
||||
// * the local client identifier.
|
||||
// *********************************************************************
|
||||
virtual void registerClient ( short localID ) = 0;
|
||||
virtual void unregisterClient ( short localID ) = 0;
|
||||
};
|
||||
|
||||
#endif /* _CDEV_SESSION_MANAGER_H_ */
|
||||
@@ -0,0 +1,90 @@
|
||||
#include "cdevSystem.h"
|
||||
#include "cdevSessionManager.h"
|
||||
|
||||
class GENERIC_SERVER_API cdevSystemEventHandler : public cdevEventHandler
|
||||
{
|
||||
private:
|
||||
int cdevfd;
|
||||
|
||||
public:
|
||||
cdevSystemEventHandler ( cdevReactor & Reactor, int fd )
|
||||
: cdevfd(fd)
|
||||
{
|
||||
Reactor.registerHandler(this, READ_MASK|WRITE_MASK|EXCEPT_MASK);
|
||||
}
|
||||
|
||||
~cdevSystemEventHandler ( void )
|
||||
{
|
||||
if(reactor) reactor->extractHandler(this);
|
||||
handleClose();
|
||||
}
|
||||
|
||||
int handleInput ( void )
|
||||
{
|
||||
cdevSystem::defaultSystem().poll();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handleOutput ( void )
|
||||
{
|
||||
cdevSystem::defaultSystem().flush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handleExcept ( void )
|
||||
{
|
||||
cdevSystem::defaultSystem().poll();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getHandle ( void ) const
|
||||
{
|
||||
return cdevfd;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class GENERIC_SERVER_API cdevSystemEventManager : public cdevEventHandler
|
||||
{
|
||||
public:
|
||||
cdevSystemEventManager ( cdevReactor &Reactor=cdevSessionManager::Reactor, double Rate = 30.0 )
|
||||
{
|
||||
setTimeoutRate(Rate);
|
||||
Reactor.registerTimer(this);
|
||||
cdevSystem::defaultSystem().addFdChangedCallback
|
||||
(cdevSystemEventManager::fdChangedCallback, this);
|
||||
}
|
||||
|
||||
~cdevSystemEventManager ( void )
|
||||
{
|
||||
if(reactor) reactor->extractHandler(this);
|
||||
handleClose();
|
||||
}
|
||||
|
||||
int handleTimeout ( void )
|
||||
{
|
||||
cdevSystem::defaultSystem().pend(0.0001);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fdChangedCallback ( int fd, int opened, void * arg )
|
||||
{
|
||||
cdevSystemEventManager *manager = (cdevSystemEventManager *)arg;
|
||||
cdevEventHandler *handler;
|
||||
cdevReactor *reactor = manager->reactor;
|
||||
|
||||
if(reactor)
|
||||
{
|
||||
if(opened && reactor->getHandler(fd, handler)!=0)
|
||||
{
|
||||
handler = new cdevSystemEventHandler(*reactor, fd);
|
||||
}
|
||||
else if(!opened && reactor->getHandler(fd, handler)==0)
|
||||
{
|
||||
delete handler;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user