Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

another ip sync bug discovered. but still not the one im looking for

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