Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/network/MasterServer.cc @ 8887

Last change on this file since 8887 was 8858, checked in by landauf, 13 years ago

merged output branch back to trunk.

Changes:

  • you have to include util/Output.h instead of util/Debug.h
  • COUT(x) is now called orxout(level)
  • output levels are now defined by an enum instead of numbers. see util/Output.h for the definition
  • it's possible to use output contexts with orxout(level, context). see util/Output.h for some common contexts. you can define more contexts
  • you must use 'endl' at the end of an output message, '\n' does not flush the message

Output levels:

  • instead of COUT(0) use orxout()
  • instead of COUT(1) use orxout(user_error) or orxout(internal_error)
  • instead of COUT(2) use orxout(user_warning) or orxout(internal_warning)
  • instead of COUT(3) use orxout(user_status/user_info) or orxout(internal_status/internal_info)
  • instead of COUT(4) use orxout(verbose)
  • instead of COUT(5) use orxout(verbose_more)
  • instead of COUT(6) use orxout(verbose_ultra)

Guidelines:

  • user_* levels are for the user, visible in the console and the log-file
  • internal_* levels are for developers, visible in the log-file
  • verbose_* levels are for debugging, only visible if the context of the output is activated

Usage in C++:

  • orxout() << "message" << endl;
  • orxout(level) << "message" << endl;
  • orxout(level, context) << "message" << endl;

Usage in Lua:

  • orxout("message")
  • orxout(orxonox.level.levelname, "message")
  • orxout(orxonox.level.levelname, "context", "message")

Usage in Tcl (and in the in-game-console):

  • orxout levelname message
  • orxout_context levelname context message
  • shortcuts: log message, error message, warning message, status message, info message, debug message
  • Property svn:eol-style set to native
