Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9633 was 9633, checked in by patrick, 19 years ago

override, wrong send perm

File size: 22.1 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 &&
[9633]245               ( SharedNetworkData::getInstance()->isUserLocal( this->owner) || this->owner ==  SharedNetworkData::getInstance()->getHostID())) {
[9627]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
[9628]410      else if( (*it)->checkPermission( PERMISSION_OWNER ) && SharedNetworkData::getInstance()->isUserProxyServerActive( userId) &&
411                 this->owner != SharedNetworkData::getInstance()->getHostID()) {
[9627]412        hasPermission = true; b3 = true; }
[9592]413
[9625]414    // Permission   MASTER_SERVER accept if:
415    // sender == MASTER_SERVER
[9627]416    else if( (*it)->checkPermission( PERMISSION_MASTER_SERVER) && SharedNetworkData::getInstance()->isUserMasterServer( userId)) {
417      hasPermission = true; b4 = true; }
[9625]418    // sender == PROXY_SERVER && im not MASTER_SERVER && im not PROXY_SERVER
419    else if( (*it)->checkPermission( PERMISSION_MASTER_SERVER) && SharedNetworkData::getInstance()->isClient() &&
[9627]420               SharedNetworkData::getInstance()->isUserProxyServerActive( userId)) {
421      hasPermission = true; b5 = true; }
[9592]422
[9625]423    // Permission   SERVER accept if:
424    // sender == SERVER
[9629]425    else if( (*it)->checkPermission( PERMISSION_SERVER ) && !SharedNetworkData::getInstance()->isUserClient( userId) &&
426               SharedNetworkData::getInstance()->isClient()) {
[9627]427      hasPermission = true; b6 = true; }
[9633]428    // sender == SERVER && i am SERVER && user is not local
[9630]429    else if(  (*it)->checkPermission( PERMISSION_SERVER ) &&
430                !SharedNetworkData::getInstance()->isUserClient( userId) &&
[9629]431                !SharedNetworkData::getInstance()->isClient() &&
[9632]432                !SharedNetworkData::getInstance()->isUserLocal( this->owner) &&
433                this->owner !=  SharedNetworkData::getInstance()->getHostID()) {
[9629]434      hasPermission = true; b7 = true; }
[9592]435
[9629]436
[9625]437    // Pemission    ALL accept if:
[9627]438    else if(  (*it)->checkPermission( PERMISSION_ALL )) {
[9629]439      hasPermission = true; b8 = true; }
[9592]440
[9625]441   // no rights to over-write local data
[9406]442    else
443      hasPermission = false;
444
445
446
447    // if it has the permission to write do it
448    if( hasPermission)
[7954]449    {
450      n = (*it)->readFromBuf( stateTo->data + i, stateTo->dataLength - i );
451      i += n;
[9406]452      //NETPRINTF(0)("%s::setvar %s %d\n", getClassCName(), (*it)->getName().c_str(), n);
[9626]453//       PRINTF(0)("recieving: %s %d\n",  (*it)->getName().c_str(), n);
[7954]454      //(*it)->debug();
[9627]455
456//       if( this->isA(CL_PLAYABLE))
457//       {
458//         PRINTF(0)("ms: %i, ps: %i, c: %i, sender: %i, reciever: %i, owner: %i, perm: (ow %i, ms %i, s %i, a %i)\n",
459//         SharedNetworkData::getInstance()->isMasterServer(), SharedNetworkData::getInstance()->isProxyServerActive(), SharedNetworkData::getInstance()->isClient(),
460//         userId, SharedNetworkData::getInstance()->getHostID(), this->owner,
461//         (*it)->checkPermission( PERMISSION_OWNER ), (*it)->checkPermission( PERMISSION_MASTER_SERVER ),
462//         (*it)->checkPermission( PERMISSION_SERVER ), (*it)->checkPermission( PERMISSION_ALL ));
[9629]463//         PRINTF(0)("hasPermission: %i, eval: %i, %i, %i, %i, %i, %i, %i, %i\n", hasPermission, b1, b2, b3, b4, b5, b6, b7, b8);
[9627]464//         PRINTF(0)("rec %s %s %d\n", this->getClassCName(), (*it)->getName().c_str(), n);
465//       }
466
467
[7954]468      if ( (*it)->getHasChanged() )
469      {
470        changes.push_back( (*it)->getVarId() );
471      }
472    }
473    else
474    {
[9494]475//       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]476      n = (*it)->getSizeFromBuf( stateTo->data + i, stateTo->dataLength - i );
[9406]477      //NETPRINTF(0)("%s::setvar %s %d\n", getClassCName(), (*it)->getName().c_str(), n);
[7954]478      //(*it)->debug();
479      i += n;
480    }
481  }
482
483  this->varChangeHandler( changes );
[9406]484
[7954]485  return i;
[5997]486}
487
[7954]488 /**
489 * override this function to be notified on change
490 * of your registred variables.
491 * @param id id's which have changed
492 */
493void Synchronizeable::varChangeHandler( std::list<int> & id )
494{
495}
[6695]496
[5997]497/**
[7954]498 * registers a varable to be synchronized over network
499 * @param var see src/lib/network/synchronizeable_var/ for available classes
[5997]500 */
[7954]501void Synchronizeable::registerVar( SynchronizeableVar * var )
[5997]502{
[7954]503  syncVarList.push_back( var );
[5997]504}
505
506/**
[7954]507 * registers a varable to be synchronized over network
508 * return value is passed to varChangeHandler on change
509 * @param var see src/lib/network/synchronizeable_var/ for available classes
510 * @return handle passed to varChangeHandler on changes
[5997]511 */
[7954]512int Synchronizeable::registerVarId( SynchronizeableVar * var )
[5997]513{
[7954]514  syncVarList.push_back( var );
515  var->setWatched( true );
516  var->setVarId( syncVarList.size()-1 );
517  return syncVarList.size()-1;
[5997]518}
519
520/**
[7954]521 * removed user's states from memory
522 * @param userId user to clean
[5997]523 */
[7954]524void Synchronizeable::cleanUpUser( int userId )
[5997]525{
[9625]526  if ( (int)recvStates.size() > userId )
[7954]527  {
[8228]528    for ( std::list<StateHistoryEntry*>::iterator it = recvStates[userId].begin(); it != recvStates[userId].end(); it++ )
[7954]529    {
[8228]530      if ( (*it)->data )
[8623]531      {
[8228]532        delete [] (*it)->data;
[8623]533        (*it)->data = NULL;
534      }
[9406]535
[8228]536      delete *it;
[7954]537    }
[8228]538    recvStates[userId].clear();
[7954]539  }
[9406]540
[9625]541  if ( (int)sentStates.size() > userId )
[7954]542  {
[9406]543
[8228]544    for ( std::list<StateHistoryEntry*>::iterator it = sentStates[userId].begin(); it != sentStates[userId].end(); it++ )
[7954]545    {
[8228]546      if ( (*it)->data )
[8623]547      {
[8228]548        delete [] (*it)->data;
[8623]549        (*it)->data = NULL;
550      }
[9406]551
[8228]552      delete *it;
[7954]553    }
[8228]554    sentStates[userId].clear();
[7954]555  }
[5997]556}
[6139]557
[6341]558/**
[7954]559 * this function is called after recieving a state.
[9406]560 * @param userId
561 * @param stateId
562 * @param fromStateId
[6341]563 */
[7954]564void Synchronizeable::handleRecvState( int userId, int stateId, int fromStateId )
[6341]565{
[7954]566   //make sure this user has his history
[9625]567  if ( (int)recvStates.size() <= userId )
[7954]568    recvStates.resize( userId+1 );
[9406]569
[7954]570  //remove old states
571  StateHistory::iterator it = recvStates[userId].begin();
572
573#if 0
574  while ( it != recvStates[userId].end() && (*it)->stateId < fromStateId )
575    it++;
576
577  if ( it != recvStates[userId].begin() )
578  {
579    for ( StateHistory::iterator it2 = recvStates[userId].begin(); it2 != it; it2++ )
580    {
581      if ( (*it2)->data != NULL )
582      {
583        delete [] (*it2)->data;
584        (*it2)->data = NULL;
585      }
586    }
587    recvStates[userId].erase( recvStates[userId].begin(), it );
588  }
589#endif
590
591  for ( it = recvStates[userId].begin(); it != recvStates[userId].end();  )
592  {
593    if ( (*it)->stateId < fromStateId )
594    {
595      StateHistory::iterator delIt = it;
596      it ++;
[9406]597
[7954]598      if ( (*delIt)->data )
[8623]599      {
[7954]600        delete [] (*delIt)->data;
[8623]601        (*delIt)->data = NULL;
602      }
603      delete *delIt;
[7954]604      recvStates[userId].erase( delIt );
[9406]605
[7954]606      continue;
607    }
608    it++;
609  }
[9406]610
[7954]611  StateHistory::iterator fromState = recvStates[userId].end();
612  StateHistory::iterator toState = recvStates[userId].end();
[9406]613
[7954]614  for ( it = recvStates[userId].begin(); it != recvStates[userId].end(); it++ )
615  {
616    if ( (*it)->stateId == stateId )
617      toState = it;
618    if ( (*it)->stateId == fromStateId )
619      fromState = it;
[9406]620
[7954]621    if ( fromState != recvStates[userId].end() && toState != recvStates[userId].end() )
622      break;
623  }
[9406]624
[7954]625  // setStateDiff was not called and i know fromStateId
626  if ( fromState != recvStates[userId].end() && toState == recvStates[userId].end() )
627  {
628    StateHistoryEntry * entry = new StateHistoryEntry;
[9406]629
[7954]630    entry->dataLength = (*fromState)->dataLength;
631    if ( entry->dataLength > 0 )
632    {
633      entry->data = new byte[entry->dataLength];
[9406]634
[7954]635      assert( (*fromState)->data );
636      memcpy( entry->data, (*fromState)->data, entry->dataLength );
637    }
638    else
639      entry->data = NULL;
[9406]640
[7954]641    entry->sizeList = (*fromState)->sizeList;
642    entry->stateId = stateId;
[9406]643
[7954]644    recvStates[userId].push_back(entry);
645  }
[6341]646}
[6139]647
[6341]648/**
[7954]649 * this function is called after sending a state
[9406]650 * @param userId
651 * @param stateId
652 * @param fromStateId
[6341]653 */
[7954]654void Synchronizeable::handleSentState( int userId, int stateId, int fromStateId )
[6341]655{
[7954]656   //make sure this user has his history
[9625]657  if ( (int)sentStates.size() <= userId )
[7954]658    sentStates.resize( userId+1 );
659
660   //remove old states
661  StateHistory::iterator it = sentStates[userId].begin();
662
663  for ( it = sentStates[userId].begin(); it != sentStates[userId].end();  )
664  {
665    if ( (*it)->stateId < fromStateId )
666    {
667      StateHistory::iterator delIt = it;
668      it ++;
[9406]669
[7954]670      if ( (*delIt)->data )
[8623]671      {
[7954]672        delete [] (*delIt)->data;
[8623]673        (*delIt)->data = NULL;
674      }
675      delete *delIt;
[7954]676      sentStates[userId].erase( delIt );
[9406]677
[7954]678      continue;
679    }
680    it++;
681  }
682
[9406]683
[7954]684  StateHistory::iterator fromState = sentStates[userId].end();
685  StateHistory::iterator toState = sentStates[userId].end();
[9406]686
[7954]687  for ( it = sentStates[userId].begin(); it != sentStates[userId].end(); it++ )
688  {
689    if ( (*it)->stateId == stateId )
690      toState = it;
691    if ( (*it)->stateId == fromStateId )
692      fromState = it;
[9406]693
[7954]694    if ( fromState != sentStates[userId].end() && toState != sentStates[userId].end() )
695      break;
696  }
697
[9406]698
[7954]699  // getStateDiff was not called and i know fromStateId
700  if ( fromState != sentStates[userId].end() && toState == sentStates[userId].end() )
701  {
702    StateHistoryEntry * entry = new StateHistoryEntry;
[9406]703
[7954]704    entry->dataLength = (*fromState)->dataLength;
705    if ( entry->dataLength > 0 )
706    {
707      entry->data = new byte[entry->dataLength];
[9406]708
[7954]709      assert( (*fromState)->data );
710      memcpy( entry->data, (*fromState)->data, entry->dataLength );
711    }
712    else
713      entry->data = NULL;
[9406]714
[7954]715    entry->sizeList = (*fromState)->sizeList;
716    entry->stateId = stateId;
[9406]717
[7954]718    sentStates[userId].push_back(entry);
719  }
[9406]720
[6341]721}
[6139]722
[6341]723
724
Note: See TracBrowser for help on using the repository browser.