Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/network/Server.cc @ 11772

Last change on this file since 11772 was 11103, checked in by landauf, 9 years ago

fixed warnings (release build).
fixed error in GravityBombField

  • Property svn:eol-style set to native
File size: 13.2 KB
RevLine 
[1502]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:
[3084]23 *      Oliver Scheuss
[1502]24 *   Co-authors:
25 *      ...
26 *
27 */
28
29//
30// C++ Implementation: Server
31//
32// Description:
33//
34//
35// Author:  Oliver Scheuss, (C) 2007
36//
37// Copyright: See COPYING file that comes with this distribution
38//
39//
40
41#include "Server.h"
42
[5749]43#define WIN32_LEAN_AND_MEAN
[2773]44#include <enet/enet.h>
[1755]45#include <cassert>
[3214]46#include <string>
[1502]47
[5929]48#include "util/Clock.h"
[8858]49#include "util/Output.h"
[7284]50#include "core/command/Executor.h"
[1735]51#include "packet/Chat.h"
[3214]52#include "packet/ClassID.h"
53#include "packet/DeleteObjects.h"
54#include "packet/FunctionIDs.h"
55#include "packet/Gamestate.h"
[1735]56#include "packet/Welcome.h"
[8327]57// #include "ClientInformation.h"
[3084]58#include "FunctionCallManager.h"
[3214]59#include "GamestateManager.h"
[1502]60
[2171]61namespace orxonox
[1502]62{
[2087]63  const unsigned int MAX_FAILURES = 20;
[1747]64
[1502]65  /**
66  * Constructor for default values (bindaddress is set to ENET_HOST_ANY
67  *
68  */
[7163]69  Server::Server()
70  {
[3304]71    this->timeSinceLastUpdate_=0;
[1502]72  }
[1747]73
[7163]74  Server::Server(int port)
75  {
[3214]76    this->setPort( port );
[3304]77    this->timeSinceLastUpdate_=0;
[1502]78  }
[10622]79/*
80  Server::Server(int port, const std::string name)
81  {
82    this->setPort( port );
83    this->timeSinceLastUpdate_=0;
84    this->serverName_=name;
85  }*/
[1502]86  /**
87  * Constructor
88  * @param port Port to listen on
89  * @param bindAddress Address to listen on
90  */
[7163]91  Server::Server(int port, const std::string& bindAddress)
92  {
[3214]93    this->setPort( port );
94    this->setBindAddress( bindAddress );
[3304]95    this->timeSinceLastUpdate_=0;
[1502]96  }
97
98  /**
[1907]99  * @brief Destructor
100  */
[7163]101  Server::~Server()
102  {
[1907]103  }
[1502]104
105  /**
106  * This function opens the server by creating the listener thread
107  */
[7163]108  void Server::open()
109  {
110    Host::setActive(true);
[8858]111    orxout(verbose, context::network) << "opening server" << endl;
[3214]112    this->openListener();
[8858]113
[7801]114    /* make discoverable on LAN */
[7163]115    LANDiscoverable::setActivity(true);
[10622]116    LANDiscoverable::updateClientNumber(0);
[7801]117
118    /* make discoverable on WAN */
119    WANDiscoverable::setActivity(true);
[10622]120    WANDiscoverable::updateClientNumber(0);
[7801]121
122    /* done */
[1502]123    return;
124  }
125
126  /**
127  * This function closes the server
128  */
[7163]129  void Server::close()
130  {
131    Host::setActive(false);
[8858]132    orxout(verbose, context::network) << "closing server" << endl;
[3214]133    this->disconnectClients();
134    this->closeListener();
[7801]135
136    /* tell master server we're closing */
[8858]137    orxout(internal_info, context::network) << "disconnecting." << endl;
138    WANDiscoverable::setActivity(false);
139    orxout(internal_info, context::network) << "disconnecting done" << endl;
[7801]140
[7163]141    LANDiscoverable::setActivity(false);
[1502]142    return;
143  }
144
145  /**
146  * Run this function once every tick
147  * calls processQueue and updateGamestate
148  * @param time time since last tick
149  */
[7163]150  void Server::update(const Clock& time)
151  {
[3304]152    // receive incoming packets
[3214]153    Connection::processQueue();
[7801]154
[7163]155    // receive and process incoming discovery packets
156    LANDiscoverable::update();
[6417]157
[8327]158    if ( GamestateManager::hasPeers() )
[3214]159    {
[3304]160      // process incoming gamestates
161      GamestateManager::processGamestates();
[7801]162      FunctionCallManager::processBufferedFunctionCalls();
[6417]163
[3304]164      // send function calls to clients
[7801]165      FunctionCallManager::sendCalls( static_cast<Host*>(this) );
[6417]166
[3304]167      //this steers our network frequency
168      timeSinceLastUpdate_+=time.getDeltaTime();
169      if(timeSinceLastUpdate_>=NETWORK_PERIOD)
170      {
171        timeSinceLastUpdate_ -= static_cast<unsigned int>( timeSinceLastUpdate_ / NETWORK_PERIOD ) * NETWORK_PERIOD;
172        updateGamestate();
173      }
[7801]174//       sendPackets(); // flush the enet queue
[1502]175    }
176  }
[1747]177
[7801]178  void Server::queuePacket(ENetPacket *packet, int clientID, uint8_t channelID)
[7163]179  {
[7801]180    ServerConnection::addPacket(packet, clientID, channelID);
[1735]181  }
[6417]182
[2087]183  /**
[6417]184   * @brief: returns ping time to client in milliseconds
[2087]185   */
[7163]186  unsigned int Server::getRTT(unsigned int clientID)
187  {
[8327]188//     assert(ClientInformation::findClient(clientID));
189//     return ClientInformation::findClient(clientID)->getRTT();
190    // TODO: reimplement
191    return 0;
[2087]192  }
[6417]193
[5961]194  void Server::printRTT()
195  {
[11071]196//     for( ClientInformation* temp=ClientInformation::getBegin(); temp!=nullptr; temp=temp->next() )
[8858]197//       orxout(message) << "Round trip time to client with ID: " << temp->getID() << " is " << temp->getRTT() << " ms" << endl;
[5961]198  }
[1502]199
200  /**
[2087]201   * @brief: return packet loss ratio to client (scales from 0 to 1)
202   */
[8351]203  float Server::getPacketLoss(unsigned int clientID)
[7163]204  {
[8327]205//     assert(ClientInformation::findClient(clientID));
206//     return ClientInformation::findClient(clientID)->getPacketLoss();
207    return 0.;
[2087]208  }
[1502]209
210  /**
211  * takes a new snapshot of the gamestate and sends it to the clients
212  */
[7163]213  void Server::updateGamestate()
214  {
[8327]215    if( this->clientIDs_.size()==0 )
[2662]216      //no client connected
[3304]217      return;
218    GamestateManager::update();
[8858]219//     orxout(verbose_more, context::network) << "Server: one gamestate update complete, goig to sendGameState" << endl;
220    //orxout(verbose_more, context::network) << "updated gamestate, sending it" << endl;
[1502]221    //if(clients->getGamestateID()!=GAMESTATEID_INITIAL)
[7801]222    sendGameStates();
[1907]223    sendObjectDeletes();
[8858]224//     orxout(verbose_more, context::network) << "Server: one sendGameState turn complete, repeat in next tick" << endl;
225    //orxout(verbose_more, context::network) << "sent gamestate" << endl;
[1502]226  }
227
228  /**
[7801]229  * sends the current gamestate to all peers
[1502]230  */
[7801]231  bool Server::sendGameStates()
[7163]232  {
[7801]233    std::vector<packet::Gamestate*> gamestates = GamestateManager::getGamestates();
[11071]234    for( packet::Gamestate* gamestate : gamestates )
[7801]235    {
[11071]236      gamestate->send(static_cast<Host*>(this));
[7801]237    }
[1502]238    return true;
239  }
[1747]240
[7801]241
[7163]242  bool Server::sendObjectDeletes()
243  {
[8327]244//     ClientInformation *temp = ClientInformation::getBegin();
[11071]245//     if( temp == nullptr )
[2662]246      //no client connected
[8327]247    if( this->clientIDs_.size()==0 )
[2662]248      return true;
[1907]249    packet::DeleteObjects *del = new packet::DeleteObjects();
250    if(!del->fetchIDs())
[5929]251    {
252      delete del;
[1907]253      return true;  //everything ok (no deletes this tick)
[5929]254    }
[8858]255//     orxout(verbose, context::network) << "sending DeleteObjects" << endl;
[11071]256//     while(temp != nullptr){
[8327]257//       if( !(temp->getSynched()) )
258//       {
[8858]259//         orxout(verbose_more, context::network) << "Server: not sending gamestate" << endl;
[8327]260//         temp=temp->next();
261//         continue;
262//       }
263//       int cid = temp->getID(); //get client id
264//       packet::DeleteObjects *cd = new packet::DeleteObjects(*del);
265//       assert(cd);
266    del->setPeerID(NETWORK_PEER_ID_BROADCAST);
267    if ( !del->send( static_cast<Host*>(this) ) )
[8858]268      orxout(internal_warning, context::network) << "Server: could not broadcast deleteObjects packet" << endl;
[8327]269//       temp=temp->next();
[1907]270      // gs gets automatically deleted by enet callback
[8327]271//     }
272//     delete del;
[1907]273    return true;
274  }
[1747]275
[1907]276
[8327]277  void Server::addPeer(uint32_t peerID)
[7163]278  {
[8327]279//     static unsigned int newid=1;
[8858]280//
281//     orxout(internal_info, context::network) << "Server: adding client" << endl;
[8327]282//     ClientInformation *temp = ClientInformation::insertBack(new ClientInformation);
283//     if(!temp)
284//     {
[8858]285//       orxout(internal_warning, context::network) << "Server: could not add client" << endl;
[8327]286//     }
287//     temp->setID(newid);
288//     temp->setPeer(event->peer);
[2087]289
290    // inform all the listeners
[8327]291    this->clientIDs_.push_back(peerID);
[10622]292    WANDiscoverable::updateClientNumber(this->clientIDs_.size());
293    LANDiscoverable::updateClientNumber(this->clientIDs_.size());
294
[8327]295    ClientConnectionListener::broadcastClientConnected(peerID);
296    GamestateManager::addPeer(peerID);
[2087]297
[8327]298//     ++newid;
[2087]299
[8858]300    orxout(internal_info, context::network) << "Server: added client id: " << peerID << endl;
[10622]301
[8327]302    createClient(peerID);
[2087]303}
[1747]304
[8327]305  void Server::removePeer(uint32_t peerID)
[5929]306  {
[8858]307    orxout(verbose, context::network) << "removing client from list" << endl;
[8327]308//     ClientInformation *client = ClientInformation::findClient(&event->peer->address);
309//     if(!client)
310//       return;
311//     else
312//     {
313  std::vector<uint32_t>::iterator it;
314  for( it=this->clientIDs_.begin(); it!=this->clientIDs_.end(); ++it )
315  {
316    if( *it == peerID )
[5929]317    {
[8327]318      this->clientIDs_.erase(it);
319      break;
320    }
321  }
[10622]322  WANDiscoverable::updateClientNumber(this->clientIDs_.size());
323  LANDiscoverable::updateClientNumber(this->clientIDs_.size());
324
[8327]325  ClientConnectionListener::broadcastClientDisconnected(peerID);
326  GamestateManager::removePeer(peerID);
[5929]327      //ServerConnection::disconnectClient( client );
[5961]328      //ClientConnectionListener::broadcastClientDisconnected( client->getID() ); //this is done in ClientInformation now
[8327]329//       delete client;
330//     }
[5929]331  }
[8858]332
[7801]333  void Server::processPacket(packet::Packet* packet)
334  {
335    if( packet->isReliable() )
336    {
[8327]337      if( this->getLastReceivedGamestateID(packet->getPeerID()) >= packet->getRequiredGamestateID() )
[7801]338        packet->process(static_cast<Host*>(this));
339      else
340        this->packetQueue_.push_back(packet);
341    }
342    else
343      packet->process(static_cast<Host*>(this));
344  }
[5929]345
[7801]346
[7163]347  bool Server::createClient(int clientID)
348  {
[8327]349//     ClientInformation *temp = ClientInformation::findClient(clientID);
350//     if(!temp)
351//     {
[8858]352//       orxout(internal_error, context::network) << "Server. could not create client with id: " << clientID << endl;
[8327]353//       return false;
354//     }
[8858]355//     orxout(verbose, context::network) << "Con.Man: creating client id: " << temp->getID() << endl;
[6417]356
[3084]357    // synchronise class ids
[8327]358    syncClassid(clientID);
[6417]359
[3084]360    // now synchronise functionIDs
361    packet::FunctionIDs *fIDs = new packet::FunctionIDs();
[7801]362    fIDs->setPeerID(clientID);
363    bool b = fIDs->send( static_cast<Host*>(this) );
[3084]364    assert(b);
[6417]365
[8327]366//     temp->setSynched(true);
[7801]367    GamestateManager::setSynched(clientID);
[8858]368
369    orxout(verbose, context::network) << "sending welcome" << endl;
[8706]370    packet::Welcome *w = new packet::Welcome(clientID);
[8327]371    w->setPeerID(clientID);
[7801]372    b = w->send( static_cast<Host*>(this) );
[1907]373    assert(b);
[11103]374    (void)b; // avoid compiler warning
[8327]375//     packet::Gamestate *g = new packet::Gamestate();
376//     g->setPeerID(clientID);
377//     b = g->collectData(0,packet::GAMESTATE_MODE_SERVER);
[7801]378//     assert(b);
[8327]379//     if(!b)
380//       return false; //no data for the client
381// //     b = g->compressData();
382// //     assert(b);
383//     b = g->send( static_cast<Host*>(this) );
384//     assert(b);
[1502]385    return true;
386  }
[6417]387
[8327]388  void Server::disconnectClient( uint32_t clientID )
[7163]389  {
[8327]390    ServerConnection::disconnectClient( clientID );
391    GamestateManager::removePeer( clientID );
[5929]392    // inform all the listeners
[5961]393    // ClientConnectionListener::broadcastClientDisconnected(client->getID()); // this is done in ClientInformation now
[1502]394  }
[2087]395
[8858]396  /**
397   * @brief Sends a chat message to the given target ID.
398   * @param message message to be sent
399   * @param sourceID the ID of the sender
400   * @param targetID the ID of the receiver
401   */
402  void Server::doSendChat(const std::string& message, unsigned int sourceID, unsigned int targetID)
[7163]403  {
[8858]404    // check if the target exists. just ignore the message otherwise
405    if (!this->isValidTarget(targetID)) // TODO: remove this if an invalid clientIDs don't trigger assertions anymore
406      return;
407
408    // send the message to the target
409    packet::Chat* packet = new packet::Chat(message, sourceID, targetID);
410    packet->setPeerID(targetID);
411    packet->send( static_cast<Host*>(this) );
412
413    // if the target is (or includes) this host as well, call the parent function which passes the message to the listeners
414    if (targetID == NETWORK_PEER_ID_BROADCAST || targetID == Host::getPlayerID())
415      Host::doReceiveChat(message, sourceID, targetID);
[2087]416  }
417
[8858]418  /**
419   * @brief Gets called if a packet::Chat packet is received. Forwards the packet to the target
420   * and calls the parent function if necessary.
421   */
422  void Server::doReceiveChat(const std::string& message, unsigned int sourceID, unsigned int targetID)
[7163]423  {
[8858]424      this->doSendChat(message, sourceID, targetID);
[2087]425  }
426
[8858]427  /**
428   * @brief Returns true if the target ID is in the list of clients (or if it
429   * corresponds to the broadcast or the server ID).
430   */
431  bool Server::isValidTarget(unsigned int targetID)
[7163]432  {
[8858]433    if (targetID == NETWORK_PEER_ID_BROADCAST || targetID == NETWORK_PEER_ID_SERVER)
434      return true;
[2087]435
[11071]436    for( uint32_t id : this->clientIDs_ )
437      if( id == targetID )
[8858]438        return true;
439
440    return false;
[1907]441  }
[1747]442
[7163]443  void Server::syncClassid(unsigned int clientID)
444  {
[3214]445    int failures=0;
446    packet::ClassID *classid = new packet::ClassID();
[7801]447    classid->setPeerID(clientID);
448    while(!classid->send( static_cast<Host*>(this) ) && failures < 10){
[3214]449      failures++;
450    }
451    assert(failures<10);
[8858]452    orxout(verbose, context::network) << "syncClassid:\tall synchClassID packets have been sent" << endl;
[3214]453  }
454
[1502]455}
Note: See TracBrowser for help on using the repository browser.