Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

network_game_manager: implemented some functions

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