Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/formation/src/libraries/network/MasterServer.cc @ 9114

Last change on this file since 9114 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
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 *      Sandro 'smerkli' Merkli
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "MasterServer.h"
30#include "util/ScopedSingletonManager.h"
31#include "core/CoreIncludes.h"
32#include "core/CorePrereqs.h"
33
34namespace orxonox
35{
36  /* helpers */
37  static void 
38  helper_output_debug( ENetEvent *event, char *addrconv )
39  {
40    orxout(verbose, context::master_server)
41      << "A packet of length" 
42      << event->packet->dataLength
43      << " containing "
44      << (const char*)event->packet->data
45      << " was received from "
46      << addrconv
47      << " on channel "
48      << event->channelID << endl;
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 ) 
69      { orxout(internal_warning, context::master_server) << "Masterserver.cc: Memory allocation failed." << endl;
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
90    /* create end-of-list packet */
91    reply = enet_packet_create( MSPROTO_SERVERLIST_END,
92        MSPROTO_SERVERLIST_END_LEN + 1,
93        ENET_PACKET_FLAG_RELIABLE );
94
95    /* send end-of-list packet */
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
105  /***** EVENTS *****/
106  /* connect event */
107  int 
108  MasterServer::eventConnect( ENetEvent *event )
109  { /* check for bad parameters */
110    if( !event )
111    { orxout(internal_warning, context::master_server) << "MasterServer::eventConnect: No event given." << endl;
112      return -1;
113    }
114
115    /* convert address to string. */
116    char *addrconv = (char *) calloc( 50, 1 );
117    enet_address_get_host_ip( &(event->peer->address), addrconv, 49 );
118
119    /* output debug info */
120    orxout(verbose, context::master_server) << "A new client connected from " 
121      << addrconv
122      << " on port " 
123      << event->peer->address.port << endl;
124
125    /* store string form of address here */
126    event->peer->data = addrconv; 
127
128    /* all fine. */
129    return 0;
130  }
131
132  /* disconnect event */
133  int 
134  MasterServer::eventDisconnect( ENetEvent *event )
135  { /* check for bad parameters */
136    if( !event )
137    { orxout(internal_warning, context::master_server) << "No event given." << endl;
138      return -1;
139    }
140
141    /* output that the disconnect happened */
142    orxout(verbose, context::master_server) << (char*)event->peer->data << " disconnected." << endl;
143
144    /* create string from peer data */
145    std::string name = std::string( (char*)event->peer->data );
146
147    /* remove the server from the list it belongs to */
148    this->mainlist.delServerByName( name );
149
150    /* Reset the peer's client information. */
151    if( event->peer->data ) free( event->peer->data );
152
153    /* done */
154    return 0;
155  }
156
157  /* data event */
158  int 
159  MasterServer::eventData( ENetEvent *event )
160  { /* validate packet */
161    if( !event || !(event->packet) || !(event->peer) )
162    { orxout(internal_warning, context::master_server) << "No complete event given." << endl;
163      return -1;
164    }
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 );
169
170    /* output debug info about the data that has come */
171    helper_output_debug( event, addrconv );
172
173    /* GAME SERVER OR CLIENT CONNECTION? */
174    if( !strncmp( (char *)event->packet->data, MSPROTO_GAME_SERVER, 
175      MSPROTO_GAME_SERVER_LEN ) )
176    { /* Game server */
177
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 */
182        mainlist.addServer( packet::ServerInformation( event ) );
183       
184        /* tell people we did so */
185        orxout(internal_info, context::master_server) << "Added new server to list: " << 
186          packet::ServerInformation( event ).getServerIP() << endl;
187      }
188
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 */
197        this->mainlist.delServerByAddress( name );
198
199        /* tell the user */
200        orxout(internal_info, context::master_server) << "Removed server " << name << " from list." << endl;
201      }
202
203      /* TODO add hook for disconnect here */
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,
209        MSPROTO_REQ_LIST, MSPROTO_REQ_LIST_LEN ) )
210        /* send server list */
211        helper_sendlist( event );
212    }
213    else
214    { /* bad message, don't do anything. */ } 
215
216    /* delete addrconv */
217    if( addrconv ) free( addrconv );
218
219    /* Clean up the packet now that we're done using it. */
220    enet_packet_destroy( event->packet );
221    return 0;
222  }
223
224
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 )
232    { 
233      orxout(user_error, context::master_server) << "Could not create ENetEvent structure, exiting." << endl;
234      exit( EXIT_FAILURE );
235    }
236
237    /* TODO schedule pings for servers somewhere here */
238   
239    /* create an iterator for the loop */
240    enet_host_service( this->server, event, 100 );
241
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;
247
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;
255    }
256
257    /* done */
258    return 0;
259  } 
260
261  /* constructor */
262  MasterServer::MasterServer()
263  {
264    /***** INITIALIZE NETWORKING *****/
265    if( enet_initialize () != 0)
266    { orxout(user_error, context::master_server) << "An error occurred while initializing ENet." << endl;
267      exit( EXIT_FAILURE );
268    }
269
270    /* register deinitialization */
271    atexit( enet_deinitialize );
272
273    /* set the quit flag to false */
274    this->quit = false;
275
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;
279
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, 
283        ORX_MSERVER_MAXCHANS, 0, 0 );
284    assert(this->server);
285
286    /* see if creation worked */
287    if( !this->server )
288    { orxout(user_error, context::master_server) << 
289        "An error occurred while trying to create an ENet server host." << endl;
290      exit( EXIT_FAILURE );
291    }
292
293    /***** INITIALIZE GAME SERVER AND PEER LISTS *****/
294    this->peers = new PeerList();
295
296    /* tell people we're now initialized */
297    orxout(internal_status, context::master_server) << "MasterServer initialized, waiting for connections." << endl;
298  }
299
300  /* destructor */
301  MasterServer::~MasterServer()
302  {
303    /***** CLEANUP PROCESS *****/
304    /* terminate all networking connections */
305    enet_host_destroy( this->server );
306
307    /* free all used memory */
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.