Ticket #3241: t3241_kick_v4.1.patch

File t3241_kick_v4.1.patch, 25.6 KB (added by elexis, 9 years ago)

Changed std::string("") to std::string(). Removed dots from non-sentences in network.js. The removal of trailing whitespace in two exisiting empty lines is intentional.

  • binaries/data/mods/public/gui/common/network.js

     
    55    {
    66    case 0: return translate("Unknown reason");
    77    case 1: return translate("Unexpected shutdown");
    88    case 2: return translate("Incorrect network protocol version");
    99    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.");
    1012    default: return sprintf(translate("\\[Invalid value %(id)s]"), { id: id });
    1113    }
    1214}
    1315
    1416function reportDisconnect(reason)
  • binaries/data/mods/public/gui/gamesetup/gamesetup.js

     
    17001700
    17011701    var message = "";
    17021702    if ("text" in msg && msg.text)
    17031703        message = escapeText(msg.text);
    17041704
     1705    // Kick / ban players
     1706    if ("text" in msg)
     1707    {
     1708        let split = msg.text.split(/\s/);
     1709        let kick = msg.text.indexOf("/kick") == 0;
     1710        let ban = msg.text.indexOf("/ban") == 0;
     1711        let playerGUID = Engine.GetPlayerGUID();
     1712        if (kick || ban)
     1713        {
     1714            if (!g_IsNetworked || !g_IsController || msg.guid != playerGUID)
     1715                return;
     1716            let trimmed = msg.text.substr(split[0].length + 1);
     1717            let matched = "";
     1718            // Reject names which don't match or are a superset of the intended name.
     1719            for each (let player in g_PlayerAssignments)
     1720                if (trimmed.indexOf(player.name) == 0 && player.name.length > matched.length)
     1721                    matched = player.name;
     1722            // Prevent the host from kicking him/herself
     1723            if (matched.length && matched != g_PlayerAssignments[playerGUID].name)
     1724            {
     1725                // Sending the message takes a while, so we phrase this past tense.
     1726                // The text should be translated for each client individually (see #3304)
     1727                Engine.SendNetworkChat(matched + " has been " + (ban ? "banned" : "kicked") + ".");
     1728                Engine.KickPlayer(matched, ban);
     1729            }
     1730            return;
     1731        }
     1732    }
     1733
    17051734    // TODO: Maybe host should have distinct font/color?
    17061735    var color = "white";
    17071736
    17081737    if (msg.guid && g_PlayerAssignments[msg.guid] && g_PlayerAssignments[msg.guid].player != -1)
    17091738    {
  • binaries/data/mods/public/gui/session/messages.js

     
    241241            obj.caption = translate("Connection to the server has been authenticated.");
    242242            obj.hidden = false;
    243243            break;
    244244        case "disconnected":
    245245            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                getDisconnectReason(message.reason) + "\n" + translate("The game has ended.");
    247248            obj.hidden = false;
    248249            break;
    249250        default:
    250251            error("Unrecognised netstatus type '" + message.status + "'");
    251252            break;
     
    325326function submitChatInput()
    326327{
    327328    var input = Engine.GetGUIObjectByName("chatInput");
    328329    var text = input.caption;
    329330    var isCheat = false;
     331
    330332    if (text.length)
    331333    {
     334        // Check cheats
    332335        if (!g_IsObserver && g_Players[Engine.GetPlayerID()].cheatsEnabled)
    333336        {
    334337            for each (var cheat in Object.keys(cheats))
    335338            {
    336339                // Line must start with the cheat.
     
    374377                isCheat = true;
    375378                break;
    376379            }
    377380        }
    378381
    379         // Observers should only send messages to "/all"
    380         if (!isCheat && (!g_IsObserver || text.indexOf("/") == -1 || text.indexOf("/all ") == 0))
     382        if (!isCheat)
    381383        {
    382             if (Engine.GetGUIObjectByName("toggleTeamChat").checked)
    383                 text = "/team " + text;
    384 
    385             if (g_IsNetworked)
    386                 Engine.SendNetworkChat(text);
     384            if (text.trim() == "/list")
     385                addChatMessage({ "type": "clientlist", "guid": "local"});
    387386            else
    388                 addChatMessage({ "type": "message", "guid": "local", "text": text });
     387            {
     388                if (Engine.GetGUIObjectByName("toggleTeamChat").checked)
     389                    text = "/team " + text;
     390
     391                if (g_IsNetworked)
     392                    Engine.SendNetworkChat(text);
     393                else
     394                    addChatMessage({ "type": "message", "guid": "local", "text": text });
     395            }
    389396        }
    390397        input.caption = ""; // Clear chat input
    391398    }
    392399
    393400    input.blur(); // Remove focus
     
    453460        if (!g_IsNetworked && msg.player == Engine.GetPlayerID())
    454461            formatted = translate("You have been defeated.");
    455462        else
    456463            formatted = sprintf(translate("%(player)s has been defeated."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" });
    457464        break;
     465    case "clientlist":
     466        let userlist = Object.keys(playerAssignments).sort(function(a,b)
     467        {
     468            let playerA = playerAssignments[a].player;
     469            let playerB = playerAssignments[b].player;
     470            if (playerA == -1 || playerB == -1)
     471                return 1;
     472            else
     473                return playerA - playerB;
     474        }).map(guid => playerAssignments[guid].name).join(",");
     475        formatted = sprintf(translate("Users: %(users)s."), { "users": userlist });
     476        break;
    458477    case "diplomacy":
    459478        var message;
    460479        if (msg.player == Engine.GetPlayerID())
    461480        {
    462481            [username, playerColor] = getUsernameAndColor(msg.player1);
     
    601620}
    602621
    603622// Parses chat messages for commands.
    604623function parseChatCommands(msg, playerAssignments)
    605624{
     625    let ban = false;
    606626    // Only interested in messages that start with '/'.
    607627    if (!msg.text || msg.text[0] != '/')
    608628        return;
    609629
    610     var sender;
     630    let playerGUID = Engine.GetPlayerGUID();
     631    let sender;
    611632    if (playerAssignments[msg.guid])
    612633        sender = playerAssignments[msg.guid].player;
    613634    else
    614635        sender = msg.player;
    615636
    616637    // TODO: It would be nice to display multiple different contexts.
    617638    // It should be made clear that only players matching the union of those receive the message.
    618639    var recurse = false;
    619640    var split = msg.text.split(/\s/);
    620 
     641    let trimmed, matched;
    621642    // Parse commands embedded in the message.
    622643    switch (split[0])
    623644    {
    624645    case "/all":
    625646        // Resets values that 'team' or 'enemy' may have set.
     
    627648        msg.hide = false;
    628649        recurse = true;
    629650        break;
    630651    case "/team":
    631652        // Check if we are in a team.
    632         if (g_Players[Engine.GetPlayerID()] && g_Players[Engine.GetPlayerID()].team != -1)
     653        if (!g_IsObserver && g_Players[Engine.GetPlayerID()] && g_Players[Engine.GetPlayerID()].team != -1)
    633654        {
    634655            if (g_Players[Engine.GetPlayerID()].team != g_Players[sender].team)
    635656                msg.hide = true;
    636657            else
    637658                msg.context = translate("Team");
     
    641662        recurse = true;
    642663        break;
    643664    case "/ally":
    644665    case "/allies":
    645666        // Check if we sent the message, or are the sender's (mutual) ally
    646         if (Engine.GetPlayerID() == sender || (g_Players[sender] && g_Players[sender].isMutualAlly[Engine.GetPlayerID()]))
     667        if (!g_IsObserver && (Engine.GetPlayerID() == sender || (g_Players[sender] && g_Players[sender].isMutualAlly[Engine.GetPlayerID()])))
    647668            msg.context = translate("Ally");
    648669        else
    649670            msg.hide = true;
    650671
    651672        recurse = true;
    652673        break;
    653674    case "/enemy":
    654675    case "/enemies":
    655676        // Check if we sent the message, or are the sender's enemy
    656         if (Engine.GetPlayerID() == sender || (g_Players[sender] && g_Players[sender].isEnemy[Engine.GetPlayerID()]))
     677        if (!g_IsObserver && (Engine.GetPlayerID() == sender || (g_Players[sender] && g_Players[sender].isEnemy[Engine.GetPlayerID()])))
    657678            msg.context = translate("Enemy");
    658679        else
    659680            msg.hide = true;
    660681
    661682        recurse = true;
    662683        break;
    663684    case "/me":
    664685        msg.action = true;
    665686        break;
     687    case "/ban":
     688        ban = true; // handle in the "kick" case
     689    case "/kick":
     690        msg.hide = true;
     691        if (!g_IsNetworked || !g_IsController || msg.guid != playerGUID)
     692            break;
     693        trimmed = msg.text.substr(split[0].length + 1);
     694        matched = "";
     695        // Reject names which don't match or are a superset of the intended name.
     696        for each (let player in playerAssignments)
     697            if (trimmed.indexOf(player.name) == 0 && player.name.length > matched.length)
     698                matched = player.name;
     699        // Prevent the host from kicking him/herself
     700        if (matched.length && matched != g_PlayerAssignments[playerGUID].name)
     701        {
     702            Engine.KickPlayer(matched, ban);
     703            // TODO: The text should be translated for each client individually (see #3304)
     704            submitChatDirectly(matched + " has been " + (ban ? "banned" : "kicked") + ".");
     705        }
     706        return;
    666707    case "/msg":
    667         var trimmed = msg.text.substr(split[0].length + 1);
    668         var matched = "";
     708        trimmed = msg.text.substr(split[0].length + 1);
     709        matched = "";
     710
     711        // Don't show private messages from observers to players
     712        if (g_PlayerAssignments[msg.guid].player == -1 && g_PlayerAssignments[playerGUID].player != -1)
     713        {
     714            msg.hide = true;
     715            return;
     716        }
    669717
    670718        // Reject names which don't match or are a superset of the intended name.
    671719        for each (var player in playerAssignments)
    672720            if (trimmed.indexOf(player.name + " ") == 0 && player.name.length > matched.length)
    673721                matched = player.name;
    674722
    675723        // If the local player's name was the longest one matched, show the message.
    676         var playerName = g_Players[Engine.GetPlayerID()].name;
    677         if (matched.length && (matched == playerName || sender == Engine.GetPlayerID()))
     724        // Show the message only for sender and recipient.
     725        if (matched.length && (msg.guid == playerGUID || matched == g_PlayerAssignments[playerGUID].name))
    678726        {
    679727            msg.context = translate("Private");
    680728            msg.text = trimmed.substr(matched.length + 1);
    681729            msg.hide = false; // Might override team message hiding.
    682730            return;
  • binaries/data/mods/public/gui/session/session.xml

     
    55<script file="gui/common/colorFades.js"/>
    66<script file="gui/common/functions_civinfo.js"/>
    77<script file="gui/common/functions_global_object.js"/>
    88<script file="gui/common/functions_utility.js"/>
    99<script file="gui/common/l10n.js"/>
     10<script file="gui/common/network.js"/>
    1011<script file="gui/common/music.js"/>
    1112<script file="gui/common/timer.js"/>
    1213<script file="gui/common/tooltips.js"/>
    1314<!-- load all scripts in this directory -->
    1415<script directory="gui/session/"/>
  • source/gui/scripting/ScriptFunctions.cpp

     
    186186    if (g_Game)
    187187        return g_Game->GetPlayerID();
    188188    return -1;
    189189}
    190190
     191std::string GetPlayerGUID(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))
     192{
     193    if (g_NetServer)
     194        return g_NetServer->GetHostGUID();
     195    else if (g_NetClient)
     196        return g_NetClient->GetGUID();
     197    else
     198        return "";
     199}
     200
    191201void SetPlayerID(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int id)
    192202{
    193203    if (g_Game)
    194204        g_Game->SetPlayerID(id);
    195205}
     
    345355    SAFE_DELETE(g_NetServer);
    346356    SAFE_DELETE(g_NetClient);
    347357    SAFE_DELETE(g_Game);
    348358}
    349359
     360void KickPlayer(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring playerName, bool ban)
     361{
     362    if (g_NetServer)
     363        g_NetServer->KickPlayer(playerName, ban);
     364}
     365
    350366JS::Value PollNetworkClient(ScriptInterface::CxPrivate* pCxPrivate)
    351367{
    352368    if (!g_NetClient)
    353369        return JS::UndefinedValue();
    354370
     
    954970    scriptInterface.RegisterFunction<void, JS::HandleValue, int, &StartGame>("StartGame");
    955971    scriptInterface.RegisterFunction<void, &Script_EndGame>("EndGame");
    956972    scriptInterface.RegisterFunction<void, std::wstring, &StartNetworkHost>("StartNetworkHost");
    957973    scriptInterface.RegisterFunction<void, std::wstring, std::string, &StartNetworkJoin>("StartNetworkJoin");
    958974    scriptInterface.RegisterFunction<void, &DisconnectNetworkGame>("DisconnectNetworkGame");
     975    scriptInterface.RegisterFunction<void, std::wstring, bool, &KickPlayer>("KickPlayer");
    959976    scriptInterface.RegisterFunction<JS::Value, &PollNetworkClient>("PollNetworkClient");
    960977    scriptInterface.RegisterFunction<void, JS::HandleValue, &SetNetworkGameAttributes>("SetNetworkGameAttributes");
    961978    scriptInterface.RegisterFunction<void, int, std::string, &AssignNetworkPlayer>("AssignNetworkPlayer");
    962979    scriptInterface.RegisterFunction<void, std::string, int, &SetNetworkPlayerStatus>("SetNetworkPlayerStatus");
    963980    scriptInterface.RegisterFunction<void, &ClearAllPlayerReady>("ClearAllPlayerReady");
     
    977994    scriptInterface.RegisterFunction<void, &QuickLoad>("QuickLoad");
    978995
    979996    // Misc functions
    980997    scriptInterface.RegisterFunction<std::wstring, std::wstring, &SetCursor>("SetCursor");
    981998    scriptInterface.RegisterFunction<int, &GetPlayerID>("GetPlayerID");
     999    scriptInterface.RegisterFunction<std::string, &GetPlayerGUID>("GetPlayerGUID");
    9821000    scriptInterface.RegisterFunction<void, int, &SetPlayerID>("SetPlayerID");
    9831001    scriptInterface.RegisterFunction<void, std::string, &OpenURL>("OpenURL");
    9841002    scriptInterface.RegisterFunction<std::wstring, &GetMatchID>("GetMatchID");
    9851003    scriptInterface.RegisterFunction<void, &RestartInAtlas>("RestartInAtlas");
    9861004    scriptInterface.RegisterFunction<bool, &AtlasIsAvailable>("AtlasIsAvailable");
  • source/network/NetClient.cpp

     
    139139    ENSURE(!m_Session); // must be called before we start the connection
    140140
    141141    m_UserName = username;
    142142}
    143143
     144CStr CNetClient::GetGUID()
     145{
     146    return m_GUID;
     147}
     148
    144149bool CNetClient::SetupConnection(const CStr& server)
    145150{
    146151    CNetClientSession* session = new CNetClientSession(*this);
    147152    bool ok = session->Connect(PS_DEFAULT_PORT, server);
    148153    SetAndOwnSession(session);
  • source/network/NetClient.h

     
    8686     * Set the user's name that will be displayed to all players.
    8787     * This must not be called after the connection setup.
    8888     */
    8989    void SetUserName(const CStrW& username);
    9090
     91    /** Returns the GUID of the client. */
     92    CStr GetGUID();
     93
    9194    /**
    9295     * Set up a connection to the remote networked server.
    9396     * @param server IP address or host name to connect to
    9497     * @return true on success, false on connection failure
    9598     */
  • source/network/NetHost.h

     
    1 /* Copyright (C) 2011 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
    55 * it under the terms of the GNU General Public License as published by
    66 * the Free Software Foundation, either version 2 of the License, or
     
    6060enum NetDisconnectReason
    6161{
    6262    NDR_UNKNOWN = 0,
    6363    NDR_UNEXPECTED_SHUTDOWN,
    6464    NDR_INCORRECT_PROTOCOL_VERSION,
    65     NDR_SERVER_ALREADY_IN_GAME
     65    NDR_SERVER_ALREADY_IN_GAME,
     66    NDR_KICKED,
     67    NDR_BANNED
    6668};
    6769
    6870class CNetHost
    6971{
    7072public:
  • source/network/NetServer.cpp

     
    127127
    128128    m_ServerTurnManager = NULL;
    129129
    130130    m_ServerName = DEFAULT_SERVER_NAME;
    131131    m_WelcomeMessage = DEFAULT_WELCOME_MESSAGE;
     132    m_HostGUID = std::string();
    132133}
    133134
    134135CNetServerWorker::~CNetServerWorker()
    135136{
    136137    if (m_State != SERVER_STATE_UNCONNECTED)
     
    604605    session->SetFirstState(NSS_HANDSHAKE);
    605606}
    606607
    607608bool CNetServerWorker::HandleConnect(CNetServerSession* session)
    608609{
     610    CNetServerWorker& server = session->GetServer();
     611
     612    // Disconnect banned IPs
     613    std::string ipAddress = session -> GetIPAddress();
     614    if(std::find(server.m_BannedIPs.begin(), server.m_BannedIPs.end(), ipAddress) != server.m_BannedIPs.end())
     615    {
     616        session->Disconnect(NDR_BANNED);
     617        return false;
     618    }
     619
     620    // Send handshake challenge
    609621    CSrvHandshakeMessage handshake;
    610622    handshake.m_Magic = PS_PROTOCOL_MAGIC;
    611623    handshake.m_ProtocolVersion = PS_PROTOCOL_VERSION;
    612624    handshake.m_SoftwareVersion = PS_PROTOCOL_VERSION;
    613625    return session->SendMessage(&handshake);
     
    615627
    616628void CNetServerWorker::OnUserJoin(CNetServerSession* session)
    617629{
    618630    AddPlayer(session->GetGUID(), session->GetUserName());
    619631
     632    if (m_HostGUID == "")
     633        m_HostGUID = session->GetGUID();
     634
    620635    CGameSetupMessage gameSetupMessage(GetScriptInterface());
    621636    gameSetupMessage.m_Data = m_GameAttributes.get();
    622637    session->SendMessage(&gameSetupMessage);
    623638
    624639    CPlayerAssignmentMessage assignMessage;
     
    630645{
    631646    RemovePlayer(session->GetGUID());
    632647
    633648    if (m_ServerTurnManager && session->GetCurrState() != NSS_JOIN_SYNCING)
    634649        m_ServerTurnManager->UninitialiseClient(session->GetHostID()); // TODO: only for non-observers
    635 
    636     // TODO: ought to switch the player controlled by that client
    637     // back to AI control, or something?
    638650}
    639651
    640652void CNetServerWorker::AddPlayer(const CStr& guid, const CStrW& name)
    641653{
    642654    // Find all player IDs in active use; we mustn't give them to a second player (excluding the unassigned ID: -1)
     
    707719        it->second.m_Status = 0;
    708720
    709721    SendPlayerAssignments();
    710722}
    711723
     724void CNetServerWorker::KickPlayer(const CStrW& playerName, bool ban)
     725{
     726    if (ban)
     727    {
     728        // Add playername to blacklist
     729        if (std::find(m_BannedPlayers.begin(), m_BannedPlayers.end(), playerName) == m_BannedPlayers.end())
     730            m_BannedPlayers.push_back(playerName);
     731
     732        // Add IP address to blacklist
     733        std::string ipAddress = GetPlayerIPAddress(playerName);
     734        if (std::find(m_BannedIPs.begin(), m_BannedIPs.end(), ipAddress) == m_BannedIPs.end())
     735            m_BannedIPs.push_back(ipAddress);
     736    }
     737
     738    // Disconnect everyone with that nick except the host
     739    for (auto session : m_Sessions)
     740    {
     741        if (session->GetUserName() == playerName && session->GetGUID() != m_HostGUID)
     742            session->Disconnect(ban ? NDR_BANNED : NDR_KICKED);
     743    }
     744}
     745
     746std::string CNetServerWorker::GetPlayerIPAddress(const CStrW& playerName)
     747{
     748    std::string ipAddress = "(error)";
     749    for (auto session : m_Sessions)
     750    {
     751        if (session->GetUserName() == playerName)
     752            return session->GetIPAddress();
     753    }
     754    return ipAddress;
     755}
     756
     757std::string CNetServerWorker::GetHostGUID()
     758{
     759    return m_HostGUID;
     760}
     761
    712762void CNetServerWorker::AssignPlayer(int playerID, const CStr& guid)
    713763{
    714764    // Remove anyone who's already assigned to this player
    715765    for (PlayerAssignmentMap::iterator it = m_PlayerAssignments.begin(); it != m_PlayerAssignments.end(); ++it)
    716766    {
     
    764814    ENSURE(event->GetType() == (uint)NMT_CLIENT_HANDSHAKE);
    765815
    766816    CNetServerSession* session = (CNetServerSession*)context;
    767817    CNetServerWorker& server = session->GetServer();
    768818
     819    // Check protocol version
    769820    CCliHandshakeMessage* message = (CCliHandshakeMessage*)event->GetParamRef();
    770821    if (message->m_ProtocolVersion != PS_PROTOCOL_VERSION)
    771822    {
    772823        session->Disconnect(NDR_INCORRECT_PROTOCOL_VERSION);
    773824        return false;
    774825    }
    775826
     827    // Send handshake response
    776828    CSrvHandshakeResponseMessage handshakeResponse;
    777829    handshakeResponse.m_UseProtocolVersion = PS_PROTOCOL_VERSION;
    778830    handshakeResponse.m_Message = server.m_WelcomeMessage;
    779831    handshakeResponse.m_Flags = 0;
    780832    session->SendMessage(&handshakeResponse);
     
    791843
    792844    CAuthenticateMessage* message = (CAuthenticateMessage*)event->GetParamRef();
    793845
    794846    CStrW username = server.DeduplicatePlayerName(SanitisePlayerName(message->m_Name));
    795847
     848    // Disconnect banned usernames
     849    if(std::find(server.m_BannedPlayers.begin(), server.m_BannedPlayers.end(), username) != server.m_BannedPlayers.end())
     850    {
     851        session->Disconnect(NDR_BANNED);
     852        return true;
     853    }
     854
    796855    bool isRejoining = false;
    797856
    798857    if (server.m_State != SERVER_STATE_PREGAME)
    799858    {
    800859//      isRejoining = true; // uncomment this to test rejoining even if the player wasn't connected previously
     
    11451204{
    11461205    CScopeLock lock(m_Worker->m_WorkerMutex);
    11471206    m_Worker->m_PlayerReadyQueue.push_back(std::make_pair(guid, ready));
    11481207}
    11491208
     1209void CNetServer::KickPlayer(const CStrW& playerName, bool ban)
     1210{
     1211    CScopeLock lock(m_Worker->m_WorkerMutex);
     1212    m_Worker->KickPlayer(playerName, ban);
     1213}
     1214
     1215std::string CNetServer::GetHostGUID()
     1216{
     1217    CScopeLock lock(m_Worker->m_WorkerMutex);
     1218    return m_Worker->GetHostGUID();
     1219}
     1220
    11501221void CNetServer::ClearAllPlayerReady()
    11511222{
    11521223    CScopeLock lock(m_Worker->m_WorkerMutex);
    11531224    m_Worker->m_PlayerResetReadyQueue.push_back(false);
    11541225}
  • source/network/NetServer.h

     
    120120     * The given GUID will be (re)assigned to the given player ID.
    121121     * Any player currently using that ID will be unassigned.
    122122     * The changes will be asynchronously propagated to all clients.
    123123     */
    124124    void AssignPlayer(int playerID, const CStr& guid);
    125    
     125
    126126    /**
    127127     * Call from the GUI to update the player readiness.
    128128     * The changes will be asynchronously propagated to all clients.
    129129     */
    130130    void SetPlayerReady(const CStr& guid, int ready);
     
    132132    /**
    133133     * Call from the GUI to set the all player readiness to 0.
    134134     * The changes will be asynchronously propagated to all clients.
    135135     */
    136136    void ClearAllPlayerReady();
    137    
     137
     138    /**
     139     * Disconnects a player from the gamesetup / session.
     140     */
     141    void KickPlayer(const CStrW& playerName, bool ban);
     142
     143    /**
     144     * Returns the GUID of the host.
     145     */
     146    std::string GetHostGUID();
     147
    138148    /**
    139149     * Call from the GUI to asynchronously notify all clients that they should start loading the game.
    140150     */
    141151    void StartGame();
    142152
     
    181191     * Send a message to the given network peer.
    182192     */
    183193    bool SendMessage(ENetPeer* peer, const CNetMessage* message);
    184194
    185195    /**
     196     * Disconnected a player from the match / gamesetup and optionally prevents him/her from rejoining.
     197     */
     198    void KickPlayer(const CStrW& playerName, bool ban);
     199
     200    /**
    186201     * Send a message to all clients who have completed the full connection process
    187202     * (i.e. are in the pre-game or in-game states).
    188203     */
    189204    bool Broadcast(const CNetMessage* message);
    190205
     206    /**
     207     * Returns the IP address of the given connected player.
     208     */
     209    std::string GetPlayerIPAddress(const CStrW& playerName);
     210
    191211private:
    192212    friend class CNetServer;
    193213    friend class CNetFileReceiveTask_ServerRejoin;
    194214
    195215    CNetServerWorker(int autostartPlayers);
     
    244264    void SetTurnLength(u32 msecs);
    245265
    246266    void AddPlayer(const CStr& guid, const CStrW& name);
    247267    void RemovePlayer(const CStr& guid);
    248268    void SetPlayerReady(const CStr& guid, const int ready);
     269    std::string GetHostGUID();
    249270    void SendPlayerAssignments();
    250271    void ClearAllPlayerReady();
    251272
    252273    void SetupSession(CNetServerSession* session);
    253274    bool HandleConnect(CNetServerSession* session);
     
    269290
    270291    void ConstructPlayerAssignmentMessage(CPlayerAssignmentMessage& message);
    271292
    272293    void HandleMessageReceive(const CNetMessage* message, CNetServerSession* session);
    273294
    274 
    275295    /**
    276296     * Internal script context for (de)serializing script messages,
    277297     * and for storing game attributes.
    278298     * (TODO: we shouldn't bother deserializing (except for debug printing of messages),
    279299     * we should just forward messages blindly and efficiently.)
     
    285305    /**
    286306     * Stores the most current game attributes.
    287307     */
    288308    DefPersistentRooted<JS::Value> m_GameAttributes;
    289309
     310    std::vector<std::string> m_BannedIPs;
     311    std::vector<std::wstring> m_BannedPlayers;
     312
    290313    int m_AutostartPlayers;
    291314
    292315    ENetHost* m_Host;
    293316    std::vector<CNetServerSession*> m_Sessions;
    294317
     
    301324
    302325    u32 m_NextHostID;
    303326
    304327    CNetServerTurnManager* m_ServerTurnManager;
    305328
     329    std::string m_HostGUID;
     330
    306331    /**
    307332     * A copy of all simulation commands received so far, indexed by
    308333     * turn number, to simplify support for rejoining etc.
    309334     * TODO: verify this doesn't use too much RAM.
    310335     */
  • source/network/NetSession.cpp

     
    1 /* Copyright (C) 2011 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
    55 * it under the terms of the GNU General Public License as published by
    66 * the Free Software Foundation, either version 2 of the License, or
     
    173173CNetServerSession::CNetServerSession(CNetServerWorker& server, ENetPeer* peer) :
    174174    m_Server(server), m_FileTransferer(this), m_Peer(peer)
    175175{
    176176}
    177177
     178std::string CNetServerSession::GetIPAddress()
     179{
     180    char ipAddress[256] = "(error)";
     181    enet_address_get_host_ip(&(m_Peer->address), ipAddress, ARRAY_SIZE(ipAddress));
     182    return std::string(ipAddress);
     183}
     184
    178185void CNetServerSession::Disconnect(u32 reason)
    179186{
    180187    Update((uint)NMT_CONNECTION_LOST, NULL);
    181188
    182189    enet_peer_disconnect(m_Peer, reason);
  • source/network/NetSession.h

     
    1 /* Copyright (C) 2011 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
    55 * it under the terms of the GNU General Public License as published by
    66 * the Free Software Foundation, either version 2 of the License, or
     
    121121
    122122    u32 GetHostID() const { return m_HostID; }
    123123    void SetHostID(u32 id) { m_HostID = id; }
    124124
    125125    /**
     126     * Returns the IP address of the client.
     127     */
     128    std::string GetIPAddress();
     129
     130    /**
    126131     * Sends a disconnection notification to the client,
    127132     * and sends a NMT_CONNECTION_LOST message to the session FSM.
    128133     * The server will receive a disconnection notification after a while.
    129134     * The server will not receive any further messages sent via this session.
    130135     */