Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

fixed the bug, that only one client could connect to the master.

File size: 35.4 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
[9538]13   co-programmer:   Patrick Boenzli  patrick@orxonox.ethz.ch
[9406]14
15     June 2006: finishing work on the network stream for pps presentation (rennerc@ee.ethz.ch)
[9538]16     July 2006: some code rearangement and integration of the proxy server mechanism (patrick@orxonox.ethz.ch)
[5566]17*/
18
19
20#define DEBUG_MODULE_NETWORK
21
[9538]22#include "proxy/proxy_control.h"
[5747]23
[5647]24#include "base_object.h"
[5731]25#include "network_protocol.h"
[7954]26#include "udp_socket.h"
27#include "udp_server_socket.h"
[9406]28#include "monitor/connection_monitor.h"
29#include "monitor/network_monitor.h"
[5647]30#include "synchronizeable.h"
[9406]31#include "ip.h"
[6341]32#include "network_game_manager.h"
[6959]33#include "shared_network_data.h"
[7954]34#include "message_manager.h"
35#include "preferences.h"
36#include "zip.h"
[6341]37
[7954]38#include "src/lib/util/loading/resource_manager.h"
39
40#include "network_log.h"
41
[9235]42#include "player_stats.h"
[7954]43
44#include "lib/util/loading/factory.h"
45
[5649]46#include "debug.h"
[6139]47#include "class_list.h"
[6144]48#include <algorithm>
[5647]49
[9406]50
[5566]51#include "network_stream.h"
52
[5594]53
[9406]54#include "converter.h"
[5595]55
[9406]56
[5747]57#define PACKAGE_SIZE  256
[5647]58
[5747]59
[9406]60/**
61 * empty constructor
62 */
[5800]63NetworkStream::NetworkStream()
[5996]64    : DataStream()
[5647]65{
66  this->init();
[5648]67  /* initialize the references */
[9494]68  this->pInfo->nodeType = NET_UNASSIGNED;
[5647]69}
70
[6695]71
[9406]72NetworkStream::NetworkStream( int nodeType)
[5996]73{
74  this->init();
75
[9406]76  this->pInfo->nodeType = nodeType;
[5996]77
[9406]78  switch( nodeType)
79  {
80    case NET_MASTER_SERVER:
81      // init the shared network data
[9494]82      SharedNetworkData::getInstance()->setHostID(NET_ID_MASTER_SERVER);
[9406]83      break;
84    case NET_PROXY_SERVER_ACTIVE:
85      // init the shared network data
[9494]86      SharedNetworkData::getInstance()->setHostID(NET_ID_PROXY_SERVER_01);
[9406]87      break;
88    case NET_PROXY_SERVER_PASSIVE:
[9494]89      // init the shared network data
90      SharedNetworkData::getInstance()->setHostID(NET_ID_PROXY_SERVER_01);
[9406]91      break;
92    case NET_CLIENT:
[9494]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");
[9494]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();
[9548]120  this->pInfo->userId = NET_UID_UNASSIGNED;
[9406]121  this->pInfo->lastAckedState = 0;
122  this->pInfo->lastRecvedState = 0;
123
[9494]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{
[9494]143  if ( this->clientSocket )
[6139]144  {
[9494]145    clientSocket->close();
146    delete clientSocket;
147    clientSocket = NULL;
[6139]148  }
[9494]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 */
192void NetworkStream::connectToMasterServer(std::string host, int port)
193{
[9494]194  int node = NET_ID_MASTER_SERVER;
195  // this create the new node in the peers map
[9406]196  this->peers[node].socket = new UdpSocket( host, port );
[9494]197  this->peers[node].userId = NET_ID_MASTER_SERVER;
[9406]198
199  this->peers[node].nodeType = NET_MASTER_SERVER;
[9494]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 */
[9494]210void NetworkStream::connectToProxyServer(int proxyId, std::string host, int port)
[9406]211{
[9494]212  PRINTF(0)("connect to proxy %s, this is proxyId %i\n", host.c_str(), proxyId);
[9406]213
[9494]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();
[9406]221}
222
223
224/**
225 * create a server
226 * @param port: interface port for all clients
227 */
[9494]228void NetworkStream::createServer(int clientPort, int proxyPort)
[9406]229{
[9494]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
[9494]252 * @param userId: start handshake for this user id (optional, default == 0)
[9246]253 */
[9494]254void NetworkStream::startHandshake(int userId)
[6695]255{
[9406]256  Handshake* hs = new Handshake(this->pInfo->nodeType);
[9494]257  // fake the unique id
258  hs->setUniqueID( NET_UID_HANDSHAKE );
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
[9494]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
[9494]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
[9494]316  if ( SharedNetworkData::getInstance()->isMasterServer())
[7954]317  {
[9406]318    // execute everytthing the master server shoudl do
[9494]319    if ( this->clientSocket )
320      this->clientSocket->update();
321    if( this->proxySocket)
322      this->proxySocket->update();
[9246]323
[6139]324    this->updateConnectionList();
[7954]325  }
[9494]326  else if( SharedNetworkData::getInstance()->isProxyServerActive())
[9406]327  {
[9494]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
334    this->updateConnectionList();
335  }
[9494]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
[9494]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    {
[9494]345      this->handleDisconnect( NET_ID_MASTER_SERVER);
[6139]346      PRINTF(1)("lost connection to server\n");
347    }
[9494]348    // check if there is a redirection command
349    if( this->bRedirect)
350    {
351      this->handleReconnect( NET_ID_MASTER_SERVER);
352    }
[6139]353  }
354
[9494]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
[9494]363  this->handleDownstream( tick );
364  this->handleUpstream( tick );
[7954]365}
366
[9246]367
368/**
[9494]369 * @brief handles incoming connections
370 *
371 * if we are a NET_MASTER_SERVER or NET_PROXY_SERVER_ACTIVE update the connection list to accept new connections (clients)
372 * start and initialize the handsake for the new clients
[9246]373 */
[7954]374void NetworkStream::updateConnectionList( )
375{
376  //check for new connections
377
[9494]378  NetworkSocket* tempNetworkSocket = NULL;
379  int userId;
[7954]380
[9494]381  if( this->clientSocket != NULL)
[6139]382  {
[9494]383    tempNetworkSocket = this->clientSocket->getNewSocket();
384
385    // we got new NET_CLIENT connecting
386    if ( tempNetworkSocket )
[6139]387    {
[9576]388      // get a userId
389//       if ( freeSocketSlots.size() > 0 )
390//       {
391//         // this should never be called
392//         userId = freeSocketSlots.back();
393//         freeSocketSlots.pop_back();
394//       }
395//       else
[9494]396      {
[9531]397        // each server (proxy and master) have an address space for new network nodes of 1000 nodes
[9541]398        userId = SharedNetworkData::getInstance()->getHostID() * 1000 + 1;
[9246]399
[9494]400        for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
401          if ( it->first >= userId )
402            userId = it->first + 1;
[9531]403
[9544]404        // make sure that this server only uses an address space of 1000
[9531]405        assert( userId < (SharedNetworkData::getInstance()->getHostID() + 1) * 1000);
[9494]406      }
407      // this creates a new entry in the peers list
408      peers[userId].socket = tempNetworkSocket;
409      peers[userId].nodeType = NET_CLIENT;
[9246]410
[9494]411      // handle the newly connected client
412      this->handleConnect(userId);
[9246]413
[9494]414      PRINTF(0)("New Client: %d\n", userId);
415    }
416  }
[6341]417
[9406]418
[9494]419  if( this->proxySocket != NULL)
420  {
421    tempNetworkSocket = this->proxySocket->getNewSocket();
[9406]422
[9494]423    // we got new NET_PROXY_SERVER_ACTIVE connecting
424    if ( tempNetworkSocket )
[7954]425    {
[9494]426      // determine the network node id
427      if ( freeSocketSlots.size() > 0 )
428      {
429        userId = freeSocketSlots.back();
430        freeSocketSlots.pop_back();
431      }
432      else
433      {
434        userId = 1;
[6498]435
[9494]436        for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
437          if ( it->first >= userId )
438            userId = it->first + 1;
439      }
[9406]440
[9494]441      // this creates a new entry in the peers list
442      peers[userId].socket = tempNetworkSocket;
443      peers[userId].nodeType = NET_PROXY_SERVER_ACTIVE;
[9406]444
[9494]445      // handle the newly connected proxy server
446      this->handleConnect(userId);
[9406]447
[9494]448      PRINTF(0)("New proxy connected: %d\n", userId);
449    }
[7954]450  }
[6341]451
[9246]452
[9570]453
[7954]454  //check if connections are ok else remove them
[8228]455  for ( PeerList::iterator it = peers.begin(); it != peers.end(); )
[7954]456  {
[9246]457    if (
[7954]458          it->second.socket &&
[9246]459          (
[7954]460            !it->second.socket->isOk()  ||
461            it->second.connectionMonitor->hasTimedOut()
462          )
463       )
464    {
465      std::string reason = "disconnected";
466      if ( it->second.connectionMonitor->hasTimedOut() )
467        reason = "timeout";
468      PRINTF(0)("Client is gone: %d (%s)\n", it->second.userId, reason.c_str());
469
[9571]470
[9494]471      this->handleDisconnect( it->second.userId);
[9571]472
[9570]473      if( SharedNetworkData::getInstance()->isProxyServerActive())
474        ProxyControl::getInstance()->signalLeaveClient(it->second.userId);
[9246]475
[9494]476      it++;
477      continue;
478    }
[7954]479
[9494]480    it++;
481  }
[9246]482
483
[9494]484}
[7954]485
486
[9494]487/**
488 * this handles new connections
489 * @param userId: the id of the new user node
490 */
491void NetworkStream::handleConnect( int userId)
492{
493  // create new handshake and init its variables
494  peers[userId].handshake = new Handshake(this->pInfo->nodeType, userId, this->networkGameManager->getUniqueID(), MessageManager::getInstance()->getUniqueID());
495  peers[userId].handshake->setUniqueID(userId);
[9246]496
[9494]497  peers[userId].connectionMonitor = new ConnectionMonitor( userId );
498  peers[userId].userId = userId;
[9246]499
[9494]500  PRINTF(0)("num sync: %d\n", synchronizeables.size());
[9246]501
[9494]502  // get the proxy server informations and write them to the handshake, if any (proxy)
503  assert( this->networkMonitor != NULL);
504  PeerInfo* pi = this->networkMonitor->getFirstChoiceProxy();
505  if( pi != NULL)
506  {
507    peers[userId].handshake->setProxy1Address( pi->ip);
[6139]508  }
[9494]509  pi = this->networkMonitor->getSecondChoiceProxy();
510  if( pi != NULL)
511    peers[userId].handshake->setProxy2Address( pi->ip);
[6139]512
[9494]513  // check if the connecting client should reconnect to a proxy server
514  if( SharedNetworkData::getInstance()->isMasterServer())
515    peers[userId].handshake->setRedirect(/*this->networkMonitor->isReconnectNextClient()*/false);
[6139]516
[9494]517  // the connecting node of course is a client
518  peers[userId].ip = peers[userId].socket->getRemoteAddress();
[7954]519}
[5800]520
[9246]521
[9494]522
523/**
524 * some debug output
525 */
[7954]526void NetworkStream::debug()
527{
[9406]528  if( SharedNetworkData::getInstance()->isMasterServer()) {
529    PRINT(0)(" Host ist Master Server with ID: %i\n", this->pInfo->userId);
530  }
[9494]531  else if( SharedNetworkData::getInstance()->isProxyServerActive()) {
[9406]532    PRINT(0)(" Host ist Proxy Server with ID: %i\n", this->pInfo->userId);
533  }
534  else {
535    PRINT(0)(" Host ist Client with ID: %i\n", this->pInfo->userId);
536  }
[6695]537
[9574]538  PRINT(0)(" Current number of connections is: %i\n", this->peers.size());
[9548]539  for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
540  {
[9574]541    PRINT(0)("  peers[%i] with uniqueId %i and address: %s\n", it->first, it->second.userId, it->second.ip.ipString().c_str());
[9548]542  }
[9574]543  PRINT(0)("\n\n");
[9548]544
545
[7954]546  PRINT(0)(" Got %i connected Synchronizeables, showing active Syncs:\n", this->synchronizeables.size());
[6139]547  for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++)
[5996]548  {
[7954]549    if( (*it)->beSynchronized() == true)
[9406]550      PRINT(0)("  Synchronizeable of class: %s::%s, with unique ID: %i, Synchronize: %i\n", (*it)->getClassCName(), (*it)->getCName(),
[7954]551               (*it)->getUniqueID(), (*it)->beSynchronized());
552  }
[9406]553  PRINT(0)(" Maximal Connections: %i\n", SharedNetworkData::getInstance()->getMaxPlayer() );
[6959]554
[7954]555}
[6959]556
557
[9246]558/**
559 * @returns the number of synchronizeables registered to this stream
560 */
[7954]561int NetworkStream::getSyncCount()
562{
563  int n = 0;
564  for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++)
565    if( (*it)->beSynchronized() == true)
566      ++n;
[5730]567
[7954]568  //return synchronizeables.size();
569  return n;
570}
[6139]571
[9246]572
[7954]573/**
[9246]574 * check if handshakes completed. if so create the network game manager else remove it again
[7954]575 */
576void NetworkStream::handleHandshakes( )
577{
578  for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
579  {
580    if ( it->second.handshake )
581    {
[9406]582      // handshake finished
[7954]583      if ( it->second.handshake->completed() )
584      {
[9406]585        //handshake is correct
[7954]586        if ( it->second.handshake->ok() )
[6341]587        {
[9494]588          // write the first informations into the node so they can be read from there for case differentiation
589          it->second.nodeType = it->second.handshake->getRemoteNodeType();
590
591          // the counter part didn't mark it free for deletion yet
[7954]592          if ( !it->second.handshake->allowDel() )
[6139]593          {
[9494]594            // make sure this is a connection:
595            // - client       <==> master server
596            // - proxy server <==> master server
[9545]597            if(  SharedNetworkData::getInstance()->isClient() ||
598                 SharedNetworkData::getInstance()->isProxyServerActive() &&
599                 SharedNetworkData::getInstance()->isUserMasterServer(it->second.userId))
[9494]600            {
[9575]601              PRINTF(4)("Handshake: i am in client role\n");
[9406]602
[7954]603              SharedNetworkData::getInstance()->setHostID( it->second.handshake->getHostId() );
[9406]604              this->pInfo->userId = SharedNetworkData::getInstance()->getHostID();
[7954]605
[9494]606#warning the ip address is not set here because it results in a segfault when connecting to a proxy server => trace this later
607//               it->second.ip = it->second.socket->getRemoteAddress();
608
609              // it->second.nodeType = it->second.handshake->getRemoteNodeType();
610              // it->second.ip = it->second.socket->getRemoteAddress();
[9406]611              // add the new server to the nodes list (it can be a NET_MASTER_SERVER or NET_PROXY_SERVER)
612              this->networkMonitor->addNode(&it->second);
613              // get proxy 1 address and add it
614              this->networkMonitor->addNode(it->second.handshake->getProxy1Address(), NET_PROXY_SERVER_ACTIVE);
615              // get proxy 2 address and add it
616              this->networkMonitor->addNode(it->second.handshake->getProxy2Address(), NET_PROXY_SERVER_ACTIVE);
617
618              // now check if the server accepted the connection
[9494]619              if( SharedNetworkData::getInstance()->isClient() && it->second.handshake->redirect() )
620              {
621                this->bRedirect = true;
622              }
[9406]623
624              // create the new network game manager and init it
[7954]625              this->networkGameManager = NetworkGameManager::getInstance();
626              this->networkGameManager->setUniqueID( it->second.handshake->getNetworkGameManagerId() );
[9406]627              // init the new message manager
[7954]628              MessageManager::getInstance()->setUniqueID( it->second.handshake->getMessageManagerId() );
[6868]629            }
[7954]630
631            PRINT(0)("handshake finished id=%d\n", it->second.handshake->getNetworkGameManagerId());
632            it->second.handshake->del();
[9494]633
[6139]634          }
635          else
636          {
[9406]637            // handshake finished registring new player
[7954]638            if ( it->second.handshake->canDel() )
[6868]639            {
[9406]640
[9494]641              if (  SharedNetworkData::getInstance()->isMasterServer() )
[7954]642              {
[9406]643                it->second.ip = it->second.socket->getRemoteAddress();
[9246]644
[9406]645                this->networkMonitor->addNode(&it->second);
646
647                this->handleNewClient( it->second.userId );
648
[9235]649                if ( PlayerStats::getStats( it->second.userId ) && it->second.handshake->getPreferedNickName() != "" )
650                {
651                  PlayerStats::getStats( it->second.userId )->setNickName( it->second.handshake->getPreferedNickName() );
652                }
[7954]653              }
[9494]654              else if ( SharedNetworkData::getInstance()->isProxyServerActive() && it->second.isClient() )
[9406]655              {
[9575]656                PRINTF(4)("Handshake: Proxy in server role: connecting %i\n", it->second.userId);
[9494]657
[9406]658                it->second.ip = it->second.socket->getRemoteAddress();
[9246]659
[9406]660                this->networkMonitor->addNode(&it->second);
661
[9537]662                // work with the ProxyControl to init the new client
[9544]663                ProxyControl::getInstance()->signalNewClient( it->second.userId);
[9406]664
[9564]665#warning dont know if this works: nick name handling
666                if ( PlayerStats::getStats( it->second.userId ) && it->second.handshake->getPreferedNickName() != "" )
667                {
668                  PlayerStats::getStats( it->second.userId )->setNickName( it->second.handshake->getPreferedNickName() );
669                }
[9406]670              }
671
[7954]672              PRINT(0)("handshake finished delete it\n");
673              delete it->second.handshake;
674              it->second.handshake = NULL;
[6868]675            }
[6139]676          }
[7954]677
[6139]678        }
679        else
680        {
[7954]681          PRINT(1)("handshake failed!\n");
682          it->second.socket->disconnectServer();
[6139]683        }
[7954]684      }
[6139]685    }
[5996]686  }
[7954]687}
[5741]688
[9246]689
[7954]690/**
[9406]691 * this functions handles a reconnect event received from the a NET_MASTER_SERVER or NET_PROXY_SERVER
692 */
693void NetworkStream::handleReconnect(int userId)
694{
[9494]695  this->bRedirect = false;
[9548]696#warning this peer will be created if it does not yet exist: dangerous
[9494]697  PeerInfo* pInfo = &this->peers[userId];
698
[9406]699  PRINTF(0)("===============================================\n");
700  PRINTF(0)("Client is redirected to the other proxy servers\n");
[9494]701  PRINTF(0)("  user id: %i\n", userId);
702  PRINTF(0)("  connecting to: %s\n", this->networkMonitor->getFirstChoiceProxy()->ip.ipString().c_str());
[9406]703  PRINTF(0)("===============================================\n");
704
705  // flush the old synchronization states, since the numbering could be completely different
706  pInfo->lastAckedState = 0;
707  pInfo->lastRecvedState = 0;
708
[9494]709  // temp save the ip address here
710  IP proxyIP = pInfo->handshake->getProxy1Address();
711
[9406]712  // disconnect from the current server and reconnect to proxy server
[9494]713  this->handleDisconnect( userId);
714  this->connectToProxyServer(NET_ID_PROXY_SERVER_01, proxyIP.ipString(), 9999);
715  #warning the ports are not yet integrated correctly in the ip class
[9406]716
717  // and restart the handshake
[9494]718  this->startHandshake( userId);
[9406]719}
720
721
722/**
[9494]723 * handles the disconnect event
724 * @param userId id of the user to remove
725 */
726void NetworkStream::handleDisconnect( int userId )
727{
728  peers[userId].socket->disconnectServer();
729  delete peers[userId].socket;
730  peers[userId].socket = NULL;
731
732  if ( peers[userId].handshake )
733    delete peers[userId].handshake;
734  peers[userId].handshake = NULL;
735
736  if ( peers[userId].connectionMonitor )
737    delete peers[userId].connectionMonitor;
738  peers[userId].connectionMonitor = NULL;
739
740
741  for ( SynchronizeableList::iterator it2 = synchronizeables.begin(); it2 != synchronizeables.end(); it2++ )  {
742    (*it2)->cleanUpUser( userId );
743  }
744
745  if( SharedNetworkData::getInstance()->isMasterServer())
746    NetworkGameManager::getInstance()->signalLeftPlayer(userId);
747
748  this->freeSocketSlots.push_back( userId );
749
750  peers.erase( userId);
751}
752
753
754
755/**
[7954]756 * handle upstream network traffic
[9494]757 * @param tick: seconds elapsed since last update
[7954]758 */
[8068]759void NetworkStream::handleUpstream( int tick )
[7954]760{
761  int offset;
762  int n;
[9246]763
[8068]764  for ( PeerList::reverse_iterator peer = peers.rbegin(); peer != peers.rend(); peer++ )
[5802]765  {
[9246]766    offset = INTSIZE; // reserve enough space for the packet length
767
768    // continue with the next peer if this peer has no socket assigned (therefore no network)
[7954]769    if ( !peer->second.socket )
770      continue;
[9246]771
772    // header informations: current state
[7954]773    n = Converter::intToByteArray( currentState, buf + offset, UDP_PACKET_SIZE - offset );
774    assert( n == INTSIZE );
775    offset += n;
[9246]776
777    // header informations: last acked state
[7954]778    n = Converter::intToByteArray( peer->second.lastAckedState, buf + offset, UDP_PACKET_SIZE - offset );
779    assert( n == INTSIZE );
780    offset += n;
[9246]781
782    // header informations: last recved state
[7954]783    n = Converter::intToByteArray( peer->second.lastRecvedState, buf + offset, UDP_PACKET_SIZE - offset );
784    assert( n == INTSIZE );
785    offset += n;
[9246]786
787    // now write all synchronizeables in the packet
[7954]788    for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
[5810]789    {
[9406]790
[7954]791      int oldOffset = offset;
792      Synchronizeable & sync = **it;
[9246]793
[9406]794
[9246]795      // do not include synchronizeables with uninit id and syncs that don't want to be synchronized
[9494]796      if ( !sync.beSynchronized() || sync.getUniqueID() <= NET_UID_UNASSIGNED )
[7954]797        continue;
[5730]798
[9246]799      // if handshake not finished only sync handshake
[7954]800      if ( peer->second.handshake && sync.getLeafClassID() != CL_HANDSHAKE )
801        continue;
[9246]802
[9406]803      // if we are a server (both master and proxy servers) and this is not our handshake
[9494]804      if ( ( SharedNetworkData::getInstance()->isMasterServer() ||
805             SharedNetworkData::getInstance()->isProxyServerActive() &&  peer->second.isClient())
806             && sync.getLeafClassID() == CL_HANDSHAKE && sync.getUniqueID() != peer->second.userId )
[7954]807        continue;
[9246]808
809      /* list of synchronizeables that will never be synchronized over the network: */
810      // do not sync null parent
[7954]811      if ( sync.getLeafClassID() == CL_NULL_PARENT )
812        continue;
[6139]813
[9406]814
815      assert( sync.getLeafClassID() != 0);
816
[7954]817      assert( offset + INTSIZE <= UDP_PACKET_SIZE );
[9246]818
[9532]819      // server fakes uniqueid == 0 for handshake synchronizeable
[9494]820      if ( ( SharedNetworkData::getInstance()->isMasterServer() ||
821             SharedNetworkData::getInstance()->isProxyServerActive() &&  peer->second.isClient() ) &&
[9534]822             ( sync.getUniqueID() >= 1000 || sync.getUniqueID() <= SharedNetworkData::getInstance()->getMaxPlayer() + 1)
[9533]823             /*<= SharedNetworkData::getInstance()->getMaxPlayer() + 1*/) // plus one to handle one client more than the max to redirect it
824        n = Converter::intToByteArray( 0, buf + offset, UDP_PACKET_SIZE - offset );
[7954]825      else
826        n = Converter::intToByteArray( sync.getUniqueID(), buf + offset, UDP_PACKET_SIZE - offset );
[9246]827
[9406]828
[7954]829      assert( n == INTSIZE );
830      offset += n;
[9246]831
[9406]832      // make space for packet size
[7954]833      offset += INTSIZE;
[6139]834
[7954]835      n = sync.getStateDiff( peer->second.userId, buf + offset, UDP_PACKET_SIZE-offset, currentState, peer->second.lastAckedState, -1000 );
836      offset += n;
[9246]837
[7954]838      assert( Converter::intToByteArray( n, buf + offset - n - INTSIZE, INTSIZE ) == INTSIZE );
[6341]839
[9246]840      // check if all data bytes == 0 -> remove data and the synchronizeable from the sync process since there is no update
841      // TODO not all synchronizeables like this maybe add Synchronizeable::canRemoveZeroDiff()
842      bool allZero = true;
843      for ( int i = 0; i < n; i++ )
844      {
845         if ( buf[i+oldOffset+2*INTSIZE] != 0 )
846           allZero = false;
847      }
848      // if there is no new data in this synchronizeable reset the data offset to the last state -> dont synchronizes
849      // data that hast not changed
850      if ( allZero )
851      {
852        offset = oldOffset;
853      }
854    } // all synchronizeables written
[6139]855
[9246]856
857
[7954]858    for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
859    {
860      Synchronizeable & sync = **it;
[9246]861
[9494]862      // again exclude all unwanted syncs
863      if ( !sync.beSynchronized() || sync.getUniqueID() <= NET_UID_UNASSIGNED)
[7954]864        continue;
[9246]865
[7954]866      sync.handleSentState( peer->second.userId, currentState, peer->second.lastAckedState );
867    }
[9246]868
869
[7954]870    assert( Converter::intToByteArray( offset, buf, INTSIZE ) == INTSIZE );
[9246]871
872    // now compress the data with the zip library
[8623]873    int compLength = 0;
[9494]874    if ( SharedNetworkData::getInstance()->isMasterServer() ||
875         SharedNetworkData::getInstance()->isProxyServerActive())
[8623]876      compLength = Zip::getInstance()->zip( buf, offset, compBuf, UDP_PACKET_SIZE, dictServer );
877    else
878      compLength = Zip::getInstance()->zip( buf, offset, compBuf, UDP_PACKET_SIZE, dictClient );
[9246]879
[8623]880    if ( compLength <= 0 )
[7954]881    {
882      PRINTF(1)("compression failed!\n");
883      continue;
884    }
[9246]885
[7954]886    assert( peer->second.socket->writePacket( compBuf, compLength ) );
[9246]887
[7954]888    if ( this->remainingBytesToWriteToDict > 0 )
[8623]889      writeToNewDict( buf, offset, true );
[9246]890
[8068]891    peer->second.connectionMonitor->processUnzippedOutgoingPacket( tick, buf, offset, currentState );
892    peer->second.connectionMonitor->processZippedOutgoingPacket( tick, compBuf, compLength, currentState );
[9246]893
[5810]894  }
[6139]895}
896
[7954]897/**
898 * handle downstream network traffic
899 */
[8068]900void NetworkStream::handleDownstream( int tick )
[6139]901{
[7954]902  int offset = 0;
[9246]903
[7954]904  int length = 0;
905  int packetLength = 0;
906  int compLength = 0;
907  int uniqueId = 0;
908  int state = 0;
909  int ackedState = 0;
910  int fromState = 0;
911  int syncDataLength = 0;
[9246]912
[7954]913  for ( PeerList::iterator peer = peers.begin(); peer != peers.end(); peer++ )
[5810]914  {
[9246]915
[7954]916    if ( !peer->second.socket )
917      continue;
[5730]918
[7954]919    while ( 0 < (compLength = peer->second.socket->readPacket( compBuf, UDP_PACKET_SIZE )) )
[6139]920    {
[8068]921      peer->second.connectionMonitor->processZippedIncomingPacket( tick, compBuf, compLength );
[9246]922
[7954]923      packetLength = Zip::getInstance()->unZip( compBuf, compLength, buf, UDP_PACKET_SIZE );
[8623]924
[7954]925      if ( packetLength < 4*INTSIZE )
926      {
927        if ( packetLength != 0 )
928          PRINTF(1)("got too small packet: %d\n", packetLength);
929        continue;
930      }
[9246]931
[7954]932      if ( this->remainingBytesToWriteToDict > 0 )
[8623]933        writeToNewDict( buf, packetLength, false );
[9246]934
[7954]935      assert( Converter::byteArrayToInt( buf, &length ) == INTSIZE );
936      assert( Converter::byteArrayToInt( buf + INTSIZE, &state ) == INTSIZE );
937      assert( Converter::byteArrayToInt( buf + 2*INTSIZE, &fromState ) == INTSIZE );
938      assert( Converter::byteArrayToInt( buf + 3*INTSIZE, &ackedState ) == INTSIZE );
939      offset = 4*INTSIZE;
[9246]940
[8623]941      peer->second.connectionMonitor->processUnzippedIncomingPacket( tick, buf, packetLength, state, ackedState );
[6139]942
[9246]943
[9406]944      //if this is an old state drop it
[7954]945      if ( state <= peer->second.lastRecvedState )
946        continue;
[9246]947
[7954]948      if ( packetLength != length )
949      {
950        PRINTF(1)("real packet length (%d) and transmitted packet length (%d) do not match!\n", packetLength, length);
951        peer->second.socket->disconnectServer();
952        continue;
953      }
[9246]954
[9406]955      while ( offset + 2 * INTSIZE < length )
[7954]956      {
[9532]957        // read the unique id of the sync
[7954]958        assert( offset > 0 );
959        assert( Converter::byteArrayToInt( buf + offset, &uniqueId ) == INTSIZE );
960        offset += INTSIZE;
[9246]961
[9532]962        // read the data length
[7954]963        assert( Converter::byteArrayToInt( buf + offset, &syncDataLength ) == INTSIZE );
964        offset += INTSIZE;
[9246]965
[7954]966        assert( syncDataLength > 0 );
967        assert( syncDataLength < 10000 );
[9246]968
[7954]969        Synchronizeable * sync = NULL;
[9246]970
[9406]971        // look for the synchronizeable in question
[7954]972        for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
[9246]973        {
[9532]974          // client thinks his handshake has a special id: hostId * 1000 (host id of this server)
975          if ( (*it)->getUniqueID() == uniqueId ||
976                 ( uniqueId == 0  && (*it)->getUniqueID() == peer->second.userId ) )
[7954]977          {
978            sync = *it;
979            break;
980          }
981        }
[9246]982
[9406]983        // this synchronizeable does not yet exist! create it
[7954]984        if ( sync == NULL )
985        {
986          PRINTF(0)("could not find sync with id %d. try to create it\n", uniqueId);
[9406]987
988          // if it is an old synchronizeable already removed, ignore it
[7954]989          if ( oldSynchronizeables.find( uniqueId ) != oldSynchronizeables.end() )
990          {
991            offset += syncDataLength;
992            continue;
993          }
[9246]994
[9494]995          // if the node we got this unknown sync we ignore it if:
996          //  - the remote host is a client
997          //  - the remote host is a proxy server and we are master server
998          // (since it has no rights to create a new sync)
999          if ( peers[peer->second.userId].isClient() ||
1000               (peers[peer->second.userId].isProxyServerActive() && SharedNetworkData::getInstance()->isMasterServer()))
[7954]1001          {
1002            offset += syncDataLength;
1003            continue;
1004          }
[9246]1005
[7954]1006          int leafClassId;
1007          if ( INTSIZE > length - offset )
1008          {
1009            offset += syncDataLength;
1010            continue;
1011          }
[6139]1012
[7954]1013          Converter::byteArrayToInt( buf + offset, &leafClassId );
[9246]1014
[7954]1015          assert( leafClassId != 0 );
[9246]1016
[9406]1017
[7954]1018          BaseObject * b = NULL;
1019          /* These are some small exeptions in creation: Not all objects can/should be created via Factory */
1020          /* Exception 1: NullParent */
1021          if( leafClassId == CL_NULL_PARENT || leafClassId == CL_SYNCHRONIZEABLE || leafClassId == CL_NETWORK_GAME_MANAGER )
1022          {
[9406]1023            PRINTF(1)("Don't create Object with ID %x, ignored!\n", (int)leafClassId);
[7954]1024            offset += syncDataLength;
1025            continue;
1026          }
1027          else
1028            b = Factory::fabricate( (ClassID)leafClassId );
[5800]1029
[7954]1030          if ( !b )
1031          {
1032            PRINTF(1)("Could not fabricate Object with classID %x\n", leafClassId);
1033            offset += syncDataLength;
1034            continue;
1035          }
[5809]1036
[7954]1037          if ( b->isA(CL_SYNCHRONIZEABLE) )
1038          {
1039            sync = dynamic_cast<Synchronizeable*>(b);
1040            sync->setUniqueID( uniqueId );
1041            sync->setSynchronized(true);
[9246]1042
[9406]1043            PRINTF(0)("Fabricated %s with id %d\n", sync->getClassCName(), sync->getUniqueID());
[7954]1044          }
1045          else
1046          {
1047            PRINTF(1)("Class with ID %x is not a synchronizeable!\n", (int)leafClassId);
1048            delete b;
1049            offset += syncDataLength;
1050            continue;
1051          }
1052        }
[6139]1053
[9246]1054
1055        int n = sync->setStateDiff( peer->second.userId, buf+offset, syncDataLength, state, fromState );
[7954]1056        offset += n;
[6498]1057
[7954]1058      }
[9246]1059
[7954]1060      if ( offset != length )
[6139]1061      {
[7954]1062        PRINTF(0)("offset (%d) != length (%d)\n", offset, length);
1063        peer->second.socket->disconnectServer();
[6139]1064      }
[9246]1065
1066
[7954]1067      for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
[6139]1068      {
[7954]1069        Synchronizeable & sync = **it;
[9246]1070
[9494]1071        if ( !sync.beSynchronized() || sync.getUniqueID() <= NET_UID_UNASSIGNED )
[7954]1072          continue;
[9246]1073
[7954]1074        sync.handleRecvState( peer->second.userId, state, fromState );
[6139]1075      }
[9246]1076
[7954]1077      assert( peer->second.lastAckedState <= ackedState );
1078      peer->second.lastAckedState = ackedState;
[9246]1079
[7954]1080      assert( peer->second.lastRecvedState < state );
1081      peer->second.lastRecvedState = state;
[8228]1082
[6139]1083    }
[9246]1084
[6139]1085  }
[9246]1086
[7954]1087}
[6139]1088
[7954]1089/**
1090 * is executed when a handshake has finished
1091 */
1092void NetworkStream::handleNewClient( int userId )
1093{
[9406]1094  // init and assign the message manager
[7954]1095  MessageManager::getInstance()->initUser( userId );
[9406]1096  // do all game relevant stuff here
[7954]1097  networkGameManager->signalNewPlayer( userId );
[5604]1098}
[6139]1099
[9406]1100
[7954]1101/**
1102 * removes old items from oldSynchronizeables
1103 */
1104void NetworkStream::cleanUpOldSyncList( )
[6139]1105{
[7954]1106  int now = SDL_GetTicks();
[9246]1107
[7954]1108  for ( std::map<int,int>::iterator it = oldSynchronizeables.begin(); it != oldSynchronizeables.end();  )
[6139]1109  {
[7954]1110    if ( it->second < now - 10*1000 )
1111    {
1112      std::map<int,int>::iterator delIt = it;
1113      it++;
1114      oldSynchronizeables.erase( delIt );
1115      continue;
1116    }
1117    it++;
[6139]1118  }
[7954]1119}
1120
1121/**
1122 * writes data to DATA/dicts/newdict
1123 * @param data pointer to data
1124 * @param length length
1125 */
[8623]1126void NetworkStream::writeToNewDict( byte * data, int length, bool upstream )
[7954]1127{
1128  if ( remainingBytesToWriteToDict <= 0 )
1129    return;
[9246]1130
[7954]1131  if ( length > remainingBytesToWriteToDict )
1132    length = remainingBytesToWriteToDict;
[9246]1133
[7954]1134  std::string fileName = ResourceManager::getInstance()->getDataDir();
1135  fileName += "/dicts/newdict";
[9246]1136
[8623]1137  if ( upstream )
1138    fileName += "_upstream";
1139  else
1140    fileName += "_downstream";
[9246]1141
[7954]1142  FILE * f = fopen( fileName.c_str(), "a" );
[9246]1143
[7954]1144  if ( !f )
[6139]1145  {
[7954]1146    PRINTF(2)("could not open %s\n", fileName.c_str());
1147    remainingBytesToWriteToDict = 0;
[6139]1148    return;
1149  }
[9246]1150
[7954]1151  if ( fwrite( data, 1, length, f ) != length )
[6341]1152  {
[7954]1153    PRINTF(2)("could not write to file\n");
1154    fclose( f );
[6341]1155    return;
1156  }
[9246]1157
[7954]1158  fclose( f );
[9246]1159
1160  remainingBytesToWriteToDict -= length;
[6139]1161}
1162
1163
[6695]1164
1165
1166
1167
Note: See TracBrowser for help on using the repository browser.