Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

proxy server not able to load the world file, some more safty in the handshake handling

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