Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

userId address spaces adjusted since the proxys are handled differently than clients

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