Ticket #3241: t3241_kick_v6.5.2.patch
File t3241_kick_v6.5.2.patch, 26.8 KB (added by , 8 years ago) |
---|
-
binaries/data/mods/public/gui/common/network.js
1 /** 2 * Get a human readable version of the given disconnect reason. 3 * 4 * @param reason {number} 5 * @returns {string} 6 */ 1 7 function getDisconnectReason(id) 2 8 { 3 9 // Must be kept in sync with source/network/NetHost.h 4 10 switch (id) 5 11 { 6 12 case 0: return translate("Unknown reason"); 7 13 case 1: return translate("Unexpected shutdown"); 8 14 case 2: return translate("Incorrect network protocol version"); 9 15 case 3: return translate("Game is loading, please try later"); 10 16 case 4: return translate("Game has already started, no observers allowed"); 17 case 5: return translate("You have been kicked from the match"); 18 case 6: return translate("You have been banned from the match"); 11 19 default: return sprintf(translate("\\[Invalid value %(id)s]"), { "id": id }); 12 20 } 13 21 } 14 22 23 /** 24 * Show the disconnect reason in a message box. 25 * 26 * @param {number} reason 27 */ 15 28 function reportDisconnect(reason) 16 29 { 17 30 var reasontext = getDisconnectReason(reason); 18 31 19 32 messageBox(400, 200, 20 33 translate("Lost connection to the server.") + "\n\n" + sprintf(translate("Reason: %(reason)s."), { reason: reasontext }), 21 34 translate("Disconnected"), 2); 22 35 } 36 37 /** 38 * Get usernames sorted by player slot, observers last. 39 * Requires g_PlayerAssignments. 40 * 41 * @returns {string[]} 42 */ 43 function getUsernameList() 44 { 45 return Object.keys(g_PlayerAssignments).sort((guidA, guidB) => { 46 47 var playerIdA = g_PlayerAssignments[guidA].player; 48 var playerIdB = g_PlayerAssignments[guidB].player; 49 50 // Sort observers last 51 if (playerIdA == -1) return +1; 52 if (playerIdB == -1) return -1; 53 54 // Sort players 55 return playerIdA - playerIdB; 56 57 }).map(guid => g_PlayerAssignments[guid].name); 58 } 59 60 /** 61 * Execute a command locally. Requires addChatMessage. 62 * 63 * @param {string} input 64 * @returns {Boolean} whether a command was executed 65 */ 66 function executeNetworkCommand(input) 67 { 68 if (input.indexOf("/") != 0) 69 return false; 70 71 var command = input.split(" ", 1)[0]; 72 var argument = input.substr(command.length + 1); 73 74 switch (command) 75 { 76 case "/list": 77 addChatMessage({ "type": "clientlist", "guid": "local" }); 78 return true; 79 80 case "/kick": 81 if (!Engine.KickPlayer(argument, false)) 82 messageBox(400, 200, translate("Could not kick client!"), translate("ERROR"), 2); 83 return true; 84 85 case "/ban": 86 if (!Engine.KickPlayer(argument, true)) 87 messageBox(400, 200, translate("Could not ban client!"), translate("ERROR"), 2); 88 return true; 89 90 default: 91 return false; 92 } 93 } -
binaries/data/mods/public/gui/gamesetup/gamesetup.js
function handleNetMessage(message) 506 506 507 507 case "chat": 508 508 addChatMessage({ "type": "message", "guid": message.guid, "text": message.text }); 509 509 break; 510 510 511 case "kicked": 512 addChatMessage({ "type": message.ban ? "banned" : "kicked", "username": message.username }); 513 break; 514 511 515 // Singular client to host message 512 516 case "ready": 513 517 g_ReadyChanged -= 1; 514 518 if (g_ReadyChanged < 1 && g_PlayerAssignments[message.guid].player != -1) 515 519 addChatMessage({ "type": "ready", "guid": message.guid, "ready": +message.status == 1 }); … … function submitChatInput() 1771 1775 var input = Engine.GetGUIObjectByName("chatInput"); 1772 1776 var text = input.caption; 1773 1777 if (!text.length) 1774 1778 return; 1775 1779 1776 Engine.SendNetworkChat(text);1777 1780 input.caption = ""; 1781 1782 if (executeNetworkCommand(text)) 1783 return; 1784 1785 Engine.SendNetworkChat(text); 1778 1786 } 1779 1787 1780 1788 function addChatMessage(msg) 1781 1789 { 1782 1790 var username = ""; … … function addChatMessage(msg) 1807 1815 case "disconnect": 1808 1816 var formattedUsername = '[color="'+ color +'"]' + username + '[/color]'; 1809 1817 formatted = '[font="sans-bold-13"] ' + sprintf(translate("== %(message)s"), { "message": sprintf(translate("%(username)s has left"), { "username": formattedUsername }) }) + '[/font]'; 1810 1818 break; 1811 1819 1820 case "clientlist": 1821 formatted = sprintf(translate("Users: %(users)s"), { "users": getUsernameList().join(",") }); 1822 break; 1823 1824 case "kicked": 1825 formatted = '[font="sans-bold-13"] ' + sprintf(translate("== %(message)s"), { "message": sprintf(translate("%(username)s has been kicked."), { "username": username }) }) + '[/font]'; 1826 break; 1827 1828 case "banned": 1829 formatted = '[font="sans-bold-13"] ' + sprintf(translate("== %(message)s"), { "message": sprintf(translate("%(username)s has been banned."), { "username": username }) }) + '[/font]'; 1830 break; 1831 1812 1832 case "message": 1813 1833 var formattedUsername = '[color="'+ color +'"]' + username + '[/color]'; 1814 1834 var formattedUsernamePrefix = '[font="sans-bold-13"]' + sprintf(translate("<%(username)s>"), { "username": formattedUsername }) + '[/font]'; 1815 1835 formatted = sprintf(translate("%(username)s %(message)s"), { "username": formattedUsernamePrefix, "message": message }); 1816 1836 break; -
binaries/data/mods/public/gui/session/messages.js
function handleNetMessage(message) 267 267 obj.caption = translate("Connection to the server has been authenticated."); 268 268 obj.hidden = false; 269 269 break; 270 270 case "disconnected": 271 271 g_Disconnected = true; 272 obj.caption = translate("Connection to the server has been lost.") + "\n\n" + translate("The game has ended."); 272 // Translation: States the reason why the client disconnected from the server. 273 obj.caption = translate("Connection to the server has been lost.") + "\n" + 274 sprintf(translate("Reason: %(reason)s."), { "reason": getDisconnectReason(message.reason) }) + "\n" + 275 translate("The game has ended."); 273 276 obj.hidden = false; 274 277 break; 275 278 default: 276 279 error("Unrecognised netstatus type '" + message.status + "'"); 277 280 break; … … function handleNetMessage(message) 323 326 324 327 case "rejoined": 325 328 addChatMessage({ "type": "rejoined", "guid": message.guid }); 326 329 break; 327 330 331 case "kicked": 332 addChatMessage({ "type": message.ban ? "banned" : "kicked", "username": message.username }); 333 break; 334 328 335 // To prevent errors, ignore these message types that occur during autostart 329 336 case "gamesetup": 330 337 case "start": 331 338 break; 332 339 … … function submitChatInput() 357 364 toggleChatWindow(); 358 365 359 366 if (!text.length) 360 367 return; 361 368 369 if (executeNetworkCommand(text)) 370 return; 371 362 372 if (executeCheat(text)) 363 373 return; 364 374 365 375 // Observers should only be able to chat with everyone. 366 376 if (g_IsObserver && text.indexOf("/") == 0 && text.indexOf("/me ") != 0) … … function addChatMessage(msg) 418 428 formatted = sprintf(translate("%(player)s has left the game."), { "player": "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 419 429 break; 420 430 case "rejoined": 421 431 formatted = sprintf(translate("%(player)s has rejoined the game."), { "player": "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 422 432 break; 433 case "clientlist": 434 formatted = sprintf(translate("Users: %(users)s"), { "users": getUsernameList().join(",") }); 435 break; 436 case "kicked": 437 formatted = sprintf(translate("%(username)s has been kicked."), { "username": msg.username }); 438 break; 439 case "banned": 440 formatted = sprintf(translate("%(username)s has been banned."), { "username": msg.username }); 441 break; 423 442 case "defeat": 424 443 // In singleplayer, the local player is "You". "You has" is incorrect. 425 444 if (!g_IsNetworked && msg.player == Engine.GetPlayerID()) 426 445 formatted = translate("You have been defeated."); 427 446 else -
binaries/data/mods/public/gui/session/session.xml
6 6 <script file="gui/common/functions_civinfo.js"/> 7 7 <script file="gui/common/functions_global_object.js"/> 8 8 <script file="gui/common/functions_utility.js"/> 9 9 <script file="gui/common/l10n.js"/> 10 10 <script file="gui/common/music.js"/> 11 <script file="gui/common/network.js"/> 11 12 <script file="gui/common/settings.js"/> 12 13 <script file="gui/common/timer.js"/> 13 14 <script file="gui/common/tooltips.js"/> 14 15 <!-- load all scripts in this directory --> 15 16 <script directory="gui/session/"/> -
source/gui/scripting/ScriptFunctions.cpp
void DisconnectNetworkGame(ScriptInterfa 351 351 SAFE_DELETE(g_NetServer); 352 352 SAFE_DELETE(g_NetClient); 353 353 SAFE_DELETE(g_Game); 354 354 } 355 355 356 bool KickPlayer(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), CStrW playerName, bool ban) 357 { 358 if (!g_NetServer) 359 return false; 360 361 return g_NetServer->KickPlayer(playerName, ban); 362 } 363 356 364 JS::Value PollNetworkClient(ScriptInterface::CxPrivate* pCxPrivate) 357 365 { 358 366 if (!g_NetClient) 359 367 return JS::UndefinedValue(); 360 368 … … void GuiScriptingInit(ScriptInterface& s 961 969 scriptInterface.RegisterFunction<void, JS::HandleValue, int, &StartGame>("StartGame"); 962 970 scriptInterface.RegisterFunction<void, &Script_EndGame>("EndGame"); 963 971 scriptInterface.RegisterFunction<void, std::wstring, &StartNetworkHost>("StartNetworkHost"); 964 972 scriptInterface.RegisterFunction<void, std::wstring, std::string, &StartNetworkJoin>("StartNetworkJoin"); 965 973 scriptInterface.RegisterFunction<void, &DisconnectNetworkGame>("DisconnectNetworkGame"); 974 scriptInterface.RegisterFunction<bool, CStrW, bool, &KickPlayer>("KickPlayer"); 966 975 scriptInterface.RegisterFunction<JS::Value, &PollNetworkClient>("PollNetworkClient"); 967 976 scriptInterface.RegisterFunction<void, JS::HandleValue, &SetNetworkGameAttributes>("SetNetworkGameAttributes"); 968 977 scriptInterface.RegisterFunction<void, int, std::string, &AssignNetworkPlayer>("AssignNetworkPlayer"); 969 978 scriptInterface.RegisterFunction<void, std::string, int, &SetNetworkPlayerStatus>("SetNetworkPlayerStatus"); 970 979 scriptInterface.RegisterFunction<void, &ClearAllPlayerReady>("ClearAllPlayerReady"); -
source/network/NetClient.cpp
CNetClient::CNetClient(CGame* game) : 91 91 92 92 AddTransition(NCS_PREGAME, (uint)NMT_CHAT, NCS_PREGAME, (void*)&OnChat, context); 93 93 AddTransition(NCS_PREGAME, (uint)NMT_READY, NCS_PREGAME, (void*)&OnReady, context); 94 94 AddTransition(NCS_PREGAME, (uint)NMT_GAME_SETUP, NCS_PREGAME, (void*)&OnGameSetup, context); 95 95 AddTransition(NCS_PREGAME, (uint)NMT_PLAYER_ASSIGNMENT, NCS_PREGAME, (void*)&OnPlayerAssignment, context); 96 AddTransition(NCS_PREGAME, (uint)NMT_KICKED, NCS_PREGAME, (void*)&OnKicked, context); 96 97 AddTransition(NCS_PREGAME, (uint)NMT_GAME_START, NCS_LOADING, (void*)&OnGameStart, context); 97 98 AddTransition(NCS_PREGAME, (uint)NMT_JOIN_SYNC_START, NCS_JOIN_SYNCING, (void*)&OnJoinSyncStart, context); 98 99 99 100 AddTransition(NCS_JOIN_SYNCING, (uint)NMT_CHAT, NCS_JOIN_SYNCING, (void*)&OnChat, context); 100 101 AddTransition(NCS_JOIN_SYNCING, (uint)NMT_GAME_SETUP, NCS_JOIN_SYNCING, (void*)&OnGameSetup, context); … … CNetClient::CNetClient(CGame* game) : 108 109 AddTransition(NCS_LOADING, (uint)NMT_GAME_SETUP, NCS_LOADING, (void*)&OnGameSetup, context); 109 110 AddTransition(NCS_LOADING, (uint)NMT_PLAYER_ASSIGNMENT, NCS_LOADING, (void*)&OnPlayerAssignment, context); 110 111 AddTransition(NCS_LOADING, (uint)NMT_LOADED_GAME, NCS_INGAME, (void*)&OnLoadedGame, context); 111 112 112 113 AddTransition(NCS_INGAME, (uint)NMT_REJOINED, NCS_INGAME, (void*)&OnRejoined, context); 114 AddTransition(NCS_INGAME, (uint)NMT_KICKED, NCS_INGAME, (void*)&OnKicked, context); 113 115 AddTransition(NCS_INGAME, (uint)NMT_CHAT, NCS_INGAME, (void*)&OnChat, context); 114 116 AddTransition(NCS_INGAME, (uint)NMT_GAME_SETUP, NCS_INGAME, (void*)&OnGameSetup, context); 115 117 AddTransition(NCS_INGAME, (uint)NMT_PLAYER_ASSIGNMENT, NCS_INGAME, (void*)&OnPlayerAssignment, context); 116 118 AddTransition(NCS_INGAME, (uint)NMT_SIMULATION_COMMAND, NCS_INGAME, (void*)&OnInGame, context); 117 119 AddTransition(NCS_INGAME, (uint)NMT_SYNC_ERROR, NCS_INGAME, (void*)&OnInGame, context); … … bool CNetClient::OnRejoined(void *contex 605 607 client->PushGuiMessage(msg); 606 608 607 609 return true; 608 610 } 609 611 612 bool CNetClient::OnKicked(void *context, CFsmEvent* event) 613 { 614 ENSURE(event->GetType() == (uint)NMT_KICKED); 615 616 CNetClient* client = (CNetClient*)context; 617 JSContext* cx = client->GetScriptInterface().GetContext(); 618 619 CKickedMessage* message = (CKickedMessage*)event->GetParamRef(); 620 JS::RootedValue msg(cx); 621 client->GetScriptInterface().Eval("({ 'type': 'kicked' })", &msg); 622 client->GetScriptInterface().SetProperty(msg, "username", message->m_Name, false); 623 client->GetScriptInterface().SetProperty(msg, "ban", message->m_Ban, false); 624 client->PushGuiMessage(msg); 625 626 return true; 627 } 628 610 629 bool CNetClient::OnLoadedGame(void* context, CFsmEvent* event) 611 630 { 612 631 ENSURE(event->GetType() == (uint)NMT_LOADED_GAME); 613 632 614 633 CNetClient* client = (CNetClient*)context; -
source/network/NetClient.h
private: 199 199 static bool OnInGame(void* context, CFsmEvent* event); 200 200 static bool OnGameStart(void* context, CFsmEvent* event); 201 201 static bool OnJoinSyncStart(void* context, CFsmEvent* event); 202 202 static bool OnJoinSyncEndCommandBatch(void* context, CFsmEvent* event); 203 203 static bool OnRejoined(void* context, CFsmEvent* event); 204 static bool OnKicked(void* context, CFsmEvent* event); 204 205 static bool OnLoadedGame(void* context, CFsmEvent* event); 205 206 206 207 /** 207 208 * Take ownership of a session object, and use it for all network communication. 208 209 */ -
source/network/NetHost.h
enum NetDisconnectReason 61 61 { 62 62 NDR_UNKNOWN = 0, 63 63 NDR_UNEXPECTED_SHUTDOWN, 64 64 NDR_INCORRECT_PROTOCOL_VERSION, 65 65 NDR_SERVER_LOADING, 66 NDR_SERVER_ALREADY_IN_GAME 66 NDR_SERVER_ALREADY_IN_GAME, 67 NDR_KICKED, 68 NDR_BANNED 67 69 }; 68 70 69 71 class CNetHost 70 72 { 71 73 public: -
source/network/NetMessage.cpp
CNetMessage* CNetMessageFactory::CreateM 133 133 134 134 case NMT_REJOINED: 135 135 pNewMessage = new CRejoinedMessage; 136 136 break; 137 137 138 case NMT_KICKED: 139 pNewMessage = new CKickedMessage; 140 break; 141 138 142 case NMT_LOADED_GAME: 139 143 pNewMessage = new CLoadedGameMessage; 140 144 break; 141 145 142 146 case NMT_SERVER_HANDSHAKE: -
source/network/NetMessages.h
26 26 #include "ps/CStr.h" 27 27 #include "scriptinterface/ScriptVal.h" 28 28 29 29 #define PS_PROTOCOL_MAGIC 0x5073013f // 'P', 's', 0x01, '?' 30 30 #define PS_PROTOCOL_MAGIC_RESPONSE 0x50630121 // 'P', 'c', 0x01, '!' 31 #define PS_PROTOCOL_VERSION 0x0101000 7// Arbitrary protocol31 #define PS_PROTOCOL_VERSION 0x01010008 // Arbitrary protocol 32 32 #define PS_DEFAULT_PORT 0x5073 // 'P', 's' 33 33 34 34 // Defines the list of message types. The order of the list must not change. 35 35 // The message types having a negative value are used internally and not sent 36 36 // over the network. The message types used for network communication have … … enum NetMessageType 56 56 NMT_FILE_TRANSFER_ACK, 57 57 58 58 NMT_JOIN_SYNC_START, 59 59 60 60 NMT_REJOINED, 61 NMT_KICKED, 61 62 62 63 NMT_LOADED_GAME, 63 64 NMT_GAME_START, 64 65 NMT_END_COMMAND_BATCH, 65 66 NMT_SYNC_CHECK, // OOS-detection hash checking … … END_NMT_CLASS() 159 160 160 161 START_NMT_CLASS_(Rejoined, NMT_REJOINED) 161 162 NMT_FIELD(CStr8, m_GUID) 162 163 END_NMT_CLASS() 163 164 165 START_NMT_CLASS_(Kicked, NMT_KICKED) 166 NMT_FIELD(CStrW, m_Name) 167 NMT_FIELD_INT(m_Ban, bool, 1) 168 END_NMT_CLASS() 169 164 170 START_NMT_CLASS_(LoadedGame, NMT_LOADED_GAME) 165 171 NMT_FIELD_INT(m_CurrentTurn, u32, 4) 166 172 END_NMT_CLASS() 167 173 168 174 START_NMT_CLASS_(GameStart, NMT_GAME_START) -
source/network/NetServer.cpp
private: 119 119 120 120 CNetServerWorker::CNetServerWorker(int autostartPlayers) : 121 121 m_AutostartPlayers(autostartPlayers), 122 122 m_Shutdown(false), 123 123 m_ScriptInterface(NULL), 124 m_NextHostID(1), m_Host(NULL), m_ Stats(NULL)124 m_NextHostID(1), m_Host(NULL), m_HostGUID(), m_Stats(NULL) 125 125 { 126 126 m_State = SERVER_STATE_UNCONNECTED; 127 127 128 128 m_ServerTurnManager = NULL; 129 129 … … bool CNetServerWorker::RunStep() 472 472 473 473 switch (event.type) 474 474 { 475 475 case ENET_EVENT_TYPE_CONNECT: 476 476 { 477 // Report the client address478 char hostname[256] = "(error)";479 enet_address_get_host_ip(&event.peer->address, hostname, ARRAY_SIZE(hostname));480 LOGMESSAGE("Net server: Received connection from %s:%u", hostname, (unsigned int)event.peer->address.port);481 482 477 // Set up a session object for this peer 483 484 478 CNetServerSession* session = new CNetServerSession(*this, event.peer); 485 479 480 // Report the client address 481 LOGMESSAGE("Net server: Received connection from %s:%u", session->GetIPAddress().c_str(), (unsigned int)event.peer->address.port); 482 486 483 m_Sessions.push_back(session); 487 484 488 485 SetupSession(session); 489 486 490 487 ENSURE(event.peer->data == NULL); … … void CNetServerWorker::SetupSession(CNet 608 605 session->SetFirstState(NSS_HANDSHAKE); 609 606 } 610 607 611 608 bool CNetServerWorker::HandleConnect(CNetServerSession* session) 612 609 { 610 CNetServerWorker& server = session->GetServer(); 611 612 // Disconnect banned IPs 613 if (std::find(server.m_BannedIPs.begin(), server.m_BannedIPs.end(), session->GetIPAddress()) != server.m_BannedIPs.end()) 614 { 615 session->Disconnect(NDR_BANNED); 616 return false; 617 } 618 619 // Send handshake challenge 613 620 CSrvHandshakeMessage handshake; 614 621 handshake.m_Magic = PS_PROTOCOL_MAGIC; 615 622 handshake.m_ProtocolVersion = PS_PROTOCOL_VERSION; 616 623 handshake.m_SoftwareVersion = PS_PROTOCOL_VERSION; 617 624 return session->SendMessage(&handshake); … … bool CNetServerWorker::HandleConnect(CNe 619 626 620 627 void CNetServerWorker::OnUserJoin(CNetServerSession* session) 621 628 { 622 629 AddPlayer(session->GetGUID(), session->GetUserName()); 623 630 631 // Host is the first to join 632 if (m_HostGUID.empty()) 633 m_HostGUID = session->GetGUID(); 634 624 635 CGameSetupMessage gameSetupMessage(GetScriptInterface()); 625 636 gameSetupMessage.m_Data = m_GameAttributes.get(); 626 637 session->SendMessage(&gameSetupMessage); 627 638 628 639 CPlayerAssignmentMessage assignMessage; … … void CNetServerWorker::ClearAllPlayerRea 711 722 it->second.m_Status = 0; 712 723 713 724 SendPlayerAssignments(); 714 725 } 715 726 727 bool CNetServerWorker::KickPlayer(const CStrW& playerName, const bool ban) 728 { 729 // Find the user with that name 730 std::vector<CNetServerSession*>::iterator it = std::find_if(m_Sessions.begin(), m_Sessions.end(), 731 [&](CNetServerSession* session) { return session->GetUserName() == playerName; }); 732 733 // and return if no one or the host has that name 734 if (it == m_Sessions.end() || (*it)->GetGUID() == m_HostGUID) 735 return false; 736 737 if (ban) 738 { 739 // Remember name 740 if (std::find(m_BannedPlayers.begin(), m_BannedPlayers.end(), playerName) == m_BannedPlayers.end()) 741 m_BannedPlayers.push_back(playerName); 742 743 // Remember IP address 744 CStr ipAddress = GetPlayerIPAddress(playerName); 745 if (ipAddress != "(error)" && std::find(m_BannedIPs.begin(), m_BannedIPs.end(), ipAddress) == m_BannedIPs.end()) 746 m_BannedIPs.push_back(ipAddress); 747 } 748 749 // Disconnect that user 750 (*it)->Disconnect(ban ? NDR_BANNED : NDR_KICKED); 751 752 // Send message notifying other clients 753 CKickedMessage kickedMessage; 754 kickedMessage.m_Name = playerName; 755 kickedMessage.m_Ban = ban; 756 Broadcast(&kickedMessage); 757 758 return true; 759 } 760 761 CStr CNetServerWorker::GetPlayerIPAddress(const CStrW& playerName) 762 { 763 for (CNetServerSession* session : m_Sessions) 764 if (session->GetUserName() == playerName) 765 return session->GetIPAddress(); 766 return "(error)"; 767 } 768 716 769 void CNetServerWorker::AssignPlayer(int playerID, const CStr& guid) 717 770 { 718 771 // Remove anyone who's already assigned to this player 719 772 for (PlayerAssignmentMap::iterator it = m_PlayerAssignments.begin(); it != m_PlayerAssignments.end(); ++it) 720 773 { … … bool CNetServerWorker::OnClientHandshake 768 821 ENSURE(event->GetType() == (uint)NMT_CLIENT_HANDSHAKE); 769 822 770 823 CNetServerSession* session = (CNetServerSession*)context; 771 824 CNetServerWorker& server = session->GetServer(); 772 825 826 // Check protocol version 773 827 CCliHandshakeMessage* message = (CCliHandshakeMessage*)event->GetParamRef(); 774 828 if (message->m_ProtocolVersion != PS_PROTOCOL_VERSION) 775 829 { 776 830 session->Disconnect(NDR_INCORRECT_PROTOCOL_VERSION); 777 831 return false; 778 832 } 779 833 834 // Send handshake response 780 835 CSrvHandshakeResponseMessage handshakeResponse; 781 836 handshakeResponse.m_UseProtocolVersion = PS_PROTOCOL_VERSION; 782 837 handshakeResponse.m_Message = server.m_WelcomeMessage; 783 838 handshakeResponse.m_Flags = 0; 784 839 session->SendMessage(&handshakeResponse); … … bool CNetServerWorker::OnAuthenticate(vo 802 857 } 803 858 804 859 CAuthenticateMessage* message = (CAuthenticateMessage*)event->GetParamRef(); 805 860 CStrW username = server.DeduplicatePlayerName(SanitisePlayerName(message->m_Name)); 806 861 862 // Disconnect banned usernames 863 if (std::find(server.m_BannedPlayers.begin(), server.m_BannedPlayers.end(), username) != server.m_BannedPlayers.end()) 864 { 865 session->Disconnect(NDR_BANNED); 866 return true; 867 } 868 807 869 // Optionally allow observers to join after the game has started 808 870 bool observerLateJoin = false; 809 871 ScriptInterface& scriptInterface = server.GetScriptInterface(); 810 872 JSContext* cx = scriptInterface.GetContext(); 811 873 JSAutoRequest rq(cx); … … CNetServer::~CNetServer() 1151 1213 bool CNetServer::SetupConnection() 1152 1214 { 1153 1215 return m_Worker->SetupConnection(); 1154 1216 } 1155 1217 1218 bool CNetServer::KickPlayer(const CStrW& playerName, const bool ban) 1219 { 1220 CScopeLock lock(m_Worker->m_WorkerMutex); 1221 return m_Worker->KickPlayer(playerName, ban); 1222 } 1223 1156 1224 void CNetServer::AssignPlayer(int playerID, const CStr& guid) 1157 1225 { 1158 1226 CScopeLock lock(m_Worker->m_WorkerMutex); 1159 1227 m_Worker->m_AssignPlayerQueue.emplace_back(playerID, guid); 1160 1228 } -
source/network/NetServer.h
public: 132 132 /** 133 133 * Call from the GUI to set the all player readiness to 0. 134 134 * The changes will be asynchronously propagated to all clients. 135 135 */ 136 136 void ClearAllPlayerReady(); 137 137 138 /** 139 * Disconnects a player from the gamesetup / session. 140 */ 141 bool KickPlayer(const CStrW& playerName, const bool ban); 142 138 143 /** 139 144 * Call from the GUI to asynchronously notify all clients that they should start loading the game. 140 145 */ 141 146 void StartGame(); 142 147 … … public: 181 186 * Send a message to the given network peer. 182 187 */ 183 188 bool SendMessage(ENetPeer* peer, const CNetMessage* message); 184 189 185 190 /** 191 * Disconnected a player from the match / gamesetup and optionally prevents him/her from rejoining. 192 */ 193 bool KickPlayer(const CStrW& playerName, const bool ban); 194 195 /** 186 196 * Send a message to all clients who have completed the full connection process 187 197 * (i.e. are in the pre-game or in-game states). 188 198 */ 189 199 bool Broadcast(const CNetMessage* message); 190 200 201 /** 202 * Returns the IP address of the given connected player. 203 */ 204 CStr GetPlayerIPAddress(const CStrW& playerName); 205 191 206 private: 192 207 friend class CNetServer; 193 208 friend class CNetFileReceiveTask_ServerRejoin; 194 209 195 210 CNetServerWorker(int autostartPlayers); … … private: 244 259 void SetTurnLength(u32 msecs); 245 260 246 261 void AddPlayer(const CStr& guid, const CStrW& name); 247 262 void RemovePlayer(const CStr& guid); 248 263 void SetPlayerReady(const CStr& guid, const int ready); 264 CStr GetHostGUID(); 249 265 void SendPlayerAssignments(); 250 266 void ClearAllPlayerReady(); 251 267 252 268 void SetupSession(CNetServerSession* session); 253 269 bool HandleConnect(CNetServerSession* session); … … private: 297 313 NetServerState m_State; 298 314 299 315 CStrW m_ServerName; 300 316 CStrW m_WelcomeMessage; 301 317 318 std::vector<CStr> m_BannedIPs; 319 std::vector<CStrW> m_BannedPlayers; 320 302 321 u32 m_NextHostID; 303 322 304 323 CNetServerTurnManager* m_ServerTurnManager; 305 324 325 CStr m_HostGUID; 326 306 327 /** 307 328 * A copy of all simulation commands received so far, indexed by 308 329 * turn number, to simplify support for rejoining etc. 309 330 * TODO: verify this doesn't use too much RAM. 310 331 */ -
source/network/NetSession.cpp
1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 5 * it under the terms of the GNU General Public License as published by 6 6 * the Free Software Foundation, either version 2 of the License, or … … bool CNetClientSession::SendMessage(cons 173 173 CNetServerSession::CNetServerSession(CNetServerWorker& server, ENetPeer* peer) : 174 174 m_Server(server), m_FileTransferer(this), m_Peer(peer) 175 175 { 176 176 } 177 177 178 CStr CNetServerSession::GetIPAddress() 179 { 180 char ipAddress[256] = "(error)"; 181 if (enet_address_get_host_ip(&(m_Peer->address), ipAddress, ARRAY_SIZE(ipAddress)) < 0) 182 { 183 LOGERROR("Could not get IP address of a client!"); 184 return "(error)"; 185 } 186 187 return CStr(ipAddress); 188 } 189 178 190 void CNetServerSession::Disconnect(u32 reason) 179 191 { 180 192 Update((uint)NMT_CONNECTION_LOST, NULL); 181 193 182 194 enet_peer_disconnect(m_Peer, reason); -
source/network/NetSession.h
1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 5 * it under the terms of the GNU General Public License as published by 6 6 * the Free Software Foundation, either version 2 of the License, or … … public: 121 121 122 122 u32 GetHostID() const { return m_HostID; } 123 123 void SetHostID(u32 id) { m_HostID = id; } 124 124 125 125 /** 126 * Returns the IP address of the client. 127 */ 128 CStr GetIPAddress(); 129 130 /** 126 131 * Sends a disconnection notification to the client, 127 132 * and sends a NMT_CONNECTION_LOST message to the session FSM. 128 133 * The server will receive a disconnection notification after a while. 129 134 * The server will not receive any further messages sent via this session. 130 135 */