few more small fixes
complete join button on webfront update for 2.2.6.0
This commit is contained in:
parent
dd82a5e3fa
commit
9d9be7f8af
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using RestEase;
|
using RestEase;
|
||||||
using SharedLibraryCore;
|
using SharedLibraryCore;
|
||||||
@ -11,6 +12,7 @@ namespace IW4MAdmin.Application.API.Master
|
|||||||
public class HeartbeatState
|
public class HeartbeatState
|
||||||
{
|
{
|
||||||
public bool Connected { get; set; }
|
public bool Connected { get; set; }
|
||||||
|
public CancellationToken Token { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Heartbeat
|
public class Heartbeat
|
||||||
|
@ -41,10 +41,9 @@ namespace IW4MAdmin.Application
|
|||||||
|
|
||||||
public IList<IRConParser> AdditionalRConParsers { get; }
|
public IList<IRConParser> AdditionalRConParsers { get; }
|
||||||
public IList<IEventParser> AdditionalEventParsers { get; }
|
public IList<IEventParser> AdditionalEventParsers { get; }
|
||||||
|
|
||||||
public ITokenAuthentication TokenAuthenticator => Authenticator;
|
public ITokenAuthentication TokenAuthenticator => Authenticator;
|
||||||
|
|
||||||
public ITokenAuthentication Authenticator => _authenticator;
|
public ITokenAuthentication Authenticator => _authenticator;
|
||||||
|
public string ExternalIPAddress { get; private set; }
|
||||||
|
|
||||||
static ApplicationManager Instance;
|
static ApplicationManager Instance;
|
||||||
readonly List<AsyncStatus> TaskStatuses;
|
readonly List<AsyncStatus> TaskStatuses;
|
||||||
@ -158,7 +157,7 @@ namespace IW4MAdmin.Application
|
|||||||
return Instance ?? (Instance = new ApplicationManager());
|
return Instance ?? (Instance = new ApplicationManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateServerStates()
|
public async Task UpdateServerStates(CancellationToken token)
|
||||||
{
|
{
|
||||||
// store the server hash code and task for it
|
// store the server hash code and task for it
|
||||||
var runningUpdateTasks = new Dictionary<long, Task>();
|
var runningUpdateTasks = new Dictionary<long, Task>();
|
||||||
@ -215,17 +214,19 @@ namespace IW4MAdmin.Application
|
|||||||
ThreadPool.GetAvailableThreads(out int availableThreads, out int m);
|
ThreadPool.GetAvailableThreads(out int availableThreads, out int m);
|
||||||
Logger.WriteDebug($"There are {workerThreads - availableThreads} active threading tasks");
|
Logger.WriteDebug($"There are {workerThreads - availableThreads} active threading tasks");
|
||||||
#endif
|
#endif
|
||||||
await Task.Delay(ConfigHandler.Configuration().RConPollRate);
|
try
|
||||||
|
{
|
||||||
|
await Task.Delay(ConfigHandler.Configuration().RConPollRate, token);
|
||||||
|
}
|
||||||
|
// if a cancellation is received, we want to return immediately
|
||||||
|
catch { break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// trigger the event processing loop to end
|
|
||||||
SetHasEvent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Init()
|
public async Task Init()
|
||||||
{
|
{
|
||||||
Running = true;
|
Running = true;
|
||||||
|
ExternalIPAddress = await Utilities.GetExternalIP();
|
||||||
|
|
||||||
#region PLUGINS
|
#region PLUGINS
|
||||||
SharedLibraryCore.Plugins.PluginImporter.Load(this);
|
SharedLibraryCore.Plugins.PluginImporter.Load(this);
|
||||||
@ -642,27 +643,34 @@ namespace IW4MAdmin.Application
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
await Task.Delay(30000);
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Task.Delay(30000, heartbeatState.Token);
|
||||||
|
}
|
||||||
|
catch { break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
|
var tokenSource = new CancellationTokenSource();
|
||||||
// this needs to be run seperately from the main thread
|
// this needs to be run seperately from the main thread
|
||||||
var _ = Task.Run(() => SendHeartbeat(new HeartbeatState()));
|
_ = Task.Run(() => SendHeartbeat(new HeartbeatState() { Token = tokenSource.Token }));
|
||||||
_ = Task.Run(() => UpdateServerStates());
|
_ = Task.Run(() => UpdateServerStates(tokenSource.Token));
|
||||||
|
|
||||||
while (Running)
|
while (Running)
|
||||||
{
|
{
|
||||||
OnQuit.Wait();
|
OnQuit.Wait();
|
||||||
|
tokenSource.Cancel();
|
||||||
OnQuit.Reset();
|
OnQuit.Reset();
|
||||||
}
|
}
|
||||||
_servers.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
Running = false;
|
Running = false;
|
||||||
|
OnQuit.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ILogger GetLogger(long serverId)
|
public ILogger GetLogger(long serverId)
|
||||||
@ -737,7 +745,7 @@ namespace IW4MAdmin.Application
|
|||||||
|
|
||||||
public void SetHasEvent()
|
public void SetHasEvent()
|
||||||
{
|
{
|
||||||
OnQuit.Set();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IList<Assembly> GetPluginAssemblies()
|
public IList<Assembly> GetPluginAssemblies()
|
||||||
|
@ -176,7 +176,7 @@ namespace IW4MAdmin
|
|||||||
{
|
{
|
||||||
if (E.Type == GameEvent.EventType.ChangePermission)
|
if (E.Type == GameEvent.EventType.ChangePermission)
|
||||||
{
|
{
|
||||||
var newPermission = (EFClient.Permission)E.Extra;
|
var newPermission = (Permission)E.Extra;
|
||||||
|
|
||||||
if (newPermission < Permission.Moderator)
|
if (newPermission < Permission.Moderator)
|
||||||
{
|
{
|
||||||
@ -189,7 +189,8 @@ namespace IW4MAdmin
|
|||||||
Manager.GetPrivilegedClients()[E.Target.ClientId] = E.Target;
|
Manager.GetPrivilegedClients()[E.Target.ClientId] = E.Target;
|
||||||
}
|
}
|
||||||
|
|
||||||
await Manager.GetClientService().UpdateLevel((Permission)E.Extra, E.Target, E.Origin);
|
Logger.WriteInfo($"{E.Origin} is setting {E.Target} to permission level {newPermission}");
|
||||||
|
await Manager.GetClientService().UpdateLevel(newPermission, E.Target, E.Origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (E.Type == GameEvent.EventType.PreConnect)
|
else if (E.Type == GameEvent.EventType.PreConnect)
|
||||||
@ -342,7 +343,7 @@ namespace IW4MAdmin
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else if (client?.State != ClientState.Disconnecting)
|
||||||
{
|
{
|
||||||
Logger.WriteWarning($"Client {E.Origin} detected as disconnecting, but could not find them in the player list");
|
Logger.WriteWarning($"Client {E.Origin} detected as disconnecting, but could not find them in the player list");
|
||||||
Logger.WriteDebug($"Expected {E.Origin} but found {GetClientsAsList().FirstOrDefault(_client => _client.ClientNumber == E.Origin.ClientNumber)}");
|
Logger.WriteDebug($"Expected {E.Origin} but found {GetClientsAsList().FirstOrDefault(_client => _client.ClientNumber == E.Origin.ClientNumber)}");
|
||||||
@ -470,9 +471,18 @@ namespace IW4MAdmin
|
|||||||
if (client.IPAddress == null &&
|
if (client.IPAddress == null &&
|
||||||
!client.IsBot &&
|
!client.IsBot &&
|
||||||
client.State == ClientState.Connected)
|
client.State == ClientState.Connected)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
await client.OnJoin(origin.IPAddress);
|
await client.OnJoin(origin.IPAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
origin.CurrentServer.Logger.WriteWarning($"Could not execute on join for {origin}");
|
||||||
|
origin.CurrentServer.Logger.WriteDebug(e.GetExceptionInfo());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
[NotMapped]
|
[NotMapped]
|
||||||
public virtual string Name
|
public virtual string Name
|
||||||
{
|
{
|
||||||
get { return CurrentAlias.Name; }
|
get { return CurrentAlias?.Name ?? "--"; }
|
||||||
set { CurrentAlias.Name = value; }
|
set { if (CurrentAlias != null) CurrentAlias.Name = value; }
|
||||||
}
|
}
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public virtual int? IPAddress
|
public virtual int? IPAddress
|
||||||
|
@ -20,5 +20,6 @@ namespace SharedLibraryCore.Dtos
|
|||||||
public long ID { get; set; }
|
public long ID { get; set; }
|
||||||
public bool Online { get; set; }
|
public bool Online { get; set; }
|
||||||
public string ConnectProtocolUrl { get; set; }
|
public string ConnectProtocolUrl { get; set; }
|
||||||
|
public string IPAddress { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,5 +46,6 @@ namespace SharedLibraryCore.Interfaces
|
|||||||
IEventParser GenerateDynamicEventParser();
|
IEventParser GenerateDynamicEventParser();
|
||||||
string Version { get;}
|
string Version { get;}
|
||||||
ITokenAuthentication TokenAuthenticator { get; }
|
ITokenAuthentication TokenAuthenticator { get; }
|
||||||
|
string ExternalIPAddress { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -467,9 +467,19 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
State = ClientState.Disconnecting;
|
State = ClientState.Disconnecting;
|
||||||
TotalConnectionTime += ConnectionLength;
|
TotalConnectionTime += ConnectionLength;
|
||||||
LastConnection = DateTime.UtcNow;
|
LastConnection = DateTime.UtcNow;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
await CurrentServer.Manager.GetClientService().Update(this);
|
await CurrentServer.Manager.GetClientService().Update(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
CurrentServer.Logger.WriteWarning($"Could not update disconnected player {this}");
|
||||||
|
CurrentServer.Logger.WriteDebug(e.GetExceptionInfo());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task OnJoin(int? ipAddress)
|
public async Task OnJoin(int? ipAddress)
|
||||||
{
|
{
|
||||||
CurrentServer.Logger.WriteDebug($"Start join for {this}::{ipAddress}::{Level.ToString()}");
|
CurrentServer.Logger.WriteDebug($"Start join for {this}::{ipAddress}::{Level.ToString()}");
|
||||||
|
@ -248,6 +248,7 @@ namespace SharedLibraryCore.Services
|
|||||||
Type = GameEvent.EventType.ChangePermission,
|
Type = GameEvent.EventType.ChangePermission,
|
||||||
Extra = newPermission,
|
Extra = newPermission,
|
||||||
Origin = origin,
|
Origin = origin,
|
||||||
|
Owner = temporalClient.CurrentServer,
|
||||||
Target = _client
|
Target = _client
|
||||||
}, ctx);
|
}, ctx);
|
||||||
#if DEBUG == true
|
#if DEBUG == true
|
||||||
@ -255,7 +256,6 @@ namespace SharedLibraryCore.Services
|
|||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
await ctx.SaveChangesAsync();
|
await ctx.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ using System.Diagnostics;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
@ -730,6 +731,53 @@ namespace SharedLibraryCore
|
|||||||
return string.Format(output, values);
|
return string.Format(output, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// https://stackoverflow.com/questions/8113546/how-to-determine-whether-an-ip-address-in-private/39120248
|
||||||
|
/// An extension method to determine if an IP address is internal, as specified in RFC1918
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="toTest">The IP address that will be tested</param>
|
||||||
|
/// <returns>Returns true if the IP is internal, false if it is external</returns>
|
||||||
|
public static bool IsInternal(this IPAddress toTest)
|
||||||
|
{
|
||||||
|
if (toTest.ToString().StartsWith("127.0.0"))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] bytes = toTest.GetAddressBytes();
|
||||||
|
switch (bytes[0])
|
||||||
|
{
|
||||||
|
case 10:
|
||||||
|
return true;
|
||||||
|
case 172:
|
||||||
|
return bytes[1] < 32 && bytes[1] >= 16;
|
||||||
|
case 192:
|
||||||
|
return bytes[1] == 168;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// retrieves the external IP address of the current running machine
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task<string> GetExternalIP()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var wc = new WebClient())
|
||||||
|
{
|
||||||
|
return await wc.DownloadStringTaskAsync("https://api.ipify.org");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if DEBUG == true
|
#if DEBUG == true
|
||||||
|
|
||||||
private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo();
|
private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo();
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using SharedLibraryCore;
|
using SharedLibraryCore;
|
||||||
using SharedLibraryCore.Dtos;
|
using SharedLibraryCore.Dtos;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace WebfrontCore.ViewComponents
|
namespace WebfrontCore.ViewComponents
|
||||||
{
|
{
|
||||||
@ -10,6 +11,7 @@ namespace WebfrontCore.ViewComponents
|
|||||||
public IViewComponentResult Invoke()
|
public IViewComponentResult Invoke()
|
||||||
{
|
{
|
||||||
var servers = Program.Manager.GetServers();
|
var servers = Program.Manager.GetServers();
|
||||||
|
|
||||||
var serverInfo = servers.Select(s => new ServerInfo()
|
var serverInfo = servers.Select(s => new ServerInfo()
|
||||||
{
|
{
|
||||||
Name = s.Hostname,
|
Name = s.Hostname,
|
||||||
@ -30,7 +32,8 @@ namespace WebfrontCore.ViewComponents
|
|||||||
}).ToList(),
|
}).ToList(),
|
||||||
ChatHistory = s.ChatHistory.ToList(),
|
ChatHistory = s.ChatHistory.ToList(),
|
||||||
Online = !s.Throttled,
|
Online = !s.Throttled,
|
||||||
ConnectProtocolUrl = s.EventParser.URLProtocolFormat.FormatExt(s.IP, s.GetPort())
|
IPAddress = $"{(IPAddress.Parse(s.IP).IsInternal() ? Program.Manager.ExternalIPAddress : s.IP)}:{s.GetPort()}",
|
||||||
|
ConnectProtocolUrl = s.EventParser.URLProtocolFormat.FormatExt(IPAddress.Parse(s.IP).IsInternal() ? Program.Manager.ExternalIPAddress : s.IP, s.GetPort())
|
||||||
}).ToList();
|
}).ToList();
|
||||||
return View("_List", serverInfo);
|
return View("_List", serverInfo);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
<div class="col-md-4 text-center text-md-left d-inline-flex justify-content-center justify-content-md-start">
|
<div class="col-md-4 text-center text-md-left d-inline-flex justify-content-center justify-content-md-start">
|
||||||
<span>@Model.Name</span>
|
<span>@Model.Name</span>
|
||||||
<a href="@Model.ConnectProtocolUrl" class="ml-2 align-self-center d-none d-md-flex server-join-button" title="@SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_HOME_JOIN_DESC"]">
|
<a href="@Model.ConnectProtocolUrl" class="ml-2 align-self-center d-none d-md-flex server-join-button" title="@SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_HOME_JOIN_DESC"]">
|
||||||
<span class="oi oi-play-circle"></span>
|
<span class="oi oi-play-circle mr-2 align-self-center"></span>
|
||||||
|
<span class="server-header-ip-address" style="display:none;">@Model.IPAddress</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center col-md-4">@Model.Map</div>
|
<div class="text-center col-md-4">@Model.Map</div>
|
||||||
|
@ -89,4 +89,10 @@ function refreshClientActivity() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('.server-join-button').click(function (e) {
|
||||||
|
$(this).children('.server-header-ip-address').show();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
setInterval(refreshClientActivity, 2000);
|
setInterval(refreshClientActivity, 2000);
|
||||||
|
Loading…
Reference in New Issue
Block a user