Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9386 was 9386, checked in by bensch, 18 years ago

orxonox/proxy: removed the dependency of the netdefs in pnode, which should decrease compile time enormously.

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