cdev-1.7.2n
This commit is contained in:
268
extensions/cdevGenericServer/cdevServer/ClientHandler.cc
Executable file
268
extensions/cdevGenericServer/cdevServer/ClientHandler.cc
Executable file
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user