Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/masterserver/src/modules/masterserver/MasterServer.cc @ 7684

Last change on this file since 7684 was 7684, checked in by smerkli, 13 years ago

further testing.

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