Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/mergeFS18/src/libraries/network/Server.cc @ 12068

Last change on this file since 12068 was 12027, checked in by merholzl, 6 years ago

Merged Masterserver, refresh button had to be removed

  • Property svn:eol-style set to native
File size: 10.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"
[3084]57#include "FunctionCallManager.h"
[3214]58#include "GamestateManager.h"
[1502]59
[2171]60namespace orxonox
[1502]61{
[2087]62  const unsigned int MAX_FAILURES = 20;
[1747]63
[1502]64  /**
65  * Constructor for default values (bindaddress is set to ENET_HOST_ANY
66  *
67  */
[7163]68  Server::Server()
69  {
[12027]70    this->timeSinceLastUpdate_ = 0;
[1502]71  }
[1747]72
[12027]73  /**
74  * Constructor
75  * @param port Port to listen on
76  */
[7163]77  Server::Server(int port)
78  {
[12027]79    this->setPort(port);
80    this->timeSinceLastUpdate_ = 0;
[1502]81  }
[12027]82
[1502]83  /**
84  * Constructor
85  * @param port Port to listen on
86  * @param bindAddress Address to listen on
87  */
[7163]88  Server::Server(int port, const std::string& bindAddress)
89  {
[12027]90    this->setPort(port);
91    this->setBindAddress(bindAddress);
92    this->timeSinceLastUpdate_ = 0;
[1502]93  }
94
95  /**
[1907]96  * @brief Destructor
97  */
[7163]98  Server::~Server()
99  {
[1907]100  }
[1502]101
102  /**
103  * This function opens the server by creating the listener thread
104  */
[7163]105  void Server::open()
106  {
107    Host::setActive(true);
[8858]108    orxout(verbose, context::network) << "opening server" << endl;
[3214]109    this->openListener();
[8858]110
[7801]111    /* make discoverable on LAN */
[7163]112    LANDiscoverable::setActivity(true);
[10622]113    LANDiscoverable::updateClientNumber(0);
[7801]114
115    /* make discoverable on WAN */
116    WANDiscoverable::setActivity(true);
[10622]117    WANDiscoverable::updateClientNumber(0);
[7801]118
119    /* done */
[1502]120    return;
121  }
122
123  /**
124  * This function closes the server
125  */
[7163]126  void Server::close()
127  {
128    Host::setActive(false);
[8858]129    orxout(verbose, context::network) << "closing server" << endl;
[3214]130    this->disconnectClients();
131    this->closeListener();
[7801]132
133    /* tell master server we're closing */
[8858]134    orxout(internal_info, context::network) << "disconnecting." << endl;
135    WANDiscoverable::setActivity(false);
136    orxout(internal_info, context::network) << "disconnecting done" << endl;
[7801]137
[7163]138    LANDiscoverable::setActivity(false);
[1502]139    return;
140  }
141
142  /**
143  * Run this function once every tick
144  * calls processQueue and updateGamestate
145  * @param time time since last tick
146  */
[7163]147  void Server::update(const Clock& time)
148  {
[3304]149    // receive incoming packets
[3214]150    Connection::processQueue();
[7801]151
[7163]152    // receive and process incoming discovery packets
153    LANDiscoverable::update();
[6417]154
[12027]155    if (GamestateManager::hasPeers())
[3214]156    {
[3304]157      // process incoming gamestates
158      GamestateManager::processGamestates();
[7801]159      FunctionCallManager::processBufferedFunctionCalls();
[6417]160
[3304]161      // send function calls to clients
[12027]162      FunctionCallManager::sendCalls(static_cast<Host*>(this));
[6417]163
[12027]164      // this steers our network frequency
165      timeSinceLastUpdate_ += time.getDeltaTime();
166      if(timeSinceLastUpdate_ >= NETWORK_PERIOD)
[3304]167      {
[12027]168        timeSinceLastUpdate_ -= static_cast<unsigned int>(timeSinceLastUpdate_ / NETWORK_PERIOD) * NETWORK_PERIOD;
169        this->updateGamestate();
[3304]170      }
[1502]171    }
172  }
[1747]173
[7801]174  void Server::queuePacket(ENetPacket *packet, int clientID, uint8_t channelID)
[7163]175  {
[7801]176    ServerConnection::addPacket(packet, clientID, channelID);
[1735]177  }
[6417]178
[2087]179  /**
[12027]180   * Print ping time to client in milliseconds.
[2087]181   */
[5961]182  void Server::printRTT()
183  {
[12027]184    // TODO: Implement
[5961]185  }
[1502]186
187  /**
[12027]188   * Take a new snapshot of the gamestate and send it to the clients.
[2087]189   */
[7163]190  void Server::updateGamestate()
191  {
[12027]192    if(this->clientIDs_.size() == 0)
193    {
194      // no client connected
[3304]195      return;
[12027]196    }
[3304]197    GamestateManager::update();
[12027]198    this->sendGameStates();
199    this->sendObjectDeletes();
[1502]200  }
201
202  /**
[12027]203   * Send the current gamestate to all peers.
204   */
[7801]205  bool Server::sendGameStates()
[7163]206  {
[7801]207    std::vector<packet::Gamestate*> gamestates = GamestateManager::getGamestates();
[12027]208    for(packet::Gamestate* gamestate : gamestates)
[7801]209    {
[11071]210      gamestate->send(static_cast<Host*>(this));
[7801]211    }
[1502]212    return true;
213  }
[1747]214
[7801]215
[12027]216  /**
217   * Send 'DeleteObjects' packet
218   */
[7163]219  bool Server::sendObjectDeletes()
220  {
[12027]221    // no client connected
222    if(this->clientIDs_.size() == 0)
223    {
[2662]224      return true;
[12027]225    }
226
[1907]227    packet::DeleteObjects *del = new packet::DeleteObjects();
228    if(!del->fetchIDs())
[5929]229    {
230      delete del;
[1907]231      return true;  //everything ok (no deletes this tick)
[5929]232    }
[12027]233
[8327]234    del->setPeerID(NETWORK_PEER_ID_BROADCAST);
[12027]235    if (!del->send( static_cast<Host*>(this)))
236    {
[8858]237      orxout(internal_warning, context::network) << "Server: could not broadcast deleteObjects packet" << endl;
[12027]238    }
239
[1907]240    return true;
241  }
[1747]242
[12027]243  /**
244   * Add a new peer to the server.
245   */
[8327]246  void Server::addPeer(uint32_t peerID)
[7163]247  {
[2087]248    // inform all the listeners
[8327]249    this->clientIDs_.push_back(peerID);
[10622]250    WANDiscoverable::updateClientNumber(this->clientIDs_.size());
251    LANDiscoverable::updateClientNumber(this->clientIDs_.size());
252
[8327]253    ClientConnectionListener::broadcastClientConnected(peerID);
254    GamestateManager::addPeer(peerID);
[2087]255
[8858]256    orxout(internal_info, context::network) << "Server: added client id: " << peerID << endl;
[10622]257
[12027]258    this->createClient(peerID);
259  }
[1747]260
[12027]261  /**
262   * Remove a peer from the server.
263   */
[8327]264  void Server::removePeer(uint32_t peerID)
[5929]265  {
[8858]266    orxout(verbose, context::network) << "removing client from list" << endl;
[12027]267
268    // erase the peer from the list
269    std::vector<uint32_t>::iterator it;
270    for(it=this->clientIDs_.begin(); it!=this->clientIDs_.end(); ++it)
[5929]271    {
[12027]272      if(*it == peerID)
273      {
274        this->clientIDs_.erase(it);
275        break;
276      }
[8327]277    }
[10622]278
[12027]279    WANDiscoverable::updateClientNumber(this->clientIDs_.size());
280    LANDiscoverable::updateClientNumber(this->clientIDs_.size());
281
282    // Send 'clientDisconnected' message
283    ClientConnectionListener::broadcastClientDisconnected(peerID);
284
285    GamestateManager::removePeer(peerID);
[5929]286  }
[8858]287
[12027]288  /**
289   * Process an incoming packet.
290   */
[7801]291  void Server::processPacket(packet::Packet* packet)
292  {
[12027]293    if(packet->isReliable())
[7801]294    {
[12027]295      if(this->getLastReceivedGamestateID(packet->getPeerID()) >= packet->getRequiredGamestateID())
296      {
[7801]297        packet->process(static_cast<Host*>(this));
[12027]298      }
[7801]299      else
[12027]300      {
[7801]301        this->packetQueue_.push_back(packet);
[12027]302      }
[7801]303    }
304    else
[12027]305    {
[7801]306      packet->process(static_cast<Host*>(this));
[12027]307    }
[7801]308  }
[5929]309
[12027]310  /**
311   * Create a client.
312   */
[7163]313  bool Server::createClient(int clientID)
314  {
[6417]315
[3084]316    // synchronise class ids
[12027]317    this->syncClassid(clientID);
[6417]318
[3084]319    // now synchronise functionIDs
320    packet::FunctionIDs *fIDs = new packet::FunctionIDs();
[7801]321    fIDs->setPeerID(clientID);
[12027]322    bool b = fIDs->send(static_cast<Host*>(this));
[3084]323    assert(b);
[6417]324
[7801]325    GamestateManager::setSynched(clientID);
[8858]326
[12027]327    // Send 'Welcome' packet to client
[8858]328    orxout(verbose, context::network) << "sending welcome" << endl;
[8706]329    packet::Welcome *w = new packet::Welcome(clientID);
[8327]330    w->setPeerID(clientID);
[12027]331    b = w->send(static_cast<Host*>(this));
[1907]332    assert(b);
[12027]333
[11103]334    (void)b; // avoid compiler warning
[1502]335    return true;
336  }
[6417]337
[12027]338  /**
339   * Disconnect a client.
340   */
341  void Server::disconnectClient(uint32_t clientID)
[7163]342  {
[12027]343    ServerConnection::disconnectClient(clientID);
344    GamestateManager::removePeer(clientID);
[1502]345  }
[2087]346
[8858]347  /**
348   * @brief Sends a chat message to the given target ID.
349   * @param message message to be sent
350   * @param sourceID the ID of the sender
351   * @param targetID the ID of the receiver
352   */
353  void Server::doSendChat(const std::string& message, unsigned int sourceID, unsigned int targetID)
[7163]354  {
[8858]355    // check if the target exists. just ignore the message otherwise
[12027]356    if (!this->isValidTarget(targetID))
357    {
[8858]358      return;
[12027]359    }
[8858]360
361    // send the message to the target
362    packet::Chat* packet = new packet::Chat(message, sourceID, targetID);
363    packet->setPeerID(targetID);
[12027]364    packet->send(static_cast<Host*>(this));
[8858]365
366    // if the target is (or includes) this host as well, call the parent function which passes the message to the listeners
367    if (targetID == NETWORK_PEER_ID_BROADCAST || targetID == Host::getPlayerID())
[12027]368    {
[8858]369      Host::doReceiveChat(message, sourceID, targetID);
[12027]370    }
[2087]371  }
372
[8858]373  /**
374   * @brief Gets called if a packet::Chat packet is received. Forwards the packet to the target
375   * and calls the parent function if necessary.
376   */
377  void Server::doReceiveChat(const std::string& message, unsigned int sourceID, unsigned int targetID)
[7163]378  {
[8858]379      this->doSendChat(message, sourceID, targetID);
[2087]380  }
381
[8858]382  /**
383   * @brief Returns true if the target ID is in the list of clients (or if it
384   * corresponds to the broadcast or the server ID).
385   */
386  bool Server::isValidTarget(unsigned int targetID)
[7163]387  {
[12027]388    // Broadcast or server ID are okay
[8858]389    if (targetID == NETWORK_PEER_ID_BROADCAST || targetID == NETWORK_PEER_ID_SERVER)
[12027]390    {
[8858]391      return true;
[12027]392    }
[2087]393
[12027]394    // IDs in the client list are okay also
395    for(uint32_t id : this->clientIDs_)
396    {
397      if(id == targetID)
398      {
[8858]399        return true;
[12027]400      }
401    }
[8858]402
403    return false;
[1907]404  }
[1747]405
[7163]406  void Server::syncClassid(unsigned int clientID)
407  {
[3214]408    packet::ClassID *classid = new packet::ClassID();
[7801]409    classid->setPeerID(clientID);
[12027]410
411    int failures = 0;
412    while(!classid->send(static_cast<Host*>(this)) && failures < 10)\
413    {
[3214]414      failures++;
415    }
416    assert(failures<10);
[8858]417    orxout(verbose, context::network) << "syncClassid:\tall synchClassID packets have been sent" << endl;
[3214]418  }
419
[1502]420}
Note: See TracBrowser for help on using the repository browser.