RTFX  0.3
Real time special effects collaborative visualization and production library.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
RTFXParcel.h
1 #ifndef __RTFX_PARCEL__
2 #define __RTFX_PARCEL__
3 
15 #include <iostream>
16 #include <boost/uuid/uuid.hpp>
17 #include <boost/uuid/uuid_generators.hpp>
18 #include <boost/lexical_cast.hpp>
19 #include <boost/uuid/uuid_io.hpp>
20 #include <time.h>
21 #include <vector>
22 
23 #include "RTFXDebug.h"
24 #include "RTFXHelpers.h"
25 
26 
27 using namespace std;
28 
29 namespace RTFX
30 {
31  /* PLANNING:
32  Format of the message header:
33  [16] boost::uuids::uuid of the message SENDER
34  [16] boost::uuids::uuid id of message?
35  [16] a string name of the mailbox (chatroom) where the data will be deposited
36  [1] a flag indicating if the data is or is not compressed, 0=no, 1=yes
37  [7] empty bits for now
38 
39  When the stream has been received, it is assigned a timestamp (the arrival time).
40  If there are no messages currently being sent:
41  Take out a lock on the mailbox access:
42  - the message is forwarded to the other clients
43  - then, the message is decoded and the contents merged with the mailbox's copy
44  of the scene data [this could have significant memory requirements, keeping
45  a copy of the scene at the server, but, it allows re-connections, new connections
46  etc. to acquire a complete copy without bugging the sourcing clients]
47  Release the lock on the mailbox.
48 
49  If there is a message currently being sent:
50  Take out a lock on the waiting message structure
51  - decode the current message and merge it with the "waiting" message structure
52  Release the lock
53 
54  When the message is sent:
55  - wait for the waiting message to become available
56  Take out a lock on the waiting message structure
57  - encode it into a message stream
58  - delete the data
59  Release lock
60  Send message
61  */
62 
69  class RTFXAPI RTFXParcel
70  {
71  public:
72 
74  RTFXParcel() { isHeaderDecoded = false; }
75 
78  {
79  }
80 
82  void CreateHeader( boost::uuids::uuid _messageID, boost::uuids::uuid _senderID, char * _mailboxID,
83  unsigned int _messageSize, RTFXBIGINT _packetNumber, RTFXBIGINT _packetCount,
84  bool _isCompressed, unsigned int _compressionType, bool _keepData, bool _isRTFX, bool _isBinary )
85  {
86  SetMessageID( _messageID );
87  SetSenderID( _senderID );
88  SetMailboxID( _mailboxID );
89  SetMessageSize( _messageSize );
90  SetPacketNumber( _packetNumber );
91  SetNumberOfPackets( _packetCount );
92  SetCompressed( _isCompressed );
93  SetCompressionType( _compressionType );
94  SetKeepData( _keepData );
95  SetRTFXData( _isRTFX );
96  SetIsBinary( _isBinary );
97 
98  EncodeHeader();
99  isHeaderDecoded = false;
100  }
101 
103  void EncodeUUID( boost::uuids::uuid _encodeMe, unsigned int _startingAt )
104  {
105  for ( unsigned int i = 0; i < 16; i ++ )
106  {
107  data[ _startingAt + i ] = _encodeMe.data[i];
108  }
109  }
110 
112  void EncodeString( char * _encodeMe, unsigned int _startingAt, unsigned int _length )
113  {
114  for ( unsigned int i = 0; i < _length; i ++ )
115  {
116  data[ _startingAt + i ] = _encodeMe[i];
117  }
118  }
119 
121  void EncodeInteger( unsigned int _encodeMe, unsigned int _startingAt )
122  {
123  char * ptr_ = &data[_startingAt];
124  memcpy( ptr_, &_encodeMe, sizeof( unsigned int ) );
125  }
126 
128  void EncodeLong( RTFXBIGINT _encodeMe, RTFXBIGINT _startingAt )
129  {
130  char * ptr_ = &data[_startingAt];
131  memcpy( ptr_, &_encodeMe, sizeof( RTFXBIGINT ) );
132  }
133 
136  void EncodeBoolean( bool _encodeMe, unsigned int _startingAt )
137  {
138  if ( _encodeMe )
139  data[_startingAt] = 124;
140  else
141  data[_startingAt] = 106;
142  }
143 
145  void CreateParcel( boost::uuids::uuid _senderID, boost::uuids::uuid _msgID, char * _mailboxID,
146  unsigned int _msgSize, RTFXBIGINT _pNum, RTFXBIGINT _pCount, bool _compressed,
147  unsigned int _compressionType, bool _keepData, bool _isRTFX, bool _isBinary, const char * _msg )
148  {
149  SetSenderID( _senderID );
150  SetMessageID( _msgID );
151  SetMailboxID( _mailboxID );
152  SetMessageSize( _msgSize );
153  SetPacketNumber( _pNum );
154  SetNumberOfPackets( _pCount );
155  SetCompressed( _compressed );
156  SetMessageData( _msg, _msgSize );
157  SetCompressionType( _compressionType );
158  SetKeepData( _keepData );
159  SetRTFXData( _isRTFX );
160  SetIsBinary( _isBinary );
161 
162  //debug( ostringstream().flush() << "RTFXParcel::CreateParcel: message data - " << _msg << endl );
163  EncodeHeader();
164  }
165 
167  void CreateParcel( boost::uuids::uuid _senderID, boost::uuids::uuid _msgID, char * _mailboxID,
168  unsigned int _msgSize, RTFXBIGINT _pNum, RTFXBIGINT _pCount, bool _compressed,
169  unsigned int _compressionType, bool _keepData, bool _isRTFX, bool _isBinary, char * _msg )
170  {
171  SetSenderID( _senderID );
172  SetMessageID( _msgID );
173  SetMailboxID( _mailboxID );
174  SetMessageSize( _msgSize );
175  SetPacketNumber( _pNum );
176  SetNumberOfPackets( _pCount );
177  SetCompressed( _compressed );
178  SetMessageData( _msg, _msgSize );
179  SetCompressionType( _compressionType );
180  SetKeepData( _keepData );
181  SetIsBinary( _isBinary );
182  SetRTFXData( _isRTFX );
183 
184  //debug( ostringstream().flush() << "RTFXParcel::CreateParcel: message data - " << _msg << endl );
185  EncodeHeader();
186  }
187 
189  void EncodeHeader()
190  {
191  EncodeUUID( senderID, 0 );
192  EncodeUUID( messageID, 16 );
193  EncodeString( ( char * )mailboxID, 32, 16 );
194  EncodeInteger( messageSize, 48 );
195  EncodeLong( packetNumber, 52 );
196  EncodeLong( numberOfPackets, 60 );
197  EncodeBoolean( isCompressed, 68 );
198  EncodeInteger( compressionType, 69 );
199  EncodeBoolean( keepDataAtServer, 73 );
200  EncodeBoolean( isDataRTFX, 74 );
201  EncodeBoolean( isBinary, 75 );
202  }
203 
205  void DecodeUUID( boost::uuids::uuid &_decodeTo, unsigned int _startingAt )
206  {
207  for ( unsigned int i = 0; i < 16; i ++ )
208  {
209  _decodeTo.data[i] = data[ _startingAt + i ];
210  }
211  }
212 
214  void DecodeString( char * _decodeTo, unsigned int _startingAt, unsigned int _length )
215  {
216  for ( unsigned int i = 0; i < _length; i ++ )
217  {
218  _decodeTo[i] = data[ _startingAt + i ];
219  }
220  }
221 
223  void DecodeLong( RTFXBIGINT &_decodeTo, RTFXBIGINT _startingAt )
224  {
225  char * ptr_ = &data[_startingAt];
226  RTFXBIGINT ret_;
227  memcpy( &ret_, ptr_, sizeof( RTFXBIGINT ) );
228  _decodeTo = ret_;
229  }
230 
232  void DecodeInteger( unsigned int &_decodeTo, unsigned int _startingAt )
233  {
234  char * ptr_ = &data[_startingAt];
235  unsigned int ret_;
236  memcpy( &ret_, ptr_, sizeof( unsigned int ) );
237  _decodeTo = ret_;
238  }
239 
241  void DecodeBoolean( bool &_decodeTo, unsigned int _startingAt )
242  {
243  if ( data[_startingAt] == 106 )
244  _decodeTo = false;
245  else
246  _decodeTo = true;
247  }
248 
250  void DecodeHeader()
251  {
252  DecodeUUID( senderID, 0 );
253  DecodeUUID( messageID, 16 );
254  DecodeString( ( char * )mailboxID, 32, 16 );
255  DecodeInteger( messageSize, 48 );
256  DecodeLong( packetNumber, 52 );
257  DecodeLong( numberOfPackets, 60 );
258  DecodeBoolean( isCompressed, 68 );
259  DecodeInteger( compressionType, 69 );
260  DecodeBoolean( keepDataAtServer, 73 );
261  DecodeBoolean( isDataRTFX, 74 );
262  DecodeBoolean( isBinary, 75 );
263 
264  verbose( ostringstream().flush() << "RTFXParcel::DecodeHeader: message size - " << messageSize << endl );
265  isHeaderDecoded = false;
266  }
267 
269  bool IsHeaderDecoded() { return isHeaderDecoded; }
270 
272  static unsigned int GetMaxBodyLength() { return maxBodyLength; }
273 
275  static unsigned int GetHeaderLength() { return headerLength; }
276 
278  static unsigned int GetMaximumLength() { return maximumLength; }
279 
281  void SetMessageID( boost::uuids::uuid _mid ) { messageID = _mid; }
282 
284  boost::uuids::uuid GetMessageID() { return messageID; }
285 
287  void SetSenderID( boost::uuids::uuid _sid ) { senderID = _sid; }
288 
290  boost::uuids::uuid GetSenderID() { return senderID; }
291 
293  void SetMailboxID( char * _mid )
294  {
295  memcpy( mailboxID, _mid, 16 * sizeof( char ) );
296  }
297 
299  char * GetMailboxID() { return ( char * )mailboxID; }
300 
302  void SetMessageSize( unsigned int _ms ) { messageSize = _ms; }
303 
305  unsigned int GetMessageSize() { return messageSize; }
306 
308  void SetPacketNumber( RTFXBIGINT _pn ) { packetNumber = _pn; }
309 
311  RTFXBIGINT GetPacketNumber() { return packetNumber; }
312 
314  void SetNumberOfPackets( RTFXBIGINT _pc ) { numberOfPackets = _pc; }
315 
317  RTFXBIGINT GetNumberOfPackets() { return numberOfPackets; }
318 
320  void SetCompressed( bool _ic ) { isCompressed = _ic; }
321 
323  bool GetCompressed() { return isCompressed; }
324 
326  void SetMessageData( char * _data, unsigned int _length )
327  {
328  for ( unsigned int i = 0; i < _length; i ++ )
329  {
330  data[ headerLength + i ] = _data[i];
331  }
332  }
334  void SetMessageData( const char * _data, unsigned int _length )
335  {
336  for ( unsigned int i = 0; i < _length; i ++ )
337  {
338  data[ headerLength + i ] = _data[i];
339  }
340  }
341 
343  char * GetMessageData()
344  {
345  return ( data + headerLength );
346  }
347 
349  char * GetData()
350  {
351  return data;
352  }
353 
355  void SetCompressionType( unsigned int _type )
356  {
357  // use default of ZLIB if specified type is invalid
358  //if ( _type > 3 ) _type = 1;
359  compressionType = _type;
360  }
361 
363  unsigned int GetCompressionType()
364  {
365  return compressionType;
366  }
367 
369  void SetKeepData( bool _store )
370  {
371  keepDataAtServer = _store;
372  }
373 
375  bool GetKeepData()
376  {
377  return keepDataAtServer;
378  }
379 
381  void SetRTFXData( bool _value )
382  {
383  isDataRTFX = _value;
384  }
385 
387  bool GetRTFXData()
388  {
389  return isDataRTFX;
390  }
391 
393  void SetIsBinary( bool _isBinary )
394  {
395  isBinary = _isBinary;
396  }
397 
399  bool GetIsBinary()
400  {
401  return isBinary;
402  }
403 
404  private:
405 
407  static const unsigned int maxBodyLength = 65458; //63872;
408 
410  static const unsigned int headerLength = 76;
411 
413  static const unsigned int maximumLength = 65534;
414 
416  boost::uuids::uuid senderID; // 16
417 
419  boost::uuids::uuid messageID; // 16
420 
422  char mailboxID[16]; // 16
423 
425  unsigned int messageSize; // 4
426 
428  RTFXBIGINT packetNumber; // 8
429 
431  RTFXBIGINT numberOfPackets; // 8
432 
434  bool isCompressed; // 1
435 
437  unsigned int compressionType; // 4
438 
440  bool keepDataAtServer; // 1
441 
443  bool isBinary; // 1
444 
449  bool isDataRTFX; // 1
450 
452  char data[maximumLength];
453 
455  clock_t arrivalTime;
456 
459  };
460 
463  void CreateParcelList( vector<RTFXParcel> &_parcelList, boost::uuids::uuid _senderID, char * _mailboxName, string &_data, bool _isCompressed, unsigned int _compressionType, bool _keepDataAtServer, bool _isDataRTFX, bool _isBinary );
464 
467  string ReAssembleParcelMessageFromList( vector<RTFXParcel> &_parcelList );
468 }
469 
470 #endif