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