Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

localhost now gets its own ip, hoover is added to the correct team

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