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
Line 
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
11
12### File Specific:
13   main-programmer: Christoph Renner (rennerc@ee.ethz.ch)
14   co-programmer: Patrick Boenzli (patrick@orxonox.ethz.ch)
15*/
16
17#define DEBUG_MODULE_NETWORK
18
19#include "shared_network_data.h"
20#include "network_stream.h"
21#include "netdefs.h"
22#include "network_log.h"
23#include "network_game_manager.h"
24
25#include "state.h"
26
27#include <cassert>
28
29#include "synchronizeable.h"
30
31#include "converter.h"
32
33
34
35/**
36 *  default constructor
37 */
38Synchronizeable::Synchronizeable()
39{
40  this->setClassID(CL_SYNCHRONIZEABLE, "Synchronizeable");
41  this->owner = 0;
42//   this->setIsServer(SharedNetworkData::getInstance()->getHostID() == 0);
43  this->uniqueID = NET_UID_UNASSIGNED;
44  this->networkStream = NULL;
45  this->bSynchronize = false;
46
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  }
54
55  /* make sure loadClassId is first synced var because this is read by networkStream */
56  assert( syncVarList.size() == 0 );
57  mLeafClassId = this->registerVarId( new SynchronizeableInt( (int*)&this->getLeafClassID(), (int*)&this->getLeafClassID(), "leafClassId", PERMISSION_MASTER_SERVER) );
58
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 ) );
61}
62
63
64
65/**
66 *  default destructor deletes all unneded stuff
67 */
68Synchronizeable::~Synchronizeable()
69{
70  if ( this->networkStream )
71  {
72    this->networkStream->disconnectSynchronizeable(*this);
73
74    // remove the message manager only by the server
75    if ( (SharedNetworkData::getInstance()->isMasterServer() )
76           && this->beSynchronized() && this->getUniqueID() > 0 && !this->isA( CL_MESSAGE_MANAGER ) )
77      NetworkGameManager::getInstance()->removeSynchronizeable( this->getUniqueID() );
78  }
79
80  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
81  {
82    delete *it;
83  }
84  syncVarList.clear();
85
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  }
99
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  }
112}
113
114
115
116/**
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
125 */
126int Synchronizeable::getStateDiff( int userId, byte* data, int maxLength, int stateId, int fromStateId, int priorityTH )
127{
128  //make sure this user has his history
129  if ( (int)sentStates.size() <= userId )
130    sentStates.resize( userId+1 );
131
132  //calculate needed memory
133  int neededSize = 0;
134
135  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
136  {
137    //PRINTF(0)("SIZE = %d %s\n", (*it)->getSize(), (*it)->getName().c_str());
138    neededSize += (*it)->getSize();
139  }
140
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      }
162
163      delete *it2;
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;
184
185    sentStates[userId].push_back( stateFrom );
186  }
187  else
188    stateFrom = (*it);
189
190  StateHistoryEntry * stateTo = new StateHistoryEntry;
191
192  sentStates[userId].push_back( stateTo );
193
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;
202
203  bool sizeChanged = false;
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  {
208
209    ////////////////////////////////
210    // Data SENDING Permissions
211    ////////////////////////////////
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;
215
216
217    // Permission   OWNER accept if:
218    // I am the owner
219    if(       (*it)->checkPermission( PERMISSION_OWNER ) && this->owner == SharedNetworkData::getInstance()->getHostID()) {
220      hasPermission = true; b1 = true; }
221    // reciever != owner && owner is local
222    else if(  (*it)->checkPermission( PERMISSION_OWNER ) && userId != this->owner &&
223                (SharedNetworkData::getInstance()->isUserLocal(this->owner) || this->owner == SharedNetworkData::getInstance()->getHostID())) {
224      hasPermission = true; b2 = true; }
225
226
227    // Permission   MASTER_SERVER accept if:
228    // im MASTER_SERVER
229    else if( (*it)->checkPermission( PERMISSION_MASTER_SERVER ) && SharedNetworkData::getInstance()->isMasterServer()) {
230      hasPermission = true; b3 = true; }
231    // im PROXY_SERVER && reciever == CLIENT
232    else if( (*it)->checkPermission( PERMISSION_MASTER_SERVER ) && SharedNetworkData::getInstance()->isProxyServerActive() &&
233               SharedNetworkData::getInstance()->isUserClient( userId)) {
234      hasPermission = true;  b4 = true; }
235
236
237    // Pemission    SERVER accept if:
238    // i am server && reciever == CLIENT
239    else if( (*it)->checkPermission( PERMISSION_SERVER ) && !SharedNetworkData::getInstance()->isClient() &&
240               SharedNetworkData::getInstance()->isUserClient( userId)) {
241      hasPermission = true; b5 = true; }
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 &&
245               ( SharedNetworkData::getInstance()->isUserLocal( userId) || this->owner ==  SharedNetworkData::getInstance()->getHostID())) {
246      hasPermission = true; b6 = true; }
247
248
249    // Permission   ALL accept if:
250    else if( (*it)->checkPermission( PERMISSION_ALL )) {
251      hasPermission = true; b7 = true; }
252    // or else refuse sending data
253    else
254      hasPermission = false;
255
256
257
258    if ( sizeIter == stateFrom->sizeList.end() || *sizeIter != (*it)->getSize() )
259      sizeChanged = true;
260
261    if ( ( hasPermission && (*it)->getPriority() >= priorityTH ) || sizeChanged )
262    {
263      n = (*it)->writeToBuf( stateTo->data+i, stateTo->dataLength - i );
264      //NETPRINTF(0)("getvar %s %d\n", (*it)->getName().c_str(), n);
265//       PRINTF(0)("sending %s %d\n", (*it)->getName().c_str(), n);
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
279      stateTo->sizeList.push_back( n );
280      // this is only for very hardcore debug sessions
281      // (*it)->debug();
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
300  if ( i != neededSize )
301  {
302    PRINTF(0)("strange error: (%s) %d != %d\n", this->getClassCName(), i, neededSize);
303    assert(false);
304  }
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
318/**
319 * sets a new state out of a diff created on another host (recieving data)
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
326 *
327 * @todo check for permissions
328 */
329int Synchronizeable::setStateDiff( int userId, byte* data, int length, int stateId, int fromStateId )
330{
331  //make sure this user has his history
332  if ( (int)recvStates.size() <= userId )
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
345  // search the state from wich the diff is made of
346  StateHistory::iterator it = recvStates[userId].begin();
347  while ( it != recvStates[userId].end() && (*it)->stateId != fromStateId )
348    it++;
349
350  // if this is the first state to receive
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;
360
361    recvStates[userId].push_back( stateFrom );
362  }
363  else
364    stateFrom = (*it);
365
366
367  // apply diff
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  }
375
376  //add state to state history
377  recvStates[userId].push_back( stateTo );
378
379  int i = 0;
380  int n = 0;
381  std::list<int> changes;
382
383  // extract the new state for every client
384  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
385  {
386    // DATA PERMISSIONS
387    // check if this synchronizeable has the permissions to write the data
388
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;
392
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
403    if(      (*it)->checkPermission( PERMISSION_OWNER ) && this->owner == userId) {
404      hasPermission = true; b1 = true; }
405    // sender == MASTER_SERVER
406    else if( (*it)->checkPermission( PERMISSION_OWNER ) && SharedNetworkData::getInstance()->isUserMasterServer( userId)
407               && this->owner != SharedNetworkData::getInstance()->getHostID()) {
408      hasPermission = true; b2 = true; }
409    // sender == PROXY_SERVER
410      else if( (*it)->checkPermission( PERMISSION_OWNER ) && SharedNetworkData::getInstance()->isUserProxyServerActive( userId)) {
411        hasPermission = true; b3 = true; }
412
413    // Permission   MASTER_SERVER accept if:
414    // sender == MASTER_SERVER
415    else if( (*it)->checkPermission( PERMISSION_MASTER_SERVER) && SharedNetworkData::getInstance()->isUserMasterServer( userId)) {
416      hasPermission = true; b4 = true; }
417    // sender == PROXY_SERVER && im not MASTER_SERVER && im not PROXY_SERVER
418    else if( (*it)->checkPermission( PERMISSION_MASTER_SERVER) && SharedNetworkData::getInstance()->isClient() &&
419               SharedNetworkData::getInstance()->isUserProxyServerActive( userId)) {
420      hasPermission = true; b5 = true; }
421
422    // Permission   SERVER accept if:
423    // sender == SERVER
424    else if( (*it)->checkPermission( PERMISSION_SERVER ) && !SharedNetworkData::getInstance()->isUserClient( userId) ) {
425      hasPermission = true; b6 = true; }
426
427    // Pemission    ALL accept if:
428    else if(  (*it)->checkPermission( PERMISSION_ALL )) {
429      hasPermission = true; b7 = true; }
430
431   // no rights to over-write local data
432    else
433      hasPermission = false;
434
435
436
437    // if it has the permission to write do it
438    if( hasPermission)
439    {
440      n = (*it)->readFromBuf( stateTo->data + i, stateTo->dataLength - i );
441      i += n;
442      //NETPRINTF(0)("%s::setvar %s %d\n", getClassCName(), (*it)->getName().c_str(), n);
443//       PRINTF(0)("recieving: %s %d\n",  (*it)->getName().c_str(), n);
444      //(*it)->debug();
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
458      if ( (*it)->getHasChanged() )
459      {
460        changes.push_back( (*it)->getVarId() );
461      }
462    }
463    else
464    {
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 );
466      n = (*it)->getSizeFromBuf( stateTo->data + i, stateTo->dataLength - i );
467      //NETPRINTF(0)("%s::setvar %s %d\n", getClassCName(), (*it)->getName().c_str(), n);
468      //(*it)->debug();
469      i += n;
470    }
471  }
472
473  this->varChangeHandler( changes );
474
475  return i;
476}
477
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}
486
487/**
488 * registers a varable to be synchronized over network
489 * @param var see src/lib/network/synchronizeable_var/ for available classes
490 */
491void Synchronizeable::registerVar( SynchronizeableVar * var )
492{
493  syncVarList.push_back( var );
494}
495
496/**
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
501 */
502int Synchronizeable::registerVarId( SynchronizeableVar * var )
503{
504  syncVarList.push_back( var );
505  var->setWatched( true );
506  var->setVarId( syncVarList.size()-1 );
507  return syncVarList.size()-1;
508}
509
510/**
511 * removed user's states from memory
512 * @param userId user to clean
513 */
514void Synchronizeable::cleanUpUser( int userId )
515{
516  if ( (int)recvStates.size() > userId )
517  {
518    for ( std::list<StateHistoryEntry*>::iterator it = recvStates[userId].begin(); it != recvStates[userId].end(); it++ )
519    {
520      if ( (*it)->data )
521      {
522        delete [] (*it)->data;
523        (*it)->data = NULL;
524      }
525
526      delete *it;
527    }
528    recvStates[userId].clear();
529  }
530
531  if ( (int)sentStates.size() > userId )
532  {
533
534    for ( std::list<StateHistoryEntry*>::iterator it = sentStates[userId].begin(); it != sentStates[userId].end(); it++ )
535    {
536      if ( (*it)->data )
537      {
538        delete [] (*it)->data;
539        (*it)->data = NULL;
540      }
541
542      delete *it;
543    }
544    sentStates[userId].clear();
545  }
546}
547
548/**
549 * this function is called after recieving a state.
550 * @param userId
551 * @param stateId
552 * @param fromStateId
553 */
554void Synchronizeable::handleRecvState( int userId, int stateId, int fromStateId )
555{
556   //make sure this user has his history
557  if ( (int)recvStates.size() <= userId )
558    recvStates.resize( userId+1 );
559
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 ++;
587
588      if ( (*delIt)->data )
589      {
590        delete [] (*delIt)->data;
591        (*delIt)->data = NULL;
592      }
593      delete *delIt;
594      recvStates[userId].erase( delIt );
595
596      continue;
597    }
598    it++;
599  }
600
601  StateHistory::iterator fromState = recvStates[userId].end();
602  StateHistory::iterator toState = recvStates[userId].end();
603
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;
610
611    if ( fromState != recvStates[userId].end() && toState != recvStates[userId].end() )
612      break;
613  }
614
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;
619
620    entry->dataLength = (*fromState)->dataLength;
621    if ( entry->dataLength > 0 )
622    {
623      entry->data = new byte[entry->dataLength];
624
625      assert( (*fromState)->data );
626      memcpy( entry->data, (*fromState)->data, entry->dataLength );
627    }
628    else
629      entry->data = NULL;
630
631    entry->sizeList = (*fromState)->sizeList;
632    entry->stateId = stateId;
633
634    recvStates[userId].push_back(entry);
635  }
636}
637
638/**
639 * this function is called after sending a state
640 * @param userId
641 * @param stateId
642 * @param fromStateId
643 */
644void Synchronizeable::handleSentState( int userId, int stateId, int fromStateId )
645{
646   //make sure this user has his history
647  if ( (int)sentStates.size() <= userId )
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 ++;
659
660      if ( (*delIt)->data )
661      {
662        delete [] (*delIt)->data;
663        (*delIt)->data = NULL;
664      }
665      delete *delIt;
666      sentStates[userId].erase( delIt );
667
668      continue;
669    }
670    it++;
671  }
672
673
674  StateHistory::iterator fromState = sentStates[userId].end();
675  StateHistory::iterator toState = sentStates[userId].end();
676
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;
683
684    if ( fromState != sentStates[userId].end() && toState != sentStates[userId].end() )
685      break;
686  }
687
688
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;
693
694    entry->dataLength = (*fromState)->dataLength;
695    if ( entry->dataLength > 0 )
696    {
697      entry->data = new byte[entry->dataLength];
698
699      assert( (*fromState)->data );
700      memcpy( entry->data, (*fromState)->data, entry->dataLength );
701    }
702    else
703      entry->data = NULL;
704
705    entry->sizeList = (*fromState)->sizeList;
706    entry->stateId = stateId;
707
708    sentStates[userId].push_back(entry);
709  }
710
711}
712
713
714
Note: See TracBrowser for help on using the repository browser.