Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/proxy/src/lib/network/network_stream.cc @ 9279

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

number of players calculus

File size: 24.9 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### File Specific:
12   main-programmer: Christoph Renner rennerc@ee.ethz.ch
13   co-programmer:   Patrick Boenzli  boenzlip@orxonox.ethz.ch
14
15     June 2006: finishing work on the network stream for pps presentation (rennerc@ee.ethz.ch)
16     July 2006: some code rearangement and integration of the proxy server mechanism (boenzlip@ee.ethz.ch)
17*/
18
19
20#define DEBUG_MODULE_NETWORK
21
22
23#include "base_object.h"
24#include "network_protocol.h"
25#include "udp_socket.h"
26#include "udp_server_socket.h"
27#include "monitor/connection_monitor.h"
28#include "monitor/network_monitor.h"
29#include "synchronizeable.h"
30#include "network_game_manager.h"
31#include "shared_network_data.h"
32#include "message_manager.h"
33#include "preferences.h"
34#include "zip.h"
35
36#include "src/lib/util/loading/resource_manager.h"
37
38#include "network_log.h"
39
40#include "player_stats.h"
41
42#include "lib/util/loading/factory.h"
43
44#include "debug.h"
45#include "class_list.h"
46#include <algorithm>
47
48
49#include "network_stream.h"
50
51
52using namespace std;
53
54
55#define PACKAGE_SIZE  256
56
57
58/**
59 * empty constructor
60 */
61NetworkStream::NetworkStream()
62    : DataStream()
63{
64  this->init();
65  /* initialize the references */
66  this->nodeType = NET_CLIENT;
67}
68
69
70/**
71 * start as a client, connect to a server
72 *  @param host: host name (address)
73 *  @param port: port number
74 */
75NetworkStream::NetworkStream( std::string host, int port )
76{
77  this->nodeType = NET_CLIENT;
78  this->init();
79  this->peers[0].socket = new UdpSocket( host, port );
80  this->peers[0].userId = 0;
81  this->peers[0].isMasterServer = true;
82  this->peers[0].connectionMonitor = new ConnectionMonitor( 0 );
83}
84
85
86/**
87 * start as a server
88 *  @param port: at this port
89 */
90NetworkStream::NetworkStream( int port )
91{
92  this->nodeType = NET_MASTER_SERVER;
93  this->init();
94  this->serverSocket = new UdpServerSocket(port);
95}
96
97
98/**
99 * generic init functions
100 */
101void NetworkStream::init()
102{
103  /* set the class id for the base object */
104  this->setClassID(CL_NETWORK_STREAM, "NetworkStream");
105  this->serverSocket = NULL;
106  this->networkGameManager = NULL;
107  this->networkMonitor = new NetworkMonitor(this);
108
109  this->myHostId = 0;
110  this->currentState = 0;
111
112  remainingBytesToWriteToDict = Preferences::getInstance()->getInt( "compression", "writedict", 0 );
113
114  assert( Zip::getInstance()->loadDictionary( "testdict" ) >= 0 );
115  this->dictClient = Zip::getInstance()->loadDictionary( "dict2pl_client" );
116  assert( this->dictClient >= 0 );
117  this->dictServer = Zip::getInstance()->loadDictionary( "dict2p_server" );
118  assert( this->dictServer >= 0 );
119}
120
121
122/**
123 * deconstructor
124 */
125NetworkStream::~NetworkStream()
126{
127  if ( this->serverSocket )
128  {
129    serverSocket->close();
130    delete serverSocket;
131    serverSocket = NULL;
132  }
133  for ( PeerList::iterator i = peers.begin(); i!=peers.end(); i++)
134  {
135    if ( i->second.socket )
136    {
137      i->second.socket->disconnectServer();
138      delete i->second.socket;
139      i->second.socket = NULL;
140    }
141
142    if ( i->second.handshake )
143    {
144      delete i->second.handshake;
145      i->second.handshake = NULL;
146    }
147
148    if ( i->second.connectionMonitor )
149    {
150      delete i->second.connectionMonitor;
151      i->second.connectionMonitor = NULL;
152    }
153  }
154  for ( SynchronizeableList::const_iterator it = getSyncBegin(); it != getSyncEnd(); it ++ )
155    (*it)->setNetworkStream( NULL );
156}
157
158
159/**
160 * creates a new instance of the network game manager
161 */
162void NetworkStream::createNetworkGameManager()
163{
164  this->networkGameManager = NetworkGameManager::getInstance();
165  // setUniqueID( maxCon+2 ) because we need one id for every handshake
166  // and one for handshake to reject client maxCon+1
167  this->networkGameManager->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
168  MessageManager::getInstance()->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
169}
170
171
172/**
173 * starts the network handshake
174 */
175void NetworkStream::startHandshake()
176{
177  Handshake* hs = new Handshake(this->nodeType);
178  hs->setUniqueID( 0 );
179  assert( peers[0].handshake == NULL );
180  peers[0].handshake = hs;
181
182  hs->setPreferedNickName( Preferences::getInstance()->getString( "multiplayer", "nickname", "Player" ) );
183
184//   peers[0].handshake->setSynchronized( true );
185  //this->connectSynchronizeable(*hs);
186  //this->connectSynchronizeable(*hs);
187  PRINTF(0)("NetworkStream: Handshake created: %s\n", hs->getName());
188}
189
190
191/**
192 * this functions connects a synchronizeable to the networkstream, therefore synchronizeing
193 * it all over the network and creating it on the other platforms (if and only if it is a
194 * server
195 */
196void NetworkStream::connectSynchronizeable(Synchronizeable& sync)
197{
198  this->synchronizeables.push_back(&sync);
199  sync.setNetworkStream( this );
200
201//   this->bActive = true;
202}
203
204
205/**
206 * removes the synchronizeable from the list of synchronized entities
207 */
208void NetworkStream::disconnectSynchronizeable(Synchronizeable& sync)
209{
210  // removing the Synchronizeable from the List.
211  std::list<Synchronizeable*>::iterator disconnectSynchro = std::find(this->synchronizeables.begin(), this->synchronizeables.end(), &sync);
212  if (disconnectSynchro != this->synchronizeables.end())
213    this->synchronizeables.erase(disconnectSynchro);
214
215  oldSynchronizeables[sync.getUniqueID()] = SDL_GetTicks();
216}
217
218
219/**
220 * this is called to process data from the network socket to the synchronizeable and vice versa
221 */
222void NetworkStream::processData()
223{
224  int tick = SDL_GetTicks();
225
226  this->currentState++;
227  // there was a wrap around
228  if( this->currentState < 0)
229  {
230    PRINTF(1)("A wrap around in the state variable as occured. The server was running so long? Pls restart server or write a mail to the supporters!\n");
231  }
232
233  if ( this->nodeType == NET_MASTER_SERVER )
234  {
235    // execute everytthing the master server shoudl do
236    if ( serverSocket )
237      serverSocket->update();
238
239    this->updateConnectionList();
240  }
241  else if( this->nodeType == NET_PROXY_SERVER)
242  {
243    // execute everything the proxy server should do
244  }
245  else
246  {
247    // check if the connection is ok else terminate and remove
248    if ( peers[0].socket && ( !peers[0].socket->isOk() || peers[0].connectionMonitor->hasTimedOut() ) )
249    {
250      PRINTF(1)("lost connection to server\n");
251
252      peers[0].socket->disconnectServer();
253      delete peers[0].socket;
254      peers[0].socket = NULL;
255
256      if ( peers[0].handshake )
257        delete peers[0].handshake;
258      peers[0].handshake = NULL;
259
260      if ( peers[0].connectionMonitor )
261        delete peers[0].connectionMonitor;
262      peers[0].connectionMonitor = NULL;
263    }
264  }
265
266  cleanUpOldSyncList();
267  handleHandshakes();
268
269  // order of up/downstream is important!!!!
270  // don't change it
271  handleDownstream( tick );
272  handleUpstream( tick );
273}
274
275
276/**
277 * if we are a server update the connection list to accept new connections (clients)
278 * also start the handsake for the new clients
279 */
280void NetworkStream::updateConnectionList( )
281{
282  //check for new connections
283
284  NetworkSocket* tempNetworkSocket = serverSocket->getNewSocket();
285
286  // we got new network node
287  if ( tempNetworkSocket )
288  {
289    int clientId;
290    // if there is a list of free client id slots, take these
291    if ( freeSocketSlots.size() > 0 )
292    {
293      clientId = freeSocketSlots.back();
294      freeSocketSlots.pop_back();
295      peers[clientId].socket = tempNetworkSocket;
296      peers[clientId].handshake = new Handshake(this->nodeType, clientId, this->networkGameManager->getUniqueID(), MessageManager::getInstance()->getUniqueID() );
297      peers[clientId].connectionMonitor = new ConnectionMonitor( clientId );
298      peers[clientId].handshake->setUniqueID(clientId);
299      peers[clientId].userId = clientId;
300      peers[clientId].isMasterServer = false;
301    }
302    else
303    {
304      clientId = 1;
305
306      for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
307        if ( it->first >= clientId )
308          clientId = it->first + 1;
309
310      peers[clientId].socket = tempNetworkSocket;
311      peers[clientId].handshake = new Handshake(this->nodeType, clientId, this->networkGameManager->getUniqueID(), MessageManager::getInstance()->getUniqueID());
312      peers[clientId].handshake->setUniqueID(clientId);
313      peers[clientId].connectionMonitor = new ConnectionMonitor( clientId );
314      peers[clientId].userId = clientId;
315      peers[clientId].isMasterServer = false;
316
317      PRINTF(0)("num sync: %d\n", synchronizeables.size());
318    }
319
320    // check if there are too many clients connected
321    if ( clientId > MAX_CONNECTIONS )
322    {
323      peers[clientId].handshake->doReject( "too many connections" );
324      PRINTF(0)("Will reject client %d because there are to many connections!\n", clientId);
325    }
326    else
327    {
328      PRINTF(0)("New Client: %d\n", clientId);
329    }
330
331    //this->connectSynchronizeable(*handshakes[clientId]);
332  }
333
334
335
336  //check if connections are ok else remove them
337  for ( PeerList::iterator it = peers.begin(); it != peers.end(); )
338  {
339    if (
340          it->second.socket &&
341          (
342            !it->second.socket->isOk()  ||
343            it->second.connectionMonitor->hasTimedOut()
344          )
345       )
346    {
347      std::string reason = "disconnected";
348      if ( it->second.connectionMonitor->hasTimedOut() )
349        reason = "timeout";
350      PRINTF(0)("Client is gone: %d (%s)\n", it->second.userId, reason.c_str());
351
352
353      // clean up the network data
354      it->second.socket->disconnectServer();
355      delete it->second.socket;
356      it->second.socket = NULL;
357
358      if ( it->second.connectionMonitor )
359        delete it->second.connectionMonitor;
360      it->second.connectionMonitor = NULL;
361
362      if ( it->second.handshake )
363        delete it->second.handshake;
364      it->second.handshake = NULL;
365
366      for ( SynchronizeableList::iterator it2 = synchronizeables.begin(); it2 != synchronizeables.end(); it2++ )
367      {
368        (*it2)->cleanUpUser( it->second.userId );
369      }
370
371      NetworkGameManager::getInstance()->signalLeftPlayer(it->second.userId);
372
373      freeSocketSlots.push_back( it->second.userId );
374
375      PeerList::iterator delit = it;
376      it++;
377
378      peers.erase( delit );
379
380      continue;
381    }
382
383    it++;
384  }
385
386
387}
388
389
390void NetworkStream::debug()
391{
392  if( this->isMasterServer())
393    PRINT(0)(" Host ist Server with ID: %i\n", this->myHostId);
394  else
395    PRINT(0)(" Host ist Client with ID: %i\n", this->myHostId);
396
397  PRINT(0)(" Got %i connected Synchronizeables, showing active Syncs:\n", this->synchronizeables.size());
398  for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++)
399  {
400    if( (*it)->beSynchronized() == true)
401      PRINT(0)("  Synchronizeable of class: %s::%s, with unique ID: %i, Synchronize: %i\n", (*it)->getClassName(), (*it)->getName(),
402               (*it)->getUniqueID(), (*it)->beSynchronized());
403  }
404  PRINT(0)(" Maximal Connections: %i\n", MAX_CONNECTIONS );
405
406}
407
408
409/**
410 * @returns the number of synchronizeables registered to this stream
411 */
412int NetworkStream::getSyncCount()
413{
414  int n = 0;
415  for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++)
416    if( (*it)->beSynchronized() == true)
417      ++n;
418
419  //return synchronizeables.size();
420  return n;
421}
422
423
424/**
425 * check if handshakes completed. if so create the network game manager else remove it again
426 */
427void NetworkStream::handleHandshakes( )
428{
429  for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
430  {
431    if ( it->second.handshake )
432    {
433      // handshake finished
434      if ( it->second.handshake->completed() )
435      {
436        //handshake is correct
437        if ( it->second.handshake->ok() )
438        {
439          if ( !it->second.handshake->allowDel() )
440          {
441            if ( this->nodeType == NET_CLIENT )
442            {
443              SharedNetworkData::getInstance()->setHostID( it->second.handshake->getHostId() );
444              myHostId = SharedNetworkData::getInstance()->getHostID();
445
446//               PRINTF(0)("remote host is a %i\n", it->second.handshake->getRemoteNodeType());
447              it->second.nodeType = it->second.handshake->getRemoteNodeType();
448
449              this->networkGameManager = NetworkGameManager::getInstance();
450              this->networkGameManager->setUniqueID( it->second.handshake->getNetworkGameManagerId() );
451              MessageManager::getInstance()->setUniqueID( it->second.handshake->getMessageManagerId() );
452            }
453
454
455            PRINT(0)("handshake finished id=%d\n", it->second.handshake->getNetworkGameManagerId());
456
457            it->second.handshake->del();
458          }
459          else
460          {
461            // handsheke finished registring new player
462            if ( it->second.handshake->canDel() )
463            {
464              if ( this->nodeType == NET_MASTER_SERVER )
465              {
466                it->second.nodeType = it->second.handshake->getRemoteNodeType();
467
468                handleNewClient( it->second.userId );
469
470                if ( PlayerStats::getStats( it->second.userId ) && it->second.handshake->getPreferedNickName() != "" )
471                {
472                  PlayerStats::getStats( it->second.userId )->setNickName( it->second.handshake->getPreferedNickName() );
473                }
474              }
475
476              PRINT(0)("handshake finished delete it\n");
477              delete it->second.handshake;
478              it->second.handshake = NULL;
479            }
480          }
481
482        }
483        else
484        {
485          PRINT(1)("handshake failed!\n");
486          it->second.socket->disconnectServer();
487        }
488      }
489    }
490  }
491}
492
493
494/**
495 * handle upstream network traffic
496 */
497void NetworkStream::handleUpstream( int tick )
498{
499  int offset;
500  int n;
501
502  for ( PeerList::reverse_iterator peer = peers.rbegin(); peer != peers.rend(); peer++ )
503  {
504    offset = INTSIZE; // reserve enough space for the packet length
505
506    // continue with the next peer if this peer has no socket assigned (therefore no network)
507    if ( !peer->second.socket )
508      continue;
509
510    // header informations: current state
511    n = Converter::intToByteArray( currentState, buf + offset, UDP_PACKET_SIZE - offset );
512    assert( n == INTSIZE );
513    offset += n;
514
515    // header informations: last acked state
516    n = Converter::intToByteArray( peer->second.lastAckedState, buf + offset, UDP_PACKET_SIZE - offset );
517    assert( n == INTSIZE );
518    offset += n;
519
520    // header informations: last recved state
521    n = Converter::intToByteArray( peer->second.lastRecvedState, buf + offset, UDP_PACKET_SIZE - offset );
522    assert( n == INTSIZE );
523    offset += n;
524
525    // now write all synchronizeables in the packet
526    for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
527    {
528      int oldOffset = offset;
529      Synchronizeable & sync = **it;
530
531      // do not include synchronizeables with uninit id and syncs that don't want to be synchronized
532      if ( !sync.beSynchronized() || sync.getUniqueID() < 0 )
533        continue;
534
535      // if handshake not finished only sync handshake
536      if ( peer->second.handshake && sync.getLeafClassID() != CL_HANDSHAKE )
537        continue;
538
539      // if we are a server and this is not our handshake
540      if ( isMasterServer() && sync.getLeafClassID() == CL_HANDSHAKE && sync.getUniqueID() != peer->second.userId )
541        continue;
542
543      /* list of synchronizeables that will never be synchronized over the network: */
544      // do not sync null parent
545      if ( sync.getLeafClassID() == CL_NULL_PARENT )
546        continue;
547
548      assert( offset + INTSIZE <= UDP_PACKET_SIZE );
549
550      // server fakes uniqueid == 0 for handshake
551      if ( this->isMasterServer() && sync.getUniqueID() < MAX_CONNECTIONS - 1 )
552        n = Converter::intToByteArray( 0, buf + offset, UDP_PACKET_SIZE - offset );
553      else
554        n = Converter::intToByteArray( sync.getUniqueID(), buf + offset, UDP_PACKET_SIZE - offset );
555
556      assert( n == INTSIZE );
557      offset += n;
558
559      // make space for size
560      offset += INTSIZE;
561
562      n = sync.getStateDiff( peer->second.userId, buf + offset, UDP_PACKET_SIZE-offset, currentState, peer->second.lastAckedState, -1000 );
563      offset += n;
564
565      assert( Converter::intToByteArray( n, buf + offset - n - INTSIZE, INTSIZE ) == INTSIZE );
566
567      // check if all data bytes == 0 -> remove data and the synchronizeable from the sync process since there is no update
568      // TODO not all synchronizeables like this maybe add Synchronizeable::canRemoveZeroDiff()
569      bool allZero = true;
570      for ( int i = 0; i < n; i++ )
571      {
572         if ( buf[i+oldOffset+2*INTSIZE] != 0 )
573           allZero = false;
574      }
575      // if there is no new data in this synchronizeable reset the data offset to the last state -> dont synchronizes
576      // data that hast not changed
577      if ( allZero )
578      {
579        offset = oldOffset;
580      }
581    } // all synchronizeables written
582
583
584
585    for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
586    {
587      Synchronizeable & sync = **it;
588
589      if ( !sync.beSynchronized() || sync.getUniqueID() < 0 )
590        continue;
591
592      sync.handleSentState( peer->second.userId, currentState, peer->second.lastAckedState );
593    }
594
595
596    assert( Converter::intToByteArray( offset, buf, INTSIZE ) == INTSIZE );
597
598    // now compress the data with the zip library
599    int compLength = 0;
600    if ( this->isMasterServer() )
601      compLength = Zip::getInstance()->zip( buf, offset, compBuf, UDP_PACKET_SIZE, dictServer );
602    else
603      compLength = Zip::getInstance()->zip( buf, offset, compBuf, UDP_PACKET_SIZE, dictClient );
604
605    if ( compLength <= 0 )
606    {
607      PRINTF(1)("compression failed!\n");
608      continue;
609    }
610
611    assert( peer->second.socket->writePacket( compBuf, compLength ) );
612
613    if ( this->remainingBytesToWriteToDict > 0 )
614      writeToNewDict( buf, offset, true );
615
616    peer->second.connectionMonitor->processUnzippedOutgoingPacket( tick, buf, offset, currentState );
617    peer->second.connectionMonitor->processZippedOutgoingPacket( tick, compBuf, compLength, currentState );
618
619  }
620}
621
622/**
623 * handle downstream network traffic
624 */
625void NetworkStream::handleDownstream( int tick )
626{
627  int offset = 0;
628
629  int length = 0;
630  int packetLength = 0;
631  int compLength = 0;
632  int uniqueId = 0;
633  int state = 0;
634  int ackedState = 0;
635  int fromState = 0;
636  int syncDataLength = 0;
637
638  for ( PeerList::iterator peer = peers.begin(); peer != peers.end(); peer++ )
639  {
640
641    if ( !peer->second.socket )
642      continue;
643
644    while ( 0 < (compLength = peer->second.socket->readPacket( compBuf, UDP_PACKET_SIZE )) )
645    {
646      peer->second.connectionMonitor->processZippedIncomingPacket( tick, compBuf, compLength );
647
648      packetLength = Zip::getInstance()->unZip( compBuf, compLength, buf, UDP_PACKET_SIZE );
649
650      if ( packetLength < 4*INTSIZE )
651      {
652        if ( packetLength != 0 )
653          PRINTF(1)("got too small packet: %d\n", packetLength);
654        continue;
655      }
656
657      if ( this->remainingBytesToWriteToDict > 0 )
658        writeToNewDict( buf, packetLength, false );
659
660      assert( Converter::byteArrayToInt( buf, &length ) == INTSIZE );
661      assert( Converter::byteArrayToInt( buf + INTSIZE, &state ) == INTSIZE );
662      assert( Converter::byteArrayToInt( buf + 2*INTSIZE, &fromState ) == INTSIZE );
663      assert( Converter::byteArrayToInt( buf + 3*INTSIZE, &ackedState ) == INTSIZE );
664      offset = 4*INTSIZE;
665
666      peer->second.connectionMonitor->processUnzippedIncomingPacket( tick, buf, packetLength, state, ackedState );
667
668
669      //if this is an old state drop it
670      if ( state <= peer->second.lastRecvedState )
671        continue;
672
673      if ( packetLength != length )
674      {
675        PRINTF(1)("real packet length (%d) and transmitted packet length (%d) do not match!\n", packetLength, length);
676        peer->second.socket->disconnectServer();
677        continue;
678      }
679
680      while ( offset + 2*INTSIZE < length )
681      {
682        assert( offset > 0 );
683        assert( Converter::byteArrayToInt( buf + offset, &uniqueId ) == INTSIZE );
684        offset += INTSIZE;
685
686        assert( Converter::byteArrayToInt( buf + offset, &syncDataLength ) == INTSIZE );
687        offset += INTSIZE;
688
689        assert( syncDataLength > 0 );
690        assert( syncDataLength < 10000 );
691
692        Synchronizeable * sync = NULL;
693
694        for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
695        {
696        //                                        client thinks his handshake has id 0!!!!!
697          if ( (*it)->getUniqueID() == uniqueId || ( uniqueId == 0 && (*it)->getUniqueID() == peer->second.userId ) )
698          {
699            sync = *it;
700            break;
701          }
702        }
703
704        if ( sync == NULL )
705        {
706          PRINTF(0)("could not find sync with id %d. try to create it\n", uniqueId);
707          if ( oldSynchronizeables.find( uniqueId ) != oldSynchronizeables.end() )
708          {
709            offset += syncDataLength;
710            continue;
711          }
712
713          if ( !peers[peer->second.userId].isMasterServer )
714          {
715            offset += syncDataLength;
716            continue;
717          }
718
719          int leafClassId;
720          if ( INTSIZE > length - offset )
721          {
722            offset += syncDataLength;
723            continue;
724          }
725
726          Converter::byteArrayToInt( buf + offset, &leafClassId );
727
728          assert( leafClassId != 0 );
729
730          BaseObject * b = NULL;
731          /* These are some small exeptions in creation: Not all objects can/should be created via Factory */
732          /* Exception 1: NullParent */
733          if( leafClassId == CL_NULL_PARENT || leafClassId == CL_SYNCHRONIZEABLE || leafClassId == CL_NETWORK_GAME_MANAGER )
734          {
735            PRINTF(1)("Can not create Class with ID %x!\n", (int)leafClassId);
736            offset += syncDataLength;
737            continue;
738          }
739          else
740            b = Factory::fabricate( (ClassID)leafClassId );
741
742          if ( !b )
743          {
744            PRINTF(1)("Could not fabricate Object with classID %x\n", leafClassId);
745            offset += syncDataLength;
746            continue;
747          }
748
749          if ( b->isA(CL_SYNCHRONIZEABLE) )
750          {
751            sync = dynamic_cast<Synchronizeable*>(b);
752            sync->setUniqueID( uniqueId );
753            sync->setSynchronized(true);
754
755            PRINTF(0)("Fabricated %s with id %d\n", sync->getClassName(), sync->getUniqueID());
756          }
757          else
758          {
759            PRINTF(1)("Class with ID %x is not a synchronizeable!\n", (int)leafClassId);
760            delete b;
761            offset += syncDataLength;
762            continue;
763          }
764        }
765
766
767        int n = sync->setStateDiff( peer->second.userId, buf+offset, syncDataLength, state, fromState );
768        offset += n;
769        //NETPRINTF(0)("SSSSSEEEEETTTTT: %s %d\n",sync->getClassName(), n);
770
771      }
772
773      if ( offset != length )
774      {
775        PRINTF(0)("offset (%d) != length (%d)\n", offset, length);
776        peer->second.socket->disconnectServer();
777      }
778
779
780      for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
781      {
782        Synchronizeable & sync = **it;
783
784        if ( !sync.beSynchronized() || sync.getUniqueID() < 0 )
785          continue;
786
787        sync.handleRecvState( peer->second.userId, state, fromState );
788      }
789
790      assert( peer->second.lastAckedState <= ackedState );
791      peer->second.lastAckedState = ackedState;
792
793      assert( peer->second.lastRecvedState < state );
794      peer->second.lastRecvedState = state;
795
796    }
797
798  }
799
800}
801
802/**
803 * is executed when a handshake has finished
804 */
805void NetworkStream::handleNewClient( int userId )
806{
807  // init and assign the message manager
808  MessageManager::getInstance()->initUser( userId );
809  // do all game relevant stuff here
810  networkGameManager->signalNewPlayer( userId );
811
812  // register the new client at the network monitor
813//   this->networkMonitor->addClient();
814}
815
816
817/**
818 * removes old items from oldSynchronizeables
819 */
820void NetworkStream::cleanUpOldSyncList( )
821{
822  int now = SDL_GetTicks();
823
824  for ( std::map<int,int>::iterator it = oldSynchronizeables.begin(); it != oldSynchronizeables.end();  )
825  {
826    if ( it->second < now - 10*1000 )
827    {
828      std::map<int,int>::iterator delIt = it;
829      it++;
830      oldSynchronizeables.erase( delIt );
831      continue;
832    }
833    it++;
834  }
835}
836
837/**
838 * writes data to DATA/dicts/newdict
839 * @param data pointer to data
840 * @param length length
841 */
842void NetworkStream::writeToNewDict( byte * data, int length, bool upstream )
843{
844  if ( remainingBytesToWriteToDict <= 0 )
845    return;
846
847  if ( length > remainingBytesToWriteToDict )
848    length = remainingBytesToWriteToDict;
849
850  std::string fileName = ResourceManager::getInstance()->getDataDir();
851  fileName += "/dicts/newdict";
852
853  if ( upstream )
854    fileName += "_upstream";
855  else
856    fileName += "_downstream";
857
858  FILE * f = fopen( fileName.c_str(), "a" );
859
860  if ( !f )
861  {
862    PRINTF(2)("could not open %s\n", fileName.c_str());
863    remainingBytesToWriteToDict = 0;
864    return;
865  }
866
867  if ( fwrite( data, 1, length, f ) != length )
868  {
869    PRINTF(2)("could not write to file\n");
870    fclose( f );
871    return;
872  }
873
874  fclose( f );
875
876  remainingBytesToWriteToDict -= length;
877}
878
879
880
881
882
883
Note: See TracBrowser for help on using the repository browser.