/* * AbiCollab - Code to enable the modification of remote documents. * Copyright (C) 2006 by Marc Maurer * Copyright (C) 2007 One Laptop Per Child * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #ifndef ABICOLLAB_PACKET_H #define ABICOLLAB_PACKET_H #include #include "ut_types.h" #include "ut_string_class.h" #include "px_ChangeRecord.h" #include "ut_stack.h" #include "Serialization.h" #include #include class Buddy; enum PacketType { PT_Session = 0, PT_Event, PT_Handler }; enum PacketSessionType { PACKET_CHANGERECORD, PACKET_SIGNAL, PACKET_GLOB, PACKET_REVERT, PACKET_REVERT_ACK }; enum PacketEventType { PTE_AccountAddBuddyRequest, PTE_StartSession, PTE_JoinSession, PTE_DisjoinSession, PTE_CloseSession, }; enum PClassType // send over the net to identify classes { // // base // PCT_Packet = 0, PCT_EventPacket, PCT_Event, // // packets // /* misc. session packets */ PCT_SessionPacket = 0x10, // update _PCT_FirstChange if you move this PCT_SignalSessionPacket, PCT_RevertSessionPacket, PCT_RevertAckSessionPacket, PCT_GlobSessionPacket, /* changerecord session packets */ PCT_ChangeRecordSessionPacket, // update _PCT_FirstChangeRecord if you move this PCT_Props_ChangeRecordSessionPacket, PCT_InsertSpan_ChangeRecordSessionPacket, PCT_ChangeStrux_ChangeRecordSessionPacket, PCT_DeleteStrux_ChangeRecordSessionPacket, PCT_Object_ChangeRecordSessionPacket, PCT_Data_ChangeRecordSessionPacket, PCT_Glob_ChangeRecordSessionPacket, // update _PCT_LastChange and _PCT_LastChangeRecord if you move this // // events // PCT_AccountNewEvent = 0x80, PCT_AccountOnlineEvent, PCT_AccountOfflineEvent, PCT_AccountAddBuddyEvent, PCT_AccountDeleteBuddyEvent, PCT_AccountBuddyOnlineEvent, PCT_AccountBuddyOfflineEvent, PCT_AccountAddBuddyRequestEvent, PCT_AccountBuddyAddDocumentEvent, PCT_StartSessionEvent, PCT_JoinSessionEvent, PCT_JoinSessionRequestEvent, PCT_JoinSessionRequestResponseEvent, PCT_DisjoinSessionEvent, PCT_CloseSessionEvent, PCT_GetSessionsEvent, PCT_GetSessionsResponseEvent, // // meta values (KEEP THESE UPDATED WHEN ADDING NEW PACKET TYPES!!) // // FIXME: rename _PCT_FirstChange to _PCT_FirstSession _PCT_FirstChange = PCT_SessionPacket, _PCT_LastChange = PCT_Glob_ChangeRecordSessionPacket, _PCT_FirstChangeRecord = PCT_ChangeRecordSessionPacket, _PCT_LastChangeRecord = PCT_Glob_ChangeRecordSessionPacket, _PCT_FirstEvent = PCT_AccountNewEvent, _PCT_LastEvent = PCT_GetSessionsResponseEvent, }; struct RawPacket { Buddy* buddy; // TODO: free the buddy somewhere, or make it not a pointer (please do the latter) - MARCM std::string packet; }; class PX_ChangeRecord; class SessionPacket; class AbiCollab; class AccountHandler; extern const gchar * szAbiCollab_Packet_PTName[]; UT_sint16 getPacket_PTName_Index( const gchar* name ); // returns -1, or 0 <= x <= sizeof(szAbiCollab_Packet_PTName) /************************************************************* * Packets * *************************************************************/ #define DECLARE_ABSTRACT_PACKET(Class) \ virtual PClassType getClassType() const { return PCT_##Class; } #define DECLARE_SERIALIZABLE_PACKET \ virtual void serialize(Archive & ar); #define DECLARE_PACKET(Class) \ DECLARE_ABSTRACT_PACKET(Class) \ DECLARE_SERIALIZABLE_PACKET \ virtual Packet* clone() const { return new Class( *this ); } \ static Packet* create() { return new Class(); } #define REGISTER_PACKET(Class) \ struct PacketRegister##Class { \ PacketRegister##Class() { \ Packet::registerPacketClass( PCT_##Class, Class::create, \ #Class ); \ } \ }; \ static PacketRegister##Class _PacketRegister##Class; class ABI_EXPORT Packet { public: DECLARE_ABSTRACT_PACKET(Packet); Packet(); Packet( AbiCollab* session ); virtual ~Packet() {} virtual Packet* clone() const = 0; virtual PacketType getType() const = 0; const AbiCollab* getSession() const { return m_pSession; } AbiCollab* getSession() { return m_pSession; } virtual void serialize(Archive & ar); // overridden automatically throught DECLARE_PACKET void setParent( Packet* pParent ) { m_pParent = pParent; } Packet* getParent() { return m_pParent; } virtual std::string toStr() const { return str(boost::format("Packet: hasParent: %1%\n") % (m_pParent ? "yes" : "no")); } protected: AbiCollab* m_pSession; Packet* m_pParent; /** Class reconstruction */ public: typedef Packet*(*PacketCreateFuncType)(); static Packet* createPacket( PClassType eType ); static const char* getPacketClassname( PClassType eType ); static void registerPacketClass( PClassType eType, PacketCreateFuncType createFunc, const char* szClassName ); private: struct ClassData { PacketCreateFuncType StaticConstructor; const char* ClassName; ClassData() : StaticConstructor( NULL ), ClassName( NULL ) {} }; typedef std::map ClassMap; static ClassMap& GetClassMap(); }; /************************************************************* * SessionPackets * *************************************************************/ class ABI_EXPORT SessionPacket : public Packet { public: DECLARE_ABSTRACT_PACKET(SessionPacket); DECLARE_SERIALIZABLE_PACKET; SessionPacket() : m_sSessionId(""), m_sDocUUID("") {} SessionPacket(const UT_UTF8String& sSessionId, const UT_UTF8String& sDocUUID); virtual PacketType getType() const { return PT_Session; } virtual PacketSessionType getSessionType() const = 0; const UT_UTF8String& getSessionId() const { return m_sSessionId; } void setSessionId(const UT_UTF8String& sSessionId) { m_sSessionId = sSessionId; } const UT_UTF8String& getDocUUID() const { return m_sDocUUID; } void setDocUUID(const UT_UTF8String& sDocUUID) { m_sDocUUID = sDocUUID; } virtual std::string toStr() const { return Packet::toStr() + str(boost::format("SessionPacket: m_sSessionId: %1%, m_sDocUUID: %2%\n") % m_sSessionId.utf8_str() % m_sDocUUID.utf8_str()); } private: UT_UTF8String m_sSessionId; UT_UTF8String m_sDocUUID; }; class ABI_EXPORT ChangeRecordSessionPacket : public SessionPacket { public: DECLARE_PACKET(ChangeRecordSessionPacket); ChangeRecordSessionPacket() : m_cType(PX_ChangeRecord::PXType(0)), m_iPos(0), m_iLength(0), m_iAdjust(0), m_iRev(0), m_iRemoteRev(0), m_crType(PacketSessionType(0)) {} ChangeRecordSessionPacket( const UT_UTF8String& sSessionId, PX_ChangeRecord::PXType cType, const UT_UTF8String& sDocUUID, int iPos, int iRev, int iRemoteRev, PacketSessionType crType); PX_ChangeRecord::PXType getPXType() const { return m_cType; } UT_sint32 getPos() const { return m_iPos; } UT_sint32 getLength() const { return m_iLength; } UT_sint32 getAdjust() const { return m_iAdjust; } UT_sint32 getRev() const { return m_iRev; } UT_sint32 getRemoteRev(void) const { return m_iRemoteRev; } void setPos( UT_sint32 newPos ) { m_iPos = newPos; } void setLength( UT_sint32 newLength ) { m_iLength = newLength; } void setAdjust(UT_sint32 newAdjust) { m_iAdjust = newAdjust; } void setRemoteRev( UT_sint32 newRemoteRev ) { m_iRemoteRev = newRemoteRev; } virtual PacketSessionType getSessionType() const { return m_crType; } virtual std::string toStr() const { return SessionPacket::toStr() + // TODO: add length, adj, pos, rev, remoterev str(boost::format("ChangeRecordSessionPacket: m_cType: %1%, m_iLength: %2%, m_iAdjust: %3%, m_iPos: %4%, m_iRev: %5%, m_iRemoteRev: %6%, m_crType: %7%\n") % m_cType % m_iLength % m_iAdjust % m_iPos % m_iRev % m_iRemoteRev % (UT_sint32)m_crType); } private: PX_ChangeRecord::PXType m_cType; UT_sint32 m_iLength; UT_sint32 m_iAdjust; UT_sint32 m_iPos; UT_sint32 m_iRev; UT_sint32 m_iRemoteRev; PacketSessionType m_crType; }; class ABI_EXPORT Props_ChangeRecordSessionPacket : public ChangeRecordSessionPacket { public: DECLARE_PACKET(Props_ChangeRecordSessionPacket); Props_ChangeRecordSessionPacket() : m_szAtts(NULL), m_szProps(NULL) {} Props_ChangeRecordSessionPacket( const UT_UTF8String& sSessionId, PX_ChangeRecord::PXType cType, const UT_UTF8String& sDocUUID, int iPos, int iRev, int iRemoteRev, PacketSessionType crType) : ChangeRecordSessionPacket( sSessionId, cType, sDocUUID, iPos, iRev, iRemoteRev, crType ) , m_szAtts( NULL ) , m_szProps( NULL ) {} ~Props_ChangeRecordSessionPacket() { _freeProps(); _freeAtts(); } gchar** getProps() const { return m_szProps; } const std::map& getPropMap() const { return m_sProps; } std::map& getPropMap() { return m_sProps; } gchar** getAtts() const { return m_szAtts; } const std::map& getAttMap() const { return m_sAtts; } std::map& getAttMap() { return m_sAtts; } gchar* getAttribute( const gchar* attr ) const; protected: gchar** m_szAtts; gchar** m_szProps; std::map m_sAtts; // key is index into szAbiCollab_Packet_PTName std::map m_sProps; void _freeProps(); void _freeAtts(); void _fillProps(); // uses m_sProps to make m_szProps void _fillAtts(); // uses m_sAtts to make m_szAtts }; class ABI_EXPORT InsertSpan_ChangeRecordSessionPacket : public ChangeRecordSessionPacket { public: DECLARE_PACKET(InsertSpan_ChangeRecordSessionPacket); InsertSpan_ChangeRecordSessionPacket() : m_sText("") {} InsertSpan_ChangeRecordSessionPacket( const UT_UTF8String& sSessionId, PX_ChangeRecord::PXType cType, const UT_UTF8String& sDocUUID, int iPos, int iRev, int iRemoteRev, PacketSessionType crType) : ChangeRecordSessionPacket( sSessionId, cType, sDocUUID, iPos, iRev, iRemoteRev, crType ) , m_sText("") {} virtual std::string toStr() const { return ChangeRecordSessionPacket::toStr() + str(boost::format("InsertSpan_ChangeRecordSessionPacket: m_sText: %1%\n") % m_sText.utf8_str()); } // XXX: make proper setters/getters when done! UT_UTF8String m_sText; }; class ABI_EXPORT ChangeStrux_ChangeRecordSessionPacket : public Props_ChangeRecordSessionPacket { public: DECLARE_PACKET(ChangeStrux_ChangeRecordSessionPacket); ChangeStrux_ChangeRecordSessionPacket() : m_eStruxType(PTStruxType(0)) {} ChangeStrux_ChangeRecordSessionPacket( const UT_UTF8String& sSessionId, PX_ChangeRecord::PXType cType, const UT_UTF8String& sDocUUID, int iPos, int iRev, int iRemoteRev, PacketSessionType crType) : Props_ChangeRecordSessionPacket( sSessionId, cType, sDocUUID, iPos, iRev, iRemoteRev, crType ) {} virtual std::string toStr() const { return Props_ChangeRecordSessionPacket::toStr() + str(boost::format("ChangeStrux_ChangeRecordSessionPacket: m_eStruxType: %1%\n") % m_eStruxType); } // XXX: make proper setters/getters when done! PTStruxType m_eStruxType; }; class ABI_EXPORT DeleteStrux_ChangeRecordSessionPacket : public ChangeRecordSessionPacket { public: DECLARE_PACKET(DeleteStrux_ChangeRecordSessionPacket); DeleteStrux_ChangeRecordSessionPacket() {} DeleteStrux_ChangeRecordSessionPacket( const UT_UTF8String& sSessionId, PX_ChangeRecord::PXType cType, const UT_UTF8String& sDocUUID, int iPos, int iRev, int iRemoteRev, PacketSessionType crType) : ChangeRecordSessionPacket( sSessionId, cType, sDocUUID, iPos, iRev, iRemoteRev, crType ) {} virtual std::string toStr() const { return ChangeRecordSessionPacket::toStr() + str(boost::format("DeleteStrux_ChangeRecordSessionPacket: m_eStruxType: %1%\n") % m_eStruxType); } // XXX: make proper setters/getters when done! PTStruxType m_eStruxType; }; class ABI_EXPORT Object_ChangeRecordSessionPacket : public Props_ChangeRecordSessionPacket { public: DECLARE_PACKET(Object_ChangeRecordSessionPacket); Object_ChangeRecordSessionPacket() {} Object_ChangeRecordSessionPacket( const UT_UTF8String& sSessionId, PX_ChangeRecord::PXType cType, const UT_UTF8String& sDocUUID, int iPos, int iRev, int iRemoteRev, PacketSessionType crType) : Props_ChangeRecordSessionPacket( sSessionId, cType, sDocUUID, iPos, iRev, iRemoteRev, crType ) {} virtual std::string toStr() const { return Props_ChangeRecordSessionPacket::toStr() + str(boost::format("Object_ChangeRecordSessionPacket: m_eObjectType: %1%\n") % m_eObjectType); } // XXX: make proper setters/getters when done! PTObjectType m_eObjectType; }; class ABI_EXPORT Data_ChangeRecordSessionPacket : public Props_ChangeRecordSessionPacket { public: DECLARE_PACKET(Data_ChangeRecordSessionPacket); Data_ChangeRecordSessionPacket() {} Data_ChangeRecordSessionPacket( const UT_UTF8String& sSessionId, PX_ChangeRecord::PXType cType, const UT_UTF8String& sDocUUID, int iPos, int iRev, int iRemoteRev, PacketSessionType crType) : Props_ChangeRecordSessionPacket( sSessionId, cType, sDocUUID, iPos, iRev, iRemoteRev, crType ) {} virtual std::string toStr() const { return ChangeRecordSessionPacket::toStr() + str(boost::format("Data_ChangeRecordSessionPacket: m_vecData: %1%\n") % "[DATA]"); } // XXX: make proper setters/getters when done! std::vector m_vecData; }; class ABI_EXPORT Glob_ChangeRecordSessionPacket : public ChangeRecordSessionPacket { public: DECLARE_PACKET(Glob_ChangeRecordSessionPacket); Glob_ChangeRecordSessionPacket() {} Glob_ChangeRecordSessionPacket( const UT_UTF8String& sSessionId, PX_ChangeRecord::PXType cType, const UT_UTF8String& sDocUUID, int iPos, int iRev, int iRemoteRev, PacketSessionType crType) : ChangeRecordSessionPacket( sSessionId, cType, sDocUUID, iPos, iRev, iRemoteRev, crType ) {} virtual std::string toStr() const { return ChangeRecordSessionPacket::toStr() + str(boost::format("Glob_ChangeRecordSessionPacket: m_iGLOBType: %1%\n") % ((UT_sint32)m_iGLOBType)); } // XXX: make proper setters/getters when done! UT_Byte m_iGLOBType; }; class ABI_EXPORT GlobSessionPacket : public SessionPacket { public: DECLARE_PACKET(GlobSessionPacket); GlobSessionPacket() {} GlobSessionPacket( const GlobSessionPacket& Other ); GlobSessionPacket( const UT_UTF8String& sSessionId, const UT_UTF8String& sDocUUID ) : SessionPacket(sSessionId, sDocUUID) {} ~GlobSessionPacket(); virtual PacketSessionType getSessionType() const { return PACKET_GLOB; } // I think we can ditch this - MARCM const std::vector& getPackets() const { return m_pPackets; } void addPacket(SessionPacket* pPacket); UT_sint32 getPos() const; UT_sint32 getLength() const; UT_sint32 getAdjust() const; UT_sint32 getRev() const; UT_sint32 getRemoteRev(void) const; virtual std::string toStr() const { std::string globStr = SessionPacket::toStr() + "GlobSessionPacket:\n"; for (std::vector::const_iterator cit = m_pPackets.begin(); cit != m_pPackets.end(); cit++) { globStr += "\n* "; globStr += (*cit)->toStr(); globStr += "\n"; } return globStr; } private: std::vector m_pPackets; }; class ABI_EXPORT SignalSessionPacket : public SessionPacket { public: DECLARE_PACKET(SignalSessionPacket); SignalSessionPacket() {} SignalSessionPacket(const UT_UTF8String& sSessionId, const UT_UTF8String& sDocUUID, UT_uint32 iSignal); virtual PacketSessionType getSessionType() const { return PACKET_SIGNAL; } UT_uint32 getSignalType() const { return m_iSignal; } virtual std::string toStr() const { return SessionPacket::toStr() + str(boost::format("SignalSessionPacket: m_iSignal: %1%\n") % m_iSignal); } private: UT_uint32 m_iSignal; }; class ABI_EXPORT RevertSessionPacket : public SessionPacket { public: DECLARE_PACKET(RevertSessionPacket); RevertSessionPacket() {} RevertSessionPacket(const UT_UTF8String& sSessionId, const UT_UTF8String& sDocUUID, UT_sint32 iRev); virtual PacketSessionType getSessionType() const { return PACKET_REVERT; } UT_sint32 getRev() const { return m_iRev; } virtual std::string toStr() const { return SessionPacket::toStr() + str(boost::format("RevertSessionPacket: m_iRev: %1%\n") % m_iRev); } private: UT_sint32 m_iRev; }; class ABI_EXPORT RevertAckSessionPacket : public SessionPacket { public: DECLARE_PACKET(RevertAckSessionPacket); RevertAckSessionPacket() {} RevertAckSessionPacket(const UT_UTF8String& sSessionId, const UT_UTF8String& sDocUUID, UT_sint32 iRev); virtual PacketSessionType getSessionType() const { return PACKET_REVERT_ACK; } UT_sint32 getRev() const { return m_iRev; } virtual std::string toStr() const { return SessionPacket::toStr() + str(boost::format("RevertAckSessionPacket: m_iRev: %1%\n") % m_iRev); } private: UT_sint32 m_iRev; }; #endif /* ABICOLLAB_PACKET_H */