Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/network/ConnectionManager.cc @ 2777

Last change on this file since 2777 was 2773, checked in by rgrieder, 16 years ago

Removed all enet and boost includes from header files in the network library.

  • Reduces dependencies
  • Minimises problems with windows.h
  • Speeds up the compiling process a little bit (probably negligible)
  • Also removes ugly WIN32_LEAN_AND_MEAN declarations before every enet.h include in the network library.

Removed windows.h header from util/Sleep.h by adding Sleep.cc

  • Property svn:eol-style set to native
File size: 8.8 KB
RevLine 
[1282]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Oliver Scheuss, (C) 2007
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29//
30// C++ Interface: ConnectionManager
31//
32// Description: The Class ConnectionManager manages the servers conenctions to the clients.
33// each connection is provided by a new process. communication between master process and
34// connection processes is provided by ...
35//
36//
37// Author:  Oliver Scheuss
38//
39
[1842]40#include "ConnectionManager.h"
41
[2773]42#include <enet/enet.h>
[1282]43#include <iostream>
[2773]44#include <cassert>
[1282]45// boost.thread library for multithreading support
[1755]46#include <boost/thread/thread.hpp>
[1282]47#include <boost/bind.hpp>
[2773]48#include <boost/thread/recursive_mutex.hpp>
[1282]49
50#include "util/Math.h"
[1502]51#include "util/Sleep.h"
[1282]52#include "ClientInformation.h"
[2662]53#include "synchronisable/Synchronisable.h"
[1735]54#include "packet/ClassID.h"
[1282]55
56namespace std
57{
58  bool operator< (ENetAddress a, ENetAddress b) {
59    if(a.host <= b.host)
60      return true;
61    else
62      return false;
63  }
64}
65
[2171]66namespace orxonox
[1282]67{
68  //boost::thread_group network_threads;
[2773]69  static boost::recursive_mutex enet_mutex_g;
[1747]70
[1735]71  ConnectionManager *ConnectionManager::instance_=0;
[1747]72
[1735]73  ConnectionManager::ConnectionManager():receiverThread_(0){
74    assert(instance_==0);
75    instance_=this;
[1282]76    quit=false;
[2773]77    bindAddress = new ENetAddress();
78    bindAddress->host = ENET_HOST_ANY;
79    bindAddress->port = NETWORK_PORT;
[1282]80  }
[1747]81
[1735]82  ConnectionManager::ConnectionManager(int port){
83    assert(instance_==0);
84    instance_=this;
[1502]85    quit=false;
[2773]86    bindAddress = new ENetAddress();
87    bindAddress->host = ENET_HOST_ANY;
88    bindAddress->port = port;
[1502]89  }
[1282]90
[2087]91  ConnectionManager::ConnectionManager(int port, const std::string& address) :receiverThread_(0) {
[1735]92    assert(instance_==0);
93    instance_=this;
[1282]94    quit=false;
[2773]95    bindAddress = new ENetAddress();
96    enet_address_set_host (bindAddress, address.c_str());
97    bindAddress->port = NETWORK_PORT;
[1282]98  }
99
[1735]100  ConnectionManager::ConnectionManager(int port, const char *address) : receiverThread_(0) {
101    assert(instance_==0);
102    instance_=this;
[1282]103    quit=false;
[2773]104    bindAddress = new ENetAddress();
105    enet_address_set_host (bindAddress, address);
106    bindAddress->port = NETWORK_PORT;
[1282]107  }
[1747]108
[1735]109  ConnectionManager::~ConnectionManager(){
110    if(!quit)
111      quitListener();
[1907]112    instance_=0;
[2773]113    delete bindAddress;
[1735]114  }
[1282]115
[1747]116
[1502]117  ENetEvent *ConnectionManager::getEvent(){
118    if(!buffer.isEmpty())
119      return buffer.pop();
120    else
121      return NULL;
[1282]122  }
123
124  bool ConnectionManager::queueEmpty() {
125    return buffer.isEmpty();
126  }
127
128  void ConnectionManager::createListener() {
129    receiverThread_ = new boost::thread(boost::bind(&ConnectionManager::receiverThread, this));
130    return;
131  }
132
133  bool ConnectionManager::quitListener() {
134    quit=true;
135    receiverThread_->join();
136    return true;
137  }
[1747]138
139
[1282]140  bool ConnectionManager::addPacket(ENetPacket *packet, ENetPeer *peer) {
[2773]141    boost::recursive_mutex::scoped_lock lock(enet_mutex_g);
[1735]142    if(enet_peer_send(peer, NETWORK_DEFAULT_CHANNEL, packet)!=0)
[1282]143      return false;
144    return true;
145  }
146
147  bool ConnectionManager::addPacket(ENetPacket *packet, int clientID) {
[1735]148    ClientInformation *temp = ClientInformation::findClient(clientID);
[1502]149    if(!temp){
150      COUT(3) << "C.Man: addPacket findClient failed" << std::endl;
[1282]151      return false;
[1502]152    }
[1735]153    return addPacket(packet, temp->getPeer());
[1282]154  }
155
156  bool ConnectionManager::addPacketAll(ENetPacket *packet) {
[1735]157    if(!instance_)
158      return false;
[2773]159    boost::recursive_mutex::scoped_lock lock(enet_mutex_g);
[1735]160    for(ClientInformation *i=ClientInformation::getBegin()->next(); i!=0; i=i->next()){
[1534]161      COUT(3) << "adding broadcast packet for client: " << i->getID() << std::endl;
162      if(enet_peer_send(i->getPeer(), 0, packet)!=0)
[1282]163        return false;
164    }
165    return true;
166  }
167
[1502]168  // we actually dont need that function, because host_service does that for us
[1282]169  bool ConnectionManager::sendPackets() {
[1735]170    if(server==NULL || !instance_)
[1282]171      return false;
[2773]172    boost::recursive_mutex::scoped_lock lock(enet_mutex_g);
[1502]173    enet_host_flush(server);
174    lock.unlock();
175    return true;
[1282]176  }
177
178  void ConnectionManager::receiverThread() {
179    // what about some error-handling here ?
[1502]180    ENetEvent *event;
[1282]181    atexit(enet_deinitialize);
[1502]182    { //scope of the mutex
[2773]183      boost::recursive_mutex::scoped_lock lock(enet_mutex_g);
[1502]184      enet_initialize();
[2773]185      server = enet_host_create(bindAddress, NETWORK_MAX_CONNECTIONS, 0, 0);
[1502]186      lock.unlock();
187    }
[1282]188    if(server==NULL){
189      // add some error handling here ==========================
190      quit=true;
191      return;
192    }
193
[1502]194    event = new ENetEvent;
[1282]195    while(!quit){
[1502]196      { //mutex scope
[2773]197        boost::recursive_mutex::scoped_lock lock(enet_mutex_g);
[1502]198        if(enet_host_service(server, event, NETWORK_WAIT_TIMEOUT)<0){
199          // we should never reach this point
200          quit=true;
201          continue;
202          // add some error handling here ========================
203        }
204        lock.unlock();
[1282]205      }
206      switch(event->type){
207        // log handling ================
208        case ENET_EVENT_TYPE_CONNECT:
[1502]209        case ENET_EVENT_TYPE_DISCONNECT:
[1282]210        case ENET_EVENT_TYPE_RECEIVE:
211            processData(event);
[1502]212            event = new ENetEvent;
[1282]213          break;
214        case ENET_EVENT_TYPE_NONE:
[1502]215          //receiverThread_->yield();
[2087]216          msleep(1);
[1282]217          break;
218      }
219//       usleep(100);
[1502]220      //receiverThread_->yield(); //TODO: find apropriate
[1282]221    }
222    disconnectClients();
223    // if we're finishied, destroy server
[1502]224    {
[2773]225      boost::recursive_mutex::scoped_lock lock(enet_mutex_g);
[1502]226      enet_host_destroy(server);
227      lock.unlock();
228    }
[1282]229  }
[1747]230
[1282]231  //### added some bugfixes here, but we cannot test them because
232  //### the server crashes everytime because of some gamestates
233  //### (trying to resolve that now)
234  void ConnectionManager::disconnectClients() {
235    ENetEvent event;
[1735]236    ClientInformation *temp = ClientInformation::getBegin()->next();
[1282]237    while(temp!=0){
[1502]238      {
[2773]239        boost::recursive_mutex::scoped_lock lock(enet_mutex_g);
[1502]240        enet_peer_disconnect(temp->getPeer(), 0);
241        lock.unlock();
242      }
[1282]243      temp = temp->next();
244    }
245    //bugfix: might be the reason why server crashes when clients disconnects
[1735]246    temp = ClientInformation::getBegin()->next();
[2773]247    boost::recursive_mutex::scoped_lock lock(enet_mutex_g);
[1502]248    while( temp!=0 && enet_host_service(server, &event, NETWORK_WAIT_TIMEOUT) >= 0){
[1282]249      switch (event.type)
250      {
251      case ENET_EVENT_TYPE_NONE: break;
252      case ENET_EVENT_TYPE_CONNECT: break;
253      case ENET_EVENT_TYPE_RECEIVE:
254        enet_packet_destroy(event.packet);
255        break;
256      case ENET_EVENT_TYPE_DISCONNECT:
257        COUT(4) << "disconnecting all clients" << std::endl;
[1735]258        if(ClientInformation::findClient(&(event.peer->address)))
259          delete ClientInformation::findClient(&(event.peer->address));
[1282]260        //maybe needs bugfix: might also be a reason for the server to crash
261        temp = temp->next();
262        break;
263      }
264    }
265    return;
266  }
267
268  bool ConnectionManager::processData(ENetEvent *event) {
269    // just add packet to the buffer
270    // this can be extended with some preprocessing
271    return buffer.push(event);
272  }
273
274
[1502]275
[2773]276  int ConnectionManager::getClientID(ENetPeer* peer) {
277    return getClientID(&(peer->address));
[1282]278  }
279
[2773]280  int ConnectionManager::getClientID(ENetAddress* address) {
281    return ClientInformation::findClient(address)->getID();
[1282]282  }
283
284  ENetPeer *ConnectionManager::getClientPeer(int clientID) {
[1735]285    return ClientInformation::findClient(clientID)->getPeer();
[1282]286  }
287
[2759]288
[1735]289  void ConnectionManager::syncClassid(unsigned int clientID) {
[2759]290    int failures=0;
291    packet::ClassID *classid = new packet::ClassID();
292    classid->setClientID(clientID);
293    while(!classid->send() && failures < 10){
294      failures++;
[1282]295    }
[2759]296    assert(failures<10);
[1282]297    COUT(4) << "syncClassid:\tall synchClassID packets have been sent" << std::endl;
298  }
[2759]299 
[1282]300
301  void ConnectionManager::disconnectClient(ClientInformation *client){
[1502]302    {
[2773]303      boost::recursive_mutex::scoped_lock lock(enet_mutex_g);
[1502]304      enet_peer_disconnect(client->getPeer(), 0);
305      lock.unlock();
306    }
[1282]307  }
308
[1747]309
[1282]310}
Note: See TracBrowser for help on using the repository browser.