Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

handshake: several clients can connect at the same time now

File size: 9.2 KB
RevLine 
[5566]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:
[5601]12   main-programmer: claudio
[5800]13   co-programmer:
[5566]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
[5747]22
[5647]23#include "base_object.h"
[5731]24#include "network_protocol.h"
[5647]25#include "network_socket.h"
26#include "connection_monitor.h"
27#include "synchronizeable.h"
[6043]28#include "network_manager.h"
[5647]29#include "list.h"
[5649]30#include "debug.h"
[6053]31#include "class_list.h"
[5647]32
[5566]33/* include your own header */
34#include "network_stream.h"
35
[5595]36/* probably unnecessary */
[5594]37using namespace std;
38
[5595]39
[5747]40#define PACKAGE_SIZE  256
[5647]41
[5747]42
[5800]43NetworkStream::NetworkStream()
[5996]44    : DataStream()
[5647]45{
46  this->init();
[5648]47  /* initialize the references */
[5996]48  this->type = NET_CLIENT;
[5741]49  this->networkProtocol = new NetworkProtocol();
[5648]50  this->connectionMonitor = new ConnectionMonitor();
[5647]51}
52
[6007]53NetworkStream::NetworkStream(IPaddress& address)
[5996]54{
[6007]55  this->type = NET_CLIENT;
[5996]56  this->init();
[6007]57  this->networkSockets.push_back(new NetworkSocket(address));
[5996]58  this->networkProtocol = new NetworkProtocol();
59  this->connectionMonitor = new ConnectionMonitor();
[6043]60
61  Handshake* hs = new Handshake(false);
[6090]62  hs->setUniqueID( 0 );
[6043]63  this->handshakes.push_back(hs);
64  this->connectSynchronizeable(*hs);
65  PRINTF(0)("NetworkStream: %s\n", hs->getName());
[5996]66}
[5647]67
[5996]68
[6007]69NetworkStream::NetworkStream(unsigned int port)
[5996]70{
[6007]71  this->type = NET_SERVER;
[5996]72  this->init();
[6007]73  this->serverSocket = new ServerSocket(port);
[5996]74  this->networkProtocol = new NetworkProtocol();
75  this->connectionMonitor = new ConnectionMonitor();
[6018]76  this->networkSockets.push_back( NULL );
[6053]77  this->handshakes.push_back( NULL );
[6018]78  this->bActive = true;
[6090]79
80  this->setMaxConnections( 10 );
[5996]81}
82
83
[5647]84void NetworkStream::init()
85{
86  /* set the class id for the base object */
87  this->setClassID(CL_NETWORK_STREAM, "NetworkStream");
[5996]88  this->bActive = false;
[6007]89  this->serverSocket = NULL;
[6043]90  myHostId = 0;
[5594]91}
92
[5647]93
[5566]94NetworkStream::~NetworkStream()
[5598]95{
[6007]96  if ( this->serverSocket )
97  {
98    serverSocket->close();
99    delete serverSocket;
100  }
[5723]101
[6007]102  for (NetworkSocketVector::iterator i = networkSockets.begin(); i!=networkSockets.end(); i++)
103  {
104    if ( *i )
105    {
106      (*i)->disconnectServer();
[6025]107      (*i)->destroy();
[6007]108    }
109  }
[5723]110
[6043]111  for (HandshakeVector::iterator i = handshakes.begin(); i!=handshakes.end(); i++)
112  {
113    if ( *i )
114    {
115      delete (*i);
116    }
117  }
118
[5996]119  delete connectionMonitor;
120  delete networkProtocol;
[5598]121}
122
[5996]123
124void NetworkStream::connectSynchronizeable(Synchronizeable& sync)
125{
[6007]126  this->synchronizeables.push_back(&sync);
[6062]127  sync.setNetworkStream( this );
[6007]128
129  if( this->networkSockets.size()>0 )
[5996]130    this->bActive = true;
131}
132
[6060]133void NetworkStream::disconnectSynchronizeable(Synchronizeable& sync)
134{
135  this->synchronizeables.remove(&sync);
[5996]136
[6060]137  if( this->networkSockets.size()<=0 )
138    this->bActive = false;
139}
140
141
[5604]142void NetworkStream::processData()
143{
[6018]144  if ( this->type == NET_SERVER )
145    this->updateConnectionList();
[6090]146  else
147  {
148    if ( networkSockets[0] && !networkSockets[0]->isOk() )
149    {
150      PRINTF(1)("lost connection to server\n");
[6018]151
[6090]152      //delete networkSockets[i];
153      networkSockets[0]->disconnectServer();
154      networkSockets[0]->destroy();
155      networkSockets[0] = NULL;
156      //TODO: delete handshake from synchronizeable list so i can delete it
157      if ( handshakes[0] )
158        delete handshakes[0];
159      handshakes[0] = NULL;
160    }
161  }
162
[6053]163  for (int i = 0; i<handshakes.size(); i++)
[6043]164  {
[6053]165    if ( handshakes[i] )
[6043]166    {
[6053]167      if ( handshakes[i]->completed() )
[6043]168      {
[6053]169        if ( handshakes[i]->ok() )
[6043]170        {
[6053]171          if ( type != NET_SERVER )
172          {
173            NetworkManager::getInstance()->setHostID( handshakes[i]->getHostId() );
174            myHostId = NetworkManager::getInstance()->getHostID();
175          }
[6043]176          PRINT(0)("handshake finished\n");
[6062]177          delete handshakes[i];
178          handshakes[i] = NULL;
[6059]179          //TODO: replace handshake by entitymanager
[6043]180        }
181        else
182        {
183          PRINT(1)("handshake failed!\n");
[6053]184          networkSockets[i]->disconnectServer();
[6090]185          delete handshakes[i];
186          handshakes[i] = NULL;
[6043]187          //TODO: handle error
188        }
189      }
190    }
191  }
192
193
194  /* DOWNSTREAM */
195
196  int dataLength;
197  int reciever;
198  Header header;
199  for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++)
200  {
[6059]201    //TODO: remove items from synchronizeables if they dont exist
[6062]202    if ( (*it)!=NULL && (*it)->getOwner() == myHostId )
[6043]203    {
204      do {
[6053]205        reciever = 0;
206        dataLength = (*it)->readBytes(downBuffer, DATA_STREAM_BUFFER_SIZE, &reciever);
[6043]207
[6053]208
[6043]209        if ( dataLength<=0 ){
210          reciever = 0;
211          continue;
212        }
213
[6059]214        dataLength = networkProtocol->createHeader((byte*)downBuffer, dataLength, DATA_STREAM_BUFFER_SIZE, static_cast<const Synchronizeable&>(*(*it)));
[6043]215
[6090]216        //FIXME: this is a hack, find a better way
217        Header* header = (Header*)downBuffer;
218        if ( header->synchronizeableID<100 )
219          header->synchronizeableID = 0;
220
[6043]221        if ( dataLength<=0 )
222          continue;
223
224        if ( reciever!=0 )
225        {
[6059]226          if ( networkSockets[reciever] != NULL )
[6043]227          {
[6062]228            PRINTF(5)("write %d bytes to socket %d\n", dataLength, reciever);
[6043]229            networkSockets[reciever]->writePacket(downBuffer, dataLength);
230          }
231          else
232          {
233            PRINTF(1)("networkSockets[reciever] == NULL\n");
234          }
235        }
236        else
237        {
[6053]238          for ( int i = 0; i<networkSockets.size(); i++)
[6043]239          {
[6059]240            if ( networkSockets[i] != NULL )
[6053]241            {
[6062]242              PRINTF(5)("write %d bytes to socket %d\n", dataLength, reciever);
[6043]243              networkSockets[i]->writePacket(downBuffer, dataLength);
[6053]244            }
[6043]245          }
246        }
247
248      } while( reciever!=0 );
249    }
[6059]250    else
251    {
252      PRINTF(0)("synchronizeables == NULL");
253    }
[6043]254  }
255
256  /* UPSTREAM */
257
[6053]258  for ( int i = 0; i<networkSockets.size(); i++)
[6043]259  {
260    if ( networkSockets[i] )
261    {
262      do {
263        dataLength = networkSockets[i]->readPacket(upBuffer, DATA_STREAM_BUFFER_SIZE);
264
265        if ( dataLength<=0 )
266          continue;
267
[6090]268        PRINTF(5)("read %d bytes from socket\n", dataLength);
[6043]269        header = networkProtocol->extractHeader(upBuffer, dataLength);
270        dataLength -= sizeof(header);
271
272        if ( dataLength != header.length )
273        {
274          PRINTF(1)("packetsize in header and real packetsize do not match! %d:%d\n", dataLength, header.length);
275          continue;
276        }
277
[6090]278        if ( header.synchronizeableID == 0 )
279        {
280          header.synchronizeableID = i;
281        }
282
[6043]283        for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++)
284        {
[6060]285          if ( *it && (*it)->getUniqueID()==header.synchronizeableID )
[6043]286            (*it)->writeBytes(upBuffer+sizeof(header), dataLength);
287        }
288
289      } while ( dataLength>0 );
290    }
291  }
[5604]292}
[6018]293
294void NetworkStream::updateConnectionList( )
295{
296  //check for new connections
[6025]297
[6018]298  NetworkSocket* tempNetworkSocket = serverSocket->getNewSocket();
299
300  if ( tempNetworkSocket )
301  {
302    int clientId;
303    if ( freeSocketSlots.size() >0 )
304    {
305      clientId = freeSocketSlots.back();
306      freeSocketSlots.pop_back();
307      networkSockets[clientId] = tempNetworkSocket;
[6043]308      handshakes[clientId] = new Handshake(true, clientId);
[6090]309      handshakes[clientId]->setUniqueID(clientId);
[6018]310    } else
311    {
[6025]312      clientId = networkSockets.size();
[6018]313      networkSockets.push_back(tempNetworkSocket);
[6090]314      Handshake* tHs = new Handshake(true, clientId);
315      tHs->setUniqueID(clientId);
316      handshakes.push_back(tHs);
[6018]317    }
318
[6090]319    if ( clientId > this->maxConnections )
320    {
321      handshakes[clientId]->doReject();
322      PRINTF(0)("Will reject client %d because there are to many connections!\n", clientId);
323    }
324    else
325
[6025]326    PRINTF(0)("New Client: %d\n", clientId);
[6043]327
328    this->connectSynchronizeable(*handshakes[clientId]);
[6018]329  }
330
331
332  //check if connections are ok else remove them
333  for ( int i = 1; i<networkSockets.size(); i++)
334  {
335    if ( networkSockets[i] && !networkSockets[i]->isOk() )
336    {
337      //TODO: tell EntityManager that this player left the game
[6025]338      PRINTF(0)("Client is gone: %d\n", i);
[6018]339
[6025]340      //delete networkSockets[i];
[6039]341      networkSockets[i]->disconnectServer();
[6025]342      networkSockets[i]->destroy();
[6018]343      networkSockets[i] = NULL;
[6059]344      //TODO: delete handshake from synchronizeable list so i can delete it
[6062]345      if ( handshakes[i] )
346        delete handshakes[i];
[6043]347      handshakes[i] = NULL;
[6018]348
349      if ( i == networkSockets.size()-1 )
350      {
351        networkSockets.pop_back();
[6043]352        handshakes.pop_back();
[6018]353      }
354      else
355      {
356        freeSocketSlots.push_back(i);
357      }
358    }
359  }
360
[6025]361
[6018]362}
[6043]363
[6090]364void NetworkStream::setMaxConnections( int n )
365{
366  if ( !this->isServer() )
367  {
368    PRINTF(1)("Cannot set maxConnections because I am no server.\n");
369  }
370  if ( this->networkSockets.size() > 1 )
371  {
372    PRINTF(1)("Cannot set maxConnections because there are already %d connections.\n", this->networkSockets.size());
373    return;
374  }
375  this->maxConnections = n;
376}
[6043]377
[6090]378
Note: See TracBrowser for help on using the repository browser.