· 8 years ago · Mar 30, 2018, 01:56 PM
1//
2// SuperTuxKart - a fun racing game with go-kart
3// Copyright (C) 2013-2015 SuperTuxKart-Team
4//
5// This program is free software; you can redistribute it and/or
6// modify it under the terms of the GNU General Public License
7// as published by the Free Software Foundation; either version 3
8// of the License, or (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program; if not, write to the Free Software
17// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19#include "network/protocols/server_lobby.hpp"
20
21#include "config/user_config.hpp"
22#include "karts/kart_properties_manager.hpp"
23#include "modes/world.hpp"
24#include "network/event.hpp"
25#include "network/game_setup.hpp"
26#include "network/network_config.hpp"
27#include "network/network_player_profile.hpp"
28#include "network/protocols/connect_to_peer.hpp"
29#include "network/protocol_manager.hpp"
30#include "network/race_event_manager.hpp"
31#include "network/stk_host.hpp"
32#include "network/stk_peer.hpp"
33#include "online/online_profile.hpp"
34#include "online/request_manager.hpp"
35#include "race/race_manager.hpp"
36#include "states_screens/networking_lobby.hpp"
37#include "states_screens/race_result_gui.hpp"
38#include "tracks/track_manager.hpp"
39#include "utils/log.hpp"
40#include "utils/random_generator.hpp"
41#include "utils/time.hpp"
42
43#include <algorithm>
44#include <iterator>
45#include <fstream>
46
47/** This is the central game setup protocol running in the server. It is
48 * mostly a finite state machine. Note that all nodes in ellipses and light
49 * grey background are actual states; nodes in boxes and white background
50 * are functions triggered from a state or triggering potentially a state
51 * change.
52 \dot
53 digraph interaction {
54 node [shape=box]; "Server Constructor"; "playerTrackVote"; "connectionRequested";
55 "signalRaceStartToClients"; "startedRaceOnClient"; "loadWorld";
56 node [shape=ellipse,style=filled,color=lightgrey];
57
58 "Server Constructor" -> "INIT_WAN" [label="If WAN game"]
59 "Server Constructor" -> "ACCEPTING_CLIENTS" [label="If LAN game"]
60 "INIT_WAN" -> "GETTING_PUBLIC_ADDRESS" [label="GetPublicAddress protocol callback"]
61 "GETTING_PUBLIC_ADDRESS" -> "ACCEPTING_CLIENTS" [label="Register server"]
62 "ACCEPTING_CLIENTS" -> "connectionRequested" [label="Client connection request"]
63 "connectionRequested" -> "ACCEPTING_CLIENTS"
64 "ACCEPTING_CLIENTS" -> "SELECTING" [label="Start race from authorised client"]
65 "SELECTING" -> "SELECTING" [label="Client selects kart, #laps, ..."]
66 "SELECTING" -> "playerTrackVote" [label="Client selected track"]
67 "playerTrackVote" -> "SELECTING" [label="Not all clients have selected"]
68 "playerTrackVote" -> "LOAD_WORLD" [label="All clients have selected; signal load_world to clients"]
69 "LOAD_WORLD" -> "loadWorld"
70 "loadWorld" -> "WAIT_FOR_WORLD_LOADED"
71 "WAIT_FOR_WORLD_LOADED" -> "WAIT_FOR_WORLD_LOADED" [label="Client or server loaded world"]
72 "WAIT_FOR_WORLD_LOADED" -> "signalRaceStartToClients" [label="All clients and server ready"]
73 "signalRaceStartToClients" -> "WAIT_FOR_RACE_STARTED"
74 "WAIT_FOR_RACE_STARTED" -> "startedRaceOnClient" [label="Client has started race"]
75 "startedRaceOnClient" -> "WAIT_FOR_RACE_STARTED" [label="Not all clients have started"]
76 "startedRaceOnClient" -> "DELAY_SERVER" [label="All clients have started"]
77 "DELAY_SERVER" -> "DELAY_SERVER" [label="Not done waiting"]
78 "DELAY_SERVER" -> "RACING" [label="Server starts race now"]
79 }
80 \enddot
81
82
83 * It starts with detecting the public ip address and port of this
84 * host (GetPublicAddress).
85 */
86ServerLobby::ServerLobby() : LobbyProtocol(NULL)
87{
88 m_has_created_server_id_file = false;
89 setHandleDisconnections(true);
90 m_state = SET_PUBLIC_ADDRESS;
91 updateBanList();
92} // ServerLobby
93
94//-----------------------------------------------------------------------------
95/** Destructor.
96 */
97ServerLobby::~ServerLobby()
98{
99 if (m_server_registered && NetworkConfig::get()->isWAN())
100 {
101 unregisterServer();
102 }
103} // ~ServerLobby
104
105//-----------------------------------------------------------------------------
106void ServerLobby::setup()
107{
108 LobbyProtocol::setup();
109 // We use maximum 16bit unsigned limit
110 auto all_k = kart_properties_manager->getAllAvailableKarts();
111 auto all_t = track_manager->getAllTrackIdentifiers();
112 if (all_k.size() >= 65536)
113 all_k.resize(65535);
114 if (all_t.size() >= 65536)
115 all_t.resize(65535);
116 m_available_kts.first = { all_k.begin(), all_k.end() };
117 m_available_kts.second = { all_t.begin(), all_t.end() };
118
119 m_server_registered = false;
120 m_game_setup->setNumLocalPlayers(0); // no local players on a server
121
122 // Initialise the data structures to detect if all clients and
123 // the server are ready:
124 m_server_has_loaded_world.store(false);
125 m_peers_ready.clear();
126 m_peers_votes.clear();
127 m_server_delay = 0.0;
128 Log::info("ServerLobby", "Reset server to initial state.");
129} // setup
130
131//-----------------------------------------------------------------------------
132bool ServerLobby::notifyEvent(Event* event)
133{
134 assert(m_game_setup); // assert that the setup exists
135 if (event->getType() != EVENT_TYPE_MESSAGE)
136 return false;
137
138 NetworkString &data = event->data();
139 assert(data.size()); // message not empty
140 uint8_t message_type;
141 message_type = data.getUInt8();
142 Log::info("ServerLobby", "Synchronous message received with type %d.",
143 message_type);
144 switch (message_type)
145 {
146 case LE_REQUEST_BEGIN: startSelection(event); break;
147 default: Log::error("ServerLobby", "Unknown message type %d - ignored.",
148 message_type);
149 break;
150 } // switch message_type
151 return true;
152} // notifyEvent
153
154//-----------------------------------------------------------------------------
155void ServerLobby::handleChat(Event* event)
156{
157 if (!event->getPeer()->hasPlayerProfiles())
158 {
159 Log::warn("ServerLobby", "Unauthorized peer wants to chat.");
160 return;
161 }
162 core::stringw message;
163 event->data().decodeStringW(&message);
164 if (message.size() > 0)
165 {
166 NetworkString* chat = getNetworkString();
167 chat->setSynchronous(true);
168 chat->addUInt8(LE_CHAT).encodeString(message);
169 sendMessageToPeersChangingToken(chat, /*reliable*/true);
170 delete chat;
171 }
172} // handleChat
173
174//-----------------------------------------------------------------------------
175void ServerLobby::kickHost(Event* event)
176{
177 std::unique_lock<std::mutex> lock(m_connection_mutex);
178 if (m_server_owner.lock() != event->getPeerSP())
179 return;
180 lock.unlock();
181 if (!checkDataSize(event, 4)) return;
182 NetworkString& data = event->data();
183 uint32_t host_id = data.getUInt32();
184 std::shared_ptr<STKPeer> peer = STKHost::get()->findPeerByHostId(host_id);
185 if (peer)
186 peer->kick();
187} // kickHost
188
189//-----------------------------------------------------------------------------
190bool ServerLobby::notifyEventAsynchronous(Event* event)
191{
192 assert(m_game_setup); // assert that the setup exists
193 if (event->getType() == EVENT_TYPE_MESSAGE)
194 {
195 NetworkString &data = event->data();
196 assert(data.size()); // message not empty
197 uint8_t message_type;
198 message_type = data.getUInt8();
199 Log::info("ServerLobby", "Message received with type %d.",
200 message_type);
201 switch(message_type)
202 {
203 case LE_CONNECTION_REQUESTED: connectionRequested(event); break;
204 case LE_KART_SELECTION: kartSelectionRequested(event); break;
205 case LE_CLIENT_LOADED_WORLD: finishedLoadingWorldClient(event); break;
206 case LE_STARTED_RACE: startedRaceOnClient(event); break;
207 case LE_VOTE: playerVote(event); break;
208 case LE_RACE_FINISHED_ACK: playerFinishedResult(event); break;
209 case LE_KICK_HOST: kickHost(event); break;
210 case LE_CHAT: handleChat(event); break;
211 default: break;
212 } // switch
213 } // if (event->getType() == EVENT_TYPE_MESSAGE)
214 else if (event->getType() == EVENT_TYPE_DISCONNECTED)
215 {
216 clientDisconnected(event);
217 } // if (event->getType() == EVENT_TYPE_DISCONNECTED)
218 return true;
219} // notifyEventAsynchronous
220
221//-----------------------------------------------------------------------------
222/** Create the server id file to let the graphics server client connect. */
223void ServerLobby::createServerIdFile()
224{
225 const std::string& sid = NetworkConfig::get()->getServerIdFile();
226 if (!sid.empty() && !m_has_created_server_id_file)
227 {
228 std::fstream fs;
229 fs.open(sid, std::ios::out);
230 fs.close();
231 m_has_created_server_id_file = true;
232 }
233} // createServerIdFile
234
235//-----------------------------------------------------------------------------
236/** Find out the public IP server or poll STK server asynchronously. */
237void ServerLobby::asynchronousUpdate()
238{
239 switch (m_state.load())
240 {
241 case SET_PUBLIC_ADDRESS:
242 {
243 // In case of LAN we don't need our public address or register with the
244 // STK server, so we can directly go to the accepting clients state.
245 if (NetworkConfig::get()->isLAN())
246 {
247 m_state = ACCEPTING_CLIENTS;
248 STKHost::get()->startListening();
249 createServerIdFile();
250 return;
251 }
252 STKHost::get()->setPublicAddress();
253 if (STKHost::get()->getPublicAddress().isUnset())
254 {
255 m_state = ERROR_LEAVE;
256 }
257 else
258 {
259 STKHost::get()->startListening();
260 m_state = REGISTER_SELF_ADDRESS;
261 }
262 break;
263 }
264 case REGISTER_SELF_ADDRESS:
265 {
266 // Register this server with the STK server. This will block
267 // this thread, but there is no need for the protocol manager
268 // to react to any requests before the server is registered.
269 registerServer();
270 if (m_server_registered)
271 {
272 m_state = ACCEPTING_CLIENTS;
273 createServerIdFile();
274 }
275 break;
276 }
277 case ACCEPTING_CLIENTS:
278 {
279 // Only poll the STK server if this is a WAN server.
280 if (NetworkConfig::get()->isWAN())
281 checkIncomingConnectionRequests();
282 break;
283 }
284 case ERROR_LEAVE:
285 {
286 requestTerminate();
287 m_state = EXITING;
288 STKHost::get()->setErrorMessage(_("Failed to setup server."));
289 STKHost::get()->requestShutdown();
290 break;
291 }
292 case WAIT_FOR_WORLD_LOADED:
293 {
294 // m_server_has_loaded_world is set by main thread with atomic write
295 if (m_server_has_loaded_world.load() == false)
296 return;
297 if (!checkPeersReady())
298 return;
299 m_state = WAIT_FOR_RACE_STARTED;
300 // Reset for next state usage
301 for (auto p : m_peers_ready)
302 {
303 p.second = false;
304 }
305 signalRaceStartToClients();
306 break;
307 }
308 case WAIT_FOR_RACE_STARTED:
309 // The function startedRaceOnClient() will trigger the
310 // next state.
311 break;
312 case DELAY_SERVER:
313 if (m_server_delay < StkTime::getRealTime())
314 {
315 Log::verbose("ServerLobby", "End delay at %lf",
316 StkTime::getRealTime());
317 m_state = RACING;
318 World::getWorld()->setReadyToRace();
319 }
320 break;
321 case SELECTING:
322 if (m_timeout.load() < (float)StkTime::getRealTime())
323 {
324 auto result = handleVote();
325 // Remove disconnected player (if any) one last time
326 m_game_setup->update(true);
327 auto players = m_game_setup->getConnectedPlayers();
328 NetworkString* load_world = getNetworkString();
329 load_world->setSynchronous(true);
330 load_world->addUInt8(LE_LOAD_WORLD).encodeString(std::get<0>(result))
331 .addUInt8(std::get<1>(result)).addUInt8(std::get<2>(result))
332 .addUInt8((uint8_t)players.size());
333 for (auto player : players)
334 {
335 load_world->encodeString(player->getName())
336 .addUInt32(player->getHostId())
337 .addFloat(player->getDefaultKartColor())
338 .addUInt32(player->getOnlineId())
339 .addUInt8(player->getPerPlayerDifficulty());
340 if (player->getKartName().empty())
341 {
342 RandomGenerator rg;
343 std::set<std::string>::iterator it =
344 m_available_kts.first.begin();
345 std::advance(it, rg.get((int)m_available_kts.first.size()));
346 player->setKartName(*it);
347 }
348 load_world->encodeString(player->getKartName());
349 }
350 // TODO: sort players for grand prix here
351 configRemoteKart(players);
352
353 // Reset for next state usage
354 for (auto p : m_peers_ready)
355 {
356 p.second = false;
357 }
358 m_state = LOAD_WORLD;
359 sendMessageToPeersChangingToken(load_world);
360 delete load_world;
361 }
362 break;
363 default:
364 break;
365 }
366
367} // asynchronousUpdate
368
369//-----------------------------------------------------------------------------
370bool ServerLobby::checkPeersReady() const
371{
372 bool all_ready = true;
373 for (auto p : m_peers_ready)
374 {
375 if (p.first.expired())
376 continue;
377 all_ready = all_ready && p.second;
378 if (!all_ready)
379 return false;
380 }
381 return true;
382} // checkPeersReady
383
384//-----------------------------------------------------------------------------
385/** Simple finite state machine. Once this
386 * is known, register the server and its address with the stk server so that
387 * client can find it.
388 */
389void ServerLobby::update(int ticks)
390{
391 // Check if server owner has left
392 updateServerOwner();
393 if (m_game_setup)
394 {
395 // Remove disconnected players if in these two states
396 m_game_setup->update(m_state.load() == ACCEPTING_CLIENTS ||
397 m_state.load() == SELECTING);
398 }
399 switch (m_state.load())
400 {
401 case SET_PUBLIC_ADDRESS:
402 case REGISTER_SELF_ADDRESS:
403 case ACCEPTING_CLIENTS:
404 case WAIT_FOR_WORLD_LOADED:
405 case WAIT_FOR_RACE_STARTED:
406 case DELAY_SERVER:
407 {
408 // Waiting for asynchronousUpdate
409 break;
410 }
411 case SELECTING:
412 // The function playerTrackVote will trigger the next state
413 // once all track votes have been received.
414 break;
415 case LOAD_WORLD:
416 Log::info("ServerLobbyRoom", "Starting the race loading.");
417 // This will create the world instance, i.e. load track and karts
418 loadWorld();
419 m_state = WAIT_FOR_WORLD_LOADED;
420 break;
421 case RACING:
422 if (World::getWorld() &&
423 RaceEventManager::getInstance<RaceEventManager>()->isRunning())
424 {
425 checkRaceFinished();
426 }
427 break;
428 case RESULT_DISPLAY:
429 if(StkTime::getRealTime() > m_timeout.load())
430 {
431 RaceResultGUI::getInstance()->backToLobby();
432 // notify the network world that it is stopped
433 RaceEventManager::getInstance()->stop();
434 // stop race protocols
435 auto pm = ProtocolManager::lock();
436 assert(pm);
437 pm->findAndTerminate(PROTOCOL_CONTROLLER_EVENTS);
438 pm->findAndTerminate(PROTOCOL_KART_UPDATE);
439 pm->findAndTerminate(PROTOCOL_GAME_EVENTS);
440 setup();
441 m_state = NetworkConfig::get()->isLAN() ?
442 ACCEPTING_CLIENTS : REGISTER_SELF_ADDRESS;
443 // Send a notification to all clients to exit
444 // the race result screen
445 NetworkString *exit_result_screen = getNetworkString(1);
446 exit_result_screen->setSynchronous(true);
447 exit_result_screen->addUInt8(LE_EXIT_RESULT);
448 sendMessageToPeersChangingToken(exit_result_screen,
449 /*reliable*/true);
450 delete exit_result_screen;
451 }
452 break;
453 case ERROR_LEAVE:
454 case EXITING:
455 break;
456 }
457} // update
458
459//-----------------------------------------------------------------------------
460/** Register this server (i.e. its public address) with the STK server
461 * so that clients can find it. It blocks till a response from the
462 * stk server is received (this function is executed from the
463 * ProtocolManager thread). The information about this client is added
464 * to the table 'server'.
465 */
466void ServerLobby::registerServer()
467{
468 Online::XMLRequest *request = new Online::XMLRequest();
469 const TransportAddress& addr = STKHost::get()->getPublicAddress();
470 NetworkConfig::get()->setUserDetails(request, "create");
471 request->addParameter("address", addr.getIP() );
472 request->addParameter("port", addr.getPort() );
473 request->addParameter("private_port",
474 STKHost::get()->getPrivatePort() );
475 request->addParameter("name", NetworkConfig::get()->getServerName() );
476 request->addParameter("max_players",
477 NetworkConfig::get()->getMaxPlayers());
478 request->addParameter("difficulty", race_manager->getDifficulty());
479 request->addParameter("game_mode",
480 NetworkConfig::get()->getServerGameMode(race_manager->getMinorMode(),
481 race_manager->getMajorMode()));
482 request->addParameter("password",
483 (unsigned)(!NetworkConfig::get()->getPassword().empty()));
484 request->addParameter("version",
485 (unsigned)NetworkConfig::m_server_version);
486
487 Log::info("ServerLobby", "Public server addr %s", addr.toString().c_str());
488
489 request->executeNow();
490
491 const XMLNode * result = request->getXMLData();
492 std::string rec_success;
493
494 if (result->get("success", &rec_success) && rec_success == "yes")
495 {
496 Log::info("ServerLobby", "Server is now online.");
497 m_server_registered = true;
498 }
499 else
500 {
501 irr::core::stringc error(request->getInfo().c_str());
502 Log::error("ServerLobby", "%s", error.c_str());
503 m_state = ERROR_LEAVE;
504 }
505 delete request;
506} // registerServer
507
508//-----------------------------------------------------------------------------
509/** Unregister this server (i.e. its public address) with the STK server,
510 * currently when karts enter kart selection screen it will be done.
511 */
512void ServerLobby::unregisterServer()
513{
514 const TransportAddress &addr = STKHost::get()->getPublicAddress();
515 Online::XMLRequest* request = new Online::XMLRequest();
516 NetworkConfig::get()->setUserDetails(request, "stop");
517
518 request->addParameter("address", addr.getIP());
519 request->addParameter("port", addr.getPort());
520
521 Log::info("ServerLobby", "address %s", addr.toString().c_str());
522 request->executeNow();
523
524 const XMLNode * result = request->getXMLData();
525 std::string rec_success;
526
527 if (result->get("success", &rec_success))
528 {
529 if (rec_success == "yes")
530 {
531 Log::info("ServerLobby", "Server is now unregister.");
532 }
533 else
534 {
535 Log::error("ServerLobby", "Fail to unregister server.");
536 }
537 }
538 else
539 {
540 Log::error("ServerLobby", "Fail to stop server.");
541 }
542 delete request;
543
544} // unregisterServer
545
546//-----------------------------------------------------------------------------
547/** This function is called when all clients have loaded the world and
548 * are therefore ready to start the race. It signals to all clients
549 * to start the race and then switches state to DELAY_SERVER.
550 */
551void ServerLobby::signalRaceStartToClients()
552{
553 Log::verbose("Server", "Signaling race start to clients at %lf",
554 StkTime::getRealTime());
555 NetworkString *ns = getNetworkString(1);
556 ns->addUInt8(LE_START_RACE);
557 sendMessageToPeersChangingToken(ns, /*reliable*/true);
558 delete ns;
559} // startGame
560
561//-----------------------------------------------------------------------------
562/** Instructs all clients to start the kart selection. If event is not NULL,
563 * the command comes from a client (which needs to be authorised).
564 */
565void ServerLobby::startSelection(const Event *event)
566{
567 std::lock_guard<std::mutex> lock(m_connection_mutex);
568
569 if (m_state != ACCEPTING_CLIENTS)
570 {
571 Log::warn("ServerLobby",
572 "Received startSelection while being in state %d",
573 m_state.load());
574 return;
575 }
576 if (event->getPeerSP() != m_server_owner.lock())
577 {
578 Log::warn("ServerLobby",
579 "Client %lx is not authorised to start selection.",
580 event->getPeer());
581 return;
582 }
583
584 if (NetworkConfig::get()->isWAN())
585 {
586 assert(m_server_registered);
587 unregisterServer();
588 m_server_registered = false;
589 }
590
591 NetworkString *ns = getNetworkString(1);
592 // Start selection - must be synchronous since the receiver pushes
593 // a new screen, which must be donefrom the main thread.
594 ns->setSynchronous(true);
595 ns->addUInt8(LE_START_SELECTION);
596 const auto& all_k = m_available_kts.first;
597 const auto& all_t = m_available_kts.second;
598 ns->addUInt16((uint16_t)all_k.size()).addUInt16((uint16_t)all_t.size());
599 for (const std::string& kart : all_k)
600 {
601 ns->encodeString(kart);
602 }
603 for (const std::string& track : all_t)
604 {
605 ns->encodeString(track);
606 }
607
608 sendMessageToPeersChangingToken(ns, /*reliable*/true);
609 delete ns;
610
611 m_state = SELECTING;
612
613 // Will be changed after the first vote received
614 m_timeout.store(std::numeric_limits<float>::max());
615} // startSelection
616
617//-----------------------------------------------------------------------------
618/** Query the STK server for connection requests. For each connection request
619 * start a ConnectToPeer protocol.
620 */
621void ServerLobby::checkIncomingConnectionRequests()
622{
623 // First poll every 5 seconds. Return if no polling needs to be done.
624 const float POLL_INTERVAL = 5.0f;
625 static double last_poll_time = 0;
626 if (StkTime::getRealTime() < last_poll_time + POLL_INTERVAL)
627 return;
628
629 // Keep the port open, it can be sent to anywhere as we will send to the
630 // correct peer later in ConnectToPeer.
631 BareNetworkString data;
632 data.addUInt8(0);
633 STKHost::get()->sendRawPacket(data, STKHost::get()->getStunAddress());
634
635 // Now poll the stk server
636 last_poll_time = StkTime::getRealTime();
637 Online::XMLRequest* request = new Online::XMLRequest();
638 NetworkConfig::get()->setUserDetails(request, "poll-connection-requests");
639
640 const TransportAddress &addr = STKHost::get()->getPublicAddress();
641 request->addParameter("address", addr.getIP() );
642 request->addParameter("port", addr.getPort());
643 request->addParameter("current_players", m_game_setup->getPlayerCount());
644
645 request->executeNow();
646 assert(request->isDone());
647
648 const XMLNode *result = request->getXMLData();
649 std::string success;
650
651 if (!result->get("success", &success) || success != "yes")
652 {
653 Log::error("ServerLobby", "Cannot retrieve the list.");
654 return;
655 }
656
657 // Now start a ConnectToPeer protocol for each connection request
658 const XMLNode * users_xml = result->getNode("users");
659 uint32_t id = 0;
660 for (unsigned int i = 0; i < users_xml->getNumNodes(); i++)
661 {
662 users_xml->getNode(i)->get("id", &id);
663 Log::debug("ServerLobby",
664 "User with id %d wants to connect.", id);
665 std::make_shared<ConnectToPeer>(id)->requestStart();
666 }
667 delete request;
668} // checkIncomingConnectionRequests
669
670//-----------------------------------------------------------------------------
671/** Checks if the race is finished, and if so informs the clients and switches
672 * to state RESULT_DISPLAY, during which the race result gui is shown and all
673 * clients can click on 'continue'.
674 */
675 void ServerLobby::checkRaceFinished()
676{
677 assert(RaceEventManager::getInstance()->isRunning());
678 assert(World::getWorld());
679 if(!RaceEventManager::getInstance()->isRaceOver()) return;
680
681 m_player_ready_counter = 0;
682 // Set the delay before the server forces all clients to exit the race
683 // result screen and go back to the lobby
684 m_timeout.store((float)(StkTime::getRealTime()+15.0f));
685 m_state = RESULT_DISPLAY;
686
687 // calculate karts ranks :
688 int num_karts = race_manager->getNumberOfKarts();
689 std::vector<int> karts_results;
690 std::vector<float> karts_times;
691 for (int j = 0; j < num_karts; j++)
692 {
693 float kart_time = race_manager->getKartRaceTime(j);
694 for (unsigned int i = 0; i < karts_times.size(); i++)
695 {
696 if (kart_time < karts_times[i])
697 {
698 karts_times.insert(karts_times.begin() + i, kart_time);
699 karts_results.insert(karts_results.begin() + i, j);
700 break;
701 }
702 }
703 }
704
705 NetworkString *total = getNetworkString(1 + karts_results.size());
706 total->setSynchronous(true);
707 total->addUInt8(LE_RACE_FINISHED);
708 for (unsigned int i = 0; i < karts_results.size(); i++)
709 {
710 total->addUInt8(karts_results[i]); // kart pos = i+1
711 Log::info("ServerLobby", "Kart %d finished #%d",
712 karts_results[i], i + 1);
713 }
714 sendMessageToPeersChangingToken(total, /*reliable*/ true);
715 delete total;
716 Log::info("ServerLobby", "End of game message sent");
717
718} // checkRaceFinished
719
720//-----------------------------------------------------------------------------
721/** Called when a client disconnects.
722 * \param event The disconnect event.
723 */
724void ServerLobby::clientDisconnected(Event* event)
725{
726 std::lock_guard<std::mutex> lock(m_connection_mutex);
727 auto players_on_peer = event->getPeer()->getPlayerProfiles();
728 if (players_on_peer.empty())
729 return;
730
731 NetworkString* msg = getNetworkString(2);
732 msg->addUInt8(LE_PLAYER_DISCONNECTED);
733 msg->addUInt8((uint8_t)players_on_peer.size());
734 for (auto p : players_on_peer)
735 {
736 std::string name = StringUtils::wideToUtf8(p->getName());
737 msg->encodeString(name);
738 Log::info("ServerLobby", "%s disconnected", name.c_str());
739 }
740 sendMessageToPeersChangingToken(msg, /*reliable*/true);
741 updatePlayerList();
742 delete msg;
743} // clientDisconnected
744
745//-----------------------------------------------------------------------------
746
747/*! \brief Called when a player asks for a connection.
748 * \param event : Event providing the information.
749 *
750 * Format of the data :
751 * Byte 0 1
752 * ---------------------
753 * Size | 1 |1| |
754 * Data | 4 |n| player name |
755 * ---------------------
756 */
757void ServerLobby::connectionRequested(Event* event)
758{
759 std::lock_guard<std::mutex> lock(m_connection_mutex);
760 std::shared_ptr<STKPeer> peer = event->getPeerSP();
761 peer->cleanPlayerProfiles();
762
763 const NetworkString &data = event->data();
764
765 // can we add the player ?
766 if (m_state != ACCEPTING_CLIENTS)
767 {
768 NetworkString *message = getNetworkString(2);
769 message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(RR_BUSY);
770 // send only to the peer that made the request and disconect it now
771 peer->sendPacket(message);
772 peer->reset();
773 delete message;
774 Log::verbose("ServerLobby", "Player refused: selection started");
775 return;
776 }
777
778 // Check for password
779 std::string password;
780 data.decodeString(&password);
781 if (password != NetworkConfig::get()->getPassword())
782 {
783 NetworkString *message = getNetworkString(2);
784 message->addUInt8(LE_CONNECTION_REFUSED)
785 .addUInt8(RR_INCORRECT_PASSWORD);
786 peer->sendPacket(message);
787 peer->reset();
788 delete message;
789 Log::verbose("ServerLobby", "Player refused: incorrect password");
790 return;
791 }
792
793 unsigned player_count = data.getUInt8();
794 if (m_game_setup->getPlayerCount() + player_count >
795 NetworkConfig::get()->getMaxPlayers())
796 {
797 NetworkString *message = getNetworkString(2);
798 message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(RR_TOO_MANY_PLAYERS);
799 peer->sendPacket(message);
800 peer->reset();
801 delete message;
802 Log::verbose("ServerLobby", "Player refused: too many players");
803 return;
804 }
805
806 for (unsigned i = 0; i < player_count; i++)
807 {
808 std::string name_u8;
809 data.decodeString(&name_u8);
810 core::stringw name = StringUtils::utf8ToWide(name_u8);
811 float default_kart_color = data.getFloat();
812 uint32_t online_id = data.getUInt32();
813 PerPlayerDifficulty per_player_difficulty =
814 (PerPlayerDifficulty)data.getUInt8();
815 peer->addPlayer(std::make_shared<NetworkPlayerProfile>
816 (peer, name, peer->getHostId(), default_kart_color, online_id,
817 per_player_difficulty));
818 }
819
820 bool is_banned = false;
821 auto ret = m_ban_list.find(peer->getAddress().getIP());
822 if (ret != m_ban_list.end())
823 {
824 // Ban all players
825 if (ret->second == 0)
826 {
827 is_banned = true;
828 }
829 else
830 {
831 for (auto& p : peer->getPlayerProfiles())
832 {
833 if (ret->second == p->getOnlineId())
834 {
835 is_banned = true;
836 break;
837 }
838 }
839 }
840 }
841
842 if (is_banned)
843 {
844 NetworkString *message = getNetworkString(2);
845 message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(RR_BANNED);
846 peer->cleanPlayerProfiles();
847 peer->sendPacket(message);
848 peer->reset();
849 delete message;
850 Log::verbose("ServerLobby", "Player refused: banned");
851 return;
852 }
853
854 // Connection accepted.
855 // ====================
856 std::set<std::string> client_karts, client_tracks;
857 const unsigned kart_num = data.getUInt16();
858 const unsigned track_num = data.getUInt16();
859 for (unsigned i = 0; i < kart_num; i++)
860 {
861 std::string kart;
862 data.decodeString(&kart);
863 client_karts.insert(kart);
864 }
865 for (unsigned i = 0; i < track_num; i++)
866 {
867 std::string track;
868 data.decodeString(&track);
869 client_tracks.insert(track);
870 }
871
872 // Remove karts/tracks from server that are not supported on the new client
873 // so that in the end the server has a list of all karts/tracks available
874 // on all clients
875 std::set<std::string> karts_erase, tracks_erase;
876 for (const std::string& server_kart : m_available_kts.first)
877 {
878 if (client_karts.find(server_kart) == client_karts.end())
879 {
880 karts_erase.insert(server_kart);
881 }
882 }
883 for (const std::string& server_track : m_available_kts.second)
884 {
885 if (client_tracks.find(server_track) == client_tracks.end())
886 {
887 tracks_erase.insert(server_track);
888 }
889 }
890
891 // Drop this player if he doesn't have at least 1 kart / track the same
892 // from server
893 if (karts_erase.size() == m_available_kts.first.size() ||
894 tracks_erase.size() == m_available_kts.second.size())
895 {
896 NetworkString *message = getNetworkString(2);
897 message->addUInt8(LE_CONNECTION_REFUSED)
898 .addUInt8(RR_INCOMPATIBLE_DATA);
899 peer->cleanPlayerProfiles();
900 peer->sendPacket(message);
901 peer->reset();
902 delete message;
903 Log::verbose("ServerLobby", "Player has incompatible karts / tracks");
904 return;
905 }
906
907 for (const std::string& kart_erase : karts_erase)
908 {
909 m_available_kts.first.erase(kart_erase);
910 }
911 for (const std::string& track_erase : tracks_erase)
912 {
913 m_available_kts.second.erase(track_erase);
914 }
915
916 if (!peer->isClientServerTokenSet())
917 {
918 // Now answer to the peer that just connected
919 // ------------------------------------------
920 RandomGenerator token_generator;
921 // use 4 random numbers because rand_max is probably 2^15-1.
922 uint32_t token = (uint32_t)((token_generator.get(RAND_MAX) & 0xff) << 24 |
923 (token_generator.get(RAND_MAX) & 0xff) << 16 |
924 (token_generator.get(RAND_MAX) & 0xff) << 8 |
925 (token_generator.get(RAND_MAX) & 0xff));
926
927 peer->setClientServerToken(token);
928 }
929 // send a message to the one that asked to connect
930 NetworkString *message_ack = getNetworkString(4);
931 // connection success -- return the host id of peer
932 message_ack->addUInt8(LE_CONNECTION_ACCEPTED).addUInt32(peer->getHostId());
933 peer->sendPacket(message_ack);
934 delete message_ack;
935
936 m_peers_ready[peer] = false;
937 for (std::shared_ptr<NetworkPlayerProfile> npp : peer->getPlayerProfiles())
938 {
939 m_game_setup->addPlayer(npp);
940 Log::info("ServerLobby", "New player %s with online id %u from %s.",
941 StringUtils::wideToUtf8(npp->getName()).c_str(),
942 npp->getOnlineId(), peer->getAddress().toString().c_str());
943 }
944 updatePlayerList();
945} // connectionRequested
946
947//-----------------------------------------------------------------------------
948void ServerLobby::updatePlayerList()
949{
950 if (m_state.load() != ACCEPTING_CLIENTS)
951 return;
952 auto all_profiles = STKHost::get()->getAllPlayerProfiles();
953 NetworkString* pl = getNetworkString();
954 pl->setSynchronous(true);
955 pl->addUInt8(LE_UPDATE_PLAYER_LIST).addUInt8((uint8_t)all_profiles.size());
956 for (auto profile : all_profiles)
957 {
958 pl->addUInt32(profile->getHostId()).addUInt32(profile->getOnlineId())
959 .encodeString(profile->getName());
960 uint8_t server_owner = 0;
961 if (m_server_owner.lock() == profile->getPeer())
962 server_owner = 1;
963 pl->addUInt8(server_owner);
964 }
965 sendMessageToPeersChangingToken(pl);
966 delete pl;
967} // updatePlayerList
968
969//-----------------------------------------------------------------------------
970void ServerLobby::updateServerOwner()
971{
972 if (m_state.load() < ACCEPTING_CLIENTS ||
973 m_state.load() > RESULT_DISPLAY)
974 return;
975 if (!m_server_owner.expired())
976 return;
977 auto peers = STKHost::get()->getPeers();
978 if (peers.empty())
979 return;
980 std::sort(peers.begin(), peers.end(), [](const std::shared_ptr<STKPeer> a,
981 const std::shared_ptr<STKPeer> b)->bool
982 {
983 return a->getHostId() < b->getHostId();
984 });
985
986 std::shared_ptr<STKPeer> owner;
987 std::lock_guard<std::mutex> lock(m_connection_mutex);
988 // Make sure no one access the weak pointer or adding player to peers
989 for (auto peer: peers)
990 {
991 // Only 127.0.0.1 can be server owner in case of graphics-client-server
992 if (peer->hasPlayerProfiles() &&
993 (NetworkConfig::get()->getServerIdFile().empty() ||
994 peer->getAddress().getIP() == 0x7f000001))
995 {
996 owner = peer;
997 break;
998 }
999 }
1000 if (owner)
1001 {
1002 NetworkString* ns = getNetworkString();
1003 ns->addUInt8(LE_SERVER_OWNERSHIP);
1004 owner->sendPacket(ns);
1005 delete ns;
1006 m_server_owner = owner;
1007 updatePlayerList();
1008 }
1009} // updateServerOwner
1010
1011//-----------------------------------------------------------------------------
1012/*! \brief Called when a player asks to select karts.
1013 * \param event : Event providing the information.
1014 */
1015void ServerLobby::kartSelectionRequested(Event* event)
1016{
1017 std::lock_guard<std::mutex> lock(m_connection_mutex);
1018 if (m_state != SELECTING)
1019 {
1020 Log::warn("ServerLobby", "Received kart selection while in state %d.",
1021 m_state.load());
1022 return;
1023 }
1024
1025 if (!checkDataSize(event, 1) ||
1026 event->getPeer()->getPlayerProfiles().empty())
1027 return;
1028
1029 const NetworkString& data = event->data();
1030 STKPeer* peer = event->getPeer();
1031 unsigned player_count = data.getUInt8();
1032 for (unsigned i = 0; i < player_count; i++)
1033 {
1034 std::string kart;
1035 data.decodeString(&kart);
1036 if (m_available_kts.first.find(kart) == m_available_kts.first.end())
1037 {
1038 // Will be reset to a random one later
1039 Log::debug("ServerLobby", "Player %d from peer %d chose unknown "
1040 "kart %s, use a random one", i, peer->getHostId(),
1041 kart.c_str());
1042 continue;
1043 }
1044 else
1045 {
1046 peer->getPlayerProfiles()[i]->setKartName(kart);
1047 }
1048 Log::verbose("ServerLobby", "Player %d from peer %d chose %s", i,
1049 peer->getHostId(), kart.c_str());
1050 }
1051} // kartSelectionRequested
1052
1053//-----------------------------------------------------------------------------
1054/*! \brief Called when a player votes for track(s).
1055 * \param event : Event providing the information.
1056 */
1057void ServerLobby::playerVote(Event* event)
1058{
1059 if (m_state != SELECTING)
1060 {
1061 Log::warn("ServerLobby", "Received track vote while in state %d.",
1062 m_state.load());
1063 return;
1064 }
1065
1066 if (!checkDataSize(event, 4) ||
1067 event->getPeer()->getPlayerProfiles().empty())
1068 return;
1069
1070 // Check if first vote, if so start counter
1071 if (m_timeout.load() == std::numeric_limits<float>::max())
1072 {
1073 m_timeout.store((float)StkTime::getRealTime() +
1074 UserConfigParams::m_voting_timeout);
1075 }
1076 float remaining_time = m_timeout.load() - (float)StkTime::getRealTime();
1077 if (remaining_time < 0.0f)
1078 {
1079 return;
1080 }
1081
1082 NetworkString& data = event->data();
1083 NetworkString other = NetworkString(PROTOCOL_LOBBY_ROOM);
1084 std::string name = StringUtils::wideToUtf8(event->getPeer()
1085 ->getPlayerProfiles()[0]->getName());
1086 other.addUInt8(LE_VOTE).addFloat(m_timeout.load()).encodeString(name)
1087 .addUInt32(event->getPeer()->getHostId());
1088 other += data;
1089
1090 std::string track_name;
1091 data.decodeString(&track_name);
1092 uint8_t lap = data.getUInt8();
1093 uint8_t reverse = data.getUInt8();
1094 m_peers_votes[event->getPeerSP()] =
1095 std::make_tuple(track_name, lap, reverse == 1);
1096 sendMessageToPeersChangingToken(&other);
1097
1098} // playerVote
1099
1100// ----------------------------------------------------------------------------
1101std::tuple<std::string, uint8_t, bool> ServerLobby::handleVote()
1102{
1103 // Default settings if no votes at all
1104 RandomGenerator rg;
1105 std::set<std::string>::iterator it = m_available_kts.second.begin();
1106 std::advance(it, rg.get((int)m_available_kts.second.size()));
1107 std::string final_track = *it;
1108 unsigned final_laps = UserConfigParams::m_num_laps;
1109 bool final_reverse = final_track.size() % 2 == 0;
1110
1111 std::map<std::string, unsigned> tracks;
1112 std::map<unsigned, unsigned> laps;
1113 std::map<bool, unsigned> reverses;
1114 for (auto p : m_peers_votes)
1115 {
1116 if (p.first.expired())
1117 continue;
1118 auto track_vote = tracks.find(std::get<0>(p.second));
1119 if (track_vote == tracks.end())
1120 tracks[std::get<0>(p.second)] = 1;
1121 else
1122 track_vote->second++;
1123 auto lap_vote = laps.find(std::get<1>(p.second));
1124 if (lap_vote == laps.end())
1125 laps[std::get<1>(p.second)] = 1;
1126 else
1127 lap_vote->second++;
1128 auto reverse_vote = reverses.find(std::get<2>(p.second));
1129 if (reverse_vote == reverses.end())
1130 reverses[std::get<2>(p.second)] = 1;
1131 else
1132 reverse_vote->second++;
1133 }
1134
1135 unsigned vote = 0;
1136 auto track_vote = tracks.begin();
1137 for (auto c_vote = tracks.begin(); c_vote != tracks.end(); c_vote++)
1138 {
1139 if (c_vote->second > vote)
1140 {
1141 vote = c_vote->second;
1142 track_vote = c_vote;
1143 }
1144 }
1145 if (track_vote != tracks.end())
1146 final_track = track_vote->first;
1147
1148 vote = 0;
1149 auto lap_vote = laps.begin();
1150 for (auto c_vote = laps.begin(); c_vote != laps.end(); c_vote++)
1151 {
1152 if (c_vote->second > vote)
1153 {
1154 vote = c_vote->second;
1155 lap_vote = c_vote;
1156 }
1157 }
1158 if (lap_vote != laps.end())
1159 final_laps = lap_vote->first;
1160
1161 vote = 0;
1162 auto reverse_vote = reverses.begin();
1163 for (auto c_vote = reverses.begin(); c_vote != reverses.end(); c_vote++)
1164 {
1165 if (c_vote->second > vote)
1166 {
1167 vote = c_vote->second;
1168 reverse_vote = c_vote;
1169 }
1170 }
1171 if (reverse_vote != reverses.end())
1172 final_reverse = reverse_vote->first;
1173
1174 m_game_setup->setRace(final_track, final_laps, final_reverse);
1175 return std::make_tuple(final_track, final_laps, final_reverse);
1176} // handleVote
1177
1178// ----------------------------------------------------------------------------
1179/** Called from the RaceManager of the server when the world is loaded. Marks
1180 * the server to be ready to start the race.
1181 */
1182void ServerLobby::finishedLoadingWorld()
1183{
1184 m_server_has_loaded_world.store(true);
1185} // finishedLoadingWorld;
1186
1187//-----------------------------------------------------------------------------
1188/** Called when a client notifies the server that it has loaded the world.
1189 * When all clients and the server are ready, the race can be started.
1190 */
1191void ServerLobby::finishedLoadingWorldClient(Event *event)
1192{
1193 std::shared_ptr<STKPeer> peer = event->getPeerSP();
1194 m_peers_ready.at(peer) = true;
1195 Log::info("ServerLobby", "Peer %d has finished loading world",
1196 peer->getHostId());
1197} // finishedLoadingWorldClient
1198
1199//-----------------------------------------------------------------------------
1200/** Called when a notification from a client is received that the client has
1201 * started the race. Once all clients have informed the server that they
1202 * have started the race, the server can start. This makes sure that the
1203 * server's local time is behind all clients by (at least) their latency,
1204 * which in turn means that when the server simulates local time T all
1205 * messages from clients at their local time T should have arrived at
1206 * the server, which creates smoother play experience.
1207 */
1208void ServerLobby::startedRaceOnClient(Event *event)
1209{
1210 std::shared_ptr<STKPeer> peer = event->getPeerSP();
1211 m_peers_ready.at(peer) = true;
1212 Log::info("ServerLobby", "Peer %d has started race at %lf",
1213 peer->getHostId(), StkTime::getRealTime());
1214
1215 if (checkPeersReady())
1216 {
1217 m_state = DELAY_SERVER;
1218 m_server_delay = StkTime::getRealTime() + 0.1;
1219 Log::verbose("ServerLobby", "Started delay at %lf set delay to %lf",
1220 StkTime::getRealTime(), m_server_delay);
1221 }
1222} // startedRaceOnClient
1223
1224//-----------------------------------------------------------------------------
1225/** Called when a client clicks on 'ok' on the race result screen.
1226 * If all players have clicked on 'ok', go back to the lobby.
1227 */
1228void ServerLobby::playerFinishedResult(Event *event)
1229{
1230 m_player_ready_counter++;
1231 if(m_player_ready_counter >= (int)STKHost::get()->getPeerCount())
1232 {
1233 // We can't trigger the world/race exit here, since this is called
1234 // from the protocol manager thread. So instead we force the timeout
1235 // to get triggered (which is done from the main thread):
1236 m_timeout.store(0);
1237 }
1238} // playerFinishedResult
1239
1240//-----------------------------------------------------------------------------
1241void ServerLobby::updateBanList()
1242{
1243 std::lock_guard<std::mutex> lock(m_connection_mutex);
1244 m_ban_list.clear();
1245 for (auto& ban : UserConfigParams::m_server_ban_list)
1246 {
1247 if (ban.first == "0.0.0.0")
1248 continue;
1249 m_ban_list[TransportAddress(ban.first).getIP()] = ban.second;
1250 }
1251} // updateBanList