From 40eb862eb8d5bf1a9076b515378215dd3848aa19 Mon Sep 17 00:00:00 2001 From: gmriggs Date: Wed, 11 Mar 2020 20:15:02 -0400 Subject: [PATCH 01/11] [TEST] network relogin --- Source/ACE.Server/Network/Managers/NetworkManager.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/ACE.Server/Network/Managers/NetworkManager.cs b/Source/ACE.Server/Network/Managers/NetworkManager.cs index 226d96120c..ba9ac315f5 100644 --- a/Source/ACE.Server/Network/Managers/NetworkManager.cs +++ b/Source/ACE.Server/Network/Managers/NetworkManager.cs @@ -122,6 +122,12 @@ public static void ProcessPacket(ConnectionListener connectionListener, ClientPa log.Warn($"Bad handshake from {endPoint}, aborting session."); } + if (session.State == SessionState.WorldConnected) + { + log.Debug($"Dropping {session.Player?.Name} for new session"); + session.Terminate(SessionTerminationReason.AccountInUse); + } + session.ProcessPacket(packet); } else From 71c27feee83562330b667028ef1d16d0035cf405 Mon Sep 17 00:00:00 2001 From: gmriggs Date: Sat, 14 Mar 2020 06:06:04 -0400 Subject: [PATCH 02/11] example implementation of dropping session after player is fully logged out of world to fix discussed bugs --- Source/ACE.Server/Network/Managers/NetworkManager.cs | 11 +++++++++++ Source/ACE.Server/Network/Session.cs | 3 +++ Source/ACE.Server/WorldObjects/Player.cs | 3 +++ 3 files changed, 17 insertions(+) diff --git a/Source/ACE.Server/Network/Managers/NetworkManager.cs b/Source/ACE.Server/Network/Managers/NetworkManager.cs index ba9ac315f5..0f35a480fa 100644 --- a/Source/ACE.Server/Network/Managers/NetworkManager.cs +++ b/Source/ACE.Server/Network/Managers/NetworkManager.cs @@ -111,6 +111,17 @@ public static void ProcessPacket(ConnectionListener connectionListener, ClientPa if (ConfigManager.Config.Server.Network.MaximumAllowedSessionsPerIPAddress == -1 || GetSessionEndpointTotalByAddressCount(endPoint.Address) < ConfigManager.Config.Server.Network.MaximumAllowedSessionsPerIPAddress) { + // if a character from a previous session is still logged into the world, + // we really want FindOrCreateSession to return the previous session here + // if the previous session is dropped immediately, before the character has completely exited world, + // in-game packets from the previous character will start broadcasting to client @ char select screen, + // which can cause ac client to get into weird state. + + // for example, if the server responds with 'character already in world' when character tries to log in again, + // if in-game packets from previous session are broadcast @ char select screen, + // it causes client to go into an automatic continuous loop very quickly, + // where the client tries to repeatedly re-enter the world + var session = FindOrCreateSession(connectionListener, endPoint); if (session != null) { diff --git a/Source/ACE.Server/Network/Session.cs b/Source/ACE.Server/Network/Session.cs index 8d84926850..6909b813de 100644 --- a/Source/ACE.Server/Network/Session.cs +++ b/Source/ACE.Server/Network/Session.cs @@ -259,7 +259,10 @@ public void DropSession() // At this point, if the player was on a landblock, they'll still exist on that landblock until the logout animation completes (~6s). } + } + public void DropSessionPost() + { NetworkManager.RemoveSession(this); // This is a temp fix to mark the Session.Network portion of the Session as released diff --git a/Source/ACE.Server/WorldObjects/Player.cs b/Source/ACE.Server/WorldObjects/Player.cs index ffaf8dea28..d937504dd3 100644 --- a/Source/ACE.Server/WorldObjects/Player.cs +++ b/Source/ACE.Server/WorldObjects/Player.cs @@ -491,6 +491,9 @@ public void LogOut_Inner(bool clientSessionTerminatedAbruptly = false) SetPropertiesAtLogOut(); SavePlayerToDatabase(); PlayerManager.SwitchPlayerFromOnlineToOffline(this); + + if (Session.PendingTermination != null) + Session.DropSessionPost(); }); // close any open landblock containers (chests / corpses) From 593cc5f06a1e63a9062e6f256b3234d8da01b146 Mon Sep 17 00:00:00 2001 From: gmriggs Date: Sat, 14 Mar 2020 07:12:51 -0400 Subject: [PATCH 03/11] revised implementation --- .../Network/Handlers/AuthenticationHandler.cs | 39 ++++++++++++------- .../Network/Managers/NetworkManager.cs | 6 --- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs b/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs index f04d80f9f0..103cf33c83 100644 --- a/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs +++ b/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs @@ -97,18 +97,9 @@ private static void DoLogin(Session session, PacketInboundLoginRequest loginRequ } } - - private static void AccountSelectCallback(Account account, Session session, PacketInboundLoginRequest loginRequest) + private static void SendConnectRequest(Session session) { - packetLog.DebugFormat("ConnectRequest TS: {0}", Timers.PortalYearTicks); - - if (session.Network.ConnectionData.ServerSeed == null || session.Network.ConnectionData.ClientSeed == null) - { - // these are null if ConnectionData.DiscardSeeds() is called because of some other error condition. - session.Terminate(SessionTerminationReason.BadHandshake, new GameMessageCharacterError(CharacterError.ServerCrash1)); - return; - } - + // verify: should this happen if server response with connection error? var connectRequest = new PacketOutboundConnectRequest( Timers.PortalYearTicks, session.Network.ConnectionData.ConnectionCookie, @@ -119,15 +110,27 @@ private static void AccountSelectCallback(Account account, Session session, Pack session.Network.ConnectionData.DiscardSeeds(); session.Network.EnqueueSend(connectRequest); + } + + + private static void AccountSelectCallback(Account account, Session session, PacketInboundLoginRequest loginRequest) + { + packetLog.DebugFormat("ConnectRequest TS: {0}", Timers.PortalYearTicks); + + if (session.Network.ConnectionData.ServerSeed == null || session.Network.ConnectionData.ClientSeed == null) + { + // these are null if ConnectionData.DiscardSeeds() is called because of some other error condition. + session.Terminate(SessionTerminationReason.BadHandshake, new GameMessageCharacterError(CharacterError.ServerCrash1)); + return; + } if (loginRequest.NetAuthType < NetAuthType.AccountPassword) { if (loginRequest.Account == "acservertracker:jj9h26hcsggc") { //log.Info($"Incoming ping from a Thwarg-Launcher client... Sending Pong..."); - + SendConnectRequest(session); session.Terminate(SessionTerminationReason.PongSentClosingConnection, new GameMessageCharacterError(CharacterError.ServerCrash1)); - return; } @@ -136,6 +139,7 @@ private static void AccountSelectCallback(Account account, Session session, Pack else log.Debug($"client {loginRequest.Account} connected with no Password or GlsTicket included so booting"); + SendConnectRequest(session); session.Terminate(SessionTerminationReason.NotAuthorizedNoPasswordOrGlsTicketIncludedInLoginReq, new GameMessageCharacterError(CharacterError.AccountInvalid)); return; @@ -143,6 +147,7 @@ private static void AccountSelectCallback(Account account, Session session, Pack if (account == null) { + SendConnectRequest(session); session.Terminate(SessionTerminationReason.NotAuthorizedAccountNotFound, new GameMessageCharacterError(CharacterError.AccountDoesntExist)); return; } @@ -151,6 +156,7 @@ private static void AccountSelectCallback(Account account, Session session, Pack { if (NetworkManager.Find(account.AccountName) != null) { + SendConnectRequest(session); session.Terminate(SessionTerminationReason.AccountInUse, new GameMessageCharacterError(CharacterError.Logon)); return; } @@ -165,6 +171,7 @@ private static void AccountSelectCallback(Account account, Session session, Pack else log.Debug($"client {loginRequest.Account} connected with non matching password so booting"); + SendConnectRequest(session); session.Terminate(SessionTerminationReason.NotAuthorizedPasswordMismatch, new GameMessageBootAccount(session, " because the password entered for this account was not correct.")); // TO-DO: temporary lockout of account preventing brute force password discovery @@ -179,7 +186,10 @@ private static void AccountSelectCallback(Account account, Session session, Pack if (previouslyConnectedAccount != null) { + // do not send connection request here, or else vials will fill up on new client, + // and it won't try to repeatedly reconnect until previous char is logged out of world previouslyConnectedAccount.Terminate(SessionTerminationReason.AccountLoggedIn, new GameMessageCharacterError(CharacterError.Logon)); + return; } } @@ -195,16 +205,19 @@ private static void AccountSelectCallback(Account account, Session session, Pack else log.Debug($"client {loginRequest.Account} connected with GlsTicket which is not implemented yet so booting"); + SendConnectRequest(session); session.Terminate(SessionTerminationReason.NotAuthorizedGlsTicketNotImplementedToProcLoginReq, new GameMessageCharacterError(CharacterError.AccountInvalid)); return; } // TODO: check for account bans + SendConnectRequest(session); account.UpdateLastLogin(session.EndPoint.Address); session.SetAccount(account.AccountId, account.AccountName, (AccessLevel)account.AccessLevel); + session.State = SessionState.AuthConnectResponse; } diff --git a/Source/ACE.Server/Network/Managers/NetworkManager.cs b/Source/ACE.Server/Network/Managers/NetworkManager.cs index 0f35a480fa..56b30e7211 100644 --- a/Source/ACE.Server/Network/Managers/NetworkManager.cs +++ b/Source/ACE.Server/Network/Managers/NetworkManager.cs @@ -133,12 +133,6 @@ public static void ProcessPacket(ConnectionListener connectionListener, ClientPa log.Warn($"Bad handshake from {endPoint}, aborting session."); } - if (session.State == SessionState.WorldConnected) - { - log.Debug($"Dropping {session.Player?.Name} for new session"); - session.Terminate(SessionTerminationReason.AccountInUse); - } - session.ProcessPacket(packet); } else From a9374c2184cfce41bb8d7f9fe3939b27d2bf8324 Mon Sep 17 00:00:00 2001 From: gmriggs Date: Sat, 14 Mar 2020 07:15:08 -0400 Subject: [PATCH 04/11] updating comment --- Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs b/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs index 103cf33c83..6f476858b6 100644 --- a/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs +++ b/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs @@ -99,7 +99,7 @@ private static void DoLogin(Session session, PacketInboundLoginRequest loginRequ private static void SendConnectRequest(Session session) { - // verify: should this happen if server response with connection error? + // verify: should this happen if server responds with connection error? var connectRequest = new PacketOutboundConnectRequest( Timers.PortalYearTicks, session.Network.ConnectionData.ConnectionCookie, From 7cdf68569d6d1421c6ee5c42cb5e5a696c9ac800 Mon Sep 17 00:00:00 2001 From: gmriggs Date: Sat, 14 Mar 2020 07:23:32 -0400 Subject: [PATCH 05/11] ensure the original scenario still fixed --- Source/ACE.Server/Network/Session.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/ACE.Server/Network/Session.cs b/Source/ACE.Server/Network/Session.cs index 6909b813de..7414ca238b 100644 --- a/Source/ACE.Server/Network/Session.cs +++ b/Source/ACE.Server/Network/Session.cs @@ -62,8 +62,10 @@ public Session(ConnectionListener connectionListener, IPEndPoint endPoint, ushor private bool CheckState(ClientPacket packet) { - if (packet.Header.HasFlag(PacketHeaderFlags.LoginRequest) && State != SessionState.AuthLoginRequest) - return false; + // if existing session was found in WorldConnected state, it should be pushed through for AccountSelectCallback() to terminate + + //if (packet.Header.HasFlag(PacketHeaderFlags.LoginRequest) && State != SessionState.AuthLoginRequest) + //return false; if (packet.Header.HasFlag(PacketHeaderFlags.ConnectResponse) && State != SessionState.AuthConnectResponse) return false; From 1eeae732093e83d99a32cc6becd531b2bf5d0f4d Mon Sep 17 00:00:00 2001 From: gmriggs Date: Sat, 14 Mar 2020 07:43:01 -0400 Subject: [PATCH 06/11] further updates --- Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs | 2 +- Source/ACE.Server/WorldObjects/Player.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs b/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs index 6f476858b6..623aa3d130 100644 --- a/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs +++ b/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs @@ -117,7 +117,7 @@ private static void AccountSelectCallback(Account account, Session session, Pack { packetLog.DebugFormat("ConnectRequest TS: {0}", Timers.PortalYearTicks); - if (session.Network.ConnectionData.ServerSeed == null || session.Network.ConnectionData.ClientSeed == null) + if (session.State != SessionState.WorldConnected && (session.Network.ConnectionData.ServerSeed == null || session.Network.ConnectionData.ClientSeed == null)) { // these are null if ConnectionData.DiscardSeeds() is called because of some other error condition. session.Terminate(SessionTerminationReason.BadHandshake, new GameMessageCharacterError(CharacterError.ServerCrash1)); diff --git a/Source/ACE.Server/WorldObjects/Player.cs b/Source/ACE.Server/WorldObjects/Player.cs index d937504dd3..d9d305bfe8 100644 --- a/Source/ACE.Server/WorldObjects/Player.cs +++ b/Source/ACE.Server/WorldObjects/Player.cs @@ -491,9 +491,6 @@ public void LogOut_Inner(bool clientSessionTerminatedAbruptly = false) SetPropertiesAtLogOut(); SavePlayerToDatabase(); PlayerManager.SwitchPlayerFromOnlineToOffline(this); - - if (Session.PendingTermination != null) - Session.DropSessionPost(); }); // close any open landblock containers (chests / corpses) @@ -528,6 +525,9 @@ public void LogOut_Inner(bool clientSessionTerminatedAbruptly = false) SavePlayerToDatabase(); PlayerManager.SwitchPlayerFromOnlineToOffline(this); } + + if (Session.PendingTermination != null) + Session.DropSessionPost(); } public void HandleMRT() From b6dae886d7292b519c5b6640c5a395af6470b1a8 Mon Sep 17 00:00:00 2001 From: gmriggs Date: Sat, 14 Mar 2020 08:41:17 -0400 Subject: [PATCH 07/11] fixing Terminate() spam repeatedly bumping processing time up by 2s fixing gap for players not in world --- Source/ACE.Server/Network/Session.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Source/ACE.Server/Network/Session.cs b/Source/ACE.Server/Network/Session.cs index 7414ca238b..4b5f94a465 100644 --- a/Source/ACE.Server/Network/Session.cs +++ b/Source/ACE.Server/Network/Session.cs @@ -227,11 +227,14 @@ public void Terminate(SessionTerminationReason reason, GameMessage message = nul { Network.EnqueueSend(message); } - PendingTermination = new SessionTerminationDetails() + if (PendingTermination == null) { - ExtraReason = extraReason, - Reason = reason - }; + PendingTermination = new SessionTerminationDetails() + { + ExtraReason = extraReason, + Reason = reason + }; + } } public void DropSession() @@ -261,6 +264,8 @@ public void DropSession() // At this point, if the player was on a landblock, they'll still exist on that landblock until the logout animation completes (~6s). } + else + DropSessionPost(); } public void DropSessionPost() From 389ed41d4506dbad4261fbe4f1fd5b5e7b65c99c Mon Sep 17 00:00:00 2001 From: gmriggs Date: Sat, 14 Mar 2020 08:47:28 -0400 Subject: [PATCH 08/11] moving 'setting session properties' message to show on successful connection --- Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs b/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs index 623aa3d130..18b5b1c81e 100644 --- a/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs +++ b/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs @@ -87,7 +87,6 @@ private static void DoLogin(Session session, PacketInboundLoginRequest loginRequ try { - log.Debug($"new client connected: {loginRequest.Account}. setting session properties"); AccountSelectCallback(account, session, loginRequest); } catch (Exception ex) @@ -211,6 +210,8 @@ private static void AccountSelectCallback(Account account, Session session, Pack return; } + log.Debug($"new client connected: {loginRequest.Account}. setting session properties"); + // TODO: check for account bans SendConnectRequest(session); From 64d28cfd7f7ce3bf2599b1d666a70251b5de3004 Mon Sep 17 00:00:00 2001 From: gmriggs Date: Sat, 14 Mar 2020 08:48:29 -0400 Subject: [PATCH 09/11] . --- Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs b/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs index 18b5b1c81e..a0a5f64d39 100644 --- a/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs +++ b/Source/ACE.Server/Network/Handlers/AuthenticationHandler.cs @@ -192,6 +192,8 @@ private static void AccountSelectCallback(Account account, Session session, Pack } } + log.Debug($"new client connected: {loginRequest.Account}. setting session properties"); + if (WorldManager.WorldStatus == WorldManager.WorldStatusState.Open) log.Info($"client {loginRequest.Account} connected with verified password"); else @@ -210,8 +212,6 @@ private static void AccountSelectCallback(Account account, Session session, Pack return; } - log.Debug($"new client connected: {loginRequest.Account}. setting session properties"); - // TODO: check for account bans SendConnectRequest(session); From e4344df9694f518dd178438b6ae61f800a604f15 Mon Sep 17 00:00:00 2001 From: gmriggs Date: Sat, 14 Mar 2020 08:55:02 -0400 Subject: [PATCH 10/11] make sure DropSessionPost is on end of anim chain --- Source/ACE.Server/WorldObjects/Player.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Source/ACE.Server/WorldObjects/Player.cs b/Source/ACE.Server/WorldObjects/Player.cs index d9d305bfe8..b2bf1f51c1 100644 --- a/Source/ACE.Server/WorldObjects/Player.cs +++ b/Source/ACE.Server/WorldObjects/Player.cs @@ -491,6 +491,9 @@ public void LogOut_Inner(bool clientSessionTerminatedAbruptly = false) SetPropertiesAtLogOut(); SavePlayerToDatabase(); PlayerManager.SwitchPlayerFromOnlineToOffline(this); + + if (Session.PendingTermination != null) + Session.DropSessionPost(); }); // close any open landblock containers (chests / corpses) @@ -524,10 +527,10 @@ public void LogOut_Inner(bool clientSessionTerminatedAbruptly = false) SetPropertiesAtLogOut(); SavePlayerToDatabase(); PlayerManager.SwitchPlayerFromOnlineToOffline(this); - } - if (Session.PendingTermination != null) - Session.DropSessionPost(); + if (Session.PendingTermination != null) + Session.DropSessionPost(); + } } public void HandleMRT() From d25ab818f8cdb779c2c7e34674bad615ce52d416 Mon Sep 17 00:00:00 2001 From: gmriggs Date: Sat, 5 Sep 2020 03:04:33 -0400 Subject: [PATCH 11/11] fixing world shutdown bug --- Source/ACE.Server/WorldObjects/Player.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/ACE.Server/WorldObjects/Player.cs b/Source/ACE.Server/WorldObjects/Player.cs index 2ebd2b3f23..b3ecd781f1 100644 --- a/Source/ACE.Server/WorldObjects/Player.cs +++ b/Source/ACE.Server/WorldObjects/Player.cs @@ -560,7 +560,7 @@ public void LogOut_Inner(bool clientSessionTerminatedAbruptly = false) SavePlayerToDatabase(); PlayerManager.SwitchPlayerFromOnlineToOffline(this); - if (Session.PendingTermination != null) + if (Session.PendingTermination != null || ServerManager.ShutdownInProgress) Session.DropSessionPost(); }); @@ -596,7 +596,7 @@ public void LogOut_Inner(bool clientSessionTerminatedAbruptly = false) SavePlayerToDatabase(); PlayerManager.SwitchPlayerFromOnlineToOffline(this); - if (Session.PendingTermination != null) + if (Session.PendingTermination != null || ServerManager.ShutdownInProgress) Session.DropSessionPost(); } }