//*********************************************************************
// comm.h
//*********************************************************************
#ifndef COMM_H
#define COMM_H
#ifndef FARBOOK_H
#include "block.h"
#include "hshlist.h"
#include "inilist.h"
#include "list.h"
#include "socket.h"
#include "strlist.h"
#include "thread.h"
#endif
ushort GetFVType(Pchar _MIMEType);
enum disposition {closeConnect, keepAlive};
_FBDEF(CSession)
_FBDEF(CComm)
//---------------------------------------------------------------------
// Comm result object. Used by everyone to help synchronize activities
// and to communicate results to the caller. Upon completion of a
// requested command, the caller should call the GetResult() method to
// determine the results of the command. The caller can call the
// GetHead*( nethod to obtain the message headers, and the GetBody()
// method to obtain the message content. The user is responsible to
// determine the actual type of the body object by using the virtual
// Isa() method.
//
_FBDEF(CCommResult)
class FBC_USE CCommResult: public CAtom {
public:
CCommResult(void);
CCommResult(bool _wait);
virtual ~CCommResult();
virtual FB_USE_(short) Ima(void);
virtual FB_USE_(Pchar) IAm(void);
virtual FB_USE_(bool) Isa(const short _type);
FB_USE_(void) Wait (void);
FB_USE_(void) Release (void);
FB_USE_(void) SetResult (ulong _result);
FB_USE_(ulong) GetResult (void);
FB_USE_(void) SetCode (ulong _code);
FB_USE_(ulong) GetCode (void);
FB_USE_(void) SetMssg (Pchar _mssg);
FB_USE_(Pchar) GetMssg (void);
FB_USE_(void) SetHead (RPCStrList _headers);
FB_USE_(PCStrList)
GetHead (void);
FB_USE_(void) SetType (Pchar _type);
FB_USE_(Pchar) GetType (void);
FB_USE_(void) SetBody (RPCAtom _body);
FB_USE_(PCAtom) GetBody (void);
PCSemaphore wait;
ulong result; // Result of Comm actions
ulong code; // Acknowledge code
Pchar mssg; // Acknowledge message
PCStrList headers; // Headers list
Pchar type; // Body type
PCAtom body; // Body object
}; // CCommResult
//---------------------------------------------------------------------
// CloseSession command data object. CComm::CloseSession() creates
// an object of this class to pass to a CSession object.
//
// where
//
// _sessionID is the id of the session (required)
//
_FBDEF(CCloseSession)
class FBC_USE CCloseSession: public CItem {
public:
FB_USE CCloseSession(Pchar _sessionID);
virtual FB_USE ~CCloseSession();
virtual FB_USE_(short) Ima(void);
virtual FB_USE_(Pchar) IAm(void);
virtual FB_USE_(bool) Isa(const short _type);
Pchar sessionID;
}; // CCloseSession
//---------------------------------------------------------------------
// OpenConnect command data object. CComm::OpenSession() creates
// an object of this class to pass to a CSession object.
//
// where
//
// _sessionID is the id of the session (required)
//
_FBDEF(COpenConnect)
class FBC_USE COpenConnect: public CItem {
public:
FB_USE COpenConnect(Pchar _sessionID);
virtual FB_USE ~COpenConnect();
virtual FB_USE_(short) Ima(void);
virtual FB_USE_(Pchar) IAm(void);
virtual FB_USE_(bool) Isa(const short _type);
Pchar sessionID;
}; // COpenConnect
//---------------------------------------------------------------------
// SendMessage command data object. CComm::SendMessage() creates
// an object of this class to pass to a CSession object.
//
// where
//
// _sessionID is the id of the session (required)
//
// _mssgType is the type of the message (ACK | FAR | HTTP)
//
// _command When _mssgType is "ACK", the_command parameter is
// ignored.
// When _mssgType is "HTTP", the following commands are
// recognized:
// CONNECT
// DELETE
// GET
// HEAD
// POST
// PUT
// TRACE
// When _mssgType is "FAR", the following commands are
// recognized:
// Execute a remote farSlang proc FP
// Invoke an event for a remote topic TE
// Open a remote farBook OB
// Close a remote farBook CB
// Lock a location in a remote farBook LL
// Unlock a location in a remote farBook UL
// Touch the remote session TC
// Make a remote key MK
// Verify a remote key IK
// Get a remote findlist FK
// Get a remote node GN
// Delete a remote key DK
// Read a part of a remote node RP
// Write a part of a remote node WP
// Create a remote node CR
//
// _argument depends on the message type
//
// _bodyType MIME spec for the type of the body.
// TEXT/HTML
// TEXT/PLAIN
// TEXT/XML
// TEXT/ABST
// IMAGE/BMP
// IMAGE/GIF
// IMAGE/JPG
// IMAGE/PNG
// AUDIO/MIDI
// AUDIO/MP3
// AUDIO/WAV
// VIDEO/?
// APPLICATION/?
//
// _signature is a block (TBD - omitted for now)
//
// _body is the body of the message (optional)
//
_FBDEF(CSendMessage)
class FBC_USE CSendMessage: public CItem {
public:
FB_USE CSendMessage(Pchar _sessionID,
Pchar _mssgType,
Pchar _command,
Pchar _argument,
Pchar _bodyType,
RPCBlock _signature,
RPCAtom _body,
disposition _life);
virtual FB_USE ~CSendMessage();
virtual FB_USE_(short) Ima(void);
virtual FB_USE_(Pchar) IAm(void);
virtual FB_USE_(bool) Isa(const short _type);
Pchar sessionID;
Pchar mssgType;
Pchar command;
Pchar argument;
Pchar bodyType;
PCBlock signature;
PCAtom body;
disposition life;
}; // CSendMessage
//---------------------------------------------------------------------
// ReceiveMessage command data object. CComm::ReceiveMessage() creates
// an object of this class to pass to a CSession object.
//
_FBDEF(CReceiveMessage)
class FBC_USE CReceiveMessage: public CItem {
public:
virtual FB_USE_(short) Ima(void);
virtual FB_USE_(Pchar) IAm(void);
virtual FB_USE_(bool) Isa(const short _type);
FB_USE CReceiveMessage(Pchar _sessionID,
bool _doRequest = false);
virtual FB_USE ~CReceiveMessage();
Pchar sessionID;
bool doRequest;
}; // CReceiveMessage
//---------------------------------------------------------------------
// Communications control thread command item class
//
_FBDEF(CCommCmmd)
class FBC_USE CCommCmmd: public CItem {
public:
FB_USE CCommCmmd(ulong _cmmd,
RPCItem _data,
RPCCommResult _result);
virtual FB_USE ~CCommCmmd();
virtual FB_USE_(short) Ima(void);
virtual FB_USE_(Pchar) IAm(void);
virtual FB_USE_(bool) Isa(const short _type);
FB_USE_(void) SetResult(ulong _result);
FB_USE_(PCCommResult) GetCommResult(void) {
return result;
}
ulong cmmd;
PCItem data;
PCCommResult result;
}; // CCommCmmd
//---------------------------------------------------------------------
// CSession thread dictionary class. Provides rapid lookup of session
// thread objects using their session key.
//
_FBDEF(CSessionDict)
class FBC_USE CSessionDict: public CHshList {
public:
CSessionDict(short _wide = 32);
virtual FB_USE_(short) Ima(void);
virtual FB_USE_(Pchar) IAm(void);
virtual FB_USE_(bool) Isa(const short _type);
FB_USE_(void) InsertSession (Pchar _sessionID,
RPCSession _session);
FB_USE_(PCSession) GetFirstSession(Pchar _sessionID);
FB_USE_(PCSession) RemoveSession (Pchar _sessionID);
protected:
virtual ushort hash(Pvoid _key);
PCCriticalSection cs;
}; // CSessionDict
//---------------------------------------------------------------------
// Session thread class
//
class FBC_USE CSession: public CThread {
friend class CComm;
public:
FB_USE CSession(pCComm _comm,
RPCAtom _book,
Pchar _userName,
Pchar _domain,
Pchar _sessionID,
Pchar _hostIP,
long _hostPort,
long _listenPort,
short _szPort = 8);
virtual FB_USE ~CSession();
virtual FB_USE_(short) Ima(void);
virtual FB_USE_(Pchar) IAm(void);
virtual FB_USE_(bool) Isa(const short _type);
#ifndef _SLANGER
FB_USE_(Pchar) CommID(bool _alc);
#endif
FB_USE_(Pchar) CommID(void); // for farSlang
FB_USE_(Pchar) CommIP(void);
#ifndef _SLANGER
FB_USE_(Pchar) CommIP(bool _alc);
#endif
FB_USE_(long) CommPort(void); // for farSlang
FB_USE_(void) Socket(RPCSocket _socket);
FB_USE_(PCSocket) Socket(void) { return socket; }
FB_USE_(PCCommResult) Result(void) { return result; }
virtual FB_USE_(bool) Send (RPCSendMessage _sendMssg);
virtual FB_USE_(bool) Receive(RPCReceiveMessage _recvMssg);
virtual FB_USE_(void) Run (void);
virtual FB_USE_(void) Close(void);
protected:
// Methods to construct message contents
PCBlock makeBody (RPCStrList _headers,
RPCSendMessage _sendMssg);
void makeComm (RPCStrList _headers,
RPCSendMessage _sendMssg);
bool sendHTTP (RPCSendMessage _sendMssg);
bool sendACK (RPCSendMessage _sendMssg);
bool sendFAR (RPCSendMessage _sendMssg);
bool sendMessage (RPCStrList _head,
RPCBlock _signature,
RPCBlock _body);
PCStrList receiveHeaders(void);
PCAtom receiveBody (long _szBody,
RPCStrList _headers);
// Override this method to encrypt the outgoing body
virtual bool doEncrypt(RPCStrList _headers,
RPCBlock _signature,
RPCBlock _body);
// Override this method to decrypt the incoming body
virtual bool doDecrypt(RPCStrList _headers,
RPCBlock _body);
// Override this method to handle the incoming message
virtual bool doRequest(RPCStrList _headers,
RPCAtom _body);
bool closeConnection
(RPCStrList _headers);
void ackError (Pchar _msg, ...);
// Parser methods
void getStrValue (Pchar _line);
long getIntValue (Pchar _line);
void getHeaderStrValue(RPCStrList _head,
Pchar _name,
Pchar _value,
ushort _size);
long getHeaderIntValue(RPCStrList _head,
Pchar _name);
ushort getFVType (Pchar _MIMEType);
bool error;
pCComm comm; // address of the CComm interface object
PCAtom book; // address of the farBook interface object
Pchar userName; // farVIEW Name of user
Pchar domain; // domain under which session operates
Pchar sessionID; // session identifier
Pchar hostIP; // host URL/IP
long hostPort; // host port number
long listenPort; // guest listen port number
PCSocket socket; // socket object supporting this connection
Pchar typeName; // address of type name in farBook
PCCommResult result; // address of user's result object
}; // CSession
#ifndef _SLANGER
//---------------------------------------------------------------------
// Listener thread class. One per Comm system.
//
_FBDEF(CListen)
class FBC_USE CListen: public CThread {
public:
FB_USE CListen(pCComm _comm,
short _listenPort,
RPCCommResult _result,
short _size = 8);
virtual FB_USE ~CListen();
virtual FB_USE_(short) Ima(void);
virtual FB_USE_(Pchar) IAm(void);
virtual FB_USE_(bool) Isa(const short _type);
virtual FB_USE_(void) Run(void);
FB_USE_(void) Disconnect(void);
FB_USE_(PCSocket) GetSocket (void) { return listenSocket; }
protected:
PCSession getSession(RPCSocket _socket);
pCComm comm;
PCSocket listenSocket;
short listenPort;
PCCommResult result;
}; // CListen
//---------------------------------------------------------------------
// Dead-session watcher thread class. One per Comm system.
//
_FBDEF(CWatcher)
class FBC_USE CWatcher: public CThread {
public:
CWatcher(RPCSessionDict _sessions,
RPCCommResult _result,
short _size = 8);
virtual FB_USE ~CWatcher();
virtual FB_USE_(void) Run(void);
FB_USE_(void) Done(void) { done = true; }
protected:
bool done;
pCSessionDict sessions;
PCCommResult result;
}; // CWatcher
#endif // _SLANGER
//---------------------------------------------------------------------
// Communications control class. One per system.
//
class FBC_USE CComm: public CAtom {
friend class CListen;
public:
static FB_USE_(pCComm) TheComm;
FB_USE CComm(RPCAtom _book,
Pchar _userName,
Pchar _domain,
short _listenPort,
short _pause,
short _size = 8);
virtual FB_USE ~CComm();
virtual FB_USE_(short) Ima(void);
virtual FB_USE_(Pchar) IAm(void);
virtual FB_USE_(bool) Isa(const short _type);
FB_USE_(bool) Listening (void) { return listener; }
FB_USE_(bool) OpenComm (RPCCommResult _result);
FB_USE_(bool) CloseComm (RPCCommResult _result);
FB_USE_(bool) OpenSession (Pchar _sessionID,
Pchar _hostIP,
long _hostPort,
Pchar _userName,
RPCCommResult _result);
FB_USE_(bool) CloseSession(Pchar _sessionID,
RPCCommResult _result);
FB_USE_(bool) SendMessage (Pchar _sessionID,
Pchar _mssgType,
Pchar _command,
Pchar _argument,
Pchar _bodyType,
RPCAtom _body,
disposition _life,
RPCCommResult _result);
FB_USE_(bool) ReceiveMessage
(Pchar _sessionID,
RPCCommResult _result,
bool _doRequest = false);
protected:
// Override this method if you derive from CSession
virtual PCSession newSession
(Pchar _sessionID,
Pchar _hostIP,
long _hostPort,
Pchar _userName);
void log (char _flag, Pchar _format, ...);
PCAtom book; // don't know about this!?
Pchar userName;
Pchar domain;
short listenPort;
PCListen listener;
PCCommResult listenResult;
PCWatcher watcher;
PCCommResult watcherResult;
short size;
PCSessionDict sessions;
}; // CComm
#endif // COMM_H