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
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
124  this->bRedirect = false;
125
126  this->currentState = 0;
127
128  remainingBytesToWriteToDict = Preferences::getInstance()->getInt( "compression", "writedict", 0 );
129
130  assert( Zip::getInstance()->loadDictionary( "testdict" ) >= 0 );
131  this->dictClient = Zip::getInstance()->loadDictionary( "dict2pl_client" );
132  assert( this->dictClient >= 0 );
133  this->dictServer = Zip::getInstance()->loadDictionary( "dict2p_server" );
134  assert( this->dictServer >= 0 );
135}
136
137
138/**
139 * deconstructor
140 */
141NetworkStream::~NetworkStream()
142{
143  if ( this->clientSocket )
144  {
145    clientSocket->close();
146    delete clientSocket;
147    clientSocket = NULL;
148  }
149  if ( this->proxySocket)
150  {
151    proxySocket->close();
152    delete proxySocket;
153    proxySocket = NULL;
154  }
155  for ( PeerList::iterator i = peers.begin(); i!=peers.end(); i++)
156  {
157    if ( i->second.socket )
158    {
159      i->second.socket->disconnectServer();
160      delete i->second.socket;
161      i->second.socket = NULL;
162    }
163
164    if ( i->second.handshake )
165    {
166      delete i->second.handshake;
167      i->second.handshake = NULL;
168    }
169
170    if ( i->second.connectionMonitor )
171    {
172      delete i->second.connectionMonitor;
173      i->second.connectionMonitor = NULL;
174    }
175  }
176  for ( SynchronizeableList::const_iterator it = getSyncBegin(); it != getSyncEnd(); it ++ )
177    (*it)->setNetworkStream( NULL );
178
179  if( this->pInfo)
180    delete this->pInfo;
181
182  if( this->networkMonitor)
183    delete this->networkMonitor;
184}
185
186
187/**
188 * establish a connection to a remote master server
189 * @param host: host name
190 * @param port: the port number
191 */
192void NetworkStream::connectToMasterServer(std::string host, int port)
193{
194  int node = NET_ID_MASTER_SERVER;
195  // this create the new node in the peers map
196  this->peers[node].socket = new UdpSocket( host, port );
197  this->peers[node].userId = NET_ID_MASTER_SERVER;
198
199  this->peers[node].nodeType = NET_MASTER_SERVER;
200  this->peers[node].connectionMonitor = new ConnectionMonitor( NET_ID_MASTER_SERVER );
201  this->peers[node].ip = this->peers[node].socket->getRemoteAddress();
202}
203
204
205/**
206 * establish a connection to a remote proxy server
207 * @param host: host name
208 * @param port: the port number
209 */
210void NetworkStream::connectToProxyServer(int proxyId, std::string host, int port)
211{
212  PRINTF(0)("connect to proxy %s, this is proxyId %i\n", host.c_str(), proxyId);
213
214  // this creates the new proxyId in the peers map
215  this->peers[proxyId].socket = new UdpSocket( host, port );
216  this->peers[proxyId].userId = proxyId;
217
218  this->peers[proxyId].nodeType = NET_PROXY_SERVER_ACTIVE;
219  this->peers[proxyId].connectionMonitor = new ConnectionMonitor( proxyId );
220  this->peers[proxyId].ip = this->peers[proxyId].socket->getRemoteAddress();
221}
222
223
224/**
225 * create a server
226 * @param port: interface port for all clients
227 */
228void NetworkStream::createServer(int clientPort, int proxyPort)
229{
230  PRINTF(0)(" Creating new Server: listening for clients on port %i and for proxies on port %i", clientPort, proxyPort);
231  this->clientSocket= new UdpServerSocket(clientPort);
232  this->proxySocket = new UdpServerSocket(proxyPort);
233}
234
235
236/**
237 * creates a new instance of the network game manager
238 */
239void NetworkStream::createNetworkGameManager()
240{
241  this->networkGameManager = NetworkGameManager::getInstance();
242
243  this->networkGameManager->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
244  MessageManager::getInstance()->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
245}
246
247
248/**
249 * starts the network handshake
250 * handsakes are always initialized from the client side first. this starts the handshake and therefore is only
251 * executed as client
252 * @param userId: start handshake for this user id (optional, default == 0)
253 */
254void NetworkStream::startHandshake(int userId)
255{
256  Handshake* hs = new Handshake(this->pInfo->nodeType);
257  // fake the unique id
258  hs->setUniqueID( NET_UID_HANDSHAKE );
259  assert( peers[userId].handshake == NULL );
260  peers[userId].handshake = hs;
261
262  // set the preferred nick name
263  hs->setPreferedNickName( Preferences::getInstance()->getString( "multiplayer", "nickname", "Player" ) );
264
265  PRINTF(0)("NetworkStream: Handshake created: %s\n", hs->getCName());
266}
267
268
269/**
270 * this functions connects a synchronizeable to the networkstream, therefore synchronizeing
271 * it all over the network and creating it on the other platforms (if and only if it is a
272 * server
273 * @param sync: the synchronizeable to add
274 */
275void NetworkStream::connectSynchronizeable(Synchronizeable& sync)
276{
277  this->synchronizeables.push_back(&sync);
278  sync.setNetworkStream( this );
279}
280
281
282/**
283 * removes the synchronizeable from the list of synchronized entities
284 * @param sync: the syncronizeable to remove
285 */
286void NetworkStream::disconnectSynchronizeable(Synchronizeable& sync)
287{
288  // removing the Synchronizeable from the List.
289  std::list<Synchronizeable*>::iterator disconnectSynchro = std::find(this->synchronizeables.begin(), this->synchronizeables.end(), &sync);
290  if (disconnectSynchro != this->synchronizeables.end())
291    this->synchronizeables.erase(disconnectSynchro);
292
293  oldSynchronizeables[sync.getUniqueID()] = SDL_GetTicks();
294}
295
296
297/**
298 * this is called to process data from the network socket to the synchronizeable and vice versa
299 */
300void NetworkStream::processData()
301{
302  // create the network monitor after all the init work and before there is any connection handlings
303  if( this->networkMonitor == NULL)
304    this->networkMonitor = new NetworkMonitor(this);
305
306
307  int tick = SDL_GetTicks();
308
309  this->currentState++;
310  // there was a wrap around
311  if( this->currentState < 0)
312  {
313    PRINTF(1)("A wrap around in the state variable as occured. The server was running so long? Pls restart server or write a mail to the supporters!\n");
314  }
315
316  if ( SharedNetworkData::getInstance()->isMasterServer())
317  {
318    // execute everytthing the master server shoudl do
319    if ( this->clientSocket )
320      this->clientSocket->update();
321    if( this->proxySocket)
322      this->proxySocket->update();
323
324    this->updateConnectionList();
325  }
326  else if( SharedNetworkData::getInstance()->isProxyServerActive())
327  {
328    //execute everything the proxy server should do
329    if ( this->clientSocket )
330      this->clientSocket->update();
331    if( this->proxySocket)
332      this->proxySocket->update();
333
334    this->updateConnectionList();
335  }
336
337#warning make this more modular: every proxy/master server connection should be watched for termination
338  if( !SharedNetworkData::getInstance()->isMasterServer())
339  {
340    // check if the connection is ok else terminate and remove
341    if ( !peers.empty() && peers[NET_ID_MASTER_SERVER].socket &&
342          ( !peers[NET_ID_MASTER_SERVER].socket->isOk() ||
343          peers[NET_ID_MASTER_SERVER].connectionMonitor->hasTimedOut() ) )
344    {
345      this->handleDisconnect( NET_ID_MASTER_SERVER);
346      PRINTF(1)("lost connection to server\n");
347    }
348    // check if there is a redirection command
349    if( this->bRedirect)
350    {
351      this->handleReconnect( NET_ID_MASTER_SERVER);
352    }
353  }
354
355  this->cleanUpOldSyncList();
356  this->handleHandshakes();
357
358  // update the network monitor
359  this->networkMonitor->process();
360
361  // order of up/downstream is important!!!!
362  // don't change it
363  this->handleDownstream( tick );
364  this->handleUpstream( tick );
365}
366
367
368/**
369 * @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
373 */
374void NetworkStream::updateConnectionList( )
375{
376  //check for new connections
377
378  NetworkSocket* tempNetworkSocket = NULL;
379  int userId;
380
381  if( this->clientSocket != NULL)
382  {
383    tempNetworkSocket = this->clientSocket->getNewSocket();
384
385    // we got new NET_CLIENT connecting
386    if ( tempNetworkSocket )
387    {
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
396      {
397        // each server (proxy and master) have an address space for new network nodes of 1000 nodes
398        userId = SharedNetworkData::getInstance()->getHostID() * 1000 + 1;
399
400        for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
401          if ( it->first >= userId )
402            userId = it->first + 1;
403
404        // make sure that this server only uses an address space of 1000
405        assert( userId < (SharedNetworkData::getInstance()->getHostID() + 1) * 1000);
406      }
407      // this creates a new entry in the peers list
408      peers[userId].socket = tempNetworkSocket;
409      peers[userId].nodeType = NET_CLIENT;
410
411      // handle the newly connected client
412      this->handleConnect(userId);
413
414      PRINTF(0)("New Client: %d\n", userId);
415    }
416  }
417
418
419  if( this->proxySocket != NULL)
420  {
421    tempNetworkSocket = this->proxySocket->getNewSocket();
422
423    // we got new NET_PROXY_SERVER_ACTIVE connecting
424    if ( tempNetworkSocket )
425    {
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;
435
436        for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
437          if ( it->first >= userId )
438            userId = it->first + 1;
439      }
440
441      // this creates a new entry in the peers list
442      peers[userId].socket = tempNetworkSocket;
443      peers[userId].nodeType = NET_PROXY_SERVER_ACTIVE;
444
445      // handle the newly connected proxy server
446      this->handleConnect(userId);
447
448      PRINTF(0)("New proxy connected: %d\n", userId);
449    }
450  }
451
452
453
454  //check if connections are ok else remove them
455  for ( PeerList::iterator it = peers.begin(); it != peers.end(); )
456  {
457    if (
458          it->second.socket &&
459          (
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
470
471      this->handleDisconnect( it->second.userId);
472
473      if( SharedNetworkData::getInstance()->isProxyServerActive())
474        ProxyControl::getInstance()->signalLeaveClient(it->second.userId);
475
476      it++;
477      continue;
478    }
479
480    it++;
481  }
482
483
484}
485
486
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);
496
497  peers[userId].connectionMonitor = new ConnectionMonitor( userId );
498  peers[userId].userId = userId;
499
500  PRINTF(0)("num sync: %d\n", synchronizeables.size());
501
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);
508  }
509  pi = this->networkMonitor->getSecondChoiceProxy();
510  if( pi != NULL)
511    peers[userId].handshake->setProxy2Address( pi->ip);
512
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);
516
517  // the connecting node of course is a client
518  peers[userId].ip = peers[userId].socket->getRemoteAddress();
519}
520
521
522
523/**
524 * some debug output
525 */
526void NetworkStream::debug()
527{
528  if( SharedNetworkData::getInstance()->isMasterServer()) {
529    PRINT(0)(" Host ist Master Server with ID: %i\n", this->pInfo->userId);
530  }
531  else if( SharedNetworkData::getInstance()->isProxyServerActive()) {
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  }
537
538  PRINT(0)(" Current number of connections is: %i\n", this->peers.size());
539  for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
540  {
541    PRINT(0)("  peers[%i] with uniqueId %i and address: %s\n", it->first, it->second.userId, it->second.ip.ipString().c_str());
542  }
543  PRINT(0)("\n\n");
544
545
546  PRINT(0)(" Got %i connected Synchronizeables, showing active Syncs:\n", this->synchronizeables.size());
547  for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++)
548  {
549    if( (*it)->beSynchronized() == true)
550      PRINT(0)("  Synchronizeable of class: %s::%s, with unique ID: %i, Synchronize: %i\n", (*it)->getClassCName(), (*it)->getCName(),
551               (*it)->getUniqueID(), (*it)->beSynchronized());
552  }
553  PRINT(0)(" Maximal Connections: %i\n", SharedNetworkData::getInstance()->getMaxPlayer() );
554
555}
556
557
558/**
559 * @returns the number of synchronizeables registered to this stream
560 */
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;
567
568  //return synchronizeables.size();
569  return n;
570}
571
572
573/**
574 * check if handshakes completed. if so create the network game manager else remove it again
575 */
576void NetworkStream::handleHandshakes( )
577{
578  for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
579  {
580    if ( it->second.handshake )
581    {
582      // handshake finished
583      if ( it->second.handshake->completed() )
584      {
585        //handshake is correct
586        if ( it->second.handshake->ok() )
587        {
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
592          if ( !it->second.handshake->allowDel() )
593          {
594            // make sure this is a connection:
595            // - client       <==> master server
596            // - proxy server <==> master server
597            if(  SharedNetworkData::getInstance()->isClient() ||
598                 SharedNetworkData::getInstance()->isProxyServerActive() &&
599                 SharedNetworkData::getInstance()->isUserMasterServer(it->second.userId))
600            {
601              PRINTF(4)("Handshake: i am in client role\n");
602
603              SharedNetworkData::getInstance()->setHostID( it->second.handshake->getHostId() );
604              this->pInfo->userId = SharedNetworkData::getInstance()->getHostID();
605
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();
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
619              if( SharedNetworkData::getInstance()->isClient() && it->second.handshake->redirect() )
620              {
621                this->bRedirect = true;
622              }
623
624              // create the new network game manager and init it
625              this->networkGameManager = NetworkGameManager::getInstance();
626              this->networkGameManager->setUniqueID( it->second.handshake->getNetworkGameManagerId() );
627              // init the new message manager
628              MessageManager::getInstance()->setUniqueID( it->second.handshake->getMessageManagerId() );
629            }
630
631            PRINT(0)("handshake finished id=%d\n", it->second.handshake->getNetworkGameManagerId());
632            it->second.handshake->del();
633
634          }
635          else
636          {
637            // handshake finished registring new player
638            if ( it->second.handshake->canDel() )
639            {
640
641              if (  SharedNetworkData::getInstance()->isMasterServer() )
642              {
643                it->second.ip = it->second.socket->getRemoteAddress();
644
645                this->networkMonitor->addNode(&it->second);
646
647                this->handleNewClient( it->second.userId );
648
649                if ( PlayerStats::getStats( it->second.userId ) && it->second.handshake->getPreferedNickName() != "" )
650                {
651                  PlayerStats::getStats( it->second.userId )->setNickName( it->second.handshake->getPreferedNickName() );
652                }
653              }
654              else if ( SharedNetworkData::getInstance()->isProxyServerActive() && it->second.isClient() )
655              {
656                PRINTF(4)("Handshake: Proxy in server role: connecting %i\n", it->second.userId);
657
658                it->second.ip = it->second.socket->getRemoteAddress();
659
660                this->networkMonitor->addNode(&it->second);
661
662                // work with the ProxyControl to init the new client
663                ProxyControl::getInstance()->signalNewClient( it->second.userId);
664
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                }
670              }
671
672              PRINT(0)("handshake finished delete it\n");
673              delete it->second.handshake;
674              it->second.handshake = NULL;
675            }
676          }
677
678        }
679        else
680        {
681          PRINT(1)("handshake failed!\n");
682          it->second.socket->disconnectServer();
683        }
684      }
685    }
686  }
687}
688
689
690/**
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{
695  this->bRedirect = false;
696#warning this peer will be created if it does not yet exist: dangerous
697  PeerInfo* pInfo = &this->peers[userId];
698
699  PRINTF(0)("===============================================\n");
700  PRINTF(0)("Client is redirected to the other proxy servers\n");
701  PRINTF(0)("  user id: %i\n", userId);
702  PRINTF(0)("  connecting to: %s\n", this->networkMonitor->getFirstChoiceProxy()->ip.ipString().c_str());
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
709  // temp save the ip address here
710  IP proxyIP = pInfo->handshake->getProxy1Address();
711
712  // disconnect from the current server and reconnect to proxy server
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
716
717  // and restart the handshake
718  this->startHandshake( userId);
719}
720
721
722/**
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/**
756 * handle upstream network traffic
757 * @param tick: seconds elapsed since last update
758 */
759void NetworkStream::handleUpstream( int tick )
760{
761  int offset;
762  int n;
763
764  for ( PeerList::reverse_iterator peer = peers.rbegin(); peer != peers.rend(); peer++ )
765  {
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)
769    if ( !peer->second.socket )
770      continue;
771
772    // header informations: current state
773    n = Converter::intToByteArray( currentState, buf + offset, UDP_PACKET_SIZE - offset );
774    assert( n == INTSIZE );
775    offset += n;
776
777    // header informations: last acked state
778    n = Converter::intToByteArray( peer->second.lastAckedState, buf + offset, UDP_PACKET_SIZE - offset );
779    assert( n == INTSIZE );
780    offset += n;
781
782    // header informations: last recved state
783    n = Converter::intToByteArray( peer->second.lastRecvedState, buf + offset, UDP_PACKET_SIZE - offset );
784    assert( n == INTSIZE );
785    offset += n;
786
787    // now write all synchronizeables in the packet
788    for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
789    {
790
791      int oldOffset = offset;
792      Synchronizeable & sync = **it;
793
794
795      // do not include synchronizeables with uninit id and syncs that don't want to be synchronized
796      if ( !sync.beSynchronized() || sync.getUniqueID() <= NET_UID_UNASSIGNED )
797        continue;
798
799      // if handshake not finished only sync handshake
800      if ( peer->second.handshake && sync.getLeafClassID() != CL_HANDSHAKE )
801        continue;
802
803      // if we are a server (both master and proxy servers) and this is not our handshake
804      if ( ( SharedNetworkData::getInstance()->isMasterServer() ||
805             SharedNetworkData::getInstance()->isProxyServerActive() &&  peer->second.isClient())
806             && sync.getLeafClassID() == CL_HANDSHAKE && sync.getUniqueID() != peer->second.userId )
807        continue;
808
809      /* list of synchronizeables that will never be synchronized over the network: */
810      // do not sync null parent
811      if ( sync.getLeafClassID() == CL_NULL_PARENT )
812        continue;
813
814
815      assert( sync.getLeafClassID() != 0);
816
817      assert( offset + INTSIZE <= UDP_PACKET_SIZE );
818
819      // server fakes uniqueid == 0 for handshake synchronizeable
820      if ( ( SharedNetworkData::getInstance()->isMasterServer() ||
821             SharedNetworkData::getInstance()->isProxyServerActive() &&  peer->second.isClient() ) &&
822             ( sync.getUniqueID() >= 1000 || sync.getUniqueID() <= SharedNetworkData::getInstance()->getMaxPlayer() + 1)
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 );
825      else
826        n = Converter::intToByteArray( sync.getUniqueID(), buf + offset, UDP_PACKET_SIZE - offset );
827
828
829      assert( n == INTSIZE );
830      offset += n;
831
832      // make space for packet size
833      offset += INTSIZE;
834
835      n = sync.getStateDiff( peer->second.userId, buf + offset, UDP_PACKET_SIZE-offset, currentState, peer->second.lastAckedState, -1000 );
836      offset += n;
837
838      assert( Converter::intToByteArray( n, buf + offset - n - INTSIZE, INTSIZE ) == INTSIZE );
839
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
855
856
857
858    for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
859    {
860      Synchronizeable & sync = **it;
861
862      // again exclude all unwanted syncs
863      if ( !sync.beSynchronized() || sync.getUniqueID() <= NET_UID_UNASSIGNED)
864        continue;
865
866      sync.handleSentState( peer->second.userId, currentState, peer->second.lastAckedState );
867    }
868
869
870    assert( Converter::intToByteArray( offset, buf, INTSIZE ) == INTSIZE );
871
872    // now compress the data with the zip library
873    int compLength = 0;
874    if ( SharedNetworkData::getInstance()->isMasterServer() ||
875         SharedNetworkData::getInstance()->isProxyServerActive())
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 );
879
880    if ( compLength <= 0 )
881    {
882      PRINTF(1)("compression failed!\n");
883      continue;
884    }
885
886    assert( peer->second.socket->writePacket( compBuf, compLength ) );
887
888    if ( this->remainingBytesToWriteToDict > 0 )
889      writeToNewDict( buf, offset, true );
890
891    peer->second.connectionMonitor->processUnzippedOutgoingPacket( tick, buf, offset, currentState );
892    peer->second.connectionMonitor->processZippedOutgoingPacket( tick, compBuf, compLength, currentState );
893
894  }
895}
896
897/**
898 * handle downstream network traffic
899 */
900void NetworkStream::handleDownstream( int tick )
901{
902  int offset = 0;
903
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;
912
913  for ( PeerList::iterator peer = peers.begin(); peer != peers.end(); peer++ )
914  {
915
916    if ( !peer->second.socket )
917      continue;
918
919    while ( 0 < (compLength = peer->second.socket->readPacket( compBuf, UDP_PACKET_SIZE )) )
920    {
921      peer->second.connectionMonitor->processZippedIncomingPacket( tick, compBuf, compLength );
922
923      packetLength = Zip::getInstance()->unZip( compBuf, compLength, buf, UDP_PACKET_SIZE );
924
925      if ( packetLength < 4*INTSIZE )
926      {
927        if ( packetLength != 0 )
928          PRINTF(1)("got too small packet: %d\n", packetLength);
929        continue;
930      }
931
932      if ( this->remainingBytesToWriteToDict > 0 )
933        writeToNewDict( buf, packetLength, false );
934
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;
940
941      peer->second.connectionMonitor->processUnzippedIncomingPacket( tick, buf, packetLength, state, ackedState );
942
943
944      //if this is an old state drop it
945      if ( state <= peer->second.lastRecvedState )
946        continue;
947
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      }
954
955      while ( offset + 2 * INTSIZE < length )
956      {
957        // read the unique id of the sync
958        assert( offset > 0 );
959        assert( Converter::byteArrayToInt( buf + offset, &uniqueId ) == INTSIZE );
960        offset += INTSIZE;
961
962        // read the data length
963        assert( Converter::byteArrayToInt( buf + offset, &syncDataLength ) == INTSIZE );
964        offset += INTSIZE;
965
966        assert( syncDataLength > 0 );
967        assert( syncDataLength < 10000 );
968
969        Synchronizeable * sync = NULL;
970
971        // look for the synchronizeable in question
972        for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
973        {
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 ) )
977          {
978            sync = *it;
979            break;
980          }
981        }
982
983        // this synchronizeable does not yet exist! create it
984        if ( sync == NULL )
985        {
986          PRINTF(0)("could not find sync with id %d. try to create it\n", uniqueId);
987
988          // if it is an old synchronizeable already removed, ignore it
989          if ( oldSynchronizeables.find( uniqueId ) != oldSynchronizeables.end() )
990          {
991            offset += syncDataLength;
992            continue;
993          }
994
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()))
1001          {
1002            offset += syncDataLength;
1003            continue;
1004          }
1005
1006          int leafClassId;
1007          if ( INTSIZE > length - offset )
1008          {
1009            offset += syncDataLength;
1010            continue;
1011          }
1012
1013          Converter::byteArrayToInt( buf + offset, &leafClassId );
1014
1015          assert( leafClassId != 0 );
1016
1017
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          {
1023            PRINTF(1)("Don't create Object with ID %x, ignored!\n", (int)leafClassId);
1024            offset += syncDataLength;
1025            continue;
1026          }
1027          else
1028            b = Factory::fabricate( (ClassID)leafClassId );
1029
1030          if ( !b )
1031          {
1032            PRINTF(1)("Could not fabricate Object with classID %x\n", leafClassId);
1033            offset += syncDataLength;
1034            continue;
1035          }
1036
1037          if ( b->isA(CL_SYNCHRONIZEABLE) )
1038          {
1039            sync = dynamic_cast<Synchronizeable*>(b);
1040            sync->setUniqueID( uniqueId );
1041            sync->setSynchronized(true);
1042
1043            PRINTF(0)("Fabricated %s with id %d\n", sync->getClassCName(), sync->getUniqueID());
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        }
1053
1054
1055        int n = sync->setStateDiff( peer->second.userId, buf+offset, syncDataLength, state, fromState );
1056        offset += n;
1057
1058      }
1059
1060      if ( offset != length )
1061      {
1062        PRINTF(0)("offset (%d) != length (%d)\n", offset, length);
1063        peer->second.socket->disconnectServer();
1064      }
1065
1066
1067      for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
1068      {
1069        Synchronizeable & sync = **it;
1070
1071        if ( !sync.beSynchronized() || sync.getUniqueID() <= NET_UID_UNASSIGNED )
1072          continue;
1073
1074        sync.handleRecvState( peer->second.userId, state, fromState );
1075      }
1076
1077      assert( peer->second.lastAckedState <= ackedState );
1078      peer->second.lastAckedState = ackedState;
1079
1080      assert( peer->second.lastRecvedState < state );
1081      peer->second.lastRecvedState = state;
1082
1083    }
1084
1085  }
1086
1087}
1088
1089/**
1090 * is executed when a handshake has finished
1091 */
1092void NetworkStream::handleNewClient( int userId )
1093{
1094  // init and assign the message manager
1095  MessageManager::getInstance()->initUser( userId );
1096  // do all game relevant stuff here
1097  networkGameManager->signalNewPlayer( userId );
1098}
1099
1100
1101/**
1102 * removes old items from oldSynchronizeables
1103 */
1104void NetworkStream::cleanUpOldSyncList( )
1105{
1106  int now = SDL_GetTicks();
1107
1108  for ( std::map<int,int>::iterator it = oldSynchronizeables.begin(); it != oldSynchronizeables.end();  )
1109  {
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++;
1118  }
1119}
1120
1121/**
1122 * writes data to DATA/dicts/newdict
1123 * @param data pointer to data
1124 * @param length length
1125 */
1126void NetworkStream::writeToNewDict( byte * data, int length, bool upstream )
1127{
1128  if ( remainingBytesToWriteToDict <= 0 )
1129    return;
1130
1131  if ( length > remainingBytesToWriteToDict )
1132    length = remainingBytesToWriteToDict;
1133
1134  std::string fileName = ResourceManager::getInstance()->getDataDir();
1135  fileName += "/dicts/newdict";
1136
1137  if ( upstream )
1138    fileName += "_upstream";
1139  else
1140    fileName += "_downstream";
1141
1142  FILE * f = fopen( fileName.c_str(), "a" );
1143
1144  if ( !f )
1145  {
1146    PRINTF(2)("could not open %s\n", fileName.c_str());
1147    remainingBytesToWriteToDict = 0;
1148    return;
1149  }
1150
1151  if ( fwrite( data, 1, length, f ) != length )
1152  {
1153    PRINTF(2)("could not write to file\n");
1154    fclose( f );
1155    return;
1156  }
1157
1158  fclose( f );
1159
1160  remainingBytesToWriteToDict -= length;
1161}
1162
1163
1164
1165
1166
1167
Note: See TracBrowser for help on using the repository browser.