Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

peers get deleted correctly now

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