File size: 9.2 KB
RevLine 
[7569]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 *      Sandro 'smerkli' Merkli
24 *   Co-authors:
25 *      ...
26 *
27 */
28
[7565]29#include "MasterServer.h"
[7590]30#include "util/ScopedSingletonManager.h"
31#include "core/CoreIncludes.h"
32#include "core/CorePrereqs.h"
[7565]33
[7590]34namespace orxonox
35{
[7684]36  /* helpers */
37  static void 
38  helper_output_debug( ENetEvent *event, char *addrconv )
39  {
[8858]40    orxout(verbose, context::master_server)
41      << "A packet of length" 
[7684]42      << event->packet->dataLength
43      << " containing "
44      << (const char*)event->packet->data
45      << " was received from "
46      << addrconv
47      << " on channel "
[8858]48      << event->channelID << endl;
[7684]49  }
50
51  void
52  MasterServer::helper_sendlist( ENetEvent *event )
53  {
54    /* get an iterator */
55    std::list<packet::ServerInformation>::iterator i;
56
57    /* packet holder */
58    ENetPacket *reply;
59
60    /* loop through list elements */
61    for( i = mainlist.serverlist.begin(); i
62        != mainlist.serverlist.end(); ++i ) 
63    {
64      /* send this particular server */
65      /* build reply string */
66      char *tosend = (char *)calloc( (*i).getServerIP().length() 
67          + MSPROTO_SERVERLIST_ITEM_LEN + 2,1 );
68      if( !tosend ) 
[8858]69      { orxout(internal_warning, context::master_server) << "Masterserver.cc: Memory allocation failed." << endl;
[7684]70        continue;
71      } 
72      sprintf( tosend, "%s %s", MSPROTO_SERVERLIST_ITEM, 
73          (*i).getServerIP().c_str() );
74
75      /* create packet from it */
76      reply = enet_packet_create( tosend,
77          strlen( tosend ) + 1, 
78          ENET_PACKET_FLAG_RELIABLE);
79
80      /* Send the reply to the peer over channel id 0. */
81      enet_peer_send( event->peer, 0, reply );
82
83      /* One could just use enet_host_service() instead. */
84      enet_host_flush( this->server );
85
86      /* free the tosend buffer */
87      free( tosend );
88    } 
89
[7750]90    /* create end-of-list packet */
[7684]91    reply = enet_packet_create( MSPROTO_SERVERLIST_END,
92        MSPROTO_SERVERLIST_END_LEN + 1,
93        ENET_PACKET_FLAG_RELIABLE );
94
[7750]95    /* send end-of-list packet */
[7684]96    enet_peer_send( event->peer, 0, reply );
97
98    /* One could just use enet_host_service() instead. */
99    enet_host_flush( this->server );
100  }
101
102
103
104
[7590]105  /***** EVENTS *****/
106  /* connect event */
107  int 
[7611]108  MasterServer::eventConnect( ENetEvent *event )
[7590]109  { /* check for bad parameters */
110    if( !event )
[8858]111    { orxout(internal_warning, context::master_server) << "MasterServer::eventConnect: No event given." << endl;
[7590]112      return -1;
113    }
[7565]114
[7611]115    /* convert address to string. */
116    char *addrconv = (char *) calloc( 50, 1 );
117    enet_address_get_host_ip( &(event->peer->address), addrconv, 49 );
118
[7590]119    /* output debug info */
[8858]120    orxout(verbose, context::master_server) << "A new client connected from " 
[7611]121      << addrconv
122      << " on port " 
[8858]123      << event->peer->address.port << endl;
[7565]124
[7611]125    /* store string form of address here */
126    event->peer->data = addrconv; 
127
128    /* all fine. */
[7590]129    return 0;
[7565]130  }
131
[7590]132  /* disconnect event */
133  int 
[7611]134  MasterServer::eventDisconnect( ENetEvent *event )
[7590]135  { /* check for bad parameters */
136    if( !event )
[8858]137    { orxout(internal_warning, context::master_server) << "No event given." << endl;
[7590]138      return -1;
139    }
[7565]140
[7651]141    /* output that the disconnect happened */
[8858]142    orxout(verbose, context::master_server) << (char*)event->peer->data << " disconnected." << endl;
[7565]143
[7651]144    /* create string from peer data */
145    std::string name = std::string( (char*)event->peer->data );
146
[7590]147    /* remove the server from the list it belongs to */
[7657]148    this->mainlist.delServerByName( name );
[7565]149
[7590]150    /* Reset the peer's client information. */
[7611]151    if( event->peer->data ) free( event->peer->data );
[7651]152
153    /* done */
[7590]154    return 0;
[7565]155  }
156
[7590]157  /* data event */
158  int 
[7611]159  MasterServer::eventData( ENetEvent *event )
[7651]160  { /* validate packet */
[7611]161    if( !event || !(event->packet) || !(event->peer) )
[8858]162    { orxout(internal_warning, context::master_server) << "No complete event given." << endl;
[7590]163      return -1;
164    }
[7611]165     
166    /* generate address in readable form */
167    char *addrconv = (char *) calloc( 50, 1 );
168    enet_address_get_host_ip( &(event->peer->address), addrconv, 49 );
[7590]169
[7750]170    /* output debug info about the data that has come */
[7684]171    helper_output_debug( event, addrconv );
[7590]172
[7630]173    /* GAME SERVER OR CLIENT CONNECTION? */
[7651]174    if( !strncmp( (char *)event->packet->data, MSPROTO_GAME_SERVER, 
175      MSPROTO_GAME_SERVER_LEN ) )
176    { /* Game server */
[7630]177
[7651]178      if( !strncmp( (char *)event->packet->data
179        + MSPROTO_GAME_SERVER_LEN+1, 
180        MSPROTO_REGISTER_SERVER, MSPROTO_REGISTER_SERVER_LEN ) )
181      { /* register new server */
[7657]182        mainlist.addServer( packet::ServerInformation( event ) );
[7658]183       
184        /* tell people we did so */
[8858]185        orxout(internal_info, context::master_server) << "Added new server to list: " << 
186          packet::ServerInformation( event ).getServerIP() << endl;
[7651]187      }
[7756]188
[7763]189      else if( !strncmp( (char *)event->packet->data
190        + MSPROTO_GAME_SERVER_LEN+1,
191        MSPROTO_SERVERDC, MSPROTO_SERVERDC_LEN ) )
192      {
193        /* create string from peer data */
194        std::string name = std::string( addrconv );
195
196        /* remove the server from the list it belongs to */
[7765]197        this->mainlist.delServerByAddress( name );
[7763]198
199        /* tell the user */
[8858]200        orxout(internal_info, context::master_server) << "Removed server " << name << " from list." << endl;
[7763]201      }
202
[7756]203      /* TODO add hook for disconnect here */
[7651]204    }
205    else if( !strncmp( (char *)event->packet->data, MSPROTO_CLIENT, 
206      MSPROTO_CLIENT_LEN) )
207    { /* client */
208      if( !strncmp( (char *)event->packet->data + MSPROTO_CLIENT_LEN+1,
[7657]209        MSPROTO_REQ_LIST, MSPROTO_REQ_LIST_LEN ) )
[7684]210        /* send server list */
211        helper_sendlist( event );
[7651]212    }
213    else
214    { /* bad message, don't do anything. */ } 
215
[7611]216    /* delete addrconv */
217    if( addrconv ) free( addrconv );
218
[7590]219    /* Clean up the packet now that we're done using it. */
220    enet_packet_destroy( event->packet );
221    return 0;
222  }
[7565]223
[7611]224
[7590]225  /**** MAIN ROUTINE *****/
226  int 
227  MasterServer::run()
228  {
229    /***** ENTER MAIN LOOP *****/
230    ENetEvent *event = (ENetEvent *)calloc(sizeof(ENetEvent), sizeof(char));
231    if( event == NULL )
[7611]232    { 
[8858]233      orxout(user_error, context::master_server) << "Could not create ENetEvent structure, exiting." << endl;
[7590]234      exit( EXIT_FAILURE );
235    }
[7565]236
[7756]237    /* TODO schedule pings for servers somewhere here */
[7729]238   
[7743]239    /* create an iterator for the loop */
240    enet_host_service( this->server, event, 100 );
[7611]241
[7743]242    /* check what type of event it is and react accordingly */
243    switch (event->type)
244    { /* new connection */
245      case ENET_EVENT_TYPE_CONNECT: 
246        eventConnect( event ); break;
[7565]247
[7743]248        /* disconnect */
249      case ENET_EVENT_TYPE_DISCONNECT: 
250        eventDisconnect( event ); break;
251
252        /* incoming data */
253      case ENET_EVENT_TYPE_RECEIVE: eventData( event ); break;
254      default: break;
[7590]255    }
[7565]256
[7590]257    /* done */
258    return 0;
259  } 
[7565]260
[7590]261  /* constructor */
262  MasterServer::MasterServer()
263  {
264    /***** INITIALIZE NETWORKING *****/
265    if( enet_initialize () != 0)
[8858]266    { orxout(user_error, context::master_server) << "An error occurred while initializing ENet." << endl;
[7590]267      exit( EXIT_FAILURE );
268    }
[7565]269
[7590]270    /* register deinitialization */
271    atexit( enet_deinitialize );
[7565]272
[7729]273    /* set the quit flag to false */
274    this->quit = false;
275
[7590]276    /* Bind the server to the default localhost and port ORX_MSERVER_PORT */
277    this->address.host = ENET_HOST_ANY;
278    this->address.port = ORX_MSERVER_PORT;
[7589]279
[7590]280    /* create a host with the above settings (the last two 0 mean: accept
281     * any input/output bandwidth */
282    this->server = enet_host_create( &this->address, ORX_MSERVER_MAXCONNS, 
[7801]283        ORX_MSERVER_MAXCHANS, 0, 0 );
284    assert(this->server);
[7590]285
286    /* see if creation worked */
287    if( !this->server )
[8858]288    { orxout(user_error, context::master_server) << 
289        "An error occurred while trying to create an ENet server host." << endl;
[7611]290      exit( EXIT_FAILURE );
[7590]291    }
[7565]292
[7611]293    /***** INITIALIZE GAME SERVER AND PEER LISTS *****/
294    this->peers = new PeerList();
[7743]295
296    /* tell people we're now initialized */
[8858]297    orxout(internal_status, context::master_server) << "MasterServer initialized, waiting for connections." << endl;
[7565]298  }
299
[7590]300  /* destructor */
301  MasterServer::~MasterServer()
302  {
303    /***** CLEANUP PROCESS *****/
304    /* terminate all networking connections */
305    enet_host_destroy( this->server );
[7565]306
[7611]307    /* free all used memory */
[7590]308    /* clear the list of connected game servers */
309    /* clear the list of connected game clients */
310  }
311
312/* end of namespace */
313}
Note: See TracBrowser for help on using the repository browser.