Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7748 was 7748, checked in by rennerc, 18 years ago

implemented class to log network things to telnet

File size: 17.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: claudio
13   co-programmer:
14*/
15
16
17/* this is for debug output. It just says, that all calls to PRINT() belong to the DEBUG_MODULE_NETWORK module
18   For more information refere to https://www.orxonox.net/cgi-bin/trac.cgi/wiki/DebugOutput
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 "connection_monitor.h"
28#include "synchronizeable.h"
29#include "network_game_manager.h"
30#include "shared_network_data.h"
31#include "message_manager.h"
32
33#include "network_log.h"
34
35
36#include "lib/util/loading/factory.h"
37
38#include "debug.h"
39#include "class_list.h"
40#include <algorithm>
41
42/* include your own header */
43#include "network_stream.h"
44
45/* probably unnecessary */
46using namespace std;
47
48
49#define PACKAGE_SIZE  256
50
51
52NetworkStream::NetworkStream()
53    : DataStream()
54{
55  this->init();
56  /* initialize the references */
57  this->type = NET_CLIENT;
58  this->networkProtocol = new NetworkProtocol();
59  this->connectionMonitor = new ConnectionMonitor();
60}
61
62
63NetworkStream::NetworkStream( std::string host, int port )
64{
65  this->type = NET_CLIENT;
66  this->init();
67  this->peers[0].socket = new UdpSocket( host, port );
68  this->peers[0].userId = 0;
69  this->peers[0].isServer = true;
70  this->networkProtocol = new NetworkProtocol();
71  this->connectionMonitor = new ConnectionMonitor();
72}
73
74
75NetworkStream::NetworkStream( int port )
76{
77  this->type = NET_SERVER;
78  this->init();
79  this->serverSocket = new UdpServerSocket(port);
80  this->networkProtocol = new NetworkProtocol();
81  this->connectionMonitor = new ConnectionMonitor();
82  this->bActive = true;
83}
84
85
86void NetworkStream::init()
87{
88  /* set the class id for the base object */
89  this->setClassID(CL_NETWORK_STREAM, "NetworkStream");
90  this->bActive = false;
91  this->serverSocket = NULL;
92  this->networkGameManager = NULL;
93  myHostId = 0;
94  currentState = 0;
95}
96
97
98NetworkStream::~NetworkStream()
99{
100  if ( this->serverSocket )
101  {
102    serverSocket->close();
103    delete serverSocket;
104  }
105
106  for ( PeerList::iterator i = peers.begin(); i!=peers.end(); i++)
107  {
108    if ( i->second.socket )
109    {
110      i->second.socket->disconnectServer();
111      delete i->second.socket;
112      i->second.socket = NULL;
113    }
114   
115    if ( i->second.handshake )
116    {
117      delete i->second.handshake;
118      i->second.handshake = NULL;
119    }
120  }
121 
122  if ( serverSocket )
123  {
124    delete serverSocket;
125    serverSocket = NULL;
126  }
127
128  delete connectionMonitor;
129  delete networkProtocol;
130}
131
132
133void NetworkStream::createNetworkGameManager()
134{
135  this->networkGameManager = NetworkGameManager::getInstance();
136  // setUniqueID( maxCon+2 ) because we need one id for every handshake
137  // and one for handshake to reject client maxCon+1
138  this->networkGameManager->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
139  MessageManager::getInstance()->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
140}
141
142
143void NetworkStream::startHandshake()
144{
145  Handshake* hs = new Handshake(false);
146  hs->setUniqueID( 0 );
147  assert( peers[0].handshake == NULL );
148  peers[0].handshake = hs;
149//   peers[0].handshake->setSynchronized( true );
150  //this->connectSynchronizeable(*hs);
151  //this->connectSynchronizeable(*hs);
152  PRINTF(0)("NetworkStream: Handshake created: %s\n", hs->getName());
153}
154
155
156void NetworkStream::connectSynchronizeable(Synchronizeable& sync)
157{
158  this->synchronizeables.push_back(&sync);
159  sync.setNetworkStream( this );
160
161  this->bActive = true;
162}
163
164
165void NetworkStream::disconnectSynchronizeable(Synchronizeable& sync)
166{
167  // removing the Synchronizeable from the List.
168  std::list<Synchronizeable*>::iterator disconnectSynchro = std::find(this->synchronizeables.begin(), this->synchronizeables.end(), &sync);
169  if (disconnectSynchro != this->synchronizeables.end())
170    this->synchronizeables.erase(disconnectSynchro);
171 
172  //TODO set timestamp
173  oldSynchronizeables[sync.getUniqueID()] = 0;
174}
175
176
177void NetworkStream::processData()
178{
179  currentState++;
180 
181  if ( this->type == NET_SERVER )
182  {
183    if ( serverSocket )
184      serverSocket->update();
185   
186    this->updateConnectionList();
187  }
188  else
189  {
190    if ( peers[0].socket && !peers[0].socket->isOk() )
191    {
192      PRINTF(1)("lost connection to server\n");
193
194      peers[0].socket->disconnectServer();
195      delete peers[0].socket;
196      peers[0].socket = NULL;
197
198      if ( peers[0].handshake )
199        delete peers[0].handshake;
200      peers[0].handshake = NULL;
201    }
202  }
203
204  handleHandshakes();
205  handleUpstream();
206  handleDownstream();
207
208}
209
210void NetworkStream::updateConnectionList( )
211{
212  //check for new connections
213
214  NetworkSocket* tempNetworkSocket = serverSocket->getNewSocket();
215
216  if ( tempNetworkSocket )
217  {
218    int clientId;
219    if ( freeSocketSlots.size() >0 )
220    {
221      clientId = freeSocketSlots.back();
222      freeSocketSlots.pop_back();
223      peers[clientId].socket = tempNetworkSocket;
224      peers[clientId].handshake = new Handshake(true, clientId, this->networkGameManager->getUniqueID(), MessageManager::getInstance()->getUniqueID() );
225      peers[clientId].handshake->setUniqueID(clientId);
226      peers[clientId].userId = clientId;
227      peers[clientId].isServer = false;
228    } else
229    {
230      clientId = 1;
231     
232      for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
233        if ( it->first >= clientId )
234          clientId = it->first + 1;
235     
236      peers[clientId].socket = tempNetworkSocket;
237      peers[clientId].handshake = new Handshake(true, clientId, this->networkGameManager->getUniqueID(), MessageManager::getInstance()->getUniqueID());
238      peers[clientId].handshake->setUniqueID(clientId);
239      peers[clientId].userId = clientId;
240      peers[clientId].isServer = false;
241     
242      PRINTF(0)("num sync: %d\n", synchronizeables.size());
243    }
244
245    if ( clientId > MAX_CONNECTIONS )
246    {
247      peers[clientId].handshake->doReject( "too many connections" );
248      PRINTF(0)("Will reject client %d because there are to many connections!\n", clientId);
249    }
250    else
251
252    PRINTF(0)("New Client: %d\n", clientId);
253
254    //this->connectSynchronizeable(*handshakes[clientId]);
255  }
256
257
258  //check if connections are ok else remove them
259  for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
260  {
261    if ( it->second.socket && !it->second.socket->isOk() )
262    {
263      PRINTF(0)("Client is gone: %d\n", it->second.userId);
264
265      it->second.socket->disconnectServer();
266      delete it->second.socket;
267      it->second.socket = NULL;
268
269      if ( it->second.handshake )
270        delete it->second.handshake;
271      it->second.handshake = NULL;
272     
273      for ( SynchronizeableList::iterator it2 = synchronizeables.begin(); it2 != synchronizeables.end(); it2++ )
274      {
275        (*it2)->cleanUpUser( it->second.userId );
276      }
277
278      NetworkGameManager::getInstance()->signalLeftPlayer(it->second.userId);
279
280      freeSocketSlots.push_back( it->second.userId );
281
282    }
283  }
284
285
286}
287
288void NetworkStream::debug()
289{
290  if( this->isServer())
291    PRINT(0)(" Host ist Server with ID: %i\n", this->myHostId);
292  else
293    PRINT(0)(" Host ist Client with ID: %i\n", this->myHostId);
294
295  PRINT(0)(" Got %i connected Synchronizeables, showing active Syncs:\n", this->synchronizeables.size());
296  for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++)
297  {
298    if( (*it)->beSynchronized() == true)
299      PRINT(0)("  Synchronizeable of class: %s::%s, with unique ID: %i, Synchronize: %i\n", (*it)->getClassName(), (*it)->getName(),
300               (*it)->getUniqueID(), (*it)->beSynchronized());
301  }
302  PRINT(0)(" Maximal Connections: %i\n", MAX_CONNECTIONS );
303
304}
305
306
307int NetworkStream::getSyncCount()
308{
309  int n = 0;
310  for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++)
311    if( (*it)->beSynchronized() == true)
312      ++n;
313
314  //return synchronizeables.size();
315  return n;
316}
317
318/**
319 * check if handshakes completed
320 */
321void NetworkStream::handleHandshakes( )
322{
323  for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
324  {
325    if ( it->second.handshake )
326    {
327      if ( it->second.handshake->completed() )
328      {
329        if ( it->second.handshake->ok() )
330        {
331          if ( type != NET_SERVER )
332          {
333            SharedNetworkData::getInstance()->setHostID( it->second.handshake->getHostId() );
334            myHostId = SharedNetworkData::getInstance()->getHostID();
335
336            this->networkGameManager = NetworkGameManager::getInstance();
337            this->networkGameManager->setUniqueID( it->second.handshake->getNetworkGameManagerId() );
338            MessageManager::getInstance()->setUniqueID( it->second.handshake->getMessageManagerId() );
339          }
340
341          PRINT(0)("handshake finished id=%d\n", it->second.handshake->getNetworkGameManagerId());
342
343          delete it->second.handshake;
344          it->second.handshake = NULL;
345         
346          handleNewClient( it->second.userId );
347        }
348        else
349        {
350          PRINT(1)("handshake failed!\n");
351          it->second.socket->disconnectServer();
352        }
353      }
354    }
355  }
356}
357
358/**
359 * handle upstream network traffic
360 */
361void NetworkStream::handleUpstream( )
362{
363  byte buf[UDP_PACKET_SIZE];
364  int offset;
365  int n;
366 
367  for ( PeerList::iterator peer = peers.begin(); peer != peers.end(); peer++ )
368  {
369    offset = INTSIZE; //make already space for length
370   
371    if ( !peer->second.socket )
372      continue;
373   
374    n = Converter::intToByteArray( currentState, buf + offset, UDP_PACKET_SIZE - offset );
375    assert( n == INTSIZE );
376    offset += n;
377   
378    n = Converter::intToByteArray( peer->second.lastAckedState, buf + offset, UDP_PACKET_SIZE - offset );
379    assert( n == INTSIZE );
380    offset += n;
381   
382    n = Converter::intToByteArray( peer->second.lastRecvedState, buf + offset, UDP_PACKET_SIZE - offset );
383    assert( n == INTSIZE );
384    offset += n;
385   
386    for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
387    {
388      Synchronizeable & sync = **it;
389     
390      if ( !sync.beSynchronized() || sync.getUniqueID() < 0 )
391        continue;
392
393      //if handshake not finished only sync handshake
394      if ( peer->second.handshake && sync.getLeafClassID() != CL_HANDSHAKE )
395        continue;
396     
397      if ( isServer() && sync.getLeafClassID() == CL_HANDSHAKE && sync.getUniqueID() != peer->second.userId )
398        continue;
399     
400      //do not sync null parent
401      if ( sync.getLeafClassID() == CL_NULL_PARENT )
402        continue;
403
404      assert( offset + INTSIZE <= UDP_PACKET_SIZE );
405     
406      //server fakes uniqueid=0 for handshake
407      if ( this->isServer() && sync.getUniqueID() < MAX_CONNECTIONS - 1 )
408        n = Converter::intToByteArray( 0, buf + offset, UDP_PACKET_SIZE - offset );
409      else
410        n = Converter::intToByteArray( sync.getUniqueID(), buf + offset, UDP_PACKET_SIZE - offset );
411      assert( n == INTSIZE );
412      offset += n;
413     
414      //make space for size
415      offset += INTSIZE;
416
417      n = sync.getStateDiff( peer->second.userId, buf + offset, UDP_PACKET_SIZE-offset, currentState, peer->second.lastAckedState, -1000 );
418      offset += n;
419     
420      assert( Converter::intToByteArray( n, buf + offset - n - INTSIZE, INTSIZE ) == INTSIZE );
421    }
422   
423    assert( Converter::intToByteArray( offset, buf, INTSIZE ) == INTSIZE );
424   
425    assert( peer->second.socket->writePacket( buf, offset ) );
426    peer->second.sentStateTicks[currentState] = SDL_GetTicks();
427    PRINTF(0)("send packet: %d userId = %d\n", offset, peer->second.userId);
428  }
429}
430
431/**
432 * handle downstream network traffic
433 */
434void NetworkStream::handleDownstream( )
435{
436  byte buf[UDP_PACKET_SIZE];
437  int offset = 0;
438 
439  int length = 0;
440  int packetLength = 0;
441  int uniqueId = 0;
442  int state = 0;
443  int ackedState = 0;
444  int fromState = 0;
445  int syncDataLength = 0;
446 
447  for ( PeerList::iterator peer = peers.begin(); peer != peers.end(); peer++ )
448  {
449   
450    if ( !peer->second.socket )
451      continue;
452
453    while ( 0 < (packetLength = peer->second.socket->readPacket( buf, UDP_PACKET_SIZE )) )
454    {
455
456      if ( packetLength < 4*INTSIZE )
457      {
458        if ( packetLength != 0 )
459          PRINTF(1)("got too small packet: %d\n", packetLength);
460        continue;
461      }
462   
463      assert( Converter::byteArrayToInt( buf, &length ) == INTSIZE );
464      assert( Converter::byteArrayToInt( buf + INTSIZE, &state ) == INTSIZE );
465      assert( Converter::byteArrayToInt( buf + 2*INTSIZE, &fromState ) == INTSIZE );
466      assert( Converter::byteArrayToInt( buf + 3*INTSIZE, &ackedState ) == INTSIZE );
467      PRINTF(0)("ackedstate: %d\n", ackedState);
468      offset = 4*INTSIZE;
469
470      PRINTF(0)("got packet: %d, %d\n", length, packetLength);
471   
472    //if this is an old state drop it
473      if ( state <= peer->second.lastRecvedState )
474        continue;
475   
476      if ( packetLength != length )
477      {
478        PRINTF(1)("real packet length (%d) and transmitted packet length (%d) do not match!\n", packetLength, length);
479        peer->second.socket->disconnectServer();
480        continue;
481      }
482     
483      while ( offset < length )
484      {
485        assert( Converter::byteArrayToInt( buf + offset, &uniqueId ) == INTSIZE );
486        offset += INTSIZE;
487     
488        assert( Converter::byteArrayToInt( buf + offset, &syncDataLength ) == INTSIZE );
489        offset += INTSIZE;
490     
491        Synchronizeable * sync = NULL;
492       
493        for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
494        { 
495        //                                        client thinks his handshake has id 0!!!!!
496          if ( (*it)->getUniqueID() == uniqueId || ( uniqueId == 0 && (*it)->getUniqueID() == peer->second.userId ) )
497          {
498            sync = *it;
499            break;
500          }
501        }
502       
503        if ( sync == NULL )
504        {
505          if ( oldSynchronizeables.find( uniqueId ) != oldSynchronizeables.end() )
506          {
507            offset += syncDataLength;
508            continue;
509          }
510
511        //TODO dont accept new object from all peers (probably only servers)
512          int leafClassId;
513          if ( INTSIZE > length - offset )
514          {
515            offset += syncDataLength;
516            continue;
517          }
518
519          Converter::byteArrayToInt( buf + offset, &leafClassId );
520       
521          BaseObject * b;
522          /* These are some small exeptions in creation: Not all objects can/should be created via Factory */
523          /* Exception 1: NullParent */
524          if( leafClassId == CL_NULL_PARENT || leafClassId == CL_SYNCHRONIZEABLE )
525          {
526            PRINTF(1)("Can not create Class with ID %x!\n", (int)leafClassId);
527            offset += syncDataLength;
528            continue;
529          }
530          else
531            b = Factory::fabricate( (ClassID)leafClassId );
532
533          if ( !b )
534          {
535            PRINTF(1)("Could not fabricate Object with classID %x\n", leafClassId);
536            offset += syncDataLength;
537            continue;
538          }
539
540          if ( b->isA(CL_SYNCHRONIZEABLE) )
541          {
542            sync = dynamic_cast<Synchronizeable*>(b);
543            sync->setUniqueID( uniqueId );
544            sync->setSynchronized(true);
545 
546            PRINTF(0)("Fabricated %s with id %d\n", sync->getClassName(), sync->getUniqueID());
547          }
548          else
549          {
550            PRINTF(1)("Class with ID %x is not a synchronizeable!\n", (int)leafClassId);
551            delete b;
552            offset += syncDataLength;
553            continue;
554          }
555        }
556
557        offset += sync->setStateDiff( peer->second.userId, buf+offset, syncDataLength, state, fromState ); 
558      }
559     
560      if ( offset != length )
561      {
562        PRINTF(0)("offset (%d) != length (%d)\n", offset, length);
563        peer->second.socket->disconnectServer();
564      }
565     
566      if ( peer->second.sentStateTicks.find( ackedState ) != peer->second.sentStateTicks.end() )
567      {
568        peer->second.ackDelay.push_back( SDL_GetTicks() - peer->second.sentStateTicks[ackedState] );
569      }
570     
571      while ( peer->second.sentStateTicks.begin()->first <= ackedState )
572        peer->second.sentStateTicks.erase( peer->second.sentStateTicks.begin() );
573     
574      while ( peer->second.ackDelay.size() > 20 )
575        peer->second.ackDelay.erase( peer->second.ackDelay.begin() );
576     
577      peer->second.ping = 0;
578     
579      for ( std::list<int>::iterator it = peer->second.ackDelay.begin(); it != peer->second.ackDelay.end(); it++ )
580        peer->second.ping += *it;
581     
582      if ( peer->second.ackDelay.size() == 0 )
583        peer->second.ping = -1;
584      else
585        peer->second.ping /= peer->second.ackDelay.size();
586     
587      NETPRINTF(0)("PING: user: %d ping: %d\n", peer->second.userId, peer->second.ping );
588   
589      peer->second.lastAckedState = ackedState;
590      peer->second.lastRecvedState = state;
591     
592    }
593 
594  }
595 
596}
597
598/**
599 * is executed when a handshake has finished
600 * @todo create playable for new user
601 */
602#include "world_entities/space_ships/space_ship.h"
603void NetworkStream::handleNewClient( int userId )
604{
605  MessageManager::getInstance()->initUser( userId );
606 
607  networkGameManager->signalNewPlayer( userId );
608}
609
610
611
612
613
614
Note: See TracBrowser for help on using the repository browser.