Ticket #3241: t3241_kick_v5.patch
File t3241_kick_v5.patch, 27.9 KB (added by , 9 years ago) |
---|
-
binaries/data/mods/public/gui/common/network.js
5 5 { 6 6 case 0: return translate("Unknown reason"); 7 7 case 1: return translate("Unexpected shutdown"); 8 8 case 2: return translate("Incorrect network protocol version"); 9 9 case 3: return translate("Game has already started"); 10 case 4: return translate("You have been kicked from the match"); 11 case 5: return translate("You have been banned from the match"); 10 12 default: return sprintf(translate("\\[Invalid value %(id)s]"), { id: id }); 11 13 } 12 14 } 13 15 14 16 function reportDisconnect(reason) -
binaries/data/mods/public/gui/gamesetup/gamesetup.js
495 495 496 496 case "chat": 497 497 addChatMessage({ "type": "message", "guid": message.guid, "text": message.text }); 498 498 break; 499 499 500 case "kicked": 501 addChatMessage({ "type": message.ban ? "banned" : "kicked", "username": message.username }); 502 break; 503 500 504 // Singular client to host message 501 505 case "ready": 502 506 g_ReadyChanged -= 1; 503 507 if (g_ReadyChanged < 1 && g_PlayerAssignments[message.guid].player != -1) 504 508 addChatMessage({ "type": "ready", "guid": message.guid, "ready": +message.status == 1 }); … … 1680 1684 } 1681 1685 1682 1686 function submitChatInput() 1683 1687 { 1684 1688 var input = Engine.GetGUIObjectByName("chatInput"); 1685 var text = input.caption; 1686 if (text.length) 1689 var text = input.caption.trim(); 1690 input.caption = ""; 1691 1692 if (!text.length) 1693 return; 1694 1695 if (text.indexOf("/") == 0) 1687 1696 { 1688 Engine.SendNetworkChat(text); 1689 input.caption = ""; 1697 let kick = text.indexOf("/kick ") == 0; 1698 let ban = text.indexOf("/ban ") == 0; 1699 if (kick || ban) 1700 Engine.KickPlayer(text.substr(text.indexOf(" ") + 1), ban); 1701 return; 1690 1702 } 1703 1704 Engine.SendNetworkChat(text); 1691 1705 } 1692 1706 1693 1707 function addChatMessage(msg) 1694 1708 { 1695 1709 var username = ""; … … 1729 1743 case "disconnect": 1730 1744 var formattedUsername = '[color="'+ color +'"]' + username + '[/color]'; 1731 1745 formatted = '[font="sans-bold-13"] ' + sprintf(translate("== %(message)s"), { message: sprintf(translate("%(username)s has left"), { username: formattedUsername }) }) + '[/font]'; 1732 1746 break; 1733 1747 1748 case "kicked": 1749 formatted = '[font="sans-bold-13"] ' + sprintf(translate("== %(message)s"), { message: sprintf(translate("%(username)s has been kicked."), { username: username }) }) + '[/font]'; 1750 break; 1751 1752 case "banned": 1753 formatted = '[font="sans-bold-13"] ' + sprintf(translate("== %(message)s"), { message: sprintf(translate("%(username)s has been banned."), { username: username }) }) + '[/font]'; 1754 break; 1755 1734 1756 case "message": 1735 1757 var formattedUsername = '[color="'+ color +'"]' + username + '[/color]'; 1736 1758 var formattedUsernamePrefix = '[font="sans-bold-13"]' + sprintf(translate("<%(username)s>"), { username: formattedUsername }) + '[/font]' 1737 1759 formatted = sprintf(translate("%(username)s %(message)s"), { username: formattedUsernamePrefix, message: message }); 1738 1760 break; -
binaries/data/mods/public/gui/gamesetup/gamesetup_mp.xml
2 2 3 3 <objects> 4 4 5 5 <script file="gui/common/network.js"/> 6 6 <script file="gui/common/functions_global_object.js"/> 7 <script file="gui/common/functions_utility.js"/> 7 8 <script file="gui/gamesetup/gamesetup_mp.js"/> 8 9 9 10 <!-- Add a translucent black background to fade out the menu page --> 10 11 <object type="image" sprite="ModernFade"/> 11 12 … … 46 47 </object> 47 48 48 49 <object hotkey="confirm" type="button" size="50%+5 100%-45 100%-18 100%-17" style="ModernButtonRed"> 49 50 <translatableAttribute id="caption">Continue</translatableAttribute> 50 51 <action on="Press"> 51 var joinPlayerName = Engine.GetGUIObjectByName("joinPlayerName").caption;52 var joinPlayerName = sanitizePlayerName(Engine.GetGUIObjectByName("joinPlayerName").caption, true, true); 52 53 var joinServer = Engine.GetGUIObjectByName("joinServer").caption; 53 54 if (startJoin(joinPlayerName, joinServer)) 54 55 switchSetupPage("pageJoin", "pageConnecting"); 55 56 </action> 56 57 </object> … … 88 89 </object> 89 90 90 91 <object type="button" size="50%+5 100%-45 100%-18 100%-17" style="ModernButtonRed"> 91 92 <translatableAttribute id="caption">Continue</translatableAttribute> 92 93 <action on="Press"> 93 var hostPlayerName = Engine.GetGUIObjectByName("hostPlayerName").caption;94 var hostPlayerName = sanitizePlayerName(Engine.GetGUIObjectByName("hostPlayerName").caption, true, true); 94 95 var hostServerName = Engine.GetGUIObjectByName("hostServerName").caption; 95 96 if (startHost(hostPlayerName, hostServerName)) 96 97 switchSetupPage("pageHost", "pageConnecting"); 97 98 </action> 98 99 </object> -
binaries/data/mods/public/gui/session/messages.js
241 241 obj.caption = translate("Connection to the server has been authenticated."); 242 242 obj.hidden = false; 243 243 break; 244 244 case "disconnected": 245 245 g_Disconnected = true; 246 obj.caption = translate("Connection to the server has been lost.") + "\n\n" + translate("The game has ended."); 246 obj.caption = translate("Connection to the server has been lost.") + "\n" + 247 sprintf(translate("Reason: %(reason)s."), { reason: getDisconnectReason(message.reason) }) + "\n" + 248 translate("The game has ended."); 247 249 obj.hidden = false; 248 250 break; 249 251 default: 250 252 error("Unrecognised netstatus type '" + message.status + "'"); 251 253 break; … … 296 298 case "aichat": 297 299 addChatMessage({ "type": "message", "guid": message.guid, "text": message.text, "translate": true }); 298 300 break; 299 301 300 302 case "rejoined": 301 addChatMessage({ "type": "rejoined", "guid": message.guid });303 addChatMessage({ "type": "rejoined", "guid": message.guid }); 302 304 break; 303 305 306 case "kicked": 307 addChatMessage({ "type": message.ban ? "banned" : "kicked", "username": message.username }); 308 break; 309 304 310 // To prevent errors, ignore these message types that occur during autostart 305 311 case "gamesetup": 306 312 case "start": 307 313 break; 308 314 … … 323 329 } 324 330 325 331 function submitChatInput() 326 332 { 327 333 var input = Engine.GetGUIObjectByName("chatInput"); 328 var text = input.caption ;334 var text = input.caption.trim(); 329 335 var isCheat = false; 336 330 337 if (text.length) 331 338 { 339 // Parse cheats 332 340 if (!g_IsObserver && g_Players[Engine.GetPlayerID()].cheatsEnabled) 333 341 { 334 342 for each (var cheat in Object.keys(cheats)) 335 343 { 336 344 // Line must start with the cheat. … … 374 382 isCheat = true; 375 383 break; 376 384 } 377 385 } 378 386 387 // Parse direct commands 388 if (text.indexOf("/") == 0) 389 { 390 if (text == "/list") 391 addChatMessage({ "type": "clientlist", "guid": "local"}); 392 else 393 { 394 let kick = text.indexOf("/kick ") == 0; 395 let ban = text.indexOf("/ban ") == 0; 396 if (kick || ban) 397 Engine.KickPlayer(text.substr(text.indexOf(" ") + 1), ban); 398 } 399 } 379 400 // Observers should only send messages to "/all" 380 if (!isCheat && (!g_IsObserver || text.indexOf("/") == -1 || text.indexOf("/all ") == 0))401 else if (!isCheat && (!g_IsObserver || text.indexOf("/") == -1 || text.indexOf("/all ") == 0)) 381 402 { 382 403 if (Engine.GetGUIObjectByName("toggleTeamChat").checked) 383 404 text = "/team " + text; 384 405 385 406 if (g_IsNetworked) … … 446 467 formatted = sprintf(translate("%(player)s has left the game."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 447 468 break; 448 469 case "rejoined": 449 470 formatted = sprintf(translate("%(player)s has rejoined the game."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 450 471 break; 472 case "kicked": 473 formatted = sprintf(translate("%(username)s has been kicked."), { "username": msg.username }); 474 break; 475 case "banned": 476 formatted = sprintf(translate("%(username)s has been banned."), { "username": msg.username }); 477 break; 451 478 case "defeat": 452 479 // In singleplayer, the local player is "You". "You has" is incorrect. 453 480 if (!g_IsNetworked && msg.player == Engine.GetPlayerID()) 454 481 formatted = translate("You have been defeated."); 455 482 else 456 483 formatted = sprintf(translate("%(player)s has been defeated."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 457 484 break; 485 case "clientlist": 486 // List playernames sorted by slot, observers last 487 let userlist = Object.keys(playerAssignments).sort((guidA, guidB) => 488 { 489 let playerA = playerAssignments[guidA].player; 490 let playerB = playerAssignments[guidB].player; 491 return playerA == -1 || playerB == -1 ? 1 : playerA - playerB; 492 }).map(guid => playerAssignments[guid].name).join(","); 493 formatted = sprintf(translate("Users: %(users)s"), { "users": userlist }); 494 break; 458 495 case "diplomacy": 459 496 var message; 460 497 if (msg.player == Engine.GetPlayerID()) 461 498 { 462 499 [username, playerColor] = getUsernameAndColor(msg.player1); -
binaries/data/mods/public/gui/session/session.xml
5 5 <script file="gui/common/colorFades.js"/> 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 <script file="gui/common/network.js"/> 10 11 <script file="gui/common/music.js"/> 11 12 <script file="gui/common/timer.js"/> 12 13 <script file="gui/common/tooltips.js"/> 13 14 <!-- load all scripts in this directory --> 14 15 <script directory="gui/session/"/> -
source/gui/scripting/ScriptFunctions.cpp
345 345 SAFE_DELETE(g_NetServer); 346 346 SAFE_DELETE(g_NetClient); 347 347 SAFE_DELETE(g_Game); 348 348 } 349 349 350 void KickPlayer(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), CStrW playerName, bool ban) 351 { 352 if (g_NetServer) 353 g_NetServer->KickPlayer(playerName, ban); 354 } 355 350 356 JS::Value PollNetworkClient(ScriptInterface::CxPrivate* pCxPrivate) 351 357 { 352 358 if (!g_NetClient) 353 359 return JS::UndefinedValue(); 354 360 … … 954 960 scriptInterface.RegisterFunction<void, JS::HandleValue, int, &StartGame>("StartGame"); 955 961 scriptInterface.RegisterFunction<void, &Script_EndGame>("EndGame"); 956 962 scriptInterface.RegisterFunction<void, std::wstring, &StartNetworkHost>("StartNetworkHost"); 957 963 scriptInterface.RegisterFunction<void, std::wstring, std::string, &StartNetworkJoin>("StartNetworkJoin"); 958 964 scriptInterface.RegisterFunction<void, &DisconnectNetworkGame>("DisconnectNetworkGame"); 965 scriptInterface.RegisterFunction<void, CStrW, bool, &KickPlayer>("KickPlayer"); 959 966 scriptInterface.RegisterFunction<JS::Value, &PollNetworkClient>("PollNetworkClient"); 960 967 scriptInterface.RegisterFunction<void, JS::HandleValue, &SetNetworkGameAttributes>("SetNetworkGameAttributes"); 961 968 scriptInterface.RegisterFunction<void, int, std::string, &AssignNetworkPlayer>("AssignNetworkPlayer"); 962 969 scriptInterface.RegisterFunction<void, std::string, int, &SetNetworkPlayerStatus>("SetNetworkPlayerStatus"); 963 970 scriptInterface.RegisterFunction<void, &ClearAllPlayerReady>("ClearAllPlayerReady"); -
source/network/NetClient.cpp
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); … … 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); … … 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
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
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 … … 60 60 enum NetDisconnectReason 61 61 { 62 62 NDR_UNKNOWN = 0, 63 63 NDR_UNEXPECTED_SHUTDOWN, 64 64 NDR_INCORRECT_PROTOCOL_VERSION, 65 NDR_SERVER_ALREADY_IN_GAME 65 NDR_SERVER_ALREADY_IN_GAME, 66 NDR_KICKED, 67 NDR_BANNED 66 68 }; 67 69 68 70 class CNetHost 69 71 { 70 72 public: -
source/network/NetMessage.cpp
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
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 … … 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
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 … … 604 604 session->SetFirstState(NSS_HANDSHAKE); 605 605 } 606 606 607 607 bool CNetServerWorker::HandleConnect(CNetServerSession* session) 608 608 { 609 CNetServerWorker& server = session->GetServer(); 610 611 // Disconnect banned IPs 612 if (std::find(server.m_BannedIPs.begin(), server.m_BannedIPs.end(), session->GetIPAddress()) != server.m_BannedIPs.end()) 613 { 614 session->Disconnect(NDR_BANNED); 615 return false; 616 } 617 618 // Send handshake challenge 609 619 CSrvHandshakeMessage handshake; 610 620 handshake.m_Magic = PS_PROTOCOL_MAGIC; 611 621 handshake.m_ProtocolVersion = PS_PROTOCOL_VERSION; 612 622 handshake.m_SoftwareVersion = PS_PROTOCOL_VERSION; 613 623 return session->SendMessage(&handshake); … … 615 625 616 626 void CNetServerWorker::OnUserJoin(CNetServerSession* session) 617 627 { 618 628 AddPlayer(session->GetGUID(), session->GetUserName()); 619 629 630 if (m_HostGUID.empty()) 631 m_HostGUID = session->GetGUID(); 632 620 633 CGameSetupMessage gameSetupMessage(GetScriptInterface()); 621 634 gameSetupMessage.m_Data = m_GameAttributes.get(); 622 635 session->SendMessage(&gameSetupMessage); 623 636 624 637 CPlayerAssignmentMessage assignMessage; … … 630 643 { 631 644 RemovePlayer(session->GetGUID()); 632 645 633 646 if (m_ServerTurnManager && session->GetCurrState() != NSS_JOIN_SYNCING) 634 647 m_ServerTurnManager->UninitialiseClient(session->GetHostID()); // TODO: only for non-observers 635 636 // TODO: ought to switch the player controlled by that client637 // back to AI control, or something?638 648 } 639 649 640 650 void CNetServerWorker::AddPlayer(const CStr& guid, const CStrW& name) 641 651 { 642 652 // Find all player IDs in active use; we mustn't give them to a second player (excluding the unassigned ID: -1) … … 707 717 it->second.m_Status = 0; 708 718 709 719 SendPlayerAssignments(); 710 720 } 711 721 722 void CNetServerWorker::KickPlayer(const CStrW& playerName, const bool ban) 723 { 724 // Check if actually a user with that name is connected 725 bool exists = false; 726 for (CNetServerSession* session : m_Sessions) 727 if (session->GetUserName() == playerName) 728 { 729 // Prevent the host from kicking him/herself 730 if (session->GetGUID() == m_HostGUID) 731 return; 732 exists = true; 733 break; 734 } 735 736 if (!exists) 737 return; 738 739 if (ban) 740 { 741 // Remember playername 742 if (std::find(m_BannedPlayers.begin(), m_BannedPlayers.end(), playerName) == m_BannedPlayers.end()) 743 m_BannedPlayers.emplace_back(playerName); 744 745 // Remember IP address 746 CStr ipAddress = GetPlayerIPAddress(playerName); 747 if (std::find(m_BannedIPs.begin(), m_BannedIPs.end(), ipAddress) == m_BannedIPs.end()) 748 m_BannedIPs.push_back(ipAddress); 749 } 750 751 // Disconnect user 752 for (CNetServerSession* session : m_Sessions) 753 if (session->GetUserName() == playerName) 754 { 755 session->Disconnect(ban ? NDR_BANNED : NDR_KICKED); 756 break; 757 } 758 759 // Send message notifying other clients 760 CKickedMessage kickedMessage; 761 kickedMessage.m_Name = playerName; 762 kickedMessage.m_Ban = ban; 763 Broadcast(&kickedMessage); 764 } 765 766 CStr CNetServerWorker::GetPlayerIPAddress(const CStrW& playerName) 767 { 768 for (CNetServerSession* session : m_Sessions) 769 if (session->GetUserName() == playerName) 770 return session->GetIPAddress(); 771 return "(error)"; 772 } 773 712 774 void CNetServerWorker::AssignPlayer(int playerID, const CStr& guid) 713 775 { 714 776 // Remove anyone who's already assigned to this player 715 777 for (PlayerAssignmentMap::iterator it = m_PlayerAssignments.begin(); it != m_PlayerAssignments.end(); ++it) 716 778 { … … 764 826 ENSURE(event->GetType() == (uint)NMT_CLIENT_HANDSHAKE); 765 827 766 828 CNetServerSession* session = (CNetServerSession*)context; 767 829 CNetServerWorker& server = session->GetServer(); 768 830 831 // Check protocol version 769 832 CCliHandshakeMessage* message = (CCliHandshakeMessage*)event->GetParamRef(); 770 833 if (message->m_ProtocolVersion != PS_PROTOCOL_VERSION) 771 834 { 772 835 session->Disconnect(NDR_INCORRECT_PROTOCOL_VERSION); 773 836 return false; 774 837 } 775 838 839 // Send handshake response 776 840 CSrvHandshakeResponseMessage handshakeResponse; 777 841 handshakeResponse.m_UseProtocolVersion = PS_PROTOCOL_VERSION; 778 842 handshakeResponse.m_Message = server.m_WelcomeMessage; 779 843 handshakeResponse.m_Flags = 0; 780 844 session->SendMessage(&handshakeResponse); … … 791 855 792 856 CAuthenticateMessage* message = (CAuthenticateMessage*)event->GetParamRef(); 793 857 794 858 CStrW username = server.DeduplicatePlayerName(SanitisePlayerName(message->m_Name)); 795 859 860 // Disconnect banned usernames 861 if (std::find(server.m_BannedPlayers.begin(), server.m_BannedPlayers.end(), username) != server.m_BannedPlayers.end()) 862 { 863 session->Disconnect(NDR_BANNED); 864 return true; 865 } 866 796 867 bool isRejoining = false; 797 868 798 869 if (server.m_State != SERVER_STATE_PREGAME) 799 870 { 800 871 // isRejoining = true; // uncomment this to test rejoining even if the player wasn't connected previously … … 1133 1204 bool CNetServer::SetupConnection() 1134 1205 { 1135 1206 return m_Worker->SetupConnection(); 1136 1207 } 1137 1208 1209 void CNetServer::KickPlayer(const CStrW& playerName, const bool ban) 1210 { 1211 CScopeLock lock(m_Worker->m_WorkerMutex); 1212 m_Worker->KickPlayer(playerName, ban); 1213 } 1214 1138 1215 void CNetServer::AssignPlayer(int playerID, const CStr& guid) 1139 1216 { 1140 1217 CScopeLock lock(m_Worker->m_WorkerMutex); 1141 1218 m_Worker->m_AssignPlayerQueue.emplace_back(playerID, guid); 1142 1219 } -
source/network/NetServer.h
120 120 * The given GUID will be (re)assigned to the given player ID. 121 121 * Any player currently using that ID will be unassigned. 122 122 * The changes will be asynchronously propagated to all clients. 123 123 */ 124 124 void AssignPlayer(int playerID, const CStr& guid); 125 125 126 126 /** 127 127 * Call from the GUI to update the player readiness. 128 128 * The changes will be asynchronously propagated to all clients. 129 129 */ 130 130 void SetPlayerReady(const CStr& guid, int ready); … … 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 void 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 … … 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 void 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); … … 243 258 */ 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 void SetPlayerReady(const CStr& guid, const int ready); 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); … … 269 285 270 286 void ConstructPlayerAssignmentMessage(CPlayerAssignmentMessage& message); 271 287 272 288 void HandleMessageReceive(const CNetMessage* message, CNetServerSession* session); 273 289 274 275 290 /** 276 291 * Internal script context for (de)serializing script messages, 277 292 * and for storing game attributes. 278 293 * (TODO: we shouldn't bother deserializing (except for debug printing of messages), 279 294 * we should just forward messages blindly and efficiently.) … … 297 312 NetServerState m_State; 298 313 299 314 CStrW m_ServerName; 300 315 CStrW m_WelcomeMessage; 301 316 317 std::vector<CStr> m_BannedIPs; 318 std::vector<CStrW> m_BannedPlayers; 319 302 320 u32 m_NextHostID; 303 321 304 322 CNetServerTurnManager* m_ServerTurnManager; 305 323 324 CStr m_HostGUID; 325 306 326 /** 307 327 * A copy of all simulation commands received so far, indexed by 308 328 * turn number, to simplify support for rejoining etc. 309 329 * TODO: verify this doesn't use too much RAM. 310 330 */ -
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 … … 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 enet_address_get_host_ip(&(m_Peer->address), ipAddress, ARRAY_SIZE(ipAddress)); 182 return CStr(ipAddress); 183 } 184 178 185 void CNetServerSession::Disconnect(u32 reason) 179 186 { 180 187 Update((uint)NMT_CONNECTION_LOST, NULL); 181 188 182 189 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 … … 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 */