Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/proxy/src/lib/network/synchronizeable.cc @ 9627

Last change on this file since 9627 was 9627, checked in by patrick, 18 years ago

intrudoced very much debug information into the permission system since it seems to be THE critical part in this framework. found a bug in the variable setting

File size: 21.5 KB
RevLine 
[5523]1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
[5547]11
[5523]12### File Specific:
[9406]13   main-programmer: Christoph Renner (rennerc@ee.ethz.ch)
14   co-programmer: Patrick Boenzli (patrick@orxonox.ethz.ch)
[5547]15*/
[5523]16
[6139]17#define DEBUG_MODULE_NETWORK
18
[6695]19#include "shared_network_data.h"
20#include "network_stream.h"
[5547]21#include "netdefs.h"
[7954]22#include "network_log.h"
[8068]23#include "network_game_manager.h"
[5529]24
[6695]25#include "state.h"
[5996]26
[6753]27#include <cassert>
[6695]28
29#include "synchronizeable.h"
30
[9406]31#include "converter.h"
[6695]32
33
[9406]34
[5547]35/**
[5807]36 *  default constructor
[5547]37 */
[5996]38Synchronizeable::Synchronizeable()
[5997]39{
[6341]40  this->setClassID(CL_SYNCHRONIZEABLE, "Synchronizeable");
[8068]41  this->owner = 0;
[9406]42//   this->setIsServer(SharedNetworkData::getInstance()->getHostID() == 0);
[6695]43  this->uniqueID = NET_UID_UNASSIGNED;
[6145]44  this->networkStream = NULL;
[6695]45  this->bSynchronize = false;
[9406]46
[6695]47  if( State::isOnline())
48  {
49    NetworkStream* nd = SharedNetworkData::getInstance()->getDefaultSyncStream();
50    assert(nd != NULL);
51    nd->connectSynchronizeable(*this);
52    this->setUniqueID(SharedNetworkData::getInstance()->getNewUniqueID());
53  }
[7954]54
55  /* make sure loadClassId is first synced var because this is read by networkStream */
56  assert( syncVarList.size() == 0 );
[9625]57  mLeafClassId = this->registerVarId( new SynchronizeableInt( (int*)&this->getLeafClassID(), (int*)&this->getLeafClassID(), "leafClassId", PERMISSION_MASTER_SERVER) );
[9406]58
[9625]59  this->registerVar( new SynchronizeableInt( &this->owner, &this->owner, "owner", PERMISSION_MASTER_SERVER ) );
60  this->registerVar( new SynchronizeableString( &this->objectName, &this->objectName, "objectName", PERMISSION_MASTER_SERVER ) );
[5997]61}
62
[5523]63
[5996]64
[5547]65/**
[5807]66 *  default destructor deletes all unneded stuff
[5547]67 */
68Synchronizeable::~Synchronizeable()
[6139]69{
70  if ( this->networkStream )
[9110]71  {
[6139]72    this->networkStream->disconnectSynchronizeable(*this);
[9406]73
[9494]74    // remove the message manager only by the server
75    if ( (SharedNetworkData::getInstance()->isMasterServer() )
[9406]76           && this->beSynchronized() && this->getUniqueID() > 0 && !this->isA( CL_MESSAGE_MANAGER ) )
[9110]77      NetworkGameManager::getInstance()->removeSynchronizeable( this->getUniqueID() );
78  }
[9406]79
[8623]80  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
81  {
82    delete *it;
83  }
84  syncVarList.clear();
[9406]85
[8623]86  for ( UserStateHistory::iterator it = recvStates.begin(); it != recvStates.end(); it++ )
87  {
88    for ( StateHistory::iterator it2 = it->begin(); it2 != it->end(); it2++ )
89    {
90      if ( (*it2)->data )
91      {
92        delete [] (*it2)->data;
93        (*it2)->data = NULL;
94      }
95      delete *it2;
96    }
97
98  }
[9406]99
[8623]100  for ( UserStateHistory::iterator it = sentStates.begin(); it != sentStates.end(); it++ )
101  {
102    for ( StateHistory::iterator it2 = it->begin(); it2 != it->end(); it2++ )
103    {
104      if ( (*it2)->data )
105      {
106        delete [] (*it2)->data;
107        (*it2)->data = NULL;
108      }
109      delete *it2;
110    }
111  }
[6139]112}
[5523]113
114
[6695]115
[5547]116/**
[9406]117 * creates a diff image from two states
118 * @param userId: the userid of the user where the image will be sent to
119 * @param data: the binary data array to write to
120 * @param maxLength: maximal length of the data written (length of available space in the array)
121 * @param stateId: the state id that this diff will represent
122 * @param priorityTH: the priority threshold: all syncs below this threshold won't be synchronized
123 *
124 * @todo check for permissions
[5547]125 */
[7954]126int Synchronizeable::getStateDiff( int userId, byte* data, int maxLength, int stateId, int fromStateId, int priorityTH )
127{
128  //make sure this user has his history
[9625]129  if ( (int)sentStates.size() <= userId )
[7954]130    sentStates.resize( userId+1 );
[5547]131
[7954]132  //calculate needed memory
133  int neededSize = 0;
[5997]134
[7954]135  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
[8147]136  {
137    //PRINTF(0)("SIZE = %d %s\n", (*it)->getSize(), (*it)->getName().c_str());
[7954]138    neededSize += (*it)->getSize();
[8147]139  }
[5997]140
[7954]141  if ( !( neededSize <= maxLength ) )
142  {
143    PRINTF(0)( "%d > %d\n", neededSize, maxLength );
144    assert(false);
145  }
146
147  //remove older states from history than fromStateId
148  StateHistory::iterator it = sentStates[userId].begin();
149
150  while ( it != sentStates[userId].end() && (*it)->stateId < fromStateId )
151    it++;
152
153  if ( it != sentStates[userId].begin() )
154  {
155    for ( StateHistory::iterator it2 = sentStates[userId].begin(); it2 != it; it2++ )
156    {
157      if ( (*it2)->data != NULL )
158      {
159        delete [] (*it2)->data;
160        (*it2)->data = NULL;
161      }
[9406]162
[8623]163      delete *it2;
[7954]164    }
165    sentStates[userId].erase( sentStates[userId].begin(), it );
166  }
167
168  //find state to create diff from
169  StateHistoryEntry * stateFrom = NULL;
170
171  it = sentStates[userId].begin();
172  while ( it != sentStates[userId].end() && (*it)->stateId != fromStateId )
173    it++;
174
175  if ( it == sentStates[userId].end() )
176  {
177    StateHistoryEntry * initialEntry = new StateHistoryEntry();
178
179    initialEntry->stateId = fromStateId;
180    initialEntry->dataLength = 0;
181    initialEntry->data = NULL;
182
183    stateFrom = initialEntry;
[9406]184
[8623]185    sentStates[userId].push_back( stateFrom );
[7954]186  }
187  else
188    stateFrom = (*it);
189
[8623]190  StateHistoryEntry * stateTo = new StateHistoryEntry;
[7954]191
[8623]192  sentStates[userId].push_back( stateTo );
[9406]193
[7954]194  stateTo->stateId = stateId;
195  stateTo->dataLength = neededSize;
196  stateTo->data = new byte[ neededSize ];
197
198  std::list<int>::iterator sizeIter = stateFrom->sizeList.begin();
199
200  int i = 0;
201  int n;
[9406]202
[8623]203  bool sizeChanged = false;
[7954]204
205  // now do the actual synchronization: kick all variables to write into a common buffer
206  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
207  {
[9625]208
209    ////////////////////////////////
210    // Data SENDING Permissions
211    ////////////////////////////////
[9627]212    bool hasPermission = false;
213    bool b1, b2, b3, b4, b5, b6, b7, b8, b9;
214    b1 = b2 = b3 = b4 = b5 = b6 = b7 = b8 = b9 = false;
[9406]215
[9627]216
[9625]217    // Permission   OWNER accept if:
218    // I am the owner
[9627]219    if(       (*it)->checkPermission( PERMISSION_OWNER ) && this->owner == SharedNetworkData::getInstance()->getHostID()) {
220      hasPermission = true; b1 = true; }
[9625]221    // reciever != owner && owner is local
222    else if(  (*it)->checkPermission( PERMISSION_OWNER ) && userId != this->owner &&
[9627]223                (SharedNetworkData::getInstance()->isUserLocal(this->owner) || this->owner == SharedNetworkData::getInstance()->getHostID())) {
224      hasPermission = true; b2 = true; }
[9625]225
226
227    // Permission   MASTER_SERVER accept if:
228    // im MASTER_SERVER
[9627]229    else if( (*it)->checkPermission( PERMISSION_MASTER_SERVER ) && SharedNetworkData::getInstance()->isMasterServer()) {
230      hasPermission = true; b3 = true; }
[9625]231    // im PROXY_SERVER && reciever == CLIENT
232    else if( (*it)->checkPermission( PERMISSION_MASTER_SERVER ) && SharedNetworkData::getInstance()->isProxyServerActive() &&
[9627]233               SharedNetworkData::getInstance()->isUserClient( userId)) {
234      hasPermission = true;  b4 = true; }
[9625]235
236
237    // Pemission    SERVER accept if:
238    // i am server && reciever == CLIENT
239    else if( (*it)->checkPermission( PERMISSION_SERVER ) && !SharedNetworkData::getInstance()->isClient() &&
[9627]240               SharedNetworkData::getInstance()->isUserClient( userId)) {
241      hasPermission = true; b5 = true; }
[9625]242    // i am SERVER && reciever == SERVER && reciever != owner && ( owner is local || i am owner)
243    else if( (*it)->checkPermission( PERMISSION_SERVER ) && !SharedNetworkData::getInstance()->isClient() &&
244               userId != this->owner &&
[9627]245               ( SharedNetworkData::getInstance()->isUserLocal( userId) || this->owner ==  SharedNetworkData::getInstance()->getHostID())) {
246      hasPermission = true; b6 = true; }
[9625]247
248
249    // Permission   ALL accept if:
[9627]250    else if( (*it)->checkPermission( PERMISSION_ALL )) {
251      hasPermission = true; b7 = true; }
[9625]252    // or else refuse sending data
253    else
254      hasPermission = false;
255
256
[9626]257
[9406]258    if ( sizeIter == stateFrom->sizeList.end() || *sizeIter != (*it)->getSize() )
[8623]259      sizeChanged = true;
[9406]260
[8623]261    if ( ( hasPermission && (*it)->getPriority() >= priorityTH ) || sizeChanged )
[7954]262    {
263      n = (*it)->writeToBuf( stateTo->data+i, stateTo->dataLength - i );
[9579]264      //NETPRINTF(0)("getvar %s %d\n", (*it)->getName().c_str(), n);
[9626]265//       PRINTF(0)("sending %s %d\n", (*it)->getName().c_str(), n);
[9627]266
267//       if( this->isA(CL_PLAYABLE))
268//       {
269//         PRINTF(0)("ms: %i, ps: %i, c: %i, sender: %i, reciever: %i, owner: %i, perm: (ow %i, ms %i, s %i, a %i)\n",
270//         SharedNetworkData::getInstance()->isMasterServer(), SharedNetworkData::getInstance()->isProxyServerActive(), SharedNetworkData::getInstance()->isClient(),
271//         SharedNetworkData::getInstance()->getHostID(), userId, this->owner,
272//         (*it)->checkPermission( PERMISSION_OWNER ), (*it)->checkPermission( PERMISSION_MASTER_SERVER ),
273//         (*it)->checkPermission( PERMISSION_SERVER ), (*it)->checkPermission( PERMISSION_ALL ));
274//         PRINTF(0)("hasPermission: %i, sizeChanged: %i, eval: %i, %i, %i, %i, %i, %i, %i\n", hasPermission, sizeChanged, b1, b2, b3, b4, b5, b6, b7);
275//         PRINTF(0)("sending %s %s %d\n", this->getClassCName(), (*it)->getName().c_str(), n);
276//       }
277
278
[7954]279      stateTo->sizeList.push_back( n );
[9406]280      // this is only for very hardcore debug sessions
281      // (*it)->debug();
[7954]282      i += n;
283    }
284    else
285    {
286      for ( int j = 0; j<(*sizeIter); j++ )
287      {
288        assert( i < stateFrom->dataLength );
289        stateTo->data[i] = stateFrom->data[i];
290        i++;
291      }
292      //NETPRINTF(0)("getvar %s %d\n", (*it)->getName().c_str(), *sizeIter);
293      stateTo->sizeList.push_back( (*sizeIter) );
294    }
295
296    if ( sizeIter != stateFrom->sizeList.end() )
297      sizeIter++;
298  }
299
[8147]300  if ( i != neededSize )
301  {
[9406]302    PRINTF(0)("strange error: (%s) %d != %d\n", this->getClassCName(), i, neededSize);
[8147]303    assert(false);
304  }
[7954]305
306  //write diff to data
307  for ( i = 0; i<neededSize; i++ )
308  {
309    if ( i < stateFrom->dataLength )
310      data[i] = stateTo->data[i] - stateFrom->data[i];
311    else
312      data[i] = stateTo->data[i];
313  }
314
315  return neededSize;
316}
317
[5997]318/**
[9626]319 * sets a new state out of a diff created on another host (recieving data)
[7954]320 * @param userId hostId of user who send me that diff
321 * @param data pointer to diff
322 * @param length length of diff
323 * @param stateId id of current state
324 * @param fromStateId id of the base state id
325 * @return number bytes read
[9406]326 *
[7954]327 * @todo check for permissions
[5997]328 */
[7954]329int Synchronizeable::setStateDiff( int userId, byte* data, int length, int stateId, int fromStateId )
[5997]330{
[7954]331  //make sure this user has his history
[9625]332  if ( (int)recvStates.size() <= userId )
[7954]333    recvStates.resize( userId+1 );
334
335  //create new state
336  StateHistoryEntry * stateTo = new StateHistoryEntry();
337  stateTo->stateId = stateId;
338  stateTo->dataLength = length;
339  stateTo->data = new byte[ length ];
340
341
342  //find state to apply diff to
343  StateHistoryEntry * stateFrom = NULL;
344
[9406]345  // search the state from wich the diff is made of
[7954]346  StateHistory::iterator it = recvStates[userId].begin();
347  while ( it != recvStates[userId].end() && (*it)->stateId != fromStateId )
348    it++;
349
[9406]350  // if this is the first state to receive
[7954]351  if ( it == recvStates[userId].end() )
352  {
353    StateHistoryEntry * initialEntry = new StateHistoryEntry();
354
355    initialEntry->stateId = fromStateId;
356    initialEntry->dataLength = 0;
357    initialEntry->data = NULL;
358
359    stateFrom = initialEntry;
[9406]360
[8623]361    recvStates[userId].push_back( stateFrom );
[7954]362  }
[5997]363  else
[7954]364    stateFrom = (*it);
[9406]365
366
367  // apply diff
[7954]368  for ( int i = 0; i<length; i++ )
369  {
370    if ( i < stateFrom->dataLength )
371      stateTo->data[i] = stateFrom->data[i] + data[i];
372    else
373      stateTo->data[i] = data[i];
374  }
[9406]375
[7954]376  //add state to state history
377  recvStates[userId].push_back( stateTo );
[9406]378
[7954]379  int i = 0;
380  int n = 0;
381  std::list<int> changes;
[9406]382
383  // extract the new state for every client
[7954]384  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
385  {
[9406]386    // DATA PERMISSIONS
387    // check if this synchronizeable has the permissions to write the data
388
[9627]389    bool hasPermission = false;
390    bool b1, b2, b3, b4, b5, b6, b7, b8, b9;
391    b1 = b2 = b3 = b4 = b5 = b6 = b7 = b8 = b9 = false;
[9592]392
[9625]393    ////////////////////////////////
394    // Data RECIEVING Permissions
395    ////////////////////////////////
396
397    // i should never ever receive a state update from a synchronizeable, that belongs to me! If it does somethings wrong with the send rules
398//     assert(   !((*it)->checkPermission( PERMISSION_OWNER ) && this->owner == SharedNetworkData::getInstance()->getHostID()));
399
400
401    // Permission   OWNER accept if:
402    // sender == owner
[9627]403    if(      (*it)->checkPermission( PERMISSION_OWNER ) && this->owner == userId) {
404      hasPermission = true; b1 = true; }
[9625]405    // sender == MASTER_SERVER
[9627]406    else if( (*it)->checkPermission( PERMISSION_OWNER ) && SharedNetworkData::getInstance()->isUserMasterServer( userId)
407               && this->owner != SharedNetworkData::getInstance()->getHostID()) {
408      hasPermission = true; b2 = true; }
[9625]409    // sender == PROXY_SERVER
[9627]410      else if( (*it)->checkPermission( PERMISSION_OWNER ) && SharedNetworkData::getInstance()->isUserProxyServerActive( userId)) {
411        hasPermission = true; b3 = true; }
[9592]412
[9625]413    // Permission   MASTER_SERVER accept if:
414    // sender == MASTER_SERVER
[9627]415    else if( (*it)->checkPermission( PERMISSION_MASTER_SERVER) && SharedNetworkData::getInstance()->isUserMasterServer( userId)) {
416      hasPermission = true; b4 = true; }
[9625]417    // sender == PROXY_SERVER && im not MASTER_SERVER && im not PROXY_SERVER
418    else if( (*it)->checkPermission( PERMISSION_MASTER_SERVER) && SharedNetworkData::getInstance()->isClient() &&
[9627]419               SharedNetworkData::getInstance()->isUserProxyServerActive( userId)) {
420      hasPermission = true; b5 = true; }
[9592]421
[9625]422    // Permission   SERVER accept if:
423    // sender == SERVER
[9627]424    else if( (*it)->checkPermission( PERMISSION_SERVER ) && !SharedNetworkData::getInstance()->isUserClient( userId) ) {
425      hasPermission = true; b6 = true; }
[9592]426
[9625]427    // Pemission    ALL accept if:
[9627]428    else if(  (*it)->checkPermission( PERMISSION_ALL )) {
429      hasPermission = true; b7 = true; }
[9592]430
[9625]431   // no rights to over-write local data
[9406]432    else
433      hasPermission = false;
434
435
436
437    // if it has the permission to write do it
438    if( hasPermission)
[7954]439    {
440      n = (*it)->readFromBuf( stateTo->data + i, stateTo->dataLength - i );
441      i += n;
[9406]442      //NETPRINTF(0)("%s::setvar %s %d\n", getClassCName(), (*it)->getName().c_str(), n);
[9626]443//       PRINTF(0)("recieving: %s %d\n",  (*it)->getName().c_str(), n);
[7954]444      //(*it)->debug();
[9627]445
446//       if( this->isA(CL_PLAYABLE))
447//       {
448//         PRINTF(0)("ms: %i, ps: %i, c: %i, sender: %i, reciever: %i, owner: %i, perm: (ow %i, ms %i, s %i, a %i)\n",
449//         SharedNetworkData::getInstance()->isMasterServer(), SharedNetworkData::getInstance()->isProxyServerActive(), SharedNetworkData::getInstance()->isClient(),
450//         userId, SharedNetworkData::getInstance()->getHostID(), this->owner,
451//         (*it)->checkPermission( PERMISSION_OWNER ), (*it)->checkPermission( PERMISSION_MASTER_SERVER ),
452//         (*it)->checkPermission( PERMISSION_SERVER ), (*it)->checkPermission( PERMISSION_ALL ));
453//         PRINTF(0)("hasPermission: %i, eval: %i, %i, %i, %i, %i, %i, %i\n", hasPermission, b1, b2, b3, b4, b5, b6, b7);
454//         PRINTF(0)("rec %s %s %d\n", this->getClassCName(), (*it)->getName().c_str(), n);
455//       }
456
457
[7954]458      if ( (*it)->getHasChanged() )
459      {
460        changes.push_back( (*it)->getVarId() );
461      }
462    }
463    else
464    {
[9494]465//       PRINTF(0)("DONT SET VAR BECAUSE OF PERMISSION: %s perm: %d %d %d - %d %d %d\n", (*it)->getName().c_str(), (*it)->checkPermission( PERMISSION_MASTER_SERVER ), (*it)->checkPermission( PERMISSION_OWNER ), (*it)->checkPermission( PERMISSION_ALL ), networkStream->isUserMasterServer( userId ), this->owner, userId );
[7954]466      n = (*it)->getSizeFromBuf( stateTo->data + i, stateTo->dataLength - i );
[9406]467      //NETPRINTF(0)("%s::setvar %s %d\n", getClassCName(), (*it)->getName().c_str(), n);
[7954]468      //(*it)->debug();
469      i += n;
470    }
471  }
472
473  this->varChangeHandler( changes );
[9406]474
[7954]475  return i;
[5997]476}
477
[7954]478 /**
479 * override this function to be notified on change
480 * of your registred variables.
481 * @param id id's which have changed
482 */
483void Synchronizeable::varChangeHandler( std::list<int> & id )
484{
485}
[6695]486
[5997]487/**
[7954]488 * registers a varable to be synchronized over network
489 * @param var see src/lib/network/synchronizeable_var/ for available classes
[5997]490 */
[7954]491void Synchronizeable::registerVar( SynchronizeableVar * var )
[5997]492{
[7954]493  syncVarList.push_back( var );
[5997]494}
495
496/**
[7954]497 * registers a varable to be synchronized over network
498 * return value is passed to varChangeHandler on change
499 * @param var see src/lib/network/synchronizeable_var/ for available classes
500 * @return handle passed to varChangeHandler on changes
[5997]501 */
[7954]502int Synchronizeable::registerVarId( SynchronizeableVar * var )
[5997]503{
[7954]504  syncVarList.push_back( var );
505  var->setWatched( true );
506  var->setVarId( syncVarList.size()-1 );
507  return syncVarList.size()-1;
[5997]508}
509
510/**
[7954]511 * removed user's states from memory
512 * @param userId user to clean
[5997]513 */
[7954]514void Synchronizeable::cleanUpUser( int userId )
[5997]515{
[9625]516  if ( (int)recvStates.size() > userId )
[7954]517  {
[8228]518    for ( std::list<StateHistoryEntry*>::iterator it = recvStates[userId].begin(); it != recvStates[userId].end(); it++ )
[7954]519    {
[8228]520      if ( (*it)->data )
[8623]521      {
[8228]522        delete [] (*it)->data;
[8623]523        (*it)->data = NULL;
524      }
[9406]525
[8228]526      delete *it;
[7954]527    }
[8228]528    recvStates[userId].clear();
[7954]529  }
[9406]530
[9625]531  if ( (int)sentStates.size() > userId )
[7954]532  {
[9406]533
[8228]534    for ( std::list<StateHistoryEntry*>::iterator it = sentStates[userId].begin(); it != sentStates[userId].end(); it++ )
[7954]535    {
[8228]536      if ( (*it)->data )
[8623]537      {
[8228]538        delete [] (*it)->data;
[8623]539        (*it)->data = NULL;
540      }
[9406]541
[8228]542      delete *it;
[7954]543    }
[8228]544    sentStates[userId].clear();
[7954]545  }
[5997]546}
[6139]547
[6341]548/**
[7954]549 * this function is called after recieving a state.
[9406]550 * @param userId
551 * @param stateId
552 * @param fromStateId
[6341]553 */
[7954]554void Synchronizeable::handleRecvState( int userId, int stateId, int fromStateId )
[6341]555{
[7954]556   //make sure this user has his history
[9625]557  if ( (int)recvStates.size() <= userId )
[7954]558    recvStates.resize( userId+1 );
[9406]559
[7954]560  //remove old states
561  StateHistory::iterator it = recvStates[userId].begin();
562
563#if 0
564  while ( it != recvStates[userId].end() && (*it)->stateId < fromStateId )
565    it++;
566
567  if ( it != recvStates[userId].begin() )
568  {
569    for ( StateHistory::iterator it2 = recvStates[userId].begin(); it2 != it; it2++ )
570    {
571      if ( (*it2)->data != NULL )
572      {
573        delete [] (*it2)->data;
574        (*it2)->data = NULL;
575      }
576    }
577    recvStates[userId].erase( recvStates[userId].begin(), it );
578  }
579#endif
580
581  for ( it = recvStates[userId].begin(); it != recvStates[userId].end();  )
582  {
583    if ( (*it)->stateId < fromStateId )
584    {
585      StateHistory::iterator delIt = it;
586      it ++;
[9406]587
[7954]588      if ( (*delIt)->data )
[8623]589      {
[7954]590        delete [] (*delIt)->data;
[8623]591        (*delIt)->data = NULL;
592      }
593      delete *delIt;
[7954]594      recvStates[userId].erase( delIt );
[9406]595
[7954]596      continue;
597    }
598    it++;
599  }
[9406]600
[7954]601  StateHistory::iterator fromState = recvStates[userId].end();
602  StateHistory::iterator toState = recvStates[userId].end();
[9406]603
[7954]604  for ( it = recvStates[userId].begin(); it != recvStates[userId].end(); it++ )
605  {
606    if ( (*it)->stateId == stateId )
607      toState = it;
608    if ( (*it)->stateId == fromStateId )
609      fromState = it;
[9406]610
[7954]611    if ( fromState != recvStates[userId].end() && toState != recvStates[userId].end() )
612      break;
613  }
[9406]614
[7954]615  // setStateDiff was not called and i know fromStateId
616  if ( fromState != recvStates[userId].end() && toState == recvStates[userId].end() )
617  {
618    StateHistoryEntry * entry = new StateHistoryEntry;
[9406]619
[7954]620    entry->dataLength = (*fromState)->dataLength;
621    if ( entry->dataLength > 0 )
622    {
623      entry->data = new byte[entry->dataLength];
[9406]624
[7954]625      assert( (*fromState)->data );
626      memcpy( entry->data, (*fromState)->data, entry->dataLength );
627    }
628    else
629      entry->data = NULL;
[9406]630
[7954]631    entry->sizeList = (*fromState)->sizeList;
632    entry->stateId = stateId;
[9406]633
[7954]634    recvStates[userId].push_back(entry);
635  }
[6341]636}
[6139]637
[6341]638/**
[7954]639 * this function is called after sending a state
[9406]640 * @param userId
641 * @param stateId
642 * @param fromStateId
[6341]643 */
[7954]644void Synchronizeable::handleSentState( int userId, int stateId, int fromStateId )
[6341]645{
[7954]646   //make sure this user has his history
[9625]647  if ( (int)sentStates.size() <= userId )
[7954]648    sentStates.resize( userId+1 );
649
650   //remove old states
651  StateHistory::iterator it = sentStates[userId].begin();
652
653  for ( it = sentStates[userId].begin(); it != sentStates[userId].end();  )
654  {
655    if ( (*it)->stateId < fromStateId )
656    {
657      StateHistory::iterator delIt = it;
658      it ++;
[9406]659
[7954]660      if ( (*delIt)->data )
[8623]661      {
[7954]662        delete [] (*delIt)->data;
[8623]663        (*delIt)->data = NULL;
664      }
665      delete *delIt;
[7954]666      sentStates[userId].erase( delIt );
[9406]667
[7954]668      continue;
669    }
670    it++;
671  }
672
[9406]673
[7954]674  StateHistory::iterator fromState = sentStates[userId].end();
675  StateHistory::iterator toState = sentStates[userId].end();
[9406]676
[7954]677  for ( it = sentStates[userId].begin(); it != sentStates[userId].end(); it++ )
678  {
679    if ( (*it)->stateId == stateId )
680      toState = it;
681    if ( (*it)->stateId == fromStateId )
682      fromState = it;
[9406]683
[7954]684    if ( fromState != sentStates[userId].end() && toState != sentStates[userId].end() )
685      break;
686  }
687
[9406]688
[7954]689  // getStateDiff was not called and i know fromStateId
690  if ( fromState != sentStates[userId].end() && toState == sentStates[userId].end() )
691  {
692    StateHistoryEntry * entry = new StateHistoryEntry;
[9406]693
[7954]694    entry->dataLength = (*fromState)->dataLength;
695    if ( entry->dataLength > 0 )
696    {
697      entry->data = new byte[entry->dataLength];
[9406]698
[7954]699      assert( (*fromState)->data );
700      memcpy( entry->data, (*fromState)->data, entry->dataLength );
701    }
702    else
703      entry->data = NULL;
[9406]704
[7954]705    entry->sizeList = (*fromState)->sizeList;
706    entry->stateId = stateId;
[9406]707
[7954]708    sentStates[userId].push_back(entry);
709  }
[9406]710
[6341]711}
[6139]712
[6341]713
714
Note: See TracBrowser for help on using the repository browser.