#if !defined (_SERVER_HANDLER_H_)
#define _SERVER_HANDLER_H_

// *****************************************************************************
// * SIG_PIPE_HANDLED:
// *    This definition tells the SocketWriter class not to independently
// *    handle the SIGPIPE signal.
// *****************************************************************************
#define SIG_PIPE_HANDLED 1

#include "cdevEventHandler.h"
#include "cdevAddr.h"
#include "cdevSocketConnector.h"
#include "cdevReactor.h"

#include "SocketUtil.h"
#include "fifo.h"

class ServerInterface;
class ServerHandlerCallbackNode;
class SignalManager;

// *****************************************************************************
// * ServerHandlerCallback :
// *	This class is used by other classes to register to be informed when the
// * 	ServerHandler is destroyed.
// *****************************************************************************
class GENERIC_SERVER_API ServerHandlerCallback 
{
public:
	ServerHandlerCallback                     ( void ) {}
	virtual     ~ServerHandlerCallback        ( void ) {}
	virtual void executeServerHandlerCallback (class ServerHandler * handler) = 0;
};


// *****************************************************************************
// * ServerHandler:
// *	This class provides the mechanisms that will be used to service the
// *	requests of a client.
// *****************************************************************************
class GENERIC_SERVER_API ServerHandler :	public cdevEventHandler, 
			public SocketReader,
			public SocketWriter
{
protected:
	static SignalManager        signalManager;
	static int                  signalManagerInit;
		
	char                        hostName   [MAXHOSTNAMELEN + 1];	
	char                        server      [256];
	FifoQueue                 & queue;
	cdevSocketConnector         stream; 
	ServerInterface           * serverface;
	ServerHandlerCallbackNode * callbacks;
	size_t                      enqueuedPackets;
	size_t                      enqueuedBytes;
	short                       clientID;
	int                         contextID;
	int                         tagChanged;
	int                         serverQuitFlag;	

public:
	ServerHandler                                (char * Server, ServerInterface * Interface);
	~ServerHandler                               (void);
	virtual int                outputError       (int severity, char *name, char *formatString, ...);

	virtual int                open              (const cdevAddr &addr);

	char                     * getHostName       (void);
	char                     * getName           (void) const;
	virtual int                getHandle         (void) const;
	virtual char             * getServer         (void) const;

	virtual int                handleClose       (void);
	virtual int                handleInput       (void);
 	virtual int                handleOutput      (void);
	virtual int                handleExcept      (void);
		
	virtual void registerServerCallback          (ServerHandlerCallback *);
	virtual void unregisterServerCallback        (ServerHandlerCallback *);

	void enqueue   (char * buf, size_t  len); 
	void undequeue (char * buf, size_t  len) { queue.undequeue(buf, len); }
	int  dequeue   (char **buf, size_t *len) { return queue.dequeue(buf, len); }
	int  empty     (void)                    { return queue.empty(); }

	static short getNextClientID  ( void );
	short        getClientID      ( void )           { return clientID; }
	void         setClientID      ( short ClientID ) { clientID=ClientID; }
	int          getContextID     ( void )           { return contextID; }
	void         setContextID     ( int ContextID )  { contextID = ContextID; }
	int          getTagChangeFlag ( void )           { return tagChanged; }
	void         setTagChangeFlag ( int flag )       { tagChanged = flag; }
};

#endif /* _SERVER_HANDLER_H_ */ 
