Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/multiplayerFS15/src/libraries/network/Server.cc @ 10427

Last change on this file since 10427 was 10427, checked in by frovelli, 10 years ago

Implemented custom servernames

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