| [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" | 
|---|
| [8937] | 31 | #include "core/command/ConsoleCommand.h" | 
|---|
| [7590] | 32 | #include "core/CoreIncludes.h" | 
|---|
|  | 33 | #include "core/CorePrereqs.h" | 
|---|
| [8937] | 34 | #include "util/Output.h" | 
|---|
| [7565] | 35 |  | 
|---|
| [7590] | 36 | namespace orxonox | 
|---|
|  | 37 | { | 
|---|
| [8937] | 38 | /*** MACROS ***/ | 
|---|
|  | 39 | /* commands for the terminal interface */ | 
|---|
|  | 40 | SetConsoleCommand( "ms-listservers", &MasterServer::listServers ); | 
|---|
|  | 41 | SetConsoleCommand( "ms-delserver", &MasterServer::delServer ); | 
|---|
|  | 42 | //SetConsoleCommand( "ms-serverinfo", &MasterServer::serverInfo ); | 
|---|
|  | 43 |  | 
|---|
|  | 44 | /* forward declaration so the linker doesn't complain */ | 
|---|
|  | 45 | MasterServer *MasterServer::instance = NULL; | 
|---|
|  | 46 |  | 
|---|
|  | 47 |  | 
|---|
|  | 48 |  | 
|---|
|  | 49 |  | 
|---|
|  | 50 | /* command: list servers */ | 
|---|
|  | 51 | void | 
|---|
|  | 52 | MasterServer::listServers( void ) | 
|---|
|  | 53 | { | 
|---|
|  | 54 | /* get an iterator */ | 
|---|
|  | 55 | std::list<ServerListElem>::iterator i; | 
|---|
|  | 56 |  | 
|---|
|  | 57 | /* print list header */ | 
|---|
|  | 58 | orxout(user_info) << "List of connected servers" << std::endl; | 
|---|
|  | 59 |  | 
|---|
|  | 60 | /* loop through list elements */ | 
|---|
|  | 61 | for( i = MasterServer::getInstance()->mainlist.serverlist.begin(); | 
|---|
|  | 62 | i != MasterServer::getInstance()->mainlist.serverlist.end(); ++i ) | 
|---|
|  | 63 | { | 
|---|
|  | 64 | orxout(user_info) << "  " << (*i).ServerInfo.getServerIP() << std::endl; | 
|---|
|  | 65 | } | 
|---|
|  | 66 |  | 
|---|
|  | 67 | /* display end of list */ | 
|---|
|  | 68 | orxout(user_info) << MasterServer::getInstance()->mainlist.serverlist.size() << | 
|---|
|  | 69 | " servers connected." << std::endl; | 
|---|
|  | 70 | } | 
|---|
|  | 71 |  | 
|---|
|  | 72 | void | 
|---|
|  | 73 | MasterServer::delServer( std::string todeladdr ) | 
|---|
|  | 74 | { | 
|---|
|  | 75 | /* tell the user we're now removing the entry from the server list */ | 
|---|
|  | 76 | orxout(user_info) << "MS: Deleting server \"" << todeladdr << "\"..." | 
|---|
|  | 77 | << std::endl; | 
|---|
|  | 78 |  | 
|---|
|  | 79 | /* see if we actually have that server on our list */ | 
|---|
|  | 80 | ServerListSearchResult shandle = | 
|---|
|  | 81 | MasterServer::getInstance()->mainlist.findServerByAddress(todeladdr); | 
|---|
|  | 82 |  | 
|---|
|  | 83 | if( !shandle.success ) | 
|---|
|  | 84 | { orxout(user_info) << "MS: Server not found, not removing." << std::endl; | 
|---|
|  | 85 | return; | 
|---|
|  | 86 | } | 
|---|
|  | 87 |  | 
|---|
|  | 88 | /* force-disconnect the server */ | 
|---|
| [8952] | 89 | enet_peer_disconnect( shandle.result.peer, 0 ); | 
|---|
| [8937] | 90 |  | 
|---|
|  | 91 | /* actually remove the entry from the server list by address */ | 
|---|
|  | 92 | MasterServer::getInstance()->mainlist.delServerByAddress( todeladdr); | 
|---|
|  | 93 |  | 
|---|
|  | 94 | /* tell the user about our success */ | 
|---|
|  | 95 | orxout(user_info) << "MS: Server deletion successful." << std::endl; | 
|---|
|  | 96 | } | 
|---|
|  | 97 |  | 
|---|
|  | 98 |  | 
|---|
| [7684] | 99 | /* helpers */ | 
|---|
|  | 100 | static void | 
|---|
|  | 101 | helper_output_debug( ENetEvent *event, char *addrconv ) | 
|---|
|  | 102 | { | 
|---|
| [8858] | 103 | orxout(verbose, context::master_server) | 
|---|
|  | 104 | << "A packet of length" | 
|---|
| [7684] | 105 | << event->packet->dataLength | 
|---|
|  | 106 | << " containing " | 
|---|
|  | 107 | << (const char*)event->packet->data | 
|---|
|  | 108 | << " was received from " | 
|---|
|  | 109 | << addrconv | 
|---|
|  | 110 | << " on channel " | 
|---|
| [8858] | 111 | << event->channelID << endl; | 
|---|
| [7684] | 112 | } | 
|---|
|  | 113 |  | 
|---|
|  | 114 | void | 
|---|
|  | 115 | MasterServer::helper_sendlist( ENetEvent *event ) | 
|---|
|  | 116 | { | 
|---|
|  | 117 | /* get an iterator */ | 
|---|
| [8937] | 118 | std::list<ServerListElem>::iterator i; | 
|---|
| [7684] | 119 |  | 
|---|
|  | 120 | /* packet holder */ | 
|---|
|  | 121 | ENetPacket *reply; | 
|---|
|  | 122 |  | 
|---|
|  | 123 | /* loop through list elements */ | 
|---|
|  | 124 | for( i = mainlist.serverlist.begin(); i | 
|---|
|  | 125 | != mainlist.serverlist.end(); ++i ) | 
|---|
|  | 126 | { | 
|---|
|  | 127 | /* send this particular server */ | 
|---|
|  | 128 | /* build reply string */ | 
|---|
| [8937] | 129 | char *tosend = (char *)calloc( (*i).ServerInfo.getServerIP().length() | 
|---|
| [7684] | 130 | + MSPROTO_SERVERLIST_ITEM_LEN + 2,1 ); | 
|---|
|  | 131 | if( !tosend ) | 
|---|
| [8858] | 132 | { orxout(internal_warning, context::master_server) << "Masterserver.cc: Memory allocation failed." << endl; | 
|---|
| [7684] | 133 | continue; | 
|---|
|  | 134 | } | 
|---|
|  | 135 | sprintf( tosend, "%s %s", MSPROTO_SERVERLIST_ITEM, | 
|---|
| [8937] | 136 | (*i).ServerInfo.getServerIP().c_str() ); | 
|---|
| [7684] | 137 |  | 
|---|
|  | 138 | /* create packet from it */ | 
|---|
|  | 139 | reply = enet_packet_create( tosend, | 
|---|
|  | 140 | strlen( tosend ) + 1, | 
|---|
|  | 141 | ENET_PACKET_FLAG_RELIABLE); | 
|---|
|  | 142 |  | 
|---|
|  | 143 | /* Send the reply to the peer over channel id 0. */ | 
|---|
|  | 144 | enet_peer_send( event->peer, 0, reply ); | 
|---|
|  | 145 |  | 
|---|
|  | 146 | /* One could just use enet_host_service() instead. */ | 
|---|
|  | 147 | enet_host_flush( this->server ); | 
|---|
|  | 148 |  | 
|---|
|  | 149 | /* free the tosend buffer */ | 
|---|
|  | 150 | free( tosend ); | 
|---|
|  | 151 | } | 
|---|
|  | 152 |  | 
|---|
| [7750] | 153 | /* create end-of-list packet */ | 
|---|
| [7684] | 154 | reply = enet_packet_create( MSPROTO_SERVERLIST_END, | 
|---|
|  | 155 | MSPROTO_SERVERLIST_END_LEN + 1, | 
|---|
|  | 156 | ENET_PACKET_FLAG_RELIABLE ); | 
|---|
|  | 157 |  | 
|---|
| [7750] | 158 | /* send end-of-list packet */ | 
|---|
| [7684] | 159 | enet_peer_send( event->peer, 0, reply ); | 
|---|
|  | 160 |  | 
|---|
|  | 161 | /* One could just use enet_host_service() instead. */ | 
|---|
|  | 162 | enet_host_flush( this->server ); | 
|---|
|  | 163 | } | 
|---|
|  | 164 |  | 
|---|
| [8937] | 165 | /* maybe the two methods below can be merged into one and | 
|---|
|  | 166 | * made to use ENet's RTT functionality to check for disconnected | 
|---|
|  | 167 | * servers. | 
|---|
|  | 168 | */ | 
|---|
|  | 169 | void | 
|---|
|  | 170 | MasterServer::helper_cleanupServers( void ) | 
|---|
|  | 171 | { | 
|---|
|  | 172 | /* get an iterator */ | 
|---|
|  | 173 | std::list<ServerListElem>::iterator i; | 
|---|
|  | 174 |  | 
|---|
|  | 175 | if( mainlist.serverlist.size() == 0 ) | 
|---|
|  | 176 | return; | 
|---|
| [7684] | 177 |  | 
|---|
| [8937] | 178 | /* loop through list elements */ | 
|---|
|  | 179 | for( i = mainlist.serverlist.begin(); i | 
|---|
|  | 180 | != mainlist.serverlist.end(); ++i ) | 
|---|
|  | 181 | { /* see if we have a disconnected peer */ | 
|---|
|  | 182 | if( (*i).peer && | 
|---|
|  | 183 | ((*i).peer->state == ENET_PEER_STATE_DISCONNECTED || | 
|---|
|  | 184 | (*i).peer->state == ENET_PEER_STATE_ZOMBIE )) | 
|---|
|  | 185 | { | 
|---|
|  | 186 | /* Remove it from the list */ | 
|---|
|  | 187 | orxout(internal_warning) << (char*)(*i).peer->data << " timed out.\n"; | 
|---|
|  | 188 | mainlist.delServerByName( (*i).ServerInfo.getServerName() ); | 
|---|
| [7684] | 189 |  | 
|---|
| [8937] | 190 | /* stop iterating, we manipulated the list */ | 
|---|
|  | 191 | /* TODO note: this only removes one dead server per loop | 
|---|
|  | 192 | * iteration. not beautiful, but one iteration is ~100ms, | 
|---|
|  | 193 | * so not really relevant for the moment. | 
|---|
|  | 194 | */ | 
|---|
|  | 195 | break; | 
|---|
|  | 196 | } | 
|---|
|  | 197 | } | 
|---|
|  | 198 |  | 
|---|
|  | 199 | } | 
|---|
| [7684] | 200 |  | 
|---|
| [8937] | 201 |  | 
|---|
|  | 202 |  | 
|---|
|  | 203 |  | 
|---|
| [7590] | 204 | /***** EVENTS *****/ | 
|---|
|  | 205 | /* connect event */ | 
|---|
|  | 206 | int | 
|---|
| [7611] | 207 | MasterServer::eventConnect( ENetEvent *event ) | 
|---|
| [7590] | 208 | { /* check for bad parameters */ | 
|---|
|  | 209 | if( !event ) | 
|---|
| [8858] | 210 | { orxout(internal_warning, context::master_server) << "MasterServer::eventConnect: No event given." << endl; | 
|---|
| [7590] | 211 | return -1; | 
|---|
|  | 212 | } | 
|---|
| [7565] | 213 |  | 
|---|
| [7611] | 214 | /* convert address to string. */ | 
|---|
|  | 215 | char *addrconv = (char *) calloc( 50, 1 ); | 
|---|
|  | 216 | enet_address_get_host_ip( &(event->peer->address), addrconv, 49 ); | 
|---|
|  | 217 |  | 
|---|
| [7590] | 218 | /* output debug info */ | 
|---|
| [8858] | 219 | orxout(verbose, context::master_server) << "A new client connected from " | 
|---|
| [7611] | 220 | << addrconv | 
|---|
|  | 221 | << " on port " | 
|---|
| [8858] | 222 | << event->peer->address.port << endl; | 
|---|
| [7565] | 223 |  | 
|---|
| [7611] | 224 | /* store string form of address here */ | 
|---|
|  | 225 | event->peer->data = addrconv; | 
|---|
|  | 226 |  | 
|---|
|  | 227 | /* all fine. */ | 
|---|
| [7590] | 228 | return 0; | 
|---|
| [7565] | 229 | } | 
|---|
|  | 230 |  | 
|---|
| [7590] | 231 | /* disconnect event */ | 
|---|
|  | 232 | int | 
|---|
| [7611] | 233 | MasterServer::eventDisconnect( ENetEvent *event ) | 
|---|
| [7590] | 234 | { /* check for bad parameters */ | 
|---|
|  | 235 | if( !event ) | 
|---|
| [8858] | 236 | { orxout(internal_warning, context::master_server) << "No event given." << endl; | 
|---|
| [7590] | 237 | return -1; | 
|---|
|  | 238 | } | 
|---|
| [7565] | 239 |  | 
|---|
| [7651] | 240 | /* output that the disconnect happened */ | 
|---|
| [8858] | 241 | orxout(verbose, context::master_server) << (char*)event->peer->data << " disconnected." << endl; | 
|---|
| [7565] | 242 |  | 
|---|
| [7651] | 243 | /* create string from peer data */ | 
|---|
|  | 244 | std::string name = std::string( (char*)event->peer->data ); | 
|---|
|  | 245 |  | 
|---|
| [7590] | 246 | /* remove the server from the list it belongs to */ | 
|---|
| [7657] | 247 | this->mainlist.delServerByName( name ); | 
|---|
| [7565] | 248 |  | 
|---|
| [7590] | 249 | /* Reset the peer's client information. */ | 
|---|
| [7611] | 250 | if( event->peer->data ) free( event->peer->data ); | 
|---|
| [7651] | 251 |  | 
|---|
|  | 252 | /* done */ | 
|---|
| [7590] | 253 | return 0; | 
|---|
| [7565] | 254 | } | 
|---|
|  | 255 |  | 
|---|
| [7590] | 256 | /* data event */ | 
|---|
|  | 257 | int | 
|---|
| [7611] | 258 | MasterServer::eventData( ENetEvent *event ) | 
|---|
| [7651] | 259 | { /* validate packet */ | 
|---|
| [7611] | 260 | if( !event || !(event->packet) || !(event->peer) ) | 
|---|
| [8858] | 261 | { orxout(internal_warning, context::master_server) << "No complete event given." << endl; | 
|---|
| [7590] | 262 | return -1; | 
|---|
|  | 263 | } | 
|---|
| [7611] | 264 |  | 
|---|
|  | 265 | /* generate address in readable form */ | 
|---|
|  | 266 | char *addrconv = (char *) calloc( 50, 1 ); | 
|---|
|  | 267 | enet_address_get_host_ip( &(event->peer->address), addrconv, 49 ); | 
|---|
| [7590] | 268 |  | 
|---|
| [7750] | 269 | /* output debug info about the data that has come */ | 
|---|
| [7684] | 270 | helper_output_debug( event, addrconv ); | 
|---|
| [7590] | 271 |  | 
|---|
| [7630] | 272 | /* GAME SERVER OR CLIENT CONNECTION? */ | 
|---|
| [7651] | 273 | if( !strncmp( (char *)event->packet->data, MSPROTO_GAME_SERVER, | 
|---|
|  | 274 | MSPROTO_GAME_SERVER_LEN ) ) | 
|---|
|  | 275 | { /* Game server */ | 
|---|
| [7630] | 276 |  | 
|---|
| [7651] | 277 | if( !strncmp( (char *)event->packet->data | 
|---|
|  | 278 | + MSPROTO_GAME_SERVER_LEN+1, | 
|---|
|  | 279 | MSPROTO_REGISTER_SERVER, MSPROTO_REGISTER_SERVER_LEN ) ) | 
|---|
|  | 280 | { /* register new server */ | 
|---|
| [8937] | 281 | mainlist.addServer( packet::ServerInformation( event ), | 
|---|
|  | 282 | event->peer ); | 
|---|
| [7658] | 283 |  | 
|---|
|  | 284 | /* tell people we did so */ | 
|---|
| [8858] | 285 | orxout(internal_info, context::master_server) << "Added new server to list: " << | 
|---|
|  | 286 | packet::ServerInformation( event ).getServerIP() << endl; | 
|---|
| [7651] | 287 | } | 
|---|
| [7756] | 288 |  | 
|---|
| [7763] | 289 | else if( !strncmp( (char *)event->packet->data | 
|---|
|  | 290 | + MSPROTO_GAME_SERVER_LEN+1, | 
|---|
|  | 291 | MSPROTO_SERVERDC, MSPROTO_SERVERDC_LEN ) ) | 
|---|
|  | 292 | { | 
|---|
|  | 293 | /* create string from peer data */ | 
|---|
|  | 294 | std::string name = std::string( addrconv ); | 
|---|
|  | 295 |  | 
|---|
|  | 296 | /* remove the server from the list it belongs to */ | 
|---|
| [7765] | 297 | this->mainlist.delServerByAddress( name ); | 
|---|
| [7763] | 298 |  | 
|---|
|  | 299 | /* tell the user */ | 
|---|
| [8858] | 300 | orxout(internal_info, context::master_server) << "Removed server " << name << " from list." << endl; | 
|---|
| [7763] | 301 | } | 
|---|
|  | 302 |  | 
|---|
| [7756] | 303 | /* TODO add hook for disconnect here */ | 
|---|
| [7651] | 304 | } | 
|---|
|  | 305 | else if( !strncmp( (char *)event->packet->data, MSPROTO_CLIENT, | 
|---|
|  | 306 | MSPROTO_CLIENT_LEN) ) | 
|---|
|  | 307 | { /* client */ | 
|---|
|  | 308 | if( !strncmp( (char *)event->packet->data + MSPROTO_CLIENT_LEN+1, | 
|---|
| [7657] | 309 | MSPROTO_REQ_LIST, MSPROTO_REQ_LIST_LEN ) ) | 
|---|
| [7684] | 310 | /* send server list */ | 
|---|
|  | 311 | helper_sendlist( event ); | 
|---|
| [7651] | 312 | } | 
|---|
|  | 313 | else | 
|---|
|  | 314 | { /* bad message, don't do anything. */ } | 
|---|
|  | 315 |  | 
|---|
| [7611] | 316 | /* delete addrconv */ | 
|---|
|  | 317 | if( addrconv ) free( addrconv ); | 
|---|
|  | 318 |  | 
|---|
| [7590] | 319 | /* Clean up the packet now that we're done using it. */ | 
|---|
|  | 320 | enet_packet_destroy( event->packet ); | 
|---|
|  | 321 | return 0; | 
|---|
|  | 322 | } | 
|---|
| [7565] | 323 |  | 
|---|
| [7611] | 324 |  | 
|---|
| [7590] | 325 | /**** MAIN ROUTINE *****/ | 
|---|
|  | 326 | int | 
|---|
|  | 327 | MasterServer::run() | 
|---|
|  | 328 | { | 
|---|
|  | 329 | /***** ENTER MAIN LOOP *****/ | 
|---|
|  | 330 | ENetEvent *event = (ENetEvent *)calloc(sizeof(ENetEvent), sizeof(char)); | 
|---|
|  | 331 | if( event == NULL ) | 
|---|
| [7611] | 332 | { | 
|---|
| [8858] | 333 | orxout(user_error, context::master_server) << "Could not create ENetEvent structure, exiting." << endl; | 
|---|
| [7590] | 334 | exit( EXIT_FAILURE ); | 
|---|
|  | 335 | } | 
|---|
| [7565] | 336 |  | 
|---|
| [8937] | 337 | /* check for timed out peers and remove those from * the server list */ | 
|---|
|  | 338 | helper_cleanupServers(); | 
|---|
|  | 339 |  | 
|---|
|  | 340 |  | 
|---|
| [7743] | 341 | /* create an iterator for the loop */ | 
|---|
|  | 342 | enet_host_service( this->server, event, 100 ); | 
|---|
| [7611] | 343 |  | 
|---|
| [7743] | 344 | /* check what type of event it is and react accordingly */ | 
|---|
|  | 345 | switch (event->type) | 
|---|
|  | 346 | { /* new connection */ | 
|---|
|  | 347 | case ENET_EVENT_TYPE_CONNECT: | 
|---|
|  | 348 | eventConnect( event ); break; | 
|---|
| [7565] | 349 |  | 
|---|
| [7743] | 350 | /* disconnect */ | 
|---|
|  | 351 | case ENET_EVENT_TYPE_DISCONNECT: | 
|---|
|  | 352 | eventDisconnect( event ); break; | 
|---|
|  | 353 |  | 
|---|
|  | 354 | /* incoming data */ | 
|---|
|  | 355 | case ENET_EVENT_TYPE_RECEIVE: eventData( event ); break; | 
|---|
|  | 356 | default: break; | 
|---|
| [7590] | 357 | } | 
|---|
| [7565] | 358 |  | 
|---|
| [7590] | 359 | /* done */ | 
|---|
|  | 360 | return 0; | 
|---|
|  | 361 | } | 
|---|
| [7565] | 362 |  | 
|---|
| [7590] | 363 | /* constructor */ | 
|---|
|  | 364 | MasterServer::MasterServer() | 
|---|
|  | 365 | { | 
|---|
|  | 366 | /***** INITIALIZE NETWORKING *****/ | 
|---|
|  | 367 | if( enet_initialize () != 0) | 
|---|
| [8858] | 368 | { orxout(user_error, context::master_server) << "An error occurred while initializing ENet." << endl; | 
|---|
| [7590] | 369 | exit( EXIT_FAILURE ); | 
|---|
|  | 370 | } | 
|---|
| [7565] | 371 |  | 
|---|
| [7590] | 372 | /* register deinitialization */ | 
|---|
|  | 373 | atexit( enet_deinitialize ); | 
|---|
| [7565] | 374 |  | 
|---|
| [7729] | 375 | /* set the quit flag to false */ | 
|---|
|  | 376 | this->quit = false; | 
|---|
|  | 377 |  | 
|---|
| [7590] | 378 | /* Bind the server to the default localhost and port ORX_MSERVER_PORT */ | 
|---|
|  | 379 | this->address.host = ENET_HOST_ANY; | 
|---|
|  | 380 | this->address.port = ORX_MSERVER_PORT; | 
|---|
| [7589] | 381 |  | 
|---|
| [7590] | 382 | /* create a host with the above settings (the last two 0 mean: accept | 
|---|
|  | 383 | * any input/output bandwidth */ | 
|---|
|  | 384 | this->server = enet_host_create( &this->address, ORX_MSERVER_MAXCONNS, | 
|---|
| [7801] | 385 | ORX_MSERVER_MAXCHANS, 0, 0 ); | 
|---|
|  | 386 | assert(this->server); | 
|---|
| [7590] | 387 |  | 
|---|
|  | 388 | /* see if creation worked */ | 
|---|
|  | 389 | if( !this->server ) | 
|---|
| [8858] | 390 | { orxout(user_error, context::master_server) << | 
|---|
|  | 391 | "An error occurred while trying to create an ENet server host." << endl; | 
|---|
| [7611] | 392 | exit( EXIT_FAILURE ); | 
|---|
| [7590] | 393 | } | 
|---|
| [7565] | 394 |  | 
|---|
| [8937] | 395 | /* set pointer to this instance */ | 
|---|
|  | 396 | MasterServer::setInstance( this ); | 
|---|
| [7743] | 397 |  | 
|---|
|  | 398 | /* tell people we're now initialized */ | 
|---|
| [8858] | 399 | orxout(internal_status, context::master_server) << "MasterServer initialized, waiting for connections." << endl; | 
|---|
| [7565] | 400 | } | 
|---|
|  | 401 |  | 
|---|
| [7590] | 402 | /* destructor */ | 
|---|
|  | 403 | MasterServer::~MasterServer() | 
|---|
|  | 404 | { | 
|---|
|  | 405 | /***** CLEANUP PROCESS *****/ | 
|---|
|  | 406 | /* terminate all networking connections */ | 
|---|
|  | 407 | enet_host_destroy( this->server ); | 
|---|
| [7565] | 408 |  | 
|---|
| [7611] | 409 | /* free all used memory */ | 
|---|
| [7590] | 410 | /* clear the list of connected game servers */ | 
|---|
|  | 411 | /* clear the list of connected game clients */ | 
|---|
|  | 412 | } | 
|---|
|  | 413 |  | 
|---|
|  | 414 | /* end of namespace */ | 
|---|
|  | 415 | } | 
|---|