More work modifying client stuff
This commit is contained in:
parent
ed83c4c011
commit
9bdd7d1b8a
@ -1,83 +0,0 @@
|
|||||||
using SharedLibraryCore.Database.Models;
|
|
||||||
using SharedLibraryCore.Interfaces;
|
|
||||||
using SharedLibraryCore.Objects;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace IW4MAdmin.Application.Core
|
|
||||||
{
|
|
||||||
class ClientAuthentication : IClientAuthentication
|
|
||||||
{
|
|
||||||
private Queue<EFClient> ClientAuthenticationQueue;
|
|
||||||
private Dictionary<long, EFClient> AuthenticatedClients;
|
|
||||||
|
|
||||||
public ClientAuthentication()
|
|
||||||
{
|
|
||||||
ClientAuthenticationQueue = new Queue<EFClient>();
|
|
||||||
AuthenticatedClients = new Dictionary<long, EFClient>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AuthenticateClients(IList<EFClient> clients)
|
|
||||||
{
|
|
||||||
// we need to un-auth all the clients that have disconnected
|
|
||||||
var clientNetworkIds = clients.Select(c => c.NetworkId);
|
|
||||||
var clientsToRemove = AuthenticatedClients.Keys.Where(c => !clientNetworkIds.Contains(c));
|
|
||||||
// remove them
|
|
||||||
foreach (long Id in clientsToRemove.ToList())
|
|
||||||
{
|
|
||||||
AuthenticatedClients.Remove(Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// loop through the polled clients to see if they've been authenticated yet
|
|
||||||
foreach (var client in clients)
|
|
||||||
{
|
|
||||||
// they've not been authenticated
|
|
||||||
if (!AuthenticatedClients.TryGetValue(client.NetworkId, out EFClient value))
|
|
||||||
{
|
|
||||||
// authenticate them
|
|
||||||
client.State = EFClient.ClientState.Authenticated;
|
|
||||||
AuthenticatedClients.Add(client.NetworkId, client);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// this update their ping
|
|
||||||
// todo: this seems kinda hacky
|
|
||||||
value.Ping = client.Ping;
|
|
||||||
value.Score = client.Score;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// empty out the queue of clients detected through log
|
|
||||||
while (ClientAuthenticationQueue.Count > 0)
|
|
||||||
{
|
|
||||||
// grab each client that's connected via log
|
|
||||||
var clientToAuthenticate = ClientAuthenticationQueue.Dequeue();
|
|
||||||
// if they're not already authed, auth them
|
|
||||||
if (!AuthenticatedClients.TryGetValue(clientToAuthenticate.NetworkId, out EFClient value))
|
|
||||||
{
|
|
||||||
// authenticate them
|
|
||||||
clientToAuthenticate.State = EFClient.ClientState.Authenticated;
|
|
||||||
AuthenticatedClients.Add(clientToAuthenticate.NetworkId, clientToAuthenticate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IList<EFClient> GetAuthenticatedClients()
|
|
||||||
{
|
|
||||||
if (AuthenticatedClients.Values.Count > 18)
|
|
||||||
{
|
|
||||||
Program.ServerManager.GetLogger(0).WriteError($"auth client count is {AuthenticatedClients.Values.Count}, this is bad");
|
|
||||||
return AuthenticatedClients.Values.Take(18).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return AuthenticatedClients.Values.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RequestClientAuthentication(EFClient client)
|
|
||||||
{
|
|
||||||
ClientAuthenticationQueue.Enqueue(client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -144,7 +144,7 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
{
|
{
|
||||||
return new GameEvent()
|
return new GameEvent()
|
||||||
{
|
{
|
||||||
Type = GameEvent.EventType.Join,
|
Type = GameEvent.EventType.PreConnect,
|
||||||
Data = logLine,
|
Data = logLine,
|
||||||
Owner = server,
|
Owner = server,
|
||||||
Origin = new EFClient()
|
Origin = new EFClient()
|
||||||
@ -159,26 +159,26 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (eventType == "Q")
|
if (eventType == "Q")
|
||||||
//{
|
{
|
||||||
// var regexMatch = Regex.Match(logLine, @"^(Q;)(.{1,32});([0-9]+);(.*)$");
|
var regexMatch = Regex.Match(logLine, @"^(Q;)(.{1,32});([0-9]+);(.*)$");
|
||||||
// if (regexMatch.Success)
|
if (regexMatch.Success)
|
||||||
// {
|
{
|
||||||
// return new GameEvent()
|
return new GameEvent()
|
||||||
// {
|
{
|
||||||
// Type = GameEvent.EventType.Quit,
|
Type = GameEvent.EventType.PreDisconnect,
|
||||||
// Data = logLine,
|
Data = logLine,
|
||||||
// Owner = server,
|
Owner = server,
|
||||||
// Origin = new Player()
|
Origin = new EFClient()
|
||||||
// {
|
{
|
||||||
// Name = regexMatch.Groups[4].ToString().StripColors(),
|
Name = regexMatch.Groups[4].ToString().StripColors(),
|
||||||
// NetworkId = regexMatch.Groups[2].ToString().ConvertLong(),
|
NetworkId = regexMatch.Groups[2].ToString().ConvertLong(),
|
||||||
// ClientNumber = Convert.ToInt32(regexMatch.Groups[3].ToString()),
|
ClientNumber = Convert.ToInt32(regexMatch.Groups[3].ToString()),
|
||||||
// State = Player.ClientState.Connecting
|
State = EFClient.ClientState.Disconnecting
|
||||||
// }
|
}
|
||||||
// };
|
};
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
|
||||||
if (eventType.Contains("ExitLevel"))
|
if (eventType.Contains("ExitLevel"))
|
||||||
{
|
{
|
||||||
@ -186,14 +186,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
{
|
{
|
||||||
Type = GameEvent.EventType.MapEnd,
|
Type = GameEvent.EventType.MapEnd,
|
||||||
Data = lineSplit[0],
|
Data = lineSplit[0],
|
||||||
Origin = new EFClient()
|
Origin = Utilities.IW4MAdminClient(server),
|
||||||
{
|
Target = Utilities.IW4MAdminClient(server),
|
||||||
ClientId = 1
|
|
||||||
},
|
|
||||||
Target = new EFClient()
|
|
||||||
{
|
|
||||||
ClientId = 1
|
|
||||||
},
|
|
||||||
Owner = server
|
Owner = server
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
|
|
||||||
return new GameEvent()
|
return new GameEvent()
|
||||||
{
|
{
|
||||||
Type = GameEvent.EventType.Join,
|
Type = GameEvent.EventType.PreConnect,
|
||||||
Origin = new EFClient()
|
Origin = new EFClient()
|
||||||
{
|
{
|
||||||
ClientId = 1
|
ClientId = 1
|
||||||
|
@ -79,6 +79,7 @@ namespace IW4MAdmin.Application.IO
|
|||||||
foreach (var ev in events)
|
foreach (var ev in events)
|
||||||
{
|
{
|
||||||
Server.Manager.GetEventHandler().AddEvent(ev);
|
Server.Manager.GetEventHandler().AddEvent(ev);
|
||||||
|
await ev.WaitAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
PreviousFileSize = fileSize;
|
PreviousFileSize = fileSize;
|
||||||
|
@ -32,6 +32,7 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
|
// hack: my laziness
|
||||||
if ($"{IP}:{Port.ToString()}" == "66.150.121.184:28965")
|
if ($"{IP}:{Port.ToString()}" == "66.150.121.184:28965")
|
||||||
{
|
{
|
||||||
return 886229536;
|
return 886229536;
|
||||||
@ -56,16 +57,6 @@ namespace IW4MAdmin
|
|||||||
return Id;
|
return Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task OnClientJoined(EFClient polledClient)
|
|
||||||
{
|
|
||||||
var existingClient = Clients[polledClient.ClientNumber];
|
|
||||||
|
|
||||||
if (existingClient != null)
|
|
||||||
{
|
|
||||||
await existingClient.OnJoin(polledClient.IPAddress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override public async Task OnClientConnected(EFClient clientFromLog)
|
override public async Task OnClientConnected(EFClient clientFromLog)
|
||||||
{
|
{
|
||||||
Logger.WriteDebug($"Client slot #{clientFromLog.ClientNumber} now reserved");
|
Logger.WriteDebug($"Client slot #{clientFromLog.ClientNumber} now reserved");
|
||||||
@ -119,40 +110,49 @@ namespace IW4MAdmin
|
|||||||
Clients[client.ClientNumber] = client;
|
Clients[client.ClientNumber] = client;
|
||||||
client.OnConnect();
|
client.OnConnect();
|
||||||
|
|
||||||
|
// this only happens the preconnect event occurred from RCon polling
|
||||||
|
if (clientFromLog.IPAddress != 0)
|
||||||
|
{
|
||||||
|
await client.OnJoin(clientFromLog.IPAddress);
|
||||||
|
}
|
||||||
|
|
||||||
client.State = EFClient.ClientState.Connected;
|
client.State = EFClient.ClientState.Connected;
|
||||||
|
#if DEBUG == true
|
||||||
|
Logger.WriteDebug($"End PreConnect for {client}");
|
||||||
|
#endif
|
||||||
|
var e = new GameEvent()
|
||||||
|
{
|
||||||
|
Origin = client,
|
||||||
|
Owner = this,
|
||||||
|
Type = GameEvent.EventType.Connect
|
||||||
|
};
|
||||||
|
|
||||||
|
Manager.GetEventHandler().AddEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.WriteError($"{loc["SERVER_ERROR_ADDPLAYER"]} {clientFromLog.Name}::{clientFromLog.NetworkId}");
|
Logger.WriteError($"{loc["SERVER_ERROR_ADDPLAYER"]} {clientFromLog}");
|
||||||
Logger.WriteDebug(ex.Message);
|
Logger.WriteError(ex.GetExceptionInfo());
|
||||||
Logger.WriteDebug(ex.StackTrace);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Remove player by CLIENT NUMBER
|
override public async Task OnClientDisconnected(EFClient client)
|
||||||
override public async Task RemoveClient(int cNum)
|
|
||||||
{
|
{
|
||||||
if (cNum >= 0 && Clients[cNum] != null)
|
Logger.WriteInfo($"Client {client} [{client.State.ToString().ToLower()}] disconnecting...");
|
||||||
|
await client.OnDisconnect();
|
||||||
|
Clients[client.ClientNumber] = null;
|
||||||
|
#if DEBUG == true
|
||||||
|
Logger.WriteDebug($"End PreDisconnect for {client}");
|
||||||
|
#endif
|
||||||
|
var e = new GameEvent()
|
||||||
{
|
{
|
||||||
EFClient Leaving = Clients[cNum];
|
Origin = client,
|
||||||
|
Owner = this,
|
||||||
|
Type = GameEvent.EventType.Disconnect
|
||||||
|
};
|
||||||
|
|
||||||
// occurs when the player disconnects via log before being authenticated by RCon
|
Manager.GetEventHandler().AddEvent(e);
|
||||||
if (Leaving.State != EFClient.ClientState.Connected)
|
|
||||||
{
|
|
||||||
Clients[cNum] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.WriteInfo($"Client {Leaving} [{Leaving.State.ToString().ToLower()}] disconnecting...");
|
|
||||||
Leaving.State = EFClient.ClientState.Disconnecting;
|
|
||||||
Leaving.TotalConnectionTime += Leaving.ConnectionLength;
|
|
||||||
Leaving.LastConnection = DateTime.UtcNow;
|
|
||||||
await Manager.GetClientService().Update(Leaving);
|
|
||||||
Clients[cNum] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task ExecuteEvent(GameEvent E)
|
public override async Task ExecuteEvent(GameEvent E)
|
||||||
@ -218,27 +218,34 @@ namespace IW4MAdmin
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
override protected async Task<bool> ProcessEvent(GameEvent E)
|
override protected async Task<bool> ProcessEvent(GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Type == GameEvent.EventType.Connect)
|
if (E.Type == GameEvent.EventType.PreConnect)
|
||||||
{
|
{
|
||||||
E.Origin.State = EFClient.ClientState.Authenticated;
|
bool clientExists = GetClientsAsList().Exists(_client => _client.NetworkId.Equals(E.Origin));
|
||||||
await OnClientConnected(E.Origin);
|
|
||||||
|
|
||||||
ChatHistory.Add(new ChatInfo()
|
if (!clientExists)
|
||||||
{
|
{
|
||||||
Name = E.Origin.Name,
|
#if DEBUG == true
|
||||||
Message = "CONNECTED",
|
Logger.WriteDebug($"Begin PreConnect for {E.Origin}");
|
||||||
Time = DateTime.UtcNow
|
#endif
|
||||||
});
|
await OnClientConnected(E.Origin);
|
||||||
|
|
||||||
if (E.Origin.Level > EFClient.Permission.Moderator)
|
ChatHistory.Add(new ChatInfo()
|
||||||
{
|
{
|
||||||
E.Origin.Tell(string.Format(loc["SERVER_REPORT_COUNT"], E.Owner.Reports.Count));
|
Name = E.Origin.Name,
|
||||||
|
Message = "CONNECTED",
|
||||||
|
Time = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
if (E.Origin.Level > EFClient.Permission.Moderator)
|
||||||
|
{
|
||||||
|
E.Origin.Tell(string.Format(loc["SERVER_REPORT_COUNT"], E.Owner.Reports.Count));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
else if (E.Type == GameEvent.EventType.Join)
|
else
|
||||||
{
|
{
|
||||||
await OnClientJoined(E.Origin);
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (E.Type == GameEvent.EventType.Flag)
|
else if (E.Type == GameEvent.EventType.Flag)
|
||||||
@ -303,13 +310,9 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
else if (E.Type == GameEvent.EventType.Quit)
|
else if (E.Type == GameEvent.EventType.Quit)
|
||||||
{
|
{
|
||||||
var origin = Clients.FirstOrDefault(p => p != null && p.NetworkId == E.Origin.NetworkId);
|
var origin = GetClientsAsList().FirstOrDefault(_client => _client.NetworkId.Equals(E.Origin));
|
||||||
|
|
||||||
if (origin != null &&
|
if (origin != null)
|
||||||
// we only want to forward the event if they are connected.
|
|
||||||
origin.State == EFClient.ClientState.Connected &&
|
|
||||||
// make sure we don't get the disconnect event from every time the game ends
|
|
||||||
origin.ConnectionLength < Manager.GetApplicationSettings().Configuration().RConPollRate)
|
|
||||||
{
|
{
|
||||||
var e = new GameEvent()
|
var e = new GameEvent()
|
||||||
{
|
{
|
||||||
@ -321,29 +324,45 @@ namespace IW4MAdmin
|
|||||||
Manager.GetEventHandler().AddEvent(e);
|
Manager.GetEventHandler().AddEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (origin != null &&
|
else
|
||||||
origin.State != EFClient.ClientState.Connected)
|
|
||||||
{
|
{
|
||||||
await RemoveClient(origin.ClientNumber);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (E.Type == GameEvent.EventType.Disconnect)
|
else if (E.Type == GameEvent.EventType.PreDisconnect)
|
||||||
{
|
{
|
||||||
ChatHistory.Add(new ChatInfo()
|
// predisconnect comes from minimal rcon polled players and minimal log players
|
||||||
{
|
// so we need to disconnect the "full" version of the client
|
||||||
Name = E.Origin.Name,
|
var client = GetClientsAsList().FirstOrDefault(_client => _client.Equals(E.Origin));
|
||||||
Message = "DISCONNECTED",
|
|
||||||
Time = DateTime.UtcNow
|
|
||||||
});
|
|
||||||
|
|
||||||
var currentState = E.Origin.State;
|
if (client != null)
|
||||||
await RemoveClient(E.Origin.ClientNumber);
|
|
||||||
|
|
||||||
if (currentState != EFClient.ClientState.Connected)
|
|
||||||
{
|
{
|
||||||
throw new ServerException("Disconnecting player was not in a connected state");
|
#if DEBUG == true
|
||||||
|
Logger.WriteDebug($"Begin PreDisconnect for {client}");
|
||||||
|
#endif
|
||||||
|
ChatHistory.Add(new ChatInfo()
|
||||||
|
{
|
||||||
|
Name = client.Name,
|
||||||
|
Message = "DISCONNECTED",
|
||||||
|
Time = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
await OnClientDisconnected(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (E.Type == GameEvent.EventType.Update)
|
||||||
|
{
|
||||||
|
#if DEBUG == true
|
||||||
|
Logger.WriteDebug($"Begin Update for {E.Origin}");
|
||||||
|
#endif
|
||||||
|
await OnClientUpdate(E.Origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Type == GameEvent.EventType.Say)
|
if (E.Type == GameEvent.EventType.Say)
|
||||||
@ -440,6 +459,24 @@ namespace IW4MAdmin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Task OnClientUpdate(EFClient origin)
|
||||||
|
{
|
||||||
|
var client = Clients[origin.ClientNumber];
|
||||||
|
|
||||||
|
if (client != null)
|
||||||
|
{
|
||||||
|
client.Ping = origin.Ping;
|
||||||
|
client.Score = origin.Score;
|
||||||
|
|
||||||
|
if (origin.IPAddress == 0)
|
||||||
|
{
|
||||||
|
return client.OnJoin(origin.IPAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// lists the connecting and disconnecting clients via RCon response
|
/// lists the connecting and disconnecting clients via RCon response
|
||||||
/// array index 0 = connecting clients
|
/// array index 0 = connecting clients
|
||||||
@ -471,9 +508,15 @@ namespace IW4MAdmin
|
|||||||
}
|
}
|
||||||
|
|
||||||
var disconnectingClients = currentClients.Except(polledClients);
|
var disconnectingClients = currentClients.Except(polledClients);
|
||||||
var connectingClients = polledClients.Except(currentClients.Where(c => c.State == EFClient.ClientState.Connected));
|
var connectingClients = polledClients.Except(currentClients);
|
||||||
|
var updatedClients = polledClients.Except(connectingClients);
|
||||||
|
|
||||||
return new List<EFClient>[] { connectingClients.ToList(), disconnectingClients.ToList() };
|
return new List<EFClient>[]
|
||||||
|
{
|
||||||
|
connectingClients.ToList(),
|
||||||
|
disconnectingClients.ToList(),
|
||||||
|
updatedClients.ToList()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime start = DateTime.Now;
|
DateTime start = DateTime.Now;
|
||||||
@ -484,21 +527,30 @@ namespace IW4MAdmin
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
#region SHUTDOWN
|
||||||
if (Manager.ShutdownRequested())
|
if (Manager.ShutdownRequested())
|
||||||
{
|
{
|
||||||
// todo: fix up disconnect
|
foreach (var client in GetClientsAsList())
|
||||||
//for (int i = 0; i < EFClients.Count; i++)
|
{
|
||||||
// await RemoveClient(i);
|
var e = new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.PreDisconnect,
|
||||||
|
Origin = client,
|
||||||
|
Owner = this,
|
||||||
|
};
|
||||||
|
|
||||||
|
Manager.GetEventHandler().AddEvent(e);
|
||||||
|
await e.WaitAsync();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins)
|
foreach (var plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins)
|
||||||
{
|
{
|
||||||
await plugin.OnUnloadAsync();
|
await plugin.OnUnloadAsync();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// only check every 2 minutes if the server doesn't seem to be responding
|
return true;
|
||||||
/* if ((DateTime.Now - LastPoll).TotalMinutes < 0.5 && ConnectionErrors >= 1)
|
}
|
||||||
return true;*/
|
#endregion
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -514,7 +566,7 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
var e = new GameEvent()
|
var e = new GameEvent()
|
||||||
{
|
{
|
||||||
Type = GameEvent.EventType.Disconnect,
|
Type = GameEvent.EventType.PreDisconnect,
|
||||||
Origin = disconnectingClient,
|
Origin = disconnectingClient,
|
||||||
Owner = this
|
Owner = this
|
||||||
};
|
};
|
||||||
@ -531,16 +583,9 @@ namespace IW4MAdmin
|
|||||||
// this are our new connecting clients
|
// this are our new connecting clients
|
||||||
foreach (var client in polledClients[0])
|
foreach (var client in polledClients[0])
|
||||||
{
|
{
|
||||||
// this prevents duplicate events from being sent to the event api
|
|
||||||
if (GetClientsAsList().Count(c => c.NetworkId == client.NetworkId &&
|
|
||||||
c.State == EFClient.ClientState.Connected) != 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var e = new GameEvent()
|
var e = new GameEvent()
|
||||||
{
|
{
|
||||||
Type = GameEvent.EventType.Connect,
|
Type = GameEvent.EventType.PreConnect,
|
||||||
Origin = client,
|
Origin = client,
|
||||||
Owner = this
|
Owner = this
|
||||||
};
|
};
|
||||||
@ -552,11 +597,29 @@ namespace IW4MAdmin
|
|||||||
// wait for all the connect tasks to finish
|
// wait for all the connect tasks to finish
|
||||||
await Task.WhenAll(waiterList.Select(e => e.WaitAsync(10 * 1000)));
|
await Task.WhenAll(waiterList.Select(e => e.WaitAsync(10 * 1000)));
|
||||||
|
|
||||||
|
waiterList.Clear();
|
||||||
|
// these are the clients that have updated
|
||||||
|
foreach (var client in polledClients[2])
|
||||||
|
{
|
||||||
|
var e = new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.Update,
|
||||||
|
Origin = client,
|
||||||
|
Owner = this
|
||||||
|
};
|
||||||
|
|
||||||
|
Manager.GetEventHandler().AddEvent(e);
|
||||||
|
waiterList.Add(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.WhenAll(waiterList.Select(e => e.WaitAsync(10 * 1000)));
|
||||||
|
|
||||||
if (ConnectionErrors > 0)
|
if (ConnectionErrors > 0)
|
||||||
{
|
{
|
||||||
Logger.WriteVerbose($"{loc["MANAGER_CONNECTION_REST"]} {IP}:{Port}");
|
Logger.WriteVerbose($"{loc["MANAGER_CONNECTION_REST"]} {IP}:{Port}");
|
||||||
Throttled = false;
|
Throttled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionErrors = 0;
|
ConnectionErrors = 0;
|
||||||
LastPoll = DateTime.Now;
|
LastPoll = DateTime.Now;
|
||||||
}
|
}
|
||||||
@ -576,20 +639,6 @@ namespace IW4MAdmin
|
|||||||
LastMessage = DateTime.Now - start;
|
LastMessage = DateTime.Now - start;
|
||||||
lastCount = DateTime.Now;
|
lastCount = DateTime.Now;
|
||||||
|
|
||||||
// todo: re-enable on tick
|
|
||||||
/*
|
|
||||||
if ((DateTime.Now - tickTime).TotalMilliseconds >= 1000)
|
|
||||||
{
|
|
||||||
foreach (var Plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins)
|
|
||||||
{
|
|
||||||
if (cts.IsCancellationRequested)
|
|
||||||
break;
|
|
||||||
|
|
||||||
await Plugin.OnTickAsync(this);
|
|
||||||
}
|
|
||||||
tickTime = DateTime.Now;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// update the player history
|
// update the player history
|
||||||
if ((lastCount - playerCountStart).TotalMinutes >= SharedLibraryCore.Helpers.PlayerHistory.UpdateInterval)
|
if ((lastCount - playerCountStart).TotalMinutes >= SharedLibraryCore.Helpers.PlayerHistory.UpdateInterval)
|
||||||
{
|
{
|
||||||
@ -849,7 +898,7 @@ namespace IW4MAdmin
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
await Target.CurrentServer.RemoveClient(Target.ClientNumber);
|
await Target.CurrentServer.OnClientDisconnected(Target);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var newPenalty = new Penalty()
|
var newPenalty = new Penalty()
|
||||||
@ -887,7 +936,7 @@ namespace IW4MAdmin
|
|||||||
await Target.CurrentServer.ExecuteCommandAsync(formattedKick);
|
await Target.CurrentServer.ExecuteCommandAsync(formattedKick);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
await Target.CurrentServer.RemoveClient(Target.ClientNumber);
|
await Target.CurrentServer.OnClientDisconnected(Target);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Penalty newPenalty = new Penalty()
|
Penalty newPenalty = new Penalty()
|
||||||
@ -933,7 +982,7 @@ namespace IW4MAdmin
|
|||||||
string formattedString = String.Format(RconParser.GetCommandPrefixes().Kick, Target.ClientNumber, $"{loc["SERVER_BAN_TEXT"]} - ^5{Message} ^7({loc["SERVER_BAN_APPEAL"]} {Website})^7");
|
string formattedString = String.Format(RconParser.GetCommandPrefixes().Kick, Target.ClientNumber, $"{loc["SERVER_BAN_TEXT"]} - ^5{Message} ^7({loc["SERVER_BAN_APPEAL"]} {Website})^7");
|
||||||
await Target.CurrentServer.ExecuteCommandAsync(formattedString);
|
await Target.CurrentServer.ExecuteCommandAsync(formattedString);
|
||||||
#else
|
#else
|
||||||
await Target.CurrentServer.RemoveClient(Target.ClientNumber);
|
await Target.CurrentServer.OnClientDisconnected(Target);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -85,29 +85,7 @@ namespace IW4MAdmin.Application
|
|||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// if the origin client is not in an authorized state (detected by RCon) don't execute the event
|
|
||||||
if (GameEvent.ShouldOriginEventBeDelayed(newEvent))
|
|
||||||
{
|
|
||||||
Logger.WriteDebug($"Delaying origin execution of event type {newEvent.Type} for {newEvent.Origin} because they are not authed");
|
|
||||||
if (newEvent.Type == GameEvent.EventType.Command)
|
|
||||||
{
|
|
||||||
newEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["SERVER_DELAYED_EVENT_WAIT"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// offload it to the player to keep
|
|
||||||
newEvent.Origin.DelayedEvents.Enqueue(newEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the target client is not in an authorized state (detected by RCon) don't execute the event
|
|
||||||
else if (GameEvent.ShouldTargetEventBeDelayed(newEvent))
|
|
||||||
{
|
|
||||||
Logger.WriteDebug($"Delaying target execution of event type {newEvent.Type} for {newEvent.Target} because they are not authed");
|
|
||||||
// offload it to the player to keep
|
|
||||||
newEvent.Target.DelayedEvents.Enqueue(newEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
|
||||||
await newEvent.Owner.ExecuteEvent(newEvent);
|
await newEvent.Owner.ExecuteEvent(newEvent);
|
||||||
|
@ -1,22 +1,26 @@
|
|||||||
aniso8601==3.0.2
|
aniso8601==3.0.2
|
||||||
|
APScheduler==3.5.3
|
||||||
|
certifi==2018.10.15
|
||||||
|
chardet==3.0.4
|
||||||
click==6.7
|
click==6.7
|
||||||
Flask==1.0.2
|
Flask==1.0.2
|
||||||
Flask-JWT==0.3.2
|
Flask-JWT==0.3.2
|
||||||
Flask-JWT-Extended==3.8.1
|
Flask-JWT-Extended==3.8.1
|
||||||
Flask-RESTful==0.3.6
|
Flask-RESTful==0.3.6
|
||||||
|
idna==2.7
|
||||||
itsdangerous==0.24
|
itsdangerous==0.24
|
||||||
Jinja2==2.10
|
Jinja2==2.10
|
||||||
MarkupSafe==1.0
|
MarkupSafe==1.0
|
||||||
marshmallow==3.0.0b8
|
marshmallow==3.0.0b8
|
||||||
pip==9.0.3
|
pip==9.0.3
|
||||||
PyJWT==1.4.2
|
|
||||||
pytz==2018.5
|
|
||||||
setuptools==39.0.1
|
|
||||||
six==1.11.0
|
|
||||||
Werkzeug==0.14.1
|
|
||||||
certifi==2018.10.15
|
|
||||||
chardet==3.0.4
|
|
||||||
idna==2.7
|
|
||||||
psutil==5.4.8
|
psutil==5.4.8
|
||||||
|
pygal==2.4.0
|
||||||
|
PyJWT==1.4.2
|
||||||
|
pytz==2018.7
|
||||||
requests==2.20.0
|
requests==2.20.0
|
||||||
|
setuptools==40.5.0
|
||||||
|
six==1.11.0
|
||||||
|
timeago==1.0.8
|
||||||
|
tzlocal==1.5.1
|
||||||
urllib3==1.24
|
urllib3==1.24
|
||||||
|
Werkzeug==0.14.1
|
||||||
|
@ -244,7 +244,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
{
|
{
|
||||||
int serverId = pl.CurrentServer.GetHashCode();
|
int serverId = pl.CurrentServer.GetHashCode();
|
||||||
|
|
||||||
|
|
||||||
if (!Servers.ContainsKey(serverId))
|
if (!Servers.ContainsKey(serverId))
|
||||||
{
|
{
|
||||||
Log.WriteError($"[Stats::AddPlayer] Server with id {serverId} could not be found");
|
Log.WriteError($"[Stats::AddPlayer] Server with id {serverId} could not be found");
|
||||||
|
@ -41,13 +41,13 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
public virtual string Name
|
public virtual string Name
|
||||||
{
|
{
|
||||||
get { return CurrentAlias.Name; }
|
get { return CurrentAlias.Name; }
|
||||||
set { }
|
set { CurrentAlias.Name = value; }
|
||||||
}
|
}
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public virtual int IPAddress
|
public virtual int IPAddress
|
||||||
{
|
{
|
||||||
get { return CurrentAlias.IPAddress; }
|
get { return CurrentAlias.IPAddress; }
|
||||||
set { }
|
set { CurrentAlias.IPAddress = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
using System;
|
using SharedLibraryCore.Database.Models;
|
||||||
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using SharedLibraryCore.Database.Models;
|
|
||||||
using SharedLibraryCore.Objects;
|
|
||||||
|
|
||||||
namespace SharedLibraryCore
|
namespace SharedLibraryCore
|
||||||
{
|
{
|
||||||
@ -74,6 +73,18 @@ namespace SharedLibraryCore
|
|||||||
/// the current map changed
|
/// the current map changed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
MapChange,
|
MapChange,
|
||||||
|
/// <summary>
|
||||||
|
/// a client was detected as starting to connect
|
||||||
|
/// </summary>
|
||||||
|
PreConnect,
|
||||||
|
/// <summary>
|
||||||
|
/// a client was detecting as starting to disconnect
|
||||||
|
/// </summary>
|
||||||
|
PreDisconnect,
|
||||||
|
/// <summary>
|
||||||
|
/// a client's information was updated
|
||||||
|
/// </summary>
|
||||||
|
Update,
|
||||||
|
|
||||||
// events "generated" by clients
|
// events "generated" by clients
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -159,7 +170,10 @@ namespace SharedLibraryCore
|
|||||||
}
|
}
|
||||||
|
|
||||||
static long NextEventId;
|
static long NextEventId;
|
||||||
static long GetNextEventId() => Interlocked.Increment(ref NextEventId);
|
static long GetNextEventId()
|
||||||
|
{
|
||||||
|
return Interlocked.Increment(ref NextEventId);
|
||||||
|
}
|
||||||
|
|
||||||
public GameEvent()
|
public GameEvent()
|
||||||
{
|
{
|
||||||
@ -186,11 +200,14 @@ namespace SharedLibraryCore
|
|||||||
/// asynchronously wait for GameEvent to be processed
|
/// asynchronously wait for GameEvent to be processed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>waitable task </returns>
|
/// <returns>waitable task </returns>
|
||||||
public Task<GameEvent> WaitAsync(int timeOut = int.MaxValue) => Task.Run(() =>
|
public Task<GameEvent> WaitAsync(int timeOut = int.MaxValue)
|
||||||
{
|
{
|
||||||
OnProcessed.Wait(timeOut);
|
return Task.Run(() =>
|
||||||
return this;
|
{
|
||||||
});
|
OnProcessed.Wait(timeOut);
|
||||||
|
return this;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// determine whether an event should be delayed or not
|
/// determine whether an event should be delayed or not
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
using SharedLibraryCore.Database.Models;
|
|
||||||
using SharedLibraryCore.Objects;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace SharedLibraryCore.Interfaces
|
|
||||||
{
|
|
||||||
public interface IClientAuthentication
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// request authentication when a client join event
|
|
||||||
/// occurs in the log, as no IP is given
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="client">client that has joined from the log</param>
|
|
||||||
void RequestClientAuthentication(EFClient client);
|
|
||||||
/// <summary>
|
|
||||||
/// get all clients that have been authenticated by the status poll
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>list of all authenticated clients</returns>
|
|
||||||
IList<EFClient> GetAuthenticatedClients();
|
|
||||||
/// <summary>
|
|
||||||
/// authenticate a list of clients from status poll
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="clients">list of clients to authenticate</param>
|
|
||||||
void AuthenticateClients(IList<EFClient> clients);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,4 @@
|
|||||||
using SharedLibraryCore.Database.Models;
|
using SharedLibraryCore.Objects;
|
||||||
using SharedLibraryCore.Objects;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
@ -18,11 +17,6 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Connecting,
|
Connecting,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// represents when the client has been parsed by RCon,
|
|
||||||
/// but has not been validated against the database
|
|
||||||
/// </summary>
|
|
||||||
Authenticated,
|
|
||||||
/// <summary>
|
|
||||||
/// represents when the client has been authenticated by RCon
|
/// represents when the client has been authenticated by RCon
|
||||||
/// and validated by the database
|
/// and validated by the database
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -86,6 +80,7 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
{
|
{
|
||||||
{ "_reportCount", 0 }
|
{ "_reportCount", 0 }
|
||||||
};
|
};
|
||||||
|
CurrentAlias = CurrentAlias ?? new EFAlias();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
@ -410,7 +405,7 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
public void OnConnect()
|
public void OnConnect()
|
||||||
{
|
{
|
||||||
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||||
//#if !DEBUG
|
#if !DEBUG
|
||||||
if (Name.Length < 3)
|
if (Name.Length < 3)
|
||||||
{
|
{
|
||||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name is too short");
|
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name is too short");
|
||||||
@ -435,7 +430,7 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reserved slots stuff
|
// reserved slots stuff
|
||||||
if ((CurrentServer.GetClientsAsList().Count(_client => !_client.IsPrivileged()) - CurrentServer.MaxClients) < CurrentServer.ServerConfig.ReservedSlotNumber &&
|
if (CurrentServer.MaxClients - (CurrentServer.GetClientsAsList().Count(_client => !_client.IsPrivileged())) < CurrentServer.ServerConfig.ReservedSlotNumber &&
|
||||||
!this.IsPrivileged())
|
!this.IsPrivileged())
|
||||||
{
|
{
|
||||||
CurrentServer.Logger.WriteDebug($"Kicking {this} their spot is reserved");
|
CurrentServer.Logger.WriteDebug($"Kicking {this} their spot is reserved");
|
||||||
@ -446,13 +441,34 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
LastConnection = DateTime.UtcNow;
|
LastConnection = DateTime.UtcNow;
|
||||||
Connections += 1;
|
Connections += 1;
|
||||||
|
|
||||||
//#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task OnDisconnect()
|
||||||
|
{
|
||||||
|
State = ClientState.Disconnecting;
|
||||||
|
TotalConnectionTime += ConnectionLength;
|
||||||
|
LastConnection = DateTime.UtcNow;
|
||||||
|
await CurrentServer.Manager.GetClientService().Update(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task OnJoin(int ipAddress)
|
public async Task OnJoin(int ipAddress)
|
||||||
{
|
{
|
||||||
// todo: fix this up
|
// todo: fix this up
|
||||||
CurrentAlias.IPAddress = IPAddress;
|
var existingAlias = AliasLink.Children
|
||||||
|
.FirstOrDefault(a => a.Name == Name && a.IPAddress == ipAddress);
|
||||||
|
|
||||||
|
if (existingAlias == null)
|
||||||
|
{
|
||||||
|
CurrentServer.Logger.WriteDebug($"Client {this} has connected previously under a different ip/name");
|
||||||
|
|
||||||
|
CurrentAlias = new EFAlias()
|
||||||
|
{
|
||||||
|
IPAddress = ipAddress,
|
||||||
|
Name = Name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
await CurrentServer.Manager.GetClientService().Update(this);
|
await CurrentServer.Manager.GetClientService().Update(this);
|
||||||
|
|
||||||
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||||
@ -477,9 +493,8 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
CurrentServer.Logger.WriteInfo($"Banned client {this} trying to join...");
|
CurrentServer.Logger.WriteInfo($"Banned client {this} trying to join...");
|
||||||
var autoKickClient = Utilities.IW4MAdminClient(CurrentServer);
|
var autoKickClient = Utilities.IW4MAdminClient(CurrentServer);
|
||||||
|
|
||||||
|
|
||||||
// reban the "evading" guid
|
// reban the "evading" guid
|
||||||
if (Level != Permission.Banned &&
|
if (Level != Permission.Banned &&
|
||||||
currentBan.Type == Penalty.PenaltyType.Ban)
|
currentBan.Type == Penalty.PenaltyType.Ban)
|
||||||
{
|
{
|
||||||
// hack: re apply the automated offense to the reban
|
// hack: re apply the automated offense to the reban
|
||||||
@ -501,11 +516,7 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//string formattedKick = String.Format(
|
Kick($"{loc["SERVER_TB_REMAIN"]} ({(currentBan.Expires.Value - DateTime.UtcNow).TimeSpanText()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})", autoKickClient);
|
||||||
// RconParser.GetCommandPrefixes().Kick,
|
|
||||||
// polledPlayer.ClientNumber,
|
|
||||||
// $"{loc["SERVER_TB_REMAIN"]} ({(currentBan.Expires.Value - DateTime.UtcNow).TimeSpanText()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})");
|
|
||||||
//await this.ExecuteCommandAsync(formattedKick);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,11 +106,17 @@ namespace SharedLibraryCore.RCon
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
response = await SendPayloadAsync(payload, waitForResponse);
|
response = await SendPayloadAsync(payload, waitForResponse);
|
||||||
|
|
||||||
|
if (response.Length == 0)
|
||||||
|
{
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
|
||||||
connectionState.OnComplete.Release(1);
|
connectionState.OnComplete.Release(1);
|
||||||
connectionState.ConnectionAttempts = 0;
|
connectionState.ConnectionAttempts = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
catch/* (Exception ex)*/
|
catch
|
||||||
{
|
{
|
||||||
if (connectionState.ConnectionAttempts < StaticHelpers.AllowedConnectionFails)
|
if (connectionState.ConnectionAttempts < StaticHelpers.AllowedConnectionFails)
|
||||||
{
|
{
|
||||||
|
@ -79,7 +79,7 @@ namespace SharedLibraryCore
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cNum">Client ID of player to be removed</param>
|
/// <param name="cNum">Client ID of player to be removed</param>
|
||||||
/// <returns>true if removal succeded, false otherwise</returns>
|
/// <returns>true if removal succeded, false otherwise</returns>
|
||||||
abstract public Task RemoveClient(int cNum);
|
abstract public Task OnClientDisconnected(EFClient client);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
Loading…
Reference in New Issue
Block a user