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
RevLine 
[5566]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:
[9246]12   main-programmer: Christoph Renner rennerc@ee.ethz.ch
13   co-programmer:   Patrick Boenzli  boenzlip@orxonox.ethz.ch
[9406]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)
[5566]17*/
18
19
20#define DEBUG_MODULE_NETWORK
21
[5747]22
[5647]23#include "base_object.h"
[5731]24#include "network_protocol.h"
[7954]25#include "udp_socket.h"
26#include "udp_server_socket.h"
[9406]27#include "monitor/connection_monitor.h"
28#include "monitor/network_monitor.h"
[5647]29#include "synchronizeable.h"
[9406]30#include "ip.h"
[6341]31#include "network_game_manager.h"
[6959]32#include "shared_network_data.h"
[7954]33#include "message_manager.h"
34#include "preferences.h"
35#include "zip.h"
[6341]36
[7954]37#include "src/lib/util/loading/resource_manager.h"
38
39#include "network_log.h"
40
[9235]41#include "player_stats.h"
[7954]42
43#include "lib/util/loading/factory.h"
44
[5649]45#include "debug.h"
[6139]46#include "class_list.h"
[6144]47#include <algorithm>
[5647]48
[9406]49
[5566]50#include "network_stream.h"
51
[5594]52
[9406]53#include "converter.h"
[5595]54
[9406]55
[5747]56#define PACKAGE_SIZE  256
[5647]57
[5747]58
[9406]59/**
60 * empty constructor
61 */
[5800]62NetworkStream::NetworkStream()
[5996]63    : DataStream()
[5647]64{
65  this->init();
[5648]66  /* initialize the references */
[9473]67  this->pInfo->nodeType = NET_UNASSIGNED;
[5647]68}
69
[6695]70
[9406]71NetworkStream::NetworkStream( int nodeType)
[5996]72{
73  this->init();
74
[9406]75  this->pInfo->nodeType = nodeType;
[5996]76
[9406]77  switch( nodeType)
78  {
79    case NET_MASTER_SERVER:
80      // init the shared network data
[9452]81      SharedNetworkData::getInstance()->setHostID(NET_ID_MASTER_SERVER);
[9406]82      break;
83
84    case NET_PROXY_SERVER_ACTIVE:
85      // init the shared network data
[9452]86      SharedNetworkData::getInstance()->setHostID(NET_ID_PROXY_SERVER_01);
[9406]87      break;
88    case NET_PROXY_SERVER_PASSIVE:
[9419]89      // init the shared network data
[9452]90      SharedNetworkData::getInstance()->setHostID(NET_ID_PROXY_SERVER_01);
[9406]91      break;
92    case NET_CLIENT:
[9452]93      SharedNetworkData::getInstance()->setHostID(NET_ID_UNASSIGNED);
[9406]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;
[5649]103}
104
105
[9406]106
[9246]107/**
108 * generic init functions
109 */
[5647]110void NetworkStream::init()
111{
112  /* set the class id for the base object */
113  this->setClassID(CL_NETWORK_STREAM, "NetworkStream");
[9463]114  this->clientSocket = NULL;
115  this->proxySocket = NULL;
[6341]116  this->networkGameManager = NULL;
[9406]117  this->networkMonitor = NULL;
[9246]118
[9406]119  this->pInfo = new PeerInfo();
120  this->pInfo->userId = 0;
121  this->pInfo->lastAckedState = 0;
122  this->pInfo->lastRecvedState = 0;
123
[9433]124  this->bRedirect = false;
[9406]125
126  this->currentState = 0;
127
[7954]128  remainingBytesToWriteToDict = Preferences::getInstance()->getInt( "compression", "writedict", 0 );
[9246]129
[8623]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 );
[5594]135}
136
[5647]137
[9246]138/**
139 * deconstructor
140 */
[5566]141NetworkStream::~NetworkStream()
[5598]142{
[9463]143  if ( this->clientSocket )
[6139]144  {
[9463]145    clientSocket->close();
146    delete clientSocket;
147    clientSocket = NULL;
[6139]148  }
[9463]149  if ( this->proxySocket)
150  {
151    proxySocket->close();
152    delete proxySocket;
153    proxySocket = NULL;
154  }
[7954]155  for ( PeerList::iterator i = peers.begin(); i!=peers.end(); i++)
[6139]156  {
[7954]157    if ( i->second.socket )
[6139]158    {
[7954]159      i->second.socket->disconnectServer();
160      delete i->second.socket;
161      i->second.socket = NULL;
[6139]162    }
[9246]163
[7954]164    if ( i->second.handshake )
[6139]165    {
[7954]166      delete i->second.handshake;
167      i->second.handshake = NULL;
[6139]168    }
[9246]169
[8623]170    if ( i->second.connectionMonitor )
171    {
172      delete i->second.connectionMonitor;
173      i->second.connectionMonitor = NULL;
174    }
[6139]175  }
[8228]176  for ( SynchronizeableList::const_iterator it = getSyncBegin(); it != getSyncEnd(); it ++ )
177    (*it)->setNetworkStream( NULL );
[9406]178
179  if( this->pInfo)
180    delete this->pInfo;
181
182  if( this->networkMonitor)
183    delete this->networkMonitor;
[5598]184}
185
[5996]186
[9246]187/**
[9406]188 * establish a connection to a remote master server
189 * @param host: host name
190 * @param port: the port number
191 */
[9450]192void NetworkStream::connectToMasterServer(std::string host, int port)
[9406]193{
[9450]194  int node = NET_ID_MASTER_SERVER;
[9446]195  // this create the new node in the peers map
[9406]196  this->peers[node].socket = new UdpSocket( host, port );
[9450]197  this->peers[node].userId = NET_ID_MASTER_SERVER;
[9406]198
199  this->peers[node].nodeType = NET_MASTER_SERVER;
[9450]200  this->peers[node].connectionMonitor = new ConnectionMonitor( NET_ID_MASTER_SERVER );
[9406]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 */
[9470]210void NetworkStream::connectToProxyServer(int proxyId, std::string host, int port)
[9406]211{
[9450]212  PRINTF(0)("connect to proxy %s, this is proxyId %i\n", host.c_str(), proxyId);
[9425]213
[9450]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;
[9406]217
[9450]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();
[9406]221}
222
223
224/**
225 * create a server
226 * @param port: interface port for all clients
227 */
[9463]228void NetworkStream::createServer(int clientPort, int proxyPort)
[9406]229{
[9476]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);
[9406]233}
234
235
236/**
[9246]237 * creates a new instance of the network game manager
238 */
[6695]239void NetworkStream::createNetworkGameManager()
240{
241  this->networkGameManager = NetworkGameManager::getInstance();
[9406]242
[7954]243  this->networkGameManager->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
244  MessageManager::getInstance()->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
[6695]245}
246
247
[9246]248/**
249 * starts the network handshake
[9406]250 * handsakes are always initialized from the client side first. this starts the handshake and therefore is only
251 * executed as client
[9422]252 * @param userId: start handshake for this user id (optional, default == 0)
[9246]253 */
[9422]254void NetworkStream::startHandshake(int userId)
[6695]255{
[9471]256  Handshake* hs = new Handshake(this->pInfo->nodeType);
[9450]257  // fake the unique id
258  hs->setUniqueID( NET_UID_HANDSHAKE );
[9422]259  assert( peers[userId].handshake == NULL );
260  peers[userId].handshake = hs;
[9246]261
[9406]262  // set the preferred nick name
[9235]263  hs->setPreferedNickName( Preferences::getInstance()->getString( "multiplayer", "nickname", "Player" ) );
[9246]264
[9406]265  PRINTF(0)("NetworkStream: Handshake created: %s\n", hs->getCName());
[6695]266}
267
268
[9246]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
[9422]273 * @param sync: the synchronizeable to add
[9246]274 */
[5996]275void NetworkStream::connectSynchronizeable(Synchronizeable& sync)
276{
[6139]277  this->synchronizeables.push_back(&sync);
278  sync.setNetworkStream( this );
[5996]279}
280
[6695]281
[9246]282/**
283 * removes the synchronizeable from the list of synchronized entities
[9422]284 * @param sync: the syncronizeable to remove
[9246]285 */
[6139]286void NetworkStream::disconnectSynchronizeable(Synchronizeable& sync)
287{
[6144]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);
[9246]292
[7954]293  oldSynchronizeables[sync.getUniqueID()] = SDL_GetTicks();
[6139]294}
295
296
[9246]297/**
298 * this is called to process data from the network socket to the synchronizeable and vice versa
299 */
[5604]300void NetworkStream::processData()
301{
[9406]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
[8068]307  int tick = SDL_GetTicks();
[9246]308
[9406]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  }
[9246]315
[9472]316  if ( SharedNetworkData::getInstance()->isMasterServer())
[7954]317  {
[9406]318    // execute everytthing the master server shoudl do
[9464]319    if ( this->clientSocket )
320      this->clientSocket->update();
321    if( this->proxySocket)
322      this->proxySocket->update();
[9246]323
[6139]324    this->updateConnectionList();
[7954]325  }
[9472]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();
[9406]333
[9472]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())
[6139]339  {
[9246]340    // check if the connection is ok else terminate and remove
[9450]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() ) )
[6139]344    {
[9450]345      this->handleDisconnect( NET_ID_MASTER_SERVER);
[6139]346      PRINTF(1)("lost connection to server\n");
347    }
[9433]348    // check if there is a redirection command
349    if( this->bRedirect)
350    {
[9450]351      this->handleReconnect( NET_ID_MASTER_SERVER);
[9433]352    }
[6139]353  }
354
[9433]355  this->cleanUpOldSyncList();
356  this->handleHandshakes();
[9246]357
[9406]358  // update the network monitor
359  this->networkMonitor->process();
360
[7954]361  // order of up/downstream is important!!!!
362  // don't change it
[9433]363  this->handleDownstream( tick );
364  this->handleUpstream( tick );
[7954]365}
366
[9246]367
368/**
[9406]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
[9246]371 */
[7954]372void NetworkStream::updateConnectionList( )
373{
374  //check for new connections
375
[9465]376  NetworkSocket* tempNetworkSocket = NULL;
[9464]377  int userId;
[7954]378
[9465]379  if( this->clientSocket != NULL)
[6139]380  {
[9465]381    tempNetworkSocket = this->clientSocket->getNewSocket();
382
383    // we got new NET_CLIENT connecting
384    if ( tempNetworkSocket )
[6139]385    {
[9465]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;
[9246]395
[9465]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;
[9471]402      peers[userId].nodeType = NET_CLIENT;
[9465]403      this->handleConnect(userId);
404
405      PRINTF(0)("New Client: %d\n", userId);
[9406]406    }
[9464]407  }
[9246]408
[6341]409
[9465]410  if( this->proxySocket != NULL)
[9464]411  {
[9465]412    tempNetworkSocket = this->proxySocket->getNewSocket();
413
414    // we got new NET_PROXY_SERVER_ACTIVE connecting
415    if ( tempNetworkSocket )
[7954]416    {
[9465]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;
[6498]426
[9465]427        for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
428          if ( it->first >= userId )
429            userId = it->first + 1;
430      }
[9406]431
[9465]432      // this creates a new entry in the peers list
433      peers[userId].socket = tempNetworkSocket;
[9471]434      peers[userId].nodeType = NET_PROXY_SERVER_ACTIVE;
[9465]435      this->handleConnect(userId);
[9406]436
[9465]437      PRINTF(0)("New Proxy: %d\n", userId);
438    }
[7954]439  }
[6341]440
[9246]441
[7954]442  //check if connections are ok else remove them
[8228]443  for ( PeerList::iterator it = peers.begin(); it != peers.end(); )
[7954]444  {
[9246]445    if (
[7954]446          it->second.socket &&
[9246]447          (
[7954]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
[9419]458      this->handleDisconnect( it->second.userId);
[9246]459
[9430]460      it++;
[8228]461      continue;
[6139]462    }
[9246]463
[8228]464    it++;
[6139]465  }
466
467
[7954]468}
[5800]469
[9246]470
[9464]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
[7954]501void NetworkStream::debug()
502{
[9406]503  if( SharedNetworkData::getInstance()->isMasterServer()) {
504    PRINT(0)(" Host ist Master Server with ID: %i\n", this->pInfo->userId);
505  }
[9452]506  else if( SharedNetworkData::getInstance()->isProxyServerActive()) {
[9406]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  }
[6695]512
[7954]513  PRINT(0)(" Got %i connected Synchronizeables, showing active Syncs:\n", this->synchronizeables.size());
[6139]514  for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++)
[5996]515  {
[7954]516    if( (*it)->beSynchronized() == true)
[9406]517      PRINT(0)("  Synchronizeable of class: %s::%s, with unique ID: %i, Synchronize: %i\n", (*it)->getClassCName(), (*it)->getCName(),
[7954]518               (*it)->getUniqueID(), (*it)->beSynchronized());
519  }
[9406]520  PRINT(0)(" Maximal Connections: %i\n", SharedNetworkData::getInstance()->getMaxPlayer() );
[6959]521
[7954]522}
[6959]523
524
[9246]525/**
526 * @returns the number of synchronizeables registered to this stream
527 */
[7954]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;
[5730]534
[7954]535  //return synchronizeables.size();
536  return n;
537}
[6139]538
[9246]539
[7954]540/**
[9246]541 * check if handshakes completed. if so create the network game manager else remove it again
[7954]542 */
543void NetworkStream::handleHandshakes( )
544{
545  for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
546  {
547    if ( it->second.handshake )
548    {
[9406]549      // handshake finished
[7954]550      if ( it->second.handshake->completed() )
551      {
[9406]552        //handshake is correct
[7954]553        if ( it->second.handshake->ok() )
[6341]554        {
[9473]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
[9433]558          // the counter part didn't mark it free for deletion yet
[7954]559          if ( !it->second.handshake->allowDel() )
[6139]560          {
[9473]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())
[9430]565            {
566              SharedNetworkData::getInstance()->setHostID( it->second.handshake->getHostId() );
567              this->pInfo->userId = SharedNetworkData::getInstance()->getHostID();
[9406]568
[9479]569              it->second.ip = it->second.socket->getRemoteAddress();
570
[9473]571//               it->second.nodeType = it->second.handshake->getRemoteNodeType();
572//               it->second.ip = it->second.socket->getRemoteAddress();
[9406]573              // add the new server to the nodes list (it can be a NET_MASTER_SERVER or NET_PROXY_SERVER)
[9430]574              this->networkMonitor->addNode(&it->second);
[9406]575              // get proxy 1 address and add it
[9430]576              this->networkMonitor->addNode(it->second.handshake->getProxy1Address(), NET_PROXY_SERVER_ACTIVE);
[9406]577              // get proxy 2 address and add it
[9430]578              this->networkMonitor->addNode(it->second.handshake->getProxy2Address(), NET_PROXY_SERVER_ACTIVE);
[9406]579
580              // now check if the server accepted the connection
[9433]581              if( it->second.handshake->redirect() )
582              {
583                this->bRedirect = true;
584              }
[9430]585
586              // create the new network game manager and init it
[9425]587              this->networkGameManager = NetworkGameManager::getInstance();
588              this->networkGameManager->setUniqueID( it->second.handshake->getNetworkGameManagerId() );
[9422]589              // init the new message manager
[9425]590              MessageManager::getInstance()->setUniqueID( it->second.handshake->getMessageManagerId() );
[6868]591            }
[7954]592
[9430]593            PRINT(0)("handshake finished id=%d\n", it->second.handshake->getNetworkGameManagerId());
594            it->second.handshake->del();
595
[6139]596          }
597          else
598          {
[9406]599            // handshake finished registring new player
[7954]600            if ( it->second.handshake->canDel() )
[6868]601            {
[9406]602
[9471]603              if (  SharedNetworkData::getInstance()->isMasterServer() )
[7954]604              {
[9479]605                it->second.ip = it->second.socket->getRemoteAddress();
606
[9406]607                this->networkMonitor->addNode(&it->second);
608
609                this->handleNewClient( it->second.userId );
610
[9235]611                if ( PlayerStats::getStats( it->second.userId ) && it->second.handshake->getPreferedNickName() != "" )
612                {
613                  PlayerStats::getStats( it->second.userId )->setNickName( it->second.handshake->getPreferedNickName() );
614                }
[7954]615              }
[9472]616              else if ( SharedNetworkData::getInstance()->isProxyServerActive() && it->second.isClient() )
617              {
618                it->second.ip = it->second.socket->getRemoteAddress();
[9246]619
[9472]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
[7954]630              PRINT(0)("handshake finished delete it\n");
631              delete it->second.handshake;
632              it->second.handshake = NULL;
[6868]633            }
[6139]634          }
[7954]635
[6139]636        }
637        else
638        {
[7954]639          PRINT(1)("handshake failed!\n");
640          it->second.socket->disconnectServer();
[6139]641        }
[7954]642      }
[6139]643    }
[5996]644  }
[7954]645}
[5741]646
[9246]647
[7954]648/**
[9406]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{
[9434]653  this->bRedirect = false;
[9420]654  PeerInfo* pInfo = &this->peers[userId];
655
[9406]656  PRINTF(0)("===============================================\n");
657  PRINTF(0)("Client is redirected to the other proxy servers\n");
[9422]658  PRINTF(0)("  user id: %i\n", userId);
[9433]659  PRINTF(0)("  connecting to: %s\n", this->networkMonitor->getFirstChoiceProxy()->ip.ipString().c_str());
[9406]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;
[9420]665
666  // temp save the ip address here
667  IP proxyIP = pInfo->handshake->getProxy1Address();
668
[9406]669  // disconnect from the current server and reconnect to proxy server
[9422]670  this->handleDisconnect( userId);
[9450]671  this->connectToProxyServer(NET_ID_PROXY_SERVER_01, proxyIP.ipString(), 9999);
[9446]672  #warning the ports are not yet integrated correctly in the ip class
[9406]673
674  // and restart the handshake
[9446]675  this->startHandshake( userId);
[9406]676}
677
678
679/**
[9419]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;
[9422]696
697
[9433]698  for ( SynchronizeableList::iterator it2 = synchronizeables.begin(); it2 != synchronizeables.end(); it2++ )  {
699    (*it2)->cleanUpUser( userId );
700  }
[9422]701
[9436]702  if( SharedNetworkData::getInstance()->isMasterServer())
703    NetworkGameManager::getInstance()->signalLeftPlayer(userId);
704
705  this->freeSocketSlots.push_back( userId );
706
[9440]707  peers.erase( userId);
[9419]708}
709
710
711
712/**
[7954]713 * handle upstream network traffic
[9419]714 * @param tick: seconds elapsed since last update
[7954]715 */
[8068]716void NetworkStream::handleUpstream( int tick )
[7954]717{
718  int offset;
719  int n;
[9246]720
[8068]721  for ( PeerList::reverse_iterator peer = peers.rbegin(); peer != peers.rend(); peer++ )
[5802]722  {
[9246]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)
[7954]726    if ( !peer->second.socket )
727      continue;
[9246]728
729    // header informations: current state
[7954]730    n = Converter::intToByteArray( currentState, buf + offset, UDP_PACKET_SIZE - offset );
731    assert( n == INTSIZE );
732    offset += n;
[9246]733
734    // header informations: last acked state
[7954]735    n = Converter::intToByteArray( peer->second.lastAckedState, buf + offset, UDP_PACKET_SIZE - offset );
736    assert( n == INTSIZE );
737    offset += n;
[9246]738
739    // header informations: last recved state
[7954]740    n = Converter::intToByteArray( peer->second.lastRecvedState, buf + offset, UDP_PACKET_SIZE - offset );
741    assert( n == INTSIZE );
742    offset += n;
[9246]743
744    // now write all synchronizeables in the packet
[7954]745    for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
[5810]746    {
[9406]747
[7954]748      int oldOffset = offset;
749      Synchronizeable & sync = **it;
[9246]750
[9406]751
[9246]752      // do not include synchronizeables with uninit id and syncs that don't want to be synchronized
[9450]753      if ( !sync.beSynchronized() || sync.getUniqueID() <= NET_UID_UNASSIGNED )
[7954]754        continue;
[5730]755
[9246]756      // if handshake not finished only sync handshake
[7954]757      if ( peer->second.handshake && sync.getLeafClassID() != CL_HANDSHAKE )
758        continue;
[9246]759
[9406]760      // if we are a server (both master and proxy servers) and this is not our handshake
[9473]761      if ( ( SharedNetworkData::getInstance()->isMasterServer() ||
762             SharedNetworkData::getInstance()->isProxyServerActive() &&  peer->second.isClient())
763             && sync.getLeafClassID() == CL_HANDSHAKE && sync.getUniqueID() != peer->second.userId )
[7954]764        continue;
[9246]765
766      /* list of synchronizeables that will never be synchronized over the network: */
767      // do not sync null parent
[7954]768      if ( sync.getLeafClassID() == CL_NULL_PARENT )
769        continue;
[6139]770
[9406]771
772      assert( sync.getLeafClassID() != 0);
773
[7954]774      assert( offset + INTSIZE <= UDP_PACKET_SIZE );
[9246]775
776      // server fakes uniqueid == 0 for handshake
[9473]777      if ( ( SharedNetworkData::getInstance()->isMasterServer() ||
778             SharedNetworkData::getInstance()->isProxyServerActive() &&  peer->second.isClient() ) &&
[9406]779             sync.getUniqueID() <= SharedNetworkData::getInstance()->getMaxPlayer() + 1) // plus one to handle one client more than the max to redirect it
[7954]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 );
[9246]783
[9406]784
[7954]785      assert( n == INTSIZE );
786      offset += n;
[9246]787
[9406]788      // make space for packet size
[7954]789      offset += INTSIZE;
[6139]790
[7954]791      n = sync.getStateDiff( peer->second.userId, buf + offset, UDP_PACKET_SIZE-offset, currentState, peer->second.lastAckedState, -1000 );
792      offset += n;
[9246]793
[7954]794      assert( Converter::intToByteArray( n, buf + offset - n - INTSIZE, INTSIZE ) == INTSIZE );
[6341]795
[9246]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
[6139]811
[9246]812
813
[7954]814    for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
815    {
816      Synchronizeable & sync = **it;
[9246]817
[9450]818      // again exclude all unwanted syncs
819      if ( !sync.beSynchronized() || sync.getUniqueID() <= NET_UID_UNASSIGNED)
[7954]820        continue;
[9246]821
[7954]822      sync.handleSentState( peer->second.userId, currentState, peer->second.lastAckedState );
823    }
[9246]824
825
[7954]826    assert( Converter::intToByteArray( offset, buf, INTSIZE ) == INTSIZE );
[9246]827
828    // now compress the data with the zip library
[8623]829    int compLength = 0;
[9474]830    if ( SharedNetworkData::getInstance()->isMasterServer() ||
831         SharedNetworkData::getInstance()->isProxyServerActive())
[8623]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 );
[9246]835
[8623]836    if ( compLength <= 0 )
[7954]837    {
838      PRINTF(1)("compression failed!\n");
839      continue;
840    }
[9246]841
[7954]842    assert( peer->second.socket->writePacket( compBuf, compLength ) );
[9246]843
[7954]844    if ( this->remainingBytesToWriteToDict > 0 )
[8623]845      writeToNewDict( buf, offset, true );
[9246]846
[8068]847    peer->second.connectionMonitor->processUnzippedOutgoingPacket( tick, buf, offset, currentState );
848    peer->second.connectionMonitor->processZippedOutgoingPacket( tick, compBuf, compLength, currentState );
[9246]849
[5810]850  }
[6139]851}
852
[7954]853/**
854 * handle downstream network traffic
855 */
[8068]856void NetworkStream::handleDownstream( int tick )
[6139]857{
[7954]858  int offset = 0;
[9246]859
[7954]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;
[9246]868
[7954]869  for ( PeerList::iterator peer = peers.begin(); peer != peers.end(); peer++ )
[5810]870  {
[9246]871
[7954]872    if ( !peer->second.socket )
873      continue;
[5730]874
[7954]875    while ( 0 < (compLength = peer->second.socket->readPacket( compBuf, UDP_PACKET_SIZE )) )
[6139]876    {
[8068]877      peer->second.connectionMonitor->processZippedIncomingPacket( tick, compBuf, compLength );
[9246]878
[7954]879      packetLength = Zip::getInstance()->unZip( compBuf, compLength, buf, UDP_PACKET_SIZE );
[8623]880
[7954]881      if ( packetLength < 4*INTSIZE )
882      {
883        if ( packetLength != 0 )
884          PRINTF(1)("got too small packet: %d\n", packetLength);
885        continue;
886      }
[9246]887
[7954]888      if ( this->remainingBytesToWriteToDict > 0 )
[8623]889        writeToNewDict( buf, packetLength, false );
[9246]890
[7954]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;
[9246]896
[8623]897      peer->second.connectionMonitor->processUnzippedIncomingPacket( tick, buf, packetLength, state, ackedState );
[6139]898
[9246]899
[9406]900      //if this is an old state drop it
[7954]901      if ( state <= peer->second.lastRecvedState )
902        continue;
[9246]903
[7954]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      }
[9246]910
[9406]911      while ( offset + 2 * INTSIZE < length )
[7954]912      {
913        assert( offset > 0 );
914        assert( Converter::byteArrayToInt( buf + offset, &uniqueId ) == INTSIZE );
915        offset += INTSIZE;
[9246]916
[7954]917        assert( Converter::byteArrayToInt( buf + offset, &syncDataLength ) == INTSIZE );
918        offset += INTSIZE;
[9246]919
[7954]920        assert( syncDataLength > 0 );
921        assert( syncDataLength < 10000 );
[9246]922
[7954]923        Synchronizeable * sync = NULL;
[9246]924
[9406]925        // look for the synchronizeable in question
[7954]926        for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
[9246]927        {
[9406]928          // client thinks his handshake has id 0!!!!!
[7954]929          if ( (*it)->getUniqueID() == uniqueId || ( uniqueId == 0 && (*it)->getUniqueID() == peer->second.userId ) )
930          {
931            sync = *it;
932            break;
933          }
934        }
[9246]935
[9406]936        // this synchronizeable does not yet exist! create it
[7954]937        if ( sync == NULL )
938        {
939          PRINTF(0)("could not find sync with id %d. try to create it\n", uniqueId);
[9406]940
941          // if it is an old synchronizeable already removed, ignore it
[7954]942          if ( oldSynchronizeables.find( uniqueId ) != oldSynchronizeables.end() )
943          {
944            offset += syncDataLength;
945            continue;
946          }
[9246]947
[9406]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)
[9470]949          if ( peers[peer->second.userId].isClient() || peers[peer->second.userId].isProxyServerActive())
[7954]950          {
951            offset += syncDataLength;
952            continue;
953          }
[9246]954
[7954]955          int leafClassId;
956          if ( INTSIZE > length - offset )
957          {
958            offset += syncDataLength;
959            continue;
960          }
[6139]961
[7954]962          Converter::byteArrayToInt( buf + offset, &leafClassId );
[9246]963
[7954]964          assert( leafClassId != 0 );
[9246]965
[9406]966
[7954]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          {
[9406]972            PRINTF(1)("Don't create Object with ID %x, ignored!\n", (int)leafClassId);
[7954]973            offset += syncDataLength;
974            continue;
975          }
976          else
977            b = Factory::fabricate( (ClassID)leafClassId );
[5800]978
[7954]979          if ( !b )
980          {
981            PRINTF(1)("Could not fabricate Object with classID %x\n", leafClassId);
982            offset += syncDataLength;
983            continue;
984          }
[5809]985
[7954]986          if ( b->isA(CL_SYNCHRONIZEABLE) )
987          {
988            sync = dynamic_cast<Synchronizeable*>(b);
989            sync->setUniqueID( uniqueId );
990            sync->setSynchronized(true);
[9246]991
[9406]992            PRINTF(0)("Fabricated %s with id %d\n", sync->getClassCName(), sync->getUniqueID());
[7954]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        }
[6139]1002
[9246]1003
1004        int n = sync->setStateDiff( peer->second.userId, buf+offset, syncDataLength, state, fromState );
[7954]1005        offset += n;
[6498]1006
[7954]1007      }
[9246]1008
[7954]1009      if ( offset != length )
[6139]1010      {
[7954]1011        PRINTF(0)("offset (%d) != length (%d)\n", offset, length);
1012        peer->second.socket->disconnectServer();
[6139]1013      }
[9246]1014
1015
[7954]1016      for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
[6139]1017      {
[7954]1018        Synchronizeable & sync = **it;
[9246]1019
[9450]1020        if ( !sync.beSynchronized() || sync.getUniqueID() <= NET_UID_UNASSIGNED )
[7954]1021          continue;
[9246]1022
[7954]1023        sync.handleRecvState( peer->second.userId, state, fromState );
[6139]1024      }
[9246]1025
[7954]1026      assert( peer->second.lastAckedState <= ackedState );
1027      peer->second.lastAckedState = ackedState;
[9246]1028
[7954]1029      assert( peer->second.lastRecvedState < state );
1030      peer->second.lastRecvedState = state;
[8228]1031
[6139]1032    }
[9246]1033
[6139]1034  }
[9246]1035
[7954]1036}
[6139]1037
[7954]1038/**
1039 * is executed when a handshake has finished
1040 */
1041void NetworkStream::handleNewClient( int userId )
1042{
[9406]1043  // init and assign the message manager
[7954]1044  MessageManager::getInstance()->initUser( userId );
[9406]1045  // do all game relevant stuff here
[7954]1046  networkGameManager->signalNewPlayer( userId );
[5604]1047}
[6139]1048
[9406]1049
[7954]1050/**
1051 * removes old items from oldSynchronizeables
1052 */
1053void NetworkStream::cleanUpOldSyncList( )
[6139]1054{
[7954]1055  int now = SDL_GetTicks();
[9246]1056
[7954]1057  for ( std::map<int,int>::iterator it = oldSynchronizeables.begin(); it != oldSynchronizeables.end();  )
[6139]1058  {
[7954]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++;
[6139]1067  }
[7954]1068}
1069
1070/**
1071 * writes data to DATA/dicts/newdict
1072 * @param data pointer to data
1073 * @param length length
1074 */
[8623]1075void NetworkStream::writeToNewDict( byte * data, int length, bool upstream )
[7954]1076{
1077  if ( remainingBytesToWriteToDict <= 0 )
1078    return;
[9246]1079
[7954]1080  if ( length > remainingBytesToWriteToDict )
1081    length = remainingBytesToWriteToDict;
[9246]1082
[7954]1083  std::string fileName = ResourceManager::getInstance()->getDataDir();
1084  fileName += "/dicts/newdict";
[9246]1085
[8623]1086  if ( upstream )
1087    fileName += "_upstream";
1088  else
1089    fileName += "_downstream";
[9246]1090
[7954]1091  FILE * f = fopen( fileName.c_str(), "a" );
[9246]1092
[7954]1093  if ( !f )
[6139]1094  {
[7954]1095    PRINTF(2)("could not open %s\n", fileName.c_str());
1096    remainingBytesToWriteToDict = 0;
[6139]1097    return;
1098  }
[9246]1099
[7954]1100  if ( fwrite( data, 1, length, f ) != length )
[6341]1101  {
[7954]1102    PRINTF(2)("could not write to file\n");
1103    fclose( f );
[6341]1104    return;
1105  }
[9246]1106
[7954]1107  fclose( f );
[9246]1108
1109  remainingBytesToWriteToDict -= length;
[6139]1110}
1111
1112
[6695]1113
1114
1115
1116
Note: See TracBrowser for help on using the repository browser.