Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/output/src/libraries/network/MasterServer.cc @ 9420

Last change on this file since 9420 was 8807, checked in by landauf, 13 years ago

Replaced COUT with orxout in network library. Tried to set levels and contexts in a more or less useful way, but not really optimized. Used contexts network, packets, and master_server.
Please use endl instead of \n in the future (@smerkli) ;)

  • 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  {
[8807]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 "
[8807]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 ) 
[8807]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 )
[8807]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 */
[8807]120    orxout(verbose, context::master_server) << "A new client connected from " 
[7611]121      << addrconv
122      << " on port " 
[8807]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 )
[8807]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 */
[8807]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) )
[8807]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 */
[8807]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 */
[8807]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    { 
[8807]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)
[8807]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 )
[8807]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 */
[8807]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.