Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/masterserver/src/libraries/network/MasterServer.cc @ 7796

Last change on this file since 7796 was 7729, checked in by smerkli, 14 years ago

moved some files.

File size: 8.4 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  {
40    COUT(4) << "A packet of length" 
41      << event->packet->dataLength
42      << " containing "
43      << (const char*)event->packet->data
44      << " was received from "
45      << addrconv
46      << " on channel "
47      << event->channelID << "\n";
48  }
49
50  void
51  MasterServer::helper_sendlist( ENetEvent *event )
52  {
53    /* get an iterator */
54    std::list<packet::ServerInformation>::iterator i;
55
56    /* packet holder */
57    ENetPacket *reply;
58
59    /* loop through list elements */
60    for( i = mainlist.serverlist.begin(); i
61        != mainlist.serverlist.end(); ++i ) 
62    {
63      /* WORK MARK */
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      { COUT(2) << "Masterserver.cc: Memory allocation failed.\n";
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    /* send 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    enet_peer_send( event->peer, 0, reply );
96
97    /* One could just use enet_host_service() instead. */
98    enet_host_flush( this->server );
99  }
100
101
102
103
[7590]104  /***** EVENTS *****/
105  /* connect event */
106  int 
[7611]107  MasterServer::eventConnect( ENetEvent *event )
[7590]108  { /* check for bad parameters */
109    if( !event )
[7611]110    { COUT(2) << "MasterServer::eventConnect: No event given.\n" ;
[7590]111      return -1;
112    }
[7565]113
[7611]114    /* convert address to string. */
115    char *addrconv = (char *) calloc( 50, 1 );
116    enet_address_get_host_ip( &(event->peer->address), addrconv, 49 );
117
[7590]118    /* output debug info */
[7611]119    COUT(4) << "A new client connected from " 
120      << addrconv
121      << " on port " 
122      << event->peer->address.port << "\n";
[7565]123
[7611]124    /* store string form of address here */
125    event->peer->data = addrconv; 
126
127    /* all fine. */
[7590]128    return 0;
[7565]129  }
130
[7590]131  /* disconnect event */
132  int 
[7611]133  MasterServer::eventDisconnect( ENetEvent *event )
[7590]134  { /* check for bad parameters */
135    if( !event )
[7611]136    { COUT(2) << "No event given.\n";
[7590]137      return -1;
138    }
[7565]139
[7651]140    /* output that the disconnect happened */
[7611]141    COUT(4) << (char*)event->peer->data << " disconnected.\n";
[7565]142
[7651]143    /* create string from peer data */
144    std::string name = std::string( (char*)event->peer->data );
145
[7590]146    /* remove the server from the list it belongs to */
[7657]147    this->mainlist.delServerByName( name );
[7565]148
[7590]149    /* Reset the peer's client information. */
[7611]150    if( event->peer->data ) free( event->peer->data );
[7651]151
152    /* done */
[7590]153    return 0;
[7565]154  }
155
[7590]156  /* data event */
157  int 
[7611]158  MasterServer::eventData( ENetEvent *event )
[7651]159  { /* validate packet */
[7611]160    if( !event || !(event->packet) || !(event->peer) )
[7651]161      //|| !(event->packet->data) || !strlen(event->packet->data) )
[7611]162    { COUT(2) << "No complete event given.\n";
[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
[7611]170    /* DEBUG */
[7590]171    /* output debug info about the data that has come, to be removed */
[7684]172    helper_output_debug( event, addrconv );
[7590]173
[7630]174    /* GAME SERVER OR CLIENT CONNECTION? */
[7651]175    if( !strncmp( (char *)event->packet->data, MSPROTO_GAME_SERVER, 
176      MSPROTO_GAME_SERVER_LEN ) )
177    { /* Game server */
[7630]178
[7651]179      if( !strncmp( (char *)event->packet->data
180        + MSPROTO_GAME_SERVER_LEN+1, 
181        MSPROTO_REGISTER_SERVER, MSPROTO_REGISTER_SERVER_LEN ) )
182      { /* register new server */
[7657]183        mainlist.addServer( packet::ServerInformation( event ) );
[7658]184       
185        /* tell people we did so */
186        COUT(2) << "Added new server to list: " << 
187          packet::ServerInformation( event ).getServerIP() << "\n";
[7651]188      }
189    }
190    else if( !strncmp( (char *)event->packet->data, MSPROTO_CLIENT, 
191      MSPROTO_CLIENT_LEN) )
192    { /* client */
193      if( !strncmp( (char *)event->packet->data + MSPROTO_CLIENT_LEN+1,
[7657]194        MSPROTO_REQ_LIST, MSPROTO_REQ_LIST_LEN ) )
[7684]195        /* send server list */
196        helper_sendlist( event );
[7651]197    }
198    else
199    { /* bad message, don't do anything. */ } 
200
[7611]201    /* delete addrconv */
202    if( addrconv ) free( addrconv );
203
[7590]204    /* Clean up the packet now that we're done using it. */
205    enet_packet_destroy( event->packet );
206    return 0;
207  }
[7565]208
[7611]209
[7590]210  /**** MAIN ROUTINE *****/
211  int 
212  MasterServer::run()
213  {
214    /***** ENTER MAIN LOOP *****/
215    ENetEvent *event = (ENetEvent *)calloc(sizeof(ENetEvent), sizeof(char));
216    if( event == NULL )
[7611]217    { 
218      COUT(1) << "Could not create ENetEvent structure, exiting.\n";
[7590]219      exit( EXIT_FAILURE );
220    }
[7565]221
[7611]222    /* tell people we're now initialized and blocking. */
223    COUT(0) << "MasterServer initialized, waiting for connections.\n";
[7729]224   
225    /* endless loop until we quit */
226    while( this->quit == false )
227    {
228      /* create an iterator for the loop */
229      while( enet_host_service( this->server, event, 1000 ) >= 0 )
230      { /* check what type of event it is and react accordingly */
231        switch (event->type)
232        { /* new connection */
233          case ENET_EVENT_TYPE_CONNECT: 
234            eventConnect( event ); break;
[7611]235
[7729]236            /* disconnect */
237          case ENET_EVENT_TYPE_DISCONNECT: 
238            eventDisconnect( event ); break;
[7565]239
[7729]240            /* incoming data */
241          case ENET_EVENT_TYPE_RECEIVE: eventData( event ); break;
242          default: break;
243        }
[7590]244      }
245    }
[7565]246
[7590]247    /* done */
248    return 0;
249  } 
[7565]250
[7590]251  /* constructor */
252  MasterServer::MasterServer()
253  {
254    /***** INITIALIZE NETWORKING *****/
255    if( enet_initialize () != 0)
[7611]256    { COUT(1) << "An error occurred while initializing ENet.\n";
[7590]257      exit( EXIT_FAILURE );
258    }
[7565]259
[7590]260    /* register deinitialization */
261    atexit( enet_deinitialize );
[7565]262
[7729]263    /* set the quit flag to false */
264    this->quit = false;
265
[7590]266    /* Bind the server to the default localhost and port ORX_MSERVER_PORT */
267    this->address.host = ENET_HOST_ANY;
268    this->address.port = ORX_MSERVER_PORT;
[7589]269
[7590]270    /* create a host with the above settings (the last two 0 mean: accept
271     * any input/output bandwidth */
272    this->server = enet_host_create( &this->address, ORX_MSERVER_MAXCONNS, 
273        ORX_MSERVER_MAXCHANS, 0, 0 );     
274
275    /* see if creation worked */
276    if( !this->server )
[7611]277    { COUT(1) << 
278        "An error occurred while trying to create an ENet server host.\n";
279      exit( EXIT_FAILURE );
[7590]280    }
[7565]281
[7611]282    /***** INITIALIZE GAME SERVER AND PEER LISTS *****/
[7657]283    //this->mainlist = new ServerList();
[7611]284    this->peers = new PeerList();
[7565]285  }
286
[7590]287  /* destructor */
288  MasterServer::~MasterServer()
289  {
290    /***** CLEANUP PROCESS *****/
291    /* terminate all networking connections */
292    enet_host_destroy( this->server );
[7565]293
[7611]294    /* free all used memory */
[7590]295    /* clear the list of connected game servers */
296    /* clear the list of connected game clients */
[7565]297
[7590]298  }
299
300/* end of namespace */
301}
Note: See TracBrowser for help on using the repository browser.