Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

proxy server accepts clients again, some doc

File size: 21.3 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
203  bool hasPermission = false;
[8623]204  bool sizeChanged = false;
[7954]205
206  // now do the actual synchronization: kick all variables to write into a common buffer
207  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
208  {
[9625]209
[9406]210    // DATA PERMISSIONS
211    // check if this synchronizeable has the permissions to write the data
212
[9625]213#if 0
[9591]214    //  MASTER_SERVER |====> *
[9406]215    if( SharedNetworkData::getInstance()->isMasterServer() && (*it)->checkPermission( PERMISSION_MASTER_SERVER ))
216      hasPermission = true;
[9606]217    else if( SharedNetworkData::getInstance()->isMasterServer()  && this->networkStream->isUserLocal(userId) &&
218             this->owner != userId && (*it)->checkPermission( PERMISSION_OWNER ))
[9591]219      hasPermission = true;
[9592]220
[9591]221    // PROXY_SERVER  |====> *
[9494]222    else if( SharedNetworkData::getInstance()->isProxyServerActive() && (*it)->checkPermission( PERMISSION_PROXY_SERVER ))
[9406]223      hasPermission = true;
[9606]224    else if( SharedNetworkData::getInstance()->isProxyServerActive() && this->networkStream->isUserLocal(userId) &&
225             this->owner != userId && (*it)->checkPermission( PERMISSION_OWNER ))
[9591]226      hasPermission = true;
[9592]227    // PROXY_SERVER  |====> MASTER_SERVER
228    else if( SharedNetworkData::getInstance()->isProxyServerActive() && this->networkStream->isUserMasterServer(userId)
229             && this->networkStream->isUserLocal(userId) && (*it)->checkPermission( PERMISSION_MASTER_SERVER))
[9406]230      hasPermission = true;
[9592]231    // PROXY_SERVER  |====> CLIENT
232    else if( SharedNetworkData::getInstance()->isProxyServerActive() && this->networkStream->isUserClient(userId)
233             && this->owner != userId && (*it)->checkPermission( PERMISSION_OWNER ) )
[9406]234      hasPermission = true;
[9494]235    else if( SharedNetworkData::getInstance()->isProxyServerActive() && this->networkStream->isUserClient(userId)
[9581]236             && (*it)->checkPermission( PERMISSION_MASTER_SERVER) )
237      hasPermission = true;
[9592]238
239    // OWNER         |====> *
240    else if( this->owner == SharedNetworkData::getInstance()->getHostID() && (*it)->checkPermission( PERMISSION_OWNER ))
[9588]241      hasPermission = true;
[9592]242
243    // ALL           |====> *
244    else if( (*it)->checkPermission( PERMISSION_ALL ))
[9406]245      hasPermission = true;
[9592]246
[9406]247    else
248      hasPermission = false;
[9625]249#endif
[9406]250
[9625]251    ////////////////////////////////
252    // Data SENDING Permissions
253    ////////////////////////////////
[9406]254
[9625]255    // Permission   OWNER accept if:
256    // I am the owner
257    if(       (*it)->checkPermission( PERMISSION_OWNER ) && this->owner == SharedNetworkData::getInstance()->getHostID())
258      hasPermission = true;
259    // reciever != owner && owner is local
260    else if(  (*it)->checkPermission( PERMISSION_OWNER ) && userId != this->owner &&
261                (SharedNetworkData::getInstance()->isUserLocal(this->owner) || this->owner == SharedNetworkData::getInstance()->getHostID()))
262      hasPermission = true;
263
264
265    // Permission   MASTER_SERVER accept if:
266    // im MASTER_SERVER
267    else if( (*it)->checkPermission( PERMISSION_MASTER_SERVER ) && SharedNetworkData::getInstance()->isMasterServer())
268      hasPermission = true;
269    // im PROXY_SERVER && reciever == CLIENT
270    else if( (*it)->checkPermission( PERMISSION_MASTER_SERVER ) && SharedNetworkData::getInstance()->isProxyServerActive() &&
271               SharedNetworkData::getInstance()->isUserClient( userId))
272      hasPermission = true;
273
274
275    // Pemission    SERVER accept if:
276    // i am server && reciever == CLIENT
277    else if( (*it)->checkPermission( PERMISSION_SERVER ) && !SharedNetworkData::getInstance()->isClient() &&
278               SharedNetworkData::getInstance()->isUserClient( userId))
279      hasPermission = true;
280    // i am SERVER && reciever == SERVER && reciever != owner && ( owner is local || i am owner)
281    else if( (*it)->checkPermission( PERMISSION_SERVER ) && !SharedNetworkData::getInstance()->isClient() &&
282               userId != this->owner &&
283               ( SharedNetworkData::getInstance()->isUserLocal( userId) || this->owner ==  SharedNetworkData::getInstance()->getHostID()))
284      hasPermission = true;
285
286
287    // Permission   ALL accept if:
288    else if( (*it)->checkPermission( PERMISSION_ALL ))
289      hasPermission = true;
290
291
292    // or else refuse sending data
293    else
294      hasPermission = false;
295
296
[9626]297
298
[9406]299    if ( sizeIter == stateFrom->sizeList.end() || *sizeIter != (*it)->getSize() )
[8623]300      sizeChanged = true;
[9406]301
[8623]302    if ( ( hasPermission && (*it)->getPriority() >= priorityTH ) || sizeChanged )
[7954]303    {
304      n = (*it)->writeToBuf( stateTo->data+i, stateTo->dataLength - i );
[9579]305      //NETPRINTF(0)("getvar %s %d\n", (*it)->getName().c_str(), n);
[9626]306//       PRINTF(0)("sending %s %d\n", (*it)->getName().c_str(), n);
[7954]307      stateTo->sizeList.push_back( n );
[9406]308      // this is only for very hardcore debug sessions
309      // (*it)->debug();
[7954]310      i += n;
311    }
312    else
313    {
314      for ( int j = 0; j<(*sizeIter); j++ )
315      {
316        assert( i < stateFrom->dataLength );
317        stateTo->data[i] = stateFrom->data[i];
318        i++;
319      }
320      //NETPRINTF(0)("getvar %s %d\n", (*it)->getName().c_str(), *sizeIter);
321      stateTo->sizeList.push_back( (*sizeIter) );
322    }
323
324    if ( sizeIter != stateFrom->sizeList.end() )
325      sizeIter++;
326  }
327
[8147]328  if ( i != neededSize )
329  {
[9406]330    PRINTF(0)("strange error: (%s) %d != %d\n", this->getClassCName(), i, neededSize);
[8147]331    assert(false);
332  }
[7954]333
334  //write diff to data
335  for ( i = 0; i<neededSize; i++ )
336  {
337    if ( i < stateFrom->dataLength )
338      data[i] = stateTo->data[i] - stateFrom->data[i];
339    else
340      data[i] = stateTo->data[i];
341  }
342
343  return neededSize;
344}
345
[5997]346/**
[9626]347 * sets a new state out of a diff created on another host (recieving data)
[7954]348 * @param userId hostId of user who send me that diff
349 * @param data pointer to diff
350 * @param length length of diff
351 * @param stateId id of current state
352 * @param fromStateId id of the base state id
353 * @return number bytes read
[9406]354 *
[7954]355 * @todo check for permissions
[5997]356 */
[7954]357int Synchronizeable::setStateDiff( int userId, byte* data, int length, int stateId, int fromStateId )
[5997]358{
[7954]359  //make sure this user has his history
[9625]360  if ( (int)recvStates.size() <= userId )
[7954]361    recvStates.resize( userId+1 );
362
363  //create new state
364  StateHistoryEntry * stateTo = new StateHistoryEntry();
365  stateTo->stateId = stateId;
366  stateTo->dataLength = length;
367  stateTo->data = new byte[ length ];
368
369
370  //find state to apply diff to
371  StateHistoryEntry * stateFrom = NULL;
372
[9406]373  // search the state from wich the diff is made of
[7954]374  StateHistory::iterator it = recvStates[userId].begin();
375  while ( it != recvStates[userId].end() && (*it)->stateId != fromStateId )
376    it++;
377
[9406]378  // if this is the first state to receive
[7954]379  if ( it == recvStates[userId].end() )
380  {
381    StateHistoryEntry * initialEntry = new StateHistoryEntry();
382
383    initialEntry->stateId = fromStateId;
384    initialEntry->dataLength = 0;
385    initialEntry->data = NULL;
386
387    stateFrom = initialEntry;
[9406]388
[8623]389    recvStates[userId].push_back( stateFrom );
[7954]390  }
[5997]391  else
[7954]392    stateFrom = (*it);
[9406]393
394
395  // apply diff
[7954]396  for ( int i = 0; i<length; i++ )
397  {
398    if ( i < stateFrom->dataLength )
399      stateTo->data[i] = stateFrom->data[i] + data[i];
400    else
401      stateTo->data[i] = data[i];
402  }
[9406]403
[7954]404  //add state to state history
405  recvStates[userId].push_back( stateTo );
[9406]406
[7954]407  int i = 0;
408  int n = 0;
409  std::list<int> changes;
[9406]410  bool hasPermission = false;
411
412  // extract the new state for every client
[7954]413  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
414  {
[9406]415    // DATA PERMISSIONS
416    // check if this synchronizeable has the permissions to write the data
417
[9592]418
[9625]419    ////////////////////////////////
420    // Data RECIEVING Permissions
421    ////////////////////////////////
422
423    // i should never ever receive a state update from a synchronizeable, that belongs to me! If it does somethings wrong with the send rules
424//     assert(   !((*it)->checkPermission( PERMISSION_OWNER ) && this->owner == SharedNetworkData::getInstance()->getHostID()));
425
426
427    // Permission   OWNER accept if:
428    // sender == owner
429    if(      (*it)->checkPermission( PERMISSION_OWNER ) && this->owner == userId)
[9406]430      hasPermission = true;
[9625]431    // sender == MASTER_SERVER
432    else if( (*it)->checkPermission( PERMISSION_OWNER ) && SharedNetworkData::getInstance()->isUserMasterServer( userId))
[9592]433      hasPermission = true;
[9625]434    // sender == PROXY_SERVER
435    else if( (*it)->checkPermission( PERMISSION_OWNER ) && SharedNetworkData::getInstance()->isUserProxyServerActive( userId))
436      hasPermission = true;
[9592]437
[9625]438    // Permission   MASTER_SERVER accept if:
439    // sender == MASTER_SERVER
440    else if( (*it)->checkPermission( PERMISSION_MASTER_SERVER) && SharedNetworkData::getInstance()->isUserMasterServer( userId))
[9592]441      hasPermission = true;
[9625]442    // sender == PROXY_SERVER && im not MASTER_SERVER && im not PROXY_SERVER
443    else if( (*it)->checkPermission( PERMISSION_MASTER_SERVER) && SharedNetworkData::getInstance()->isClient() &&
444               SharedNetworkData::getInstance()->isUserProxyServerActive( userId))
[9594]445      hasPermission = true;
[9592]446
[9625]447    // Permission   SERVER accept if:
448    // sender == SERVER
449    else if( (*it)->checkPermission( PERMISSION_SERVER ) && !SharedNetworkData::getInstance()->isUserClient( userId) )
[9406]450      hasPermission = true;
[9592]451
[9625]452    // Pemission    ALL accept if:
453    else if(  (*it)->checkPermission( PERMISSION_ALL ))
[9406]454      hasPermission = true;
[9592]455
[9625]456   // no rights to over-write local data
[9406]457    else
458      hasPermission = false;
459
460
461
462    // if it has the permission to write do it
463    if( hasPermission)
[7954]464    {
465      n = (*it)->readFromBuf( stateTo->data + i, stateTo->dataLength - i );
466      i += n;
[9406]467      //NETPRINTF(0)("%s::setvar %s %d\n", getClassCName(), (*it)->getName().c_str(), n);
[9626]468//       PRINTF(0)("recieving: %s %d\n",  (*it)->getName().c_str(), n);
[7954]469      //(*it)->debug();
470      if ( (*it)->getHasChanged() )
471      {
472        changes.push_back( (*it)->getVarId() );
473      }
474    }
475    else
476    {
[9494]477//       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]478      n = (*it)->getSizeFromBuf( stateTo->data + i, stateTo->dataLength - i );
[9406]479      //NETPRINTF(0)("%s::setvar %s %d\n", getClassCName(), (*it)->getName().c_str(), n);
[7954]480      //(*it)->debug();
481      i += n;
482    }
483  }
484
485  this->varChangeHandler( changes );
[9406]486
[7954]487  return i;
[5997]488}
489
[7954]490 /**
491 * override this function to be notified on change
492 * of your registred variables.
493 * @param id id's which have changed
494 */
495void Synchronizeable::varChangeHandler( std::list<int> & id )
496{
497}
[6695]498
[5997]499/**
[7954]500 * registers a varable to be synchronized over network
501 * @param var see src/lib/network/synchronizeable_var/ for available classes
[5997]502 */
[7954]503void Synchronizeable::registerVar( SynchronizeableVar * var )
[5997]504{
[7954]505  syncVarList.push_back( var );
[5997]506}
507
508/**
[7954]509 * registers a varable to be synchronized over network
510 * return value is passed to varChangeHandler on change
511 * @param var see src/lib/network/synchronizeable_var/ for available classes
512 * @return handle passed to varChangeHandler on changes
[5997]513 */
[7954]514int Synchronizeable::registerVarId( SynchronizeableVar * var )
[5997]515{
[7954]516  syncVarList.push_back( var );
517  var->setWatched( true );
518  var->setVarId( syncVarList.size()-1 );
519  return syncVarList.size()-1;
[5997]520}
521
522/**
[7954]523 * removed user's states from memory
524 * @param userId user to clean
[5997]525 */
[7954]526void Synchronizeable::cleanUpUser( int userId )
[5997]527{
[9625]528  if ( (int)recvStates.size() > userId )
[7954]529  {
[8228]530    for ( std::list<StateHistoryEntry*>::iterator it = recvStates[userId].begin(); it != recvStates[userId].end(); it++ )
[7954]531    {
[8228]532      if ( (*it)->data )
[8623]533      {
[8228]534        delete [] (*it)->data;
[8623]535        (*it)->data = NULL;
536      }
[9406]537
[8228]538      delete *it;
[7954]539    }
[8228]540    recvStates[userId].clear();
[7954]541  }
[9406]542
[9625]543  if ( (int)sentStates.size() > userId )
[7954]544  {
[9406]545
[8228]546    for ( std::list<StateHistoryEntry*>::iterator it = sentStates[userId].begin(); it != sentStates[userId].end(); it++ )
[7954]547    {
[8228]548      if ( (*it)->data )
[8623]549      {
[8228]550        delete [] (*it)->data;
[8623]551        (*it)->data = NULL;
552      }
[9406]553
[8228]554      delete *it;
[7954]555    }
[8228]556    sentStates[userId].clear();
[7954]557  }
[5997]558}
[6139]559
[6341]560/**
[7954]561 * this function is called after recieving a state.
[9406]562 * @param userId
563 * @param stateId
564 * @param fromStateId
[6341]565 */
[7954]566void Synchronizeable::handleRecvState( int userId, int stateId, int fromStateId )
[6341]567{
[7954]568   //make sure this user has his history
[9625]569  if ( (int)recvStates.size() <= userId )
[7954]570    recvStates.resize( userId+1 );
[9406]571
[7954]572  //remove old states
573  StateHistory::iterator it = recvStates[userId].begin();
574
575#if 0
576  while ( it != recvStates[userId].end() && (*it)->stateId < fromStateId )
577    it++;
578
579  if ( it != recvStates[userId].begin() )
580  {
581    for ( StateHistory::iterator it2 = recvStates[userId].begin(); it2 != it; it2++ )
582    {
583      if ( (*it2)->data != NULL )
584      {
585        delete [] (*it2)->data;
586        (*it2)->data = NULL;
587      }
588    }
589    recvStates[userId].erase( recvStates[userId].begin(), it );
590  }
591#endif
592
593  for ( it = recvStates[userId].begin(); it != recvStates[userId].end();  )
594  {
595    if ( (*it)->stateId < fromStateId )
596    {
597      StateHistory::iterator delIt = it;
598      it ++;
[9406]599
[7954]600      if ( (*delIt)->data )
[8623]601      {
[7954]602        delete [] (*delIt)->data;
[8623]603        (*delIt)->data = NULL;
604      }
605      delete *delIt;
[7954]606      recvStates[userId].erase( delIt );
[9406]607
[7954]608      continue;
609    }
610    it++;
611  }
[9406]612
[7954]613  StateHistory::iterator fromState = recvStates[userId].end();
614  StateHistory::iterator toState = recvStates[userId].end();
[9406]615
[7954]616  for ( it = recvStates[userId].begin(); it != recvStates[userId].end(); it++ )
617  {
618    if ( (*it)->stateId == stateId )
619      toState = it;
620    if ( (*it)->stateId == fromStateId )
621      fromState = it;
[9406]622
[7954]623    if ( fromState != recvStates[userId].end() && toState != recvStates[userId].end() )
624      break;
625  }
[9406]626
[7954]627  // setStateDiff was not called and i know fromStateId
628  if ( fromState != recvStates[userId].end() && toState == recvStates[userId].end() )
629  {
630    StateHistoryEntry * entry = new StateHistoryEntry;
[9406]631
[7954]632    entry->dataLength = (*fromState)->dataLength;
633    if ( entry->dataLength > 0 )
634    {
635      entry->data = new byte[entry->dataLength];
[9406]636
[7954]637      assert( (*fromState)->data );
638      memcpy( entry->data, (*fromState)->data, entry->dataLength );
639    }
640    else
641      entry->data = NULL;
[9406]642
[7954]643    entry->sizeList = (*fromState)->sizeList;
644    entry->stateId = stateId;
[9406]645
[7954]646    recvStates[userId].push_back(entry);
647  }
[6341]648}
[6139]649
[6341]650/**
[7954]651 * this function is called after sending a state
[9406]652 * @param userId
653 * @param stateId
654 * @param fromStateId
[6341]655 */
[7954]656void Synchronizeable::handleSentState( int userId, int stateId, int fromStateId )
[6341]657{
[7954]658   //make sure this user has his history
[9625]659  if ( (int)sentStates.size() <= userId )
[7954]660    sentStates.resize( userId+1 );
661
662   //remove old states
663  StateHistory::iterator it = sentStates[userId].begin();
664
665  for ( it = sentStates[userId].begin(); it != sentStates[userId].end();  )
666  {
667    if ( (*it)->stateId < fromStateId )
668    {
669      StateHistory::iterator delIt = it;
670      it ++;
[9406]671
[7954]672      if ( (*delIt)->data )
[8623]673      {
[7954]674        delete [] (*delIt)->data;
[8623]675        (*delIt)->data = NULL;
676      }
677      delete *delIt;
[7954]678      sentStates[userId].erase( delIt );
[9406]679
[7954]680      continue;
681    }
682    it++;
683  }
684
[9406]685
[7954]686  StateHistory::iterator fromState = sentStates[userId].end();
687  StateHistory::iterator toState = sentStates[userId].end();
[9406]688
[7954]689  for ( it = sentStates[userId].begin(); it != sentStates[userId].end(); it++ )
690  {
691    if ( (*it)->stateId == stateId )
692      toState = it;
693    if ( (*it)->stateId == fromStateId )
694      fromState = it;
[9406]695
[7954]696    if ( fromState != sentStates[userId].end() && toState != sentStates[userId].end() )
697      break;
698  }
699
[9406]700
[7954]701  // getStateDiff was not called and i know fromStateId
702  if ( fromState != sentStates[userId].end() && toState == sentStates[userId].end() )
703  {
704    StateHistoryEntry * entry = new StateHistoryEntry;
[9406]705
[7954]706    entry->dataLength = (*fromState)->dataLength;
707    if ( entry->dataLength > 0 )
708    {
709      entry->data = new byte[entry->dataLength];
[9406]710
[7954]711      assert( (*fromState)->data );
712      memcpy( entry->data, (*fromState)->data, entry->dataLength );
713    }
714    else
715      entry->data = NULL;
[9406]716
[7954]717    entry->sizeList = (*fromState)->sizeList;
718    entry->stateId = stateId;
[9406]719
[7954]720    sentStates[userId].push_back(entry);
721  }
[9406]722
[6341]723}
[6139]724
[6341]725
726
Note: See TracBrowser for help on using the repository browser.