/*! * @file connection_monitor.h \brief interface for all classes that have to be synchronized */ #ifndef _SYNCHRONIZEABLE_H #define _SYNCHRONIZEABLE_H #include "base_object.h" #include "netdefs.h" #include "converter.h" #include #include //State constants: They have to be of the form 2^n #define STATE_SERVER 1 #define STATE_OUTOFSYNC 2 #define STATE_REQUESTEDSYNC 4 //macros to help writing data in byte buffer /* * Important: these macros must be used in * SYNCHELP_READ_*: virtual void writeBytes(const byte* data, int length, int sender); * SYNCHELP_WRITE_*: virtual int readBytes(byte* data, int maxLength, int * reciever); * with the same argument names! * * SYNCHELP_WRITE_BEGIN() * SYNCHELP_WRITE_INT(i) * SYNCHELP_WRITE_FLOAT(f) * SYNCHELP_WRITE_BYTE(b) * SYNCHELP_WRITE_STRING(s) * SYNCHELP_WRITE_N * * SYNCHELP_READ_BEGIN() * SYNCHELP_READ_INT(i) * SYNCHELP_READ_FLOAT(f) * SYNCHELP_READ_STRING(s,l) l = size of buffer s * SYNCHELP_READ_STRINGM(s) allocates memory for string! you have to free this after * SYNCHELP_READ_BYTE(b) * SYNCHELP_READ_N * * * * Example 1: * SYNCHELP_READ_BEGIN(); * SYNCHELP_READ_FLOAT(size); * SYNCHELP_READ_STRING( textureName, 1024 ); //1024 is the length of textureName * * Example 2: * SYNCHELP_WRITE_BEGIN(); * SYNCHELP_WRITE_FLOAT(this->size); * SYNCHELP_WRITE_STRING(this->textureName); * return SYNCHELP_WRITE_N; * */ #define SYNCHELP_WRITE_BEGIN() int __synchelp_write_i = 0; \ int __synchelp_write_n #define SYNCHELP_WRITE_INT(i) { __synchelp_write_n = \ Converter::intToByteArray( i, data+__synchelp_write_i, maxLength-__synchelp_write_i ); \ assert( __synchelp_write_n == INTSIZE ); \ if ( __synchelp_write_n <= 0) \ { \ PRINTF(1)("Buffer is too small to store a int\n"); \ return 0; \ } \ __synchelp_write_i += __synchelp_write_n; \ } #define SYNCHELP_WRITE_FLOAT(f) { __synchelp_write_n = \ Converter::floatToByteArray( f, data+__synchelp_write_i, maxLength-__synchelp_write_i ); \ assert( __synchelp_write_n == FLOATSIZE ); \ if ( __synchelp_write_n <= 0) \ { \ PRINTF(1)("Buffer is too small to store a float\n"); \ return 0; \ } \ __synchelp_write_i += __synchelp_write_n; \ } #define SYNCHELP_WRITE_BYTE(b) { \ if (maxLength - __synchelp_write_i < 1) \ { \ PRINTF(1)("Buffer is too small to store string\n"); \ return 0; \ } \ data[__synchelp_write_i] = b; \ __synchelp_write_i++; \ } #define SYNCHELP_WRITE_STRING(s) { if (s!=NULL) {\ __synchelp_write_n = \ Converter::stringToByteArray( s, data+__synchelp_write_i, strlen(s), maxLength-__synchelp_write_i ); \ assert( __synchelp_write_n == strlen(s)+INTSIZE ); \ } else {\ __synchelp_write_n = \ Converter::stringToByteArray( "", data+__synchelp_write_i, strlen(""), maxLength-__synchelp_write_i ); \ assert( __synchelp_write_n == strlen("")+INTSIZE ); } \ if ( __synchelp_write_n <= 0) \ { \ PRINTF(1)("Buffer is too small to store string\n"); \ return 0; \ } \ __synchelp_write_i += __synchelp_write_n; \ } #define SYNCHELP_WRITE_N __synchelp_write_i #define SYNCHELP_WRITE_FKT(f) { \ __synchelp_write_i += \ f( data+__synchelp_write_i, maxLength-__synchelp_write_i ); \ } #define SYNCHELP_READ_BEGIN() int __synchelp_read_i = 0; \ int __synchelp_read_n #define SYNCHELP_READ_INT(i) { \ if ( length-__synchelp_read_i < INTSIZE ) \ { \ PRINTF(1)("There is not enough data to read an int\n"); \ return 0; \ } \ __synchelp_read_n = Converter::byteArrayToInt( data+__synchelp_read_i, &i ); \ assert( __synchelp_read_n == INTSIZE ); \ __synchelp_read_i += __synchelp_read_n; \ } #define SYNCHELP_READ_FLOAT(f) { \ if ( length-__synchelp_read_i < FLOATSIZE ) \ { \ PRINTF(1)("There is not enough data to read a flaot\n"); \ return 0; \ } \ __synchelp_read_n = Converter::byteArrayToFloat( data+__synchelp_read_i, &f ); \ assert( __synchelp_read_n == FLOATSIZE ) ;\ __synchelp_read_i += __synchelp_read_n; \ } #define SYNCHELP_READ_STRING(s,l) { \ __synchelp_read_n = Converter::byteArrayToString( data+__synchelp_read_i, s, l ); \ assert( __synchelp_read_n == strlen(s)+INTSIZE ) ;\ if ( __synchelp_read_n <0 ) \ { \ PRINTF(1)("There is not enough data to read string\n"); \ return 0; \ } \ __synchelp_read_i += __synchelp_read_n; \ } #define SYNCHELP_READ_STRINGM(s) { \ __synchelp_read_n = Converter::byteArrayToStringM( data+__synchelp_read_i, s ); \ assert( __synchelp_read_n == strlen(s)+INTSIZE ) ;\ if ( __synchelp_read_n <0 ) \ { \ PRINTF(1)("There is not enough data to read string\n"); \ return 0; \ } \ __synchelp_read_i += __synchelp_read_n; \ } #define SYNCHELP_READ_BYTE(b) { \ if ( length-__synchelp_read_i < 1 ) \ { \ PRINTF(1)("There is not enough data to read a byte\n"); \ return 0; \ } \ b = data[__synchelp_read_i]; \ __synchelp_read_i ++; \ } #define SYNCHELP_READ_FKT(f) { \ __synchelp_read_i += \ f( data+__synchelp_read_i, length-__synchelp_read_i, sender); \ } #define SYNCHELP_READ_N __synchelp_read_i class NetworkStream; class Synchronizeable : virtual public BaseObject { public: Synchronizeable(); virtual ~Synchronizeable(); virtual int writeBytes(const byte* data, int length, int sender); virtual int readBytes(byte* data, int maxLength, int * reciever); virtual void writeDebug() const; virtual void readDebug() const; void setIsServer( bool isServer ); void setIsOutOfSync( bool outOfSync ); void setRequestedSync( bool requestedSync ); bool isServer(); bool isOutOfSync(); bool requestedSync(); inline void setUniqueID( int id ){ uniqueID = id; } inline int getUniqueID() const { return uniqueID; } inline int getHostID() { return this->hostID; } inline int getOwner(){ return owner; } inline void setOwner(int owner){ this->owner = owner; } /** @returns true if this Synchronizeable has to be synchronized over network */ inline bool beSynchronized() { return this->bSynchronize; } /** @param bSynchronize sets the Synchronizeable to be sunchronized or not */ inline void setSynchronized(bool bSynchronize) { this->bSynchronize = bSynchronize; } inline void requestSync( int hostID ){ this->synchronizeRequests.push_back( hostID ); } inline int getRequestSync( void ){ if ( this->synchronizeRequests.size()>0 ){ int n = *(synchronizeRequests.begin()); synchronizeRequests.pop_front(); return n; } else { return -1; } }; inline void setNetworkStream(NetworkStream* stream) { this->networkStream = stream; } inline NetworkStream* getNetworkStream() { return this->networkStream; } protected: NetworkStream* networkStream; int state; private: int uniqueID; int owner; int hostID; bool bSynchronize; std::list synchronizeRequests; }; #endif /* _SYNCHRONIZEABLE_H */