#ifndef _CDEV_PACKET_H_ #define _CDEV_PACKET_H_ #include #include #include // ***************************************************************************** // * struct cdevPacketBinaryMap : // * This is the first 32 bit integer that is passed through the socket. It // * contains a bitmap that identifies the version of the packet, as well as // * a bit field that indicates the contents of the packet. This bitfield // * simplifies the process of decoding the packet and results in a smaller // * transmission size. // ***************************************************************************** typedef union { unsigned rawData; struct { unsigned version : 16; unsigned pad : 16; } value; } cdevPacketBinaryMap; // ***************************************************************************** // * class cdevPacketBinary : // * This is the base class for all cdevPacketBinary classes. It is a pure // * virtual class that defines the mechanisms necessary for identifying // * the version of a class as well as reading or generating a binary // * stream. // * // * Enforced structural contraints... // * // * 1) Every packet that inherits from the cdevPacketBinary must have an // * XDR encoded 4 byte integer at the beginning... // * // * a) The first two bytes of that 4 byte integer is the packet version. // * // * b) The second two bytes of that 4 byte integer is user defined data. // * // * 2) The next four bytes of the packet contains a XDR encoded short // * integer that contains a 16 bit client identifier. // ***************************************************************************** class GENERIC_SERVER_API cdevPacketBinary { protected: // ********************************************************************* // * These are the data storage variables. // ********************************************************************* char * binary; size_t binaryLen; public: cdevPacketBinary ( void ); cdevPacketBinary ( cdevPacketBinary & packet ); virtual ~cdevPacketBinary ( void ); unsigned map2int ( cdevPacketBinaryMap map, unsigned & value); cdevPacketBinaryMap int2map ( cdevPacketBinaryMap &map, unsigned value); virtual int getVersion ( short & version ); virtual int getPad ( short & pad ); virtual int getClientID ( short & clientID ); virtual int setClientID ( short clientID ); virtual int streamOut ( char ** stream, size_t * len ); virtual int streamIn ( char * stream, size_t len ); virtual void detachData ( void ); virtual int attachData ( char * stream, size_t len ); }; // ***************************************************************************** // * cdevPacketBinary::map2int ( void ) // * This method will convert the cdevPacketBinaryMap to a long integer. // ***************************************************************************** inline unsigned cdevPacketBinary::map2int ( cdevPacketBinaryMap map, unsigned & value) { value = (map.value.version << 16); value |= (map.value.pad & 0xFFFF); return value; } // ***************************************************************************** // * cdevPacketBinary::int2map ( void ) // * This method will convert a long integer to a cdevPacketBinaryMap. // ***************************************************************************** inline cdevPacketBinaryMap cdevPacketBinary::int2map ( cdevPacketBinaryMap &map, unsigned value) { map.rawData = 0; map.value.version = (value >> 16); map.value.pad = (value & 0xFFFF); return map; } // ***************************************************************************** // * cdevPacketBinary::getVersion : // * This method is used to obtain the version number of the packet. // * // * Returns 0 on Success or -1 on Error // ***************************************************************************** inline int cdevPacketBinary::getVersion ( short & version ) { int result=-1; XDR_Reader reader; cdevPacketBinaryMap map; version = -1; if(binary!=NULL && binaryLen>0) { unsigned packetMap = 0; reader.attachData(binary, binaryLen); map.rawData = 0; if((result = !reader.get(packetMap))==0) { int2map(map, packetMap); version = map.value.version; } reader.detachData(); } return result; } // ***************************************************************************** // * cdevPacketBinary::getPad : // * This method is used to obtain the 16 bit integer that follows the // * packet version. // ***************************************************************************** inline int cdevPacketBinary::getPad ( short & pad ) { int result=-1; XDR_Reader reader; cdevPacketBinaryMap map; pad = -1; if(binary!=NULL && binaryLen>0) { unsigned packetMap = 0; reader.attachData(binary, binaryLen); map.rawData = 0; if((result = !reader.get(packetMap))==0) { int2map(map, packetMap); pad = map.value.pad; } reader.detachData(); } return result; } // ***************************************************************************** // * cdevPacketBinary::getClientID : // * This method is used to obtain the 16 bit integer that contains the // * client identifier. // ***************************************************************************** inline int cdevPacketBinary::getClientID ( short & clientID ) { int result = -1; XDR_Reader reader; clientID = -1; if(binary!=NULL && binaryLen>0) { reader.attachData(binary, binaryLen); if((result = !xdr_setpos(reader.xdr(), XDR_Sizeof((unsigned)1)))==0) { result = !reader.get(clientID); } reader.detachData(); } return result; } // ***************************************************************************** // * cdevPacketBinary::getClientID : // * This method is used to insert the 16 bit integer that contains the // * client identifier. // ***************************************************************************** inline int cdevPacketBinary::setClientID ( short clientID ) { int result = -1; XDR_Writer writer; if(binary!=NULL && binaryLen>0) { writer.attachData(binary, binaryLen); if((result = !xdr_setpos(writer.xdr(), XDR_Sizeof((unsigned)1)))==0) { result = !writer.put(clientID); } writer.detachData(); } return result; } // ***************************************************************************** // * cdevPacketBinary::streamIn : // * The streamIn function will read a memory buffer provided by the caller // * and then populate the class with these values. This stream remains the // * property of the caller and he is responsible for deleting it. // * // * Returns 0 on Success // ***************************************************************************** inline int cdevPacketBinary::streamIn ( char * stream, size_t len ) { if(binary!=NULL) { delete binary; binary = NULL; } binaryLen = 0; if(len>0 && stream!=NULL) { binary = new char[len]; binaryLen = len; memcpy(binary, stream, binaryLen); } return 0; } // ***************************************************************************** // * cdevPacketBinary::streamOut : // * The streamOut and streamIn functions are the bread and butter of the // * cdevPacketBinary classes. They allow the class to convert itself into a // * binary stream for transmission and then be reconstructed into a class // * when they are received on the other side. // * // * The streamOut function will allocate a memory buffer to the stream // * variable that is sufficient to store the binary representation of // * the data that is to be transmitted. This stream remains the // * property of the cdevPacketBinary class and should not be deleted by the // * caller. // * // * Returns 0 on Success // ***************************************************************************** inline int cdevPacketBinary::streamOut ( char ** stream, size_t * len ) { *stream = binary; *len = binaryLen; return 0; } // ********************************************************************* // * cdevPacketBinary::detachData : // * This method allows the caller to obtain a copy of the binary // * image that is stored in the cdevPacketBinary object (using // * streamOut), and then force the cdevPacket object to detach it // * (preventing it from being deleted when the object is destroyed.) // * // * Returns nothing. // ********************************************************************* inline void cdevPacketBinary::detachData ( void ) { binary = NULL; binaryLen = 0; } // ********************************************************************* // * cdevPacketBinary::attachData : // * This method allows the caller to assign a preallocated binary // * buffer to this object. This prevents the cdevPacketBinary class // * from having to allocate the data. // * // * Returns 0 on Success // ********************************************************************* inline int cdevPacketBinary::attachData ( char * stream, size_t len ) { if(binary!=NULL) { delete binary; binary = NULL; } binaryLen = 0; if(stream!=NULL && len>0) { binary = stream; binaryLen = len; } return 0; } // ***************************************************************************** // * cdevPacketBinary::cdevPacketBinary : // * This is the default constructor for the class. // ***************************************************************************** inline cdevPacketBinary::cdevPacketBinary ( void ) : binary(NULL), binaryLen(0) {} // ***************************************************************************** // * cdevPacketBinary::cdevPacketBinary : // * This is the copy constructor for the class. // ***************************************************************************** inline cdevPacketBinary::cdevPacketBinary ( cdevPacketBinary & packet ) : binary(NULL), binaryLen(0) { streamIn(packet.binary, packet.binaryLen); } // ***************************************************************************** // * cdevPacketBinary::~cdevPacketBinary : // * This is the destructor for the object. // ***************************************************************************** inline cdevPacketBinary::~cdevPacketBinary ( void ) { if(binary!=NULL) { delete binary; binary = NULL; } binaryLen = 0; } #endif /* _CDEV_PACKET_H_ */