Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8347 was 8327, checked in by scheusso, 14 years ago

merging network6 into trunk

  • Property svn:eol-style set to native
File size: 13.4 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"
[3214]49#include "util/Debug.h"
50#include "core/ObjectList.h"
[7284]51#include "core/command/Executor.h"
[1735]52#include "packet/Chat.h"
[3214]53#include "packet/ClassID.h"
54#include "packet/DeleteObjects.h"
55#include "packet/FunctionIDs.h"
56#include "packet/Gamestate.h"
[1735]57#include "packet/Welcome.h"
[2087]58#include "ChatListener.h"
[8327]59// #include "ClientInformation.h"
[3084]60#include "FunctionCallManager.h"
[3214]61#include "GamestateManager.h"
[7801]62#include "WANDiscovery.h"
[1502]63
[2171]64namespace orxonox
[1502]65{
[2087]66  const unsigned int MAX_FAILURES = 20;
[1747]67
[1502]68  /**
69  * Constructor for default values (bindaddress is set to ENET_HOST_ANY
70  *
71  */
[7163]72  Server::Server()
73  {
[3304]74    this->timeSinceLastUpdate_=0;
[1502]75  }
[1747]76
[7163]77  Server::Server(int port)
78  {
[3214]79    this->setPort( port );
[3304]80    this->timeSinceLastUpdate_=0;
[1502]81  }
82
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  {
[3214]90    this->setPort( port );
91    this->setBindAddress( bindAddress );
[3304]92    this->timeSinceLastUpdate_=0;
[1502]93  }
94
95  /**
[1907]96  * @brief Destructor
97  */
[7163]98  Server::~Server()
99  {
[1907]100  }
[1502]101
[7801]102
103  /** helper that connects to the master server */
104  void Server::helper_ConnectToMasterserver()
105  {
106//     WANDiscovery::getInstance().msc.sendRequest( MSPROTO_GAME_SERVER " "
107//       MSPROTO_REGISTER_SERVER );
108  }
109
[1502]110  /**
111  * This function opens the server by creating the listener thread
112  */
[7163]113  void Server::open()
114  {
115    Host::setActive(true);
[3214]116    COUT(4) << "opening server" << endl;
117    this->openListener();
[7801]118   
119    /* make discoverable on LAN */
[7163]120    LANDiscoverable::setActivity(true);
[7801]121
122    /* make discoverable on WAN */
123    WANDiscoverable::setActivity(true);
124    /* TODO this needs to be optional, we need a switch from the UI to
125     * enable/disable this
126     */
127//     helper_ConnectToMasterserver();
128
129    /* done */
[1502]130    return;
131  }
132
133  /**
134  * This function closes the server
135  */
[7163]136  void Server::close()
137  {
138    Host::setActive(false);
[3214]139    COUT(4) << "closing server" << endl;
140    this->disconnectClients();
141    this->closeListener();
[7801]142
143    /* tell master server we're closing */
144    COUT(2) << "disconnecting." << endl;
145    WANDiscoverable::setActivity(false);   
146    COUT(2) << "disconnecting done" << endl;
147
[7163]148    LANDiscoverable::setActivity(false);
[1502]149    return;
150  }
151
[7163]152  bool Server::processChat(const std::string& message, unsigned int playerID)
153  {
[8327]154//     ClientInformation *temp = ClientInformation::getBegin();
[1907]155    packet::Chat *chat;
[8327]156//     while(temp){
157    chat = new packet::Chat(message, playerID);
158    chat->setPeerID(NETWORK_PEER_ID_BROADCAST);
159    chat->send( static_cast<Host*>(this) );
160//         COUT(3) << "could not send Chat message to client ID: " << temp->getID() << std::endl;
161//       temp = temp->next();
162//     }
[2087]163//    COUT(1) << "Player " << playerID << ": " << message << std::endl;
[1907]164    return true;
[1502]165  }
166
167
[7801]168  /* handle incoming data */
169  int rephandler( char *addr, ENetEvent *ev )
170  { 
171    /* reply to pings */
172    if( !strncmp( (char *)ev->packet->data, MSPROTO_PING_GAMESERVER, 
173      MSPROTO_PING_GAMESERVER_LEN ) )
174      //this->msc.sendRequest( MSPROTO_ACK );
175      /* NOTE implement this after pollForReply
176       * reimplementation
177       */
178      return 0;
179
180    /* done handling, return all ok code 0 */
181    return 0;
182  }
183
184  void Server::helper_HandleMasterServerRequests()
185  { 
186    /* poll the master server for replies and see whether something
187     * has to be done or changed.
188     */
189    //WANDiscovery::getInstance().msc.pollForReply( rhandler, 10 );
190  }
191
[1502]192  /**
193  * Run this function once every tick
194  * calls processQueue and updateGamestate
195  * @param time time since last tick
196  */
[7163]197  void Server::update(const Clock& time)
198  {
[3304]199    // receive incoming packets
[3214]200    Connection::processQueue();
[7801]201
[7163]202    // receive and process incoming discovery packets
203    LANDiscoverable::update();
[7801]204   
205    // receive and process requests from master server
206    /* todo */
207    //helper_HandleMasterServerRequests();
[6417]208
[8327]209    if ( GamestateManager::hasPeers() )
[3214]210    {
[3304]211      // process incoming gamestates
212      GamestateManager::processGamestates();
[7801]213      FunctionCallManager::processBufferedFunctionCalls();
[6417]214
[3304]215      // send function calls to clients
[7801]216      FunctionCallManager::sendCalls( static_cast<Host*>(this) );
[6417]217
[3304]218      //this steers our network frequency
219      timeSinceLastUpdate_+=time.getDeltaTime();
220      if(timeSinceLastUpdate_>=NETWORK_PERIOD)
221      {
222        timeSinceLastUpdate_ -= static_cast<unsigned int>( timeSinceLastUpdate_ / NETWORK_PERIOD ) * NETWORK_PERIOD;
223        updateGamestate();
224      }
[7801]225//       sendPackets(); // flush the enet queue
[1502]226    }
227  }
[1747]228
[7801]229  void Server::queuePacket(ENetPacket *packet, int clientID, uint8_t channelID)
[7163]230  {
[7801]231    ServerConnection::addPacket(packet, clientID, channelID);
[1735]232  }
[6417]233
[2087]234  /**
[6417]235   * @brief: returns ping time to client in milliseconds
[2087]236   */
[7163]237  unsigned int Server::getRTT(unsigned int clientID)
238  {
[8327]239//     assert(ClientInformation::findClient(clientID));
240//     return ClientInformation::findClient(clientID)->getRTT();
241    // TODO: reimplement
242    return 0;
[2087]243  }
[6417]244
[5961]245  void Server::printRTT()
246  {
[8327]247//     for( ClientInformation* temp=ClientInformation::getBegin(); temp!=0; temp=temp->next() )
248//       COUT(0) << "Round trip time to client with ID: " << temp->getID() << " is " << temp->getRTT() << " ms" << endl;
[5961]249  }
[1502]250
251  /**
[2087]252   * @brief: return packet loss ratio to client (scales from 0 to 1)
253   */
[7163]254  double Server::getPacketLoss(unsigned int clientID)
255  {
[8327]256//     assert(ClientInformation::findClient(clientID));
257//     return ClientInformation::findClient(clientID)->getPacketLoss();
258    return 0.;
[2087]259  }
[1502]260
261  /**
262  * takes a new snapshot of the gamestate and sends it to the clients
263  */
[7163]264  void Server::updateGamestate()
265  {
[8327]266    if( this->clientIDs_.size()==0 )
[2662]267      //no client connected
[3304]268      return;
269    GamestateManager::update();
[7801]270//     COUT(5) << "Server: one gamestate update complete, goig to sendGameState" << std::endl;
[1502]271    //std::cout << "updated gamestate, sending it" << std::endl;
272    //if(clients->getGamestateID()!=GAMESTATEID_INITIAL)
[7801]273    sendGameStates();
[1907]274    sendObjectDeletes();
[7801]275//     COUT(5) << "Server: one sendGameState turn complete, repeat in next tick" << std::endl;
[1502]276    //std::cout << "sent gamestate" << std::endl;
277  }
278
279  /**
[7801]280  * sends the current gamestate to all peers
[1502]281  */
[7801]282  bool Server::sendGameStates()
[7163]283  {
[7801]284    std::vector<packet::Gamestate*> gamestates = GamestateManager::getGamestates();
285    std::vector<packet::Gamestate*>::iterator it;
286    for( it = gamestates.begin(); it != gamestates.end(); ++it )
287    {
288      (*it)->send(static_cast<Host*>(this));
289    }
[1502]290    return true;
291  }
[1747]292
[7801]293
[7163]294  bool Server::sendObjectDeletes()
295  {
[8327]296//     ClientInformation *temp = ClientInformation::getBegin();
297//     if( temp == NULL )
[2662]298      //no client connected
[8327]299    if( this->clientIDs_.size()==0 )
[2662]300      return true;
[1907]301    packet::DeleteObjects *del = new packet::DeleteObjects();
302    if(!del->fetchIDs())
[5929]303    {
304      delete del;
[1907]305      return true;  //everything ok (no deletes this tick)
[5929]306    }
[1907]307//     COUT(3) << "sending DeleteObjects" << std::endl;
[8327]308//     while(temp != NULL){
309//       if( !(temp->getSynched()) )
310//       {
311//         COUT(5) << "Server: not sending gamestate" << std::endl;
312//         temp=temp->next();
313//         continue;
314//       }
315//       int cid = temp->getID(); //get client id
316//       packet::DeleteObjects *cd = new packet::DeleteObjects(*del);
317//       assert(cd);
318    del->setPeerID(NETWORK_PEER_ID_BROADCAST);
319    if ( !del->send( static_cast<Host*>(this) ) )
320      COUT(3) << "Server: could not broadcast deleteObjects packet" << std::endl;
321//       temp=temp->next();
[1907]322      // gs gets automatically deleted by enet callback
[8327]323//     }
324//     delete del;
[1907]325    return true;
326  }
[1747]327
[1907]328
[8327]329  void Server::addPeer(uint32_t peerID)
[7163]330  {
[8327]331//     static unsigned int newid=1;
332//
333//     COUT(2) << "Server: adding client" << std::endl;
334//     ClientInformation *temp = ClientInformation::insertBack(new ClientInformation);
335//     if(!temp)
336//     {
337//       COUT(2) << "Server: could not add client" << std::endl;
338//     }
339//     temp->setID(newid);
340//     temp->setPeer(event->peer);
[2087]341
342    // inform all the listeners
[8327]343    this->clientIDs_.push_back(peerID);
344    ClientConnectionListener::broadcastClientConnected(peerID);
345    GamestateManager::addPeer(peerID);
[2087]346
[8327]347//     ++newid;
[2087]348
[8327]349    COUT(3) << "Server: added client id: " << peerID << std::endl;
350    createClient(peerID);
[2087]351}
[1747]352
[8327]353  void Server::removePeer(uint32_t peerID)
[5929]354  {
355    COUT(4) << "removing client from list" << std::endl;
[8327]356//     ClientInformation *client = ClientInformation::findClient(&event->peer->address);
357//     if(!client)
358//       return;
359//     else
360//     {
361  std::vector<uint32_t>::iterator it;
362  for( it=this->clientIDs_.begin(); it!=this->clientIDs_.end(); ++it )
363  {
364    if( *it == peerID )
[5929]365    {
[8327]366      this->clientIDs_.erase(it);
367      break;
368    }
369  }
370  ClientConnectionListener::broadcastClientDisconnected(peerID);
371  GamestateManager::removePeer(peerID);
[5929]372      //ServerConnection::disconnectClient( client );
[5961]373      //ClientConnectionListener::broadcastClientDisconnected( client->getID() ); //this is done in ClientInformation now
[8327]374//       delete client;
375//     }
[5929]376  }
[7801]377 
378  void Server::processPacket(packet::Packet* packet)
379  {
380    if( packet->isReliable() )
381    {
[8327]382      if( this->getLastReceivedGamestateID(packet->getPeerID()) >= packet->getRequiredGamestateID() )
[7801]383        packet->process(static_cast<Host*>(this));
384      else
385        this->packetQueue_.push_back(packet);
386    }
387    else
388      packet->process(static_cast<Host*>(this));
389  }
[5929]390
[7801]391
[7163]392  bool Server::createClient(int clientID)
393  {
[8327]394//     ClientInformation *temp = ClientInformation::findClient(clientID);
395//     if(!temp)
396//     {
397//       COUT(2) << "Server. could not create client with id: " << clientID << std::endl;
398//       return false;
399//     }
400//     COUT(4) << "Con.Man: creating client id: " << temp->getID() << std::endl;
[6417]401
[3084]402    // synchronise class ids
[8327]403    syncClassid(clientID);
[6417]404
[3084]405    // now synchronise functionIDs
406    packet::FunctionIDs *fIDs = new packet::FunctionIDs();
[7801]407    fIDs->setPeerID(clientID);
408    bool b = fIDs->send( static_cast<Host*>(this) );
[3084]409    assert(b);
[6417]410
[8327]411//     temp->setSynched(true);
[7801]412    GamestateManager::setSynched(clientID);
413   
[3084]414    COUT(4) << "sending welcome" << std::endl;
[8327]415    packet::Welcome *w = new packet::Welcome(clientID, OBJECTID_UNKNOWN);
416    w->setPeerID(clientID);
[7801]417    b = w->send( static_cast<Host*>(this) );
[1907]418    assert(b);
[8327]419//     packet::Gamestate *g = new packet::Gamestate();
420//     g->setPeerID(clientID);
421//     b = g->collectData(0,packet::GAMESTATE_MODE_SERVER);
[7801]422//     assert(b);
[8327]423//     if(!b)
424//       return false; //no data for the client
425// //     b = g->compressData();
426// //     assert(b);
427//     b = g->send( static_cast<Host*>(this) );
428//     assert(b);
[1502]429    return true;
430  }
[6417]431
[8327]432  void Server::disconnectClient( uint32_t clientID )
[7163]433  {
[8327]434    ServerConnection::disconnectClient( clientID );
435    GamestateManager::removePeer( clientID );
[5929]436    // inform all the listeners
[5961]437    // ClientConnectionListener::broadcastClientDisconnected(client->getID()); // this is done in ClientInformation now
[1502]438  }
[2087]439
[7163]440  bool Server::chat(const std::string& message)
441  {
[2087]442      return this->sendChat(message, Host::getPlayerID());
443  }
444
[7163]445  bool Server::broadcast(const std::string& message)
446  {
[8327]447      return this->sendChat(message, NETWORK_PEER_ID_BROADCAST);
[2087]448  }
449
[7163]450  bool Server::sendChat(const std::string& message, unsigned int clientID)
451  {
[8327]452//     ClientInformation *temp = ClientInformation::getBegin();
[1907]453    packet::Chat *chat;
[8327]454//     while(temp)
[7163]455    {
[2087]456      chat = new packet::Chat(message, clientID);
[8327]457      chat->setPeerID(NETWORK_PEER_ID_BROADCAST);
458      chat->send( static_cast<Host*>(this) );
459//         COUT(3) << "could not send Chat message to client ID: " << temp->getID() << std::endl;
460//       temp = temp->next();
[1907]461    }
[2087]462//    COUT(1) << "Player " << Host::getPlayerID() << ": " << message << std::endl;
[2171]463    for (ObjectList<ChatListener>::iterator it = ObjectList<ChatListener>::begin(); it != ObjectList<ChatListener>::end(); ++it)
[2087]464      it->incomingChat(message, clientID);
465
[1907]466    return true;
467  }
[1747]468
[7163]469  void Server::syncClassid(unsigned int clientID)
470  {
[3214]471    int failures=0;
472    packet::ClassID *classid = new packet::ClassID();
[7801]473    classid->setPeerID(clientID);
474    while(!classid->send( static_cast<Host*>(this) ) && failures < 10){
[3214]475      failures++;
476    }
477    assert(failures<10);
478    COUT(4) << "syncClassid:\tall synchClassID packets have been sent" << std::endl;
479  }
480
[1502]481}
Note: See TracBrowser for help on using the repository browser.