diff --git a/GameServer/Controllers/Api/PlayerCountApiController.cs b/GameServer/Controllers/Api/PlayerCountApiController.cs index cd98457..29b6ee8 100644 --- a/GameServer/Controllers/Api/PlayerCountApiController.cs +++ b/GameServer/Controllers/Api/PlayerCountApiController.cs @@ -21,6 +21,7 @@ public IActionResult GetSessionCount(bool? isMnr = null) { return Content($"{Session.GetSessions() .Where(x => + x != null && // TODO: Why are session objects becoming null? (isMnr != null ? x.IsMNR == isMnr : true) && x.Authenticated && x.LastPing.AddMinutes(1) > DateTime.Now) diff --git a/GameServer/Implementation/Common/Session.cs b/GameServer/Implementation/Common/Session.cs index 8bc8ff3..0e97e81 100644 --- a/GameServer/Implementation/Common/Session.cs +++ b/GameServer/Implementation/Common/Session.cs @@ -1,27 +1,40 @@ -using GameServer.Models; -using GameServer.Models.PlayerData; -using GameServer.Models.Response; +using System; +using System.Collections.Concurrent; using System.Collections.Generic; -using System; -using GameServer.Utils; +using System.IO; using System.Linq; -using NPTicket; -using Serilog; +using GameServer.Models; using GameServer.Models.Config; -using System.IO; +using GameServer.Models.PlayerData; +using GameServer.Models.Response; +using GameServer.Utils; +using Microsoft.EntityFrameworkCore.Metadata.Internal; using Newtonsoft.Json; +using NPTicket; using NPTicket.Verification; using NPTicket.Verification.Keys; +using Serilog; namespace GameServer.Implementation.Common { public class Session { - private static readonly Dictionary Sessions = []; + private static readonly ConcurrentDictionary Sessions = []; public static string Login(Database database, string ip, Platform platform, string ticket, string hmac, string console_id, Guid SessionID) { ClearSessions(); + + if (!Sessions.ContainsKey(SessionID)) + { + var errorResp = new Response + { + status = new ResponseStatus { id = -130, message = "The player doesn't exist" }, + response = new EmptyResponse { } + }; + return errorResp.Serialize(); + } + byte[] ticketData = Convert.FromBase64String(ticket.Trim('\n').Trim('\0')); List whitelist = []; if (ServerConfig.Instance.Whitelist) @@ -126,7 +139,7 @@ public static string Login(Database database, string ip, Platform platform, stri Quota = 30, CreatedAt = TimeUtils.Now, UpdatedAt = TimeUtils.Now, - PolicyAccepted = Sessions[SessionID].PolicyAccepted, + PolicyAccepted = Sessions.ContainsKey(SessionID) ? Sessions[SessionID].PolicyAccepted : false, }; if (IsPSN) newUser.PSNID = NPTicket.UserId; @@ -154,10 +167,10 @@ public static string Login(Database database, string ip, Platform platform, stri return errorResp.Serialize(); } - foreach (var Session in Sessions.Where(match => match.Value.Username == user.Username - && match.Key != SessionID && match.Value.Platform == platform)) + foreach (var Session in Sessions.Where(match => match.Value == null || (match.Value.Username == user.Username + && match.Key != SessionID && match.Value.Platform == platform))) { - Sessions.Remove(Session.Key); + Sessions.Remove(Session.Key, out _); ServerCommunication.NotifySessionDestroyed(Session.Key); } @@ -236,7 +249,7 @@ public static string SetPresence(string presence, Guid SessionID) public static Presence GetPresence(string Username) { ClearSessions(); - var Session = Sessions.FirstOrDefault(match => match.Value.Username == Username).Value; + var Session = Sessions.FirstOrDefault(match => match.Value != null && match.Value.Username == Username).Value; if (Session == null) { return Presence.OFFLINE; @@ -270,7 +283,7 @@ public static string Ping(Guid SessionID) public static void StartSession(Guid SessionID) { - Sessions.Add(SessionID, new SessionInfo + Sessions.TryAdd(SessionID, new SessionInfo { LastPing = TimeUtils.Now, Presence = Presence.OFFLINE @@ -279,18 +292,11 @@ public static void StartSession(Guid SessionID) private static void ClearSessions() { - foreach (var Session in Sessions.Where(match => match.Value.Authenticated - && (TimeUtils.Now > match.Value.LastPing.AddMinutes(60) /*|| TimeUtils.Now > match.Value.ExpiryDate*/))) - { - Sessions.Remove(Session.Key); - ServerCommunication.NotifySessionDestroyed(Session.Key); - } - - foreach (var Session in Sessions.Where(match => !match.Value.Authenticated - && TimeUtils.Now > match.Value.LastPing.AddHours(3))) + foreach (var Session in Sessions.Where(match => match.Value == null || (TimeUtils.Now > match.Value.LastPing.AddMinutes(60) /*|| TimeUtils.Now > match.Value.ExpiryDate*/))) { - Sessions.Remove(Session.Key); - ServerCommunication.NotifySessionDestroyed(Session.Key); + var sessionKey = Session.Key; + Sessions.Remove(sessionKey, out _); + ServerCommunication.NotifySessionDestroyed(sessionKey); } } @@ -348,7 +354,7 @@ public static void DestroyAllSessions() { foreach (var sessionID in Sessions.Keys.ToList()) { - Sessions.Remove(sessionID); + Sessions.Remove(sessionID, out _); ServerCommunication.NotifySessionDestroyed(sessionID); } } diff --git a/GameServer/Models/PlayerData/SessionInfo.cs b/GameServer/Models/PlayerData/SessionInfo.cs index c041d11..28cfb1d 100644 --- a/GameServer/Models/PlayerData/SessionInfo.cs +++ b/GameServer/Models/PlayerData/SessionInfo.cs @@ -8,7 +8,7 @@ public class SessionInfo { public string Username => Authenticated ? Ticket.Username : ""; public Presence Presence { get; set; } = Presence.OFFLINE; - public DateTime ExpiryDate => Ticket.ExpiryDate.DateTime; + public DateTime ExpiryDate => Authenticated ? Ticket.ExpiryDate.DateTime : TimeUtils.Now; public Ticket Ticket { get; set; } public bool Authenticated => Ticket != null; public bool PolicyAccepted { get; set; } = false;