//********************************************************************* // 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