2018-11-25 21:00:36 -05:00
using IW4MAdmin.Application.API.Master ;
2019-01-26 21:33:37 -05:00
using IW4MAdmin.Application.EventParsers ;
2019-02-15 23:19:59 -05:00
using IW4MAdmin.Application.Misc ;
2019-01-26 21:33:37 -05:00
using IW4MAdmin.Application.RconParsers ;
2018-04-08 02:44:42 -04:00
using SharedLibraryCore ;
using SharedLibraryCore.Commands ;
using SharedLibraryCore.Configuration ;
2018-08-28 17:32:59 -04:00
using SharedLibraryCore.Database ;
2018-11-05 22:01:29 -05:00
using SharedLibraryCore.Database.Models ;
2019-02-22 20:06:51 -05:00
using SharedLibraryCore.Dtos ;
2018-11-25 21:00:36 -05:00
using SharedLibraryCore.Events ;
using SharedLibraryCore.Exceptions ;
using SharedLibraryCore.Helpers ;
using SharedLibraryCore.Interfaces ;
using SharedLibraryCore.Services ;
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Reflection ;
using System.Text ;
using System.Threading ;
using System.Threading.Tasks ;
2018-09-29 15:52:22 -04:00
2018-04-08 14:48:40 -04:00
namespace IW4MAdmin.Application
2015-07-03 00:10:01 -04:00
{
2018-02-21 20:29:23 -05:00
public class ApplicationManager : IManager
2015-07-03 00:10:01 -04:00
{
2017-10-04 19:01:04 -04:00
private List < Server > _servers ;
public List < Server > Servers = > _servers . OrderByDescending ( s = > s . ClientNum ) . ToList ( ) ;
2018-11-05 22:01:29 -05:00
public Dictionary < int , EFClient > PrivilegedClients { get ; set ; }
2018-10-06 12:47:14 -04:00
public ILogger Logger = > GetLogger ( 0 ) ;
2017-06-19 13:58:01 -04:00
public bool Running { get ; private set ; }
2018-07-04 22:09:42 -04:00
public bool IsInitialized { get ; private set ; }
2018-08-27 18:07:54 -04:00
// define what the delagate function looks like
public delegate void OnServerEventEventHandler ( object sender , GameEventArgs e ) ;
// expose the event handler so we can execute the events
2018-09-02 17:59:27 -04:00
public OnServerEventEventHandler OnServerEvent { get ; set ; }
2018-04-18 16:46:53 -04:00
public DateTime StartTime { get ; private set ; }
2018-09-16 16:34:16 -04:00
public string Version = > Assembly . GetEntryAssembly ( ) . GetName ( ) . Version . ToString ( ) ;
2017-06-19 13:58:01 -04:00
2019-02-01 20:49:25 -05:00
public IList < IRConParser > AdditionalRConParsers { get ; }
public IList < IEventParser > AdditionalEventParsers { get ; }
2019-01-26 21:33:37 -05:00
2019-02-15 23:19:59 -05:00
public ITokenAuthentication TokenAuthenticator = > Authenticator ;
public ITokenAuthentication Authenticator = > _authenticator ;
2017-06-19 13:58:01 -04:00
static ApplicationManager Instance ;
2018-08-03 22:11:58 -04:00
readonly List < AsyncStatus > TaskStatuses ;
2017-05-26 18:49:27 -04:00
List < Command > Commands ;
2018-08-03 22:11:58 -04:00
readonly List < MessageToken > MessageTokens ;
2017-11-25 20:29:58 -05:00
ClientService ClientSvc ;
2018-08-03 22:11:58 -04:00
readonly AliasService AliasSvc ;
readonly PenaltyService PenaltySvc ;
2018-08-28 17:32:59 -04:00
public BaseConfigurationHandler < ApplicationConfiguration > ConfigHandler ;
2018-04-26 02:13:04 -04:00
GameEventHandler Handler ;
2018-08-28 17:32:59 -04:00
ManualResetEventSlim OnQuit ;
2018-08-03 18:10:20 -04:00
readonly IPageList PageList ;
2018-09-23 20:45:54 -04:00
readonly SemaphoreSlim ProcessingEvent = new SemaphoreSlim ( 1 , 1 ) ;
2018-11-27 19:31:48 -05:00
readonly Dictionary < long , ILogger > Loggers = new Dictionary < long , ILogger > ( ) ;
2019-02-15 23:19:59 -05:00
readonly ITokenAuthentication _authenticator ;
2019-02-22 20:06:51 -05:00
private readonly MetaService _metaService ;
2017-05-26 18:49:27 -04:00
2017-06-19 13:58:01 -04:00
private ApplicationManager ( )
2015-07-03 00:10:01 -04:00
{
2017-10-04 19:01:04 -04:00
_servers = new List < Server > ( ) ;
2017-05-26 18:49:27 -04:00
Commands = new List < Command > ( ) ;
2017-06-19 13:58:01 -04:00
TaskStatuses = new List < AsyncStatus > ( ) ;
MessageTokens = new List < MessageToken > ( ) ;
2017-11-25 20:29:58 -05:00
ClientSvc = new ClientService ( ) ;
AliasSvc = new AliasService ( ) ;
PenaltySvc = new PenaltyService ( ) ;
2018-03-18 22:25:11 -04:00
ConfigHandler = new BaseConfigurationHandler < ApplicationConfiguration > ( "IW4MAdminSettings" ) ;
2018-04-18 16:46:53 -04:00
StartTime = DateTime . UtcNow ;
2018-08-28 17:32:59 -04:00
OnQuit = new ManualResetEventSlim ( ) ;
2018-08-03 18:10:20 -04:00
PageList = new PageList ( ) ;
2019-02-01 20:49:25 -05:00
AdditionalEventParsers = new List < IEventParser > ( ) ;
AdditionalRConParsers = new List < IRConParser > ( ) ;
2018-09-29 15:52:22 -04:00
OnServerEvent + = OnGameEvent ;
2018-08-30 21:53:00 -04:00
OnServerEvent + = EventApi . OnGameEvent ;
2019-02-15 23:19:59 -05:00
_authenticator = new TokenAuthentication ( ) ;
2019-02-22 20:06:51 -05:00
_metaService = new MetaService ( ) ;
2018-08-27 18:07:54 -04:00
}
2018-09-29 15:52:22 -04:00
private async void OnGameEvent ( object sender , GameEventArgs args )
2018-08-27 18:07:54 -04:00
{
2018-09-29 15:52:22 -04:00
#if DEBUG = = true
Logger . WriteDebug ( $"Entering event process for {args.Event.Id}" ) ;
#endif
2018-09-23 20:45:54 -04:00
2018-08-27 18:07:54 -04:00
var newEvent = args . Event ;
2018-10-02 13:39:08 -04:00
// the event has failed already
if ( newEvent . Failed )
{
goto skip ;
}
2018-08-27 18:07:54 -04:00
try
2018-11-25 21:00:36 -05:00
{
await newEvent . Owner . ExecuteEvent ( newEvent ) ;
2018-09-29 15:52:22 -04:00
2018-11-25 21:00:36 -05:00
// save the event info to the database
var changeHistorySvc = new ChangeHistoryService ( ) ;
await changeHistorySvc . Add ( args . Event ) ;
2018-08-28 17:32:59 -04:00
2018-08-27 18:07:54 -04:00
#if DEBUG
2018-09-02 17:59:27 -04:00
Logger . WriteDebug ( $"Processed event with id {newEvent.Id}" ) ;
2018-08-27 18:07:54 -04:00
#endif
}
// this happens if a plugin requires login
catch ( AuthorizationException ex )
{
2018-10-02 13:39:08 -04:00
newEvent . FailReason = GameEvent . EventFailReason . Permission ;
2018-09-29 15:52:22 -04:00
newEvent . Origin . Tell ( $"{Utilities.CurrentLocalization.LocalizationIndex[" COMMAND_NOTAUTHORIZED "]} - {ex.Message}" ) ;
2018-08-27 18:07:54 -04:00
}
catch ( NetworkException ex )
{
2018-10-02 13:39:08 -04:00
newEvent . FailReason = GameEvent . EventFailReason . Exception ;
2018-08-27 18:07:54 -04:00
Logger . WriteError ( ex . Message ) ;
2018-09-23 20:45:54 -04:00
Logger . WriteDebug ( ex . GetExceptionInfo ( ) ) ;
2018-08-27 18:07:54 -04:00
}
catch ( ServerException ex )
{
2018-10-02 13:39:08 -04:00
newEvent . FailReason = GameEvent . EventFailReason . Exception ;
2018-08-27 18:07:54 -04:00
Logger . WriteWarning ( ex . Message ) ;
}
catch ( Exception ex )
{
2018-10-02 13:39:08 -04:00
newEvent . FailReason = GameEvent . EventFailReason . Exception ;
2018-08-27 18:07:54 -04:00
Logger . WriteError ( $"{Utilities.CurrentLocalization.LocalizationIndex[" SERVER_ERROR_EXCEPTION "]} {newEvent.Owner}" ) ;
2018-09-23 20:45:54 -04:00
Logger . WriteDebug ( ex . GetExceptionInfo ( ) ) ;
2018-08-27 18:07:54 -04:00
}
2018-09-23 20:45:54 -04:00
2018-11-25 21:00:36 -05:00
skip :
2018-10-02 13:39:08 -04:00
2018-08-27 18:07:54 -04:00
// tell anyone waiting for the output that we're done
2018-09-06 14:25:58 -04:00
newEvent . OnProcessed . Set ( ) ;
2018-03-14 01:36:25 -04:00
}
2017-09-29 22:42:24 -04:00
public IList < Server > GetServers ( )
2015-07-03 00:10:01 -04:00
{
2017-05-26 18:49:27 -04:00
return Servers ;
2015-07-03 00:10:01 -04:00
}
2017-09-29 22:42:24 -04:00
public IList < Command > GetCommands ( )
2015-08-17 16:38:42 -04:00
{
2017-05-26 18:49:27 -04:00
return Commands ;
2015-08-17 16:38:42 -04:00
}
2017-06-19 13:58:01 -04:00
public static ApplicationManager GetInstance ( )
2015-08-22 02:04:30 -04:00
{
2017-06-19 13:58:01 -04:00
return Instance ? ? ( Instance = new ApplicationManager ( ) ) ;
2015-08-22 02:04:30 -04:00
}
2018-07-01 20:30:38 -04:00
public async Task UpdateServerStates ( )
2018-04-26 02:13:04 -04:00
{
2018-07-01 20:30:38 -04:00
// store the server hash code and task for it
2018-11-27 19:31:48 -05:00
var runningUpdateTasks = new Dictionary < long , Task > ( ) ;
2018-04-26 20:19:42 -04:00
2018-04-28 01:22:18 -04:00
while ( Running )
2018-04-26 02:13:04 -04:00
{
2018-07-01 20:30:38 -04:00
// select the server ids that have completed the update task
var serverTasksToRemove = runningUpdateTasks
2018-08-27 18:07:54 -04:00
. Where ( ut = > ut . Value . Status = = TaskStatus . RanToCompletion | |
ut . Value . Status = = TaskStatus . Canceled | |
ut . Value . Status = = TaskStatus . Faulted )
2018-07-01 20:30:38 -04:00
. Select ( ut = > ut . Key )
. ToList ( ) ;
2018-07-04 22:09:42 -04:00
// this is to prevent the log reader from starting before the initial
2018-07-29 15:43:42 -04:00
// query of players on the server
2018-07-04 22:09:42 -04:00
if ( serverTasksToRemove . Count > 0 )
{
IsInitialized = true ;
}
2018-07-01 20:30:38 -04:00
// remove the update tasks as they have completd
2018-11-27 19:31:48 -05:00
foreach ( long serverId in serverTasksToRemove )
2018-04-28 01:22:18 -04:00
{
2018-07-01 20:30:38 -04:00
runningUpdateTasks . Remove ( serverId ) ;
}
// select the servers where the tasks have completed
2018-11-27 19:31:48 -05:00
var serverIds = Servers . Select ( s = > s . EndPoint ) . Except ( runningUpdateTasks . Select ( r = > r . Key ) ) . ToList ( ) ;
foreach ( var server in Servers . Where ( s = > serverIds . Contains ( s . EndPoint ) ) )
2018-07-01 20:30:38 -04:00
{
2018-11-27 19:31:48 -05:00
runningUpdateTasks . Add ( server . EndPoint , Task . Run ( async ( ) = >
2018-04-28 01:22:18 -04:00
{
try
{
await server . ProcessUpdatesAsync ( new CancellationToken ( ) ) ;
}
catch ( Exception e )
{
Logger . WriteWarning ( $"Failed to update status for {server}" ) ;
2018-09-23 20:45:54 -04:00
Logger . WriteDebug ( e . GetExceptionInfo ( ) ) ;
2018-04-28 01:22:18 -04:00
}
2018-06-30 21:55:16 -04:00
} ) ) ;
2018-04-28 01:22:18 -04:00
}
#if DEBUG
2018-07-01 20:30:38 -04:00
Logger . WriteDebug ( $"{runningUpdateTasks.Count} servers queued for stats updates" ) ;
2018-04-28 01:22:18 -04:00
ThreadPool . GetMaxThreads ( out int workerThreads , out int n ) ;
ThreadPool . GetAvailableThreads ( out int availableThreads , out int m ) ;
Logger . WriteDebug ( $"There are {workerThreads - availableThreads} active threading tasks" ) ;
#endif
2018-06-07 22:19:12 -04:00
await Task . Delay ( ConfigHandler . Configuration ( ) . RConPollRate ) ;
2018-04-28 01:22:18 -04:00
}
2018-09-23 20:45:54 -04:00
// trigger the event processing loop to end
SetHasEvent ( ) ;
2018-04-26 02:13:04 -04:00
}
2018-03-06 02:22:19 -05:00
public async Task Init ( )
2015-07-06 13:13:42 -04:00
{
2018-05-10 01:34:29 -04:00
Running = true ;
2019-02-04 20:38:24 -05:00
#region PLUGINS
SharedLibraryCore . Plugins . PluginImporter . Load ( this ) ;
foreach ( var Plugin in SharedLibraryCore . Plugins . PluginImporter . ActivePlugins )
{
try
{
await Plugin . OnLoadAsync ( this ) ;
}
catch ( Exception ex )
{
Logger . WriteError ( $"{Utilities.CurrentLocalization.LocalizationIndex[" SERVER_ERROR_PLUGIN "]} {Plugin.Name}" ) ;
Logger . WriteDebug ( ex . GetExceptionInfo ( ) ) ;
}
}
#endregion
2019-01-27 19:41:54 -05:00
#region CONFIG
2019-01-27 20:45:35 -05:00
var config = ConfigHandler . Configuration ( ) ;
2018-04-19 01:48:14 -04:00
// copy over default config if it doesn't exist
if ( config = = null )
2018-03-18 22:25:11 -04:00
{
2018-04-19 01:48:14 -04:00
var defaultConfig = new BaseConfigurationHandler < DefaultConfiguration > ( "DefaultSettings" ) . Configuration ( ) ;
ConfigHandler . Set ( ( ApplicationConfiguration ) new ApplicationConfiguration ( ) . Generate ( ) ) ;
var newConfig = ConfigHandler . Configuration ( ) ;
newConfig . AutoMessagePeriod = defaultConfig . AutoMessagePeriod ;
newConfig . AutoMessages = defaultConfig . AutoMessages ;
newConfig . GlobalRules = defaultConfig . GlobalRules ;
newConfig . Maps = defaultConfig . Maps ;
if ( newConfig . Servers = = null )
{
ConfigHandler . Set ( newConfig ) ;
2018-04-23 17:03:50 -04:00
newConfig . Servers = new List < ServerConfiguration > ( ) ;
do
{
2019-02-04 20:38:24 -05:00
var serverConfig = new ServerConfiguration ( ) ;
foreach ( var parser in AdditionalRConParsers )
{
serverConfig . AddRConParser ( parser ) ;
}
foreach ( var parser in AdditionalEventParsers )
{
serverConfig . AddEventParser ( parser ) ;
}
newConfig . Servers . Add ( ( ServerConfiguration ) serverConfig . Generate ( ) ) ;
2018-05-05 16:36:26 -04:00
} while ( Utilities . PromptBool ( Utilities . CurrentLocalization . LocalizationIndex [ "SETUP_SERVER_SAVE" ] ) ) ;
2018-04-23 17:03:50 -04:00
2018-04-19 01:48:14 -04:00
config = newConfig ;
await ConfigHandler . Save ( ) ;
}
2018-03-18 22:25:11 -04:00
}
2018-04-19 01:48:14 -04:00
else if ( config ! = null )
2018-04-18 16:46:53 -04:00
{
if ( string . IsNullOrEmpty ( config . Id ) )
{
config . Id = Guid . NewGuid ( ) . ToString ( ) ;
await ConfigHandler . Save ( ) ;
}
2018-04-19 01:48:14 -04:00
if ( string . IsNullOrEmpty ( config . WebfrontBindUrl ) )
{
2018-09-23 20:45:54 -04:00
config . WebfrontBindUrl = "http://0.0.0.0:1624" ;
2018-04-19 01:48:14 -04:00
await ConfigHandler . Save ( ) ;
}
2019-02-05 12:14:43 -05:00
foreach ( var serverConfig in config . Servers )
{
2019-02-09 16:35:13 -05:00
Migration . ConfigurationMigration . ModifyLogPath020919 ( serverConfig ) ;
2019-02-05 12:14:43 -05:00
if ( serverConfig . RConParserVersion = = null | | serverConfig . EventParserVersion = = null )
{
foreach ( var parser in AdditionalRConParsers )
{
serverConfig . AddRConParser ( parser ) ;
}
foreach ( var parser in AdditionalEventParsers )
{
serverConfig . AddEventParser ( parser ) ;
}
serverConfig . ModifyParsers ( ) ;
}
2019-02-09 16:35:13 -05:00
await ConfigHandler . Save ( ) ;
2019-02-05 12:14:43 -05:00
}
2018-04-18 16:46:53 -04:00
}
2018-03-18 22:25:11 -04:00
else if ( config . Servers . Count = = 0 )
2018-11-25 21:00:36 -05:00
{
2018-03-18 22:25:11 -04:00
throw new ServerException ( "A server configuration in IW4MAdminSettings.json is invalid" ) ;
2018-11-25 21:00:36 -05:00
}
2018-03-18 22:25:11 -04:00
2018-04-21 18:18:20 -04:00
Encoding . RegisterProvider ( CodePagesEncodingProvider . Instance ) ;
2018-04-22 16:04:18 -04:00
Utilities . EncodingType = Encoding . GetEncoding ( ! string . IsNullOrEmpty ( config . CustomParserEncoding ) ? config . CustomParserEncoding : "windows-1252" ) ;
2018-04-21 18:18:20 -04:00
2018-07-29 15:43:42 -04:00
#endregion
2019-01-27 19:41:54 -05:00
#region DATABASE
using ( var db = new DatabaseContext ( GetApplicationSettings ( ) . Configuration ( ) ? . ConnectionString ,
GetApplicationSettings ( ) . Configuration ( ) ? . DatabaseProvider ) )
{
await new ContextSeed ( db ) . Seed ( ) ;
}
PrivilegedClients = ( await ClientSvc . GetPrivilegedClients ( ) ) . ToDictionary ( _client = > _client . ClientId ) ;
#endregion
2018-07-29 15:43:42 -04:00
#region COMMANDS
2017-11-25 20:29:58 -05:00
if ( ClientSvc . GetOwners ( ) . Result . Count = = 0 )
2018-11-25 21:00:36 -05:00
{
2017-11-15 16:04:13 -05:00
Commands . Add ( new COwner ( ) ) ;
2018-11-25 21:00:36 -05:00
}
2017-11-15 16:04:13 -05:00
Commands . Add ( new CQuit ( ) ) ;
Commands . Add ( new CKick ( ) ) ;
Commands . Add ( new CSay ( ) ) ;
Commands . Add ( new CTempBan ( ) ) ;
Commands . Add ( new CBan ( ) ) ;
Commands . Add ( new CWhoAmI ( ) ) ;
Commands . Add ( new CList ( ) ) ;
Commands . Add ( new CHelp ( ) ) ;
Commands . Add ( new CFastRestart ( ) ) ;
Commands . Add ( new CMapRotate ( ) ) ;
Commands . Add ( new CSetLevel ( ) ) ;
Commands . Add ( new CUsage ( ) ) ;
Commands . Add ( new CUptime ( ) ) ;
Commands . Add ( new CWarn ( ) ) ;
Commands . Add ( new CWarnClear ( ) ) ;
Commands . Add ( new CUnban ( ) ) ;
Commands . Add ( new CListAdmins ( ) ) ;
Commands . Add ( new CLoadMap ( ) ) ;
Commands . Add ( new CFindPlayer ( ) ) ;
Commands . Add ( new CListRules ( ) ) ;
Commands . Add ( new CPrivateMessage ( ) ) ;
Commands . Add ( new CFlag ( ) ) ;
2018-05-08 00:58:46 -04:00
Commands . Add ( new CUnflag ( ) ) ;
2017-11-15 16:04:13 -05:00
Commands . Add ( new CReport ( ) ) ;
Commands . Add ( new CListReports ( ) ) ;
Commands . Add ( new CListBanInfo ( ) ) ;
Commands . Add ( new CListAlias ( ) ) ;
Commands . Add ( new CExecuteRCON ( ) ) ;
Commands . Add ( new CPlugins ( ) ) ;
Commands . Add ( new CIP ( ) ) ;
2017-11-18 01:59:37 -05:00
Commands . Add ( new CMask ( ) ) ;
2018-02-10 01:26:38 -05:00
Commands . Add ( new CPruneAdmins ( ) ) ;
2018-05-05 16:36:26 -04:00
Commands . Add ( new CKillServer ( ) ) ;
2018-04-04 15:38:34 -04:00
Commands . Add ( new CSetPassword ( ) ) ;
2018-04-14 00:51:38 -04:00
Commands . Add ( new CPing ( ) ) ;
2018-06-02 00:48:10 -04:00
Commands . Add ( new CSetGravatar ( ) ) ;
2018-06-02 22:21:01 -04:00
Commands . Add ( new CNextMap ( ) ) ;
2019-02-16 16:04:40 -05:00
Commands . Add ( new RequestTokenCommand ( ) ) ;
2017-06-19 13:58:01 -04:00
2018-04-08 02:44:42 -04:00
foreach ( Command C in SharedLibraryCore . Plugins . PluginImporter . ActiveCommands )
2018-11-25 21:00:36 -05:00
{
2017-06-19 13:58:01 -04:00
Commands . Add ( C ) ;
2018-11-25 21:00:36 -05:00
}
2018-07-29 15:43:42 -04:00
#endregion
2017-06-19 13:58:01 -04:00
2019-02-22 20:06:51 -05:00
#region META
async Task < List < ProfileMeta > > getLastMap ( int clientId )
{
var meta = await _metaService . GetPersistentMeta ( "LastMapPlayed" , new EFClient ( ) { ClientId = clientId } ) ;
return meta = = null ? new List < ProfileMeta > ( ) : new List < ProfileMeta > ( )
{
new ProfileMeta ( )
{
Id = meta . MetaId ,
Key = Utilities . CurrentLocalization . LocalizationIndex [ "WEBFRONT_CLIENT_META_LAST_MAP" ] ,
Value = meta . Value ,
Show = true
}
} ;
}
async Task < List < ProfileMeta > > getLastServer ( int clientId )
{
var meta = await _metaService . GetPersistentMeta ( "LastServerPlayed" , new EFClient ( ) { ClientId = clientId } ) ;
return meta = = null ? new List < ProfileMeta > ( ) : new List < ProfileMeta > ( )
{
new ProfileMeta ( )
{
Id = meta . MetaId ,
Key = Utilities . CurrentLocalization . LocalizationIndex [ "WEBFRONT_CLIENT_META_LAST_SERVER" ] ,
Value = meta . Value ,
Show = true
}
} ;
}
MetaService . AddRuntimeMeta ( getLastMap ) ;
MetaService . AddRuntimeMeta ( getLastServer ) ;
#endregion
2018-07-29 15:43:42 -04:00
#region INIT
2019-02-24 20:35:59 -05:00
int failedServers = 0 ;
int successServers = 0 ;
Exception lastException = null ;
2018-04-16 16:31:14 -04:00
async Task Init ( ServerConfiguration Conf )
{
2018-05-10 01:34:29 -04:00
// setup the event handler after the class is initialized
2019-02-24 20:35:59 -05:00
2018-05-10 01:34:29 -04:00
Handler = new GameEventHandler ( this ) ;
2019-02-24 20:35:59 -05:00
2018-04-16 16:31:14 -04:00
try
{
var ServerInstance = new IW4MServer ( this , Conf ) ;
await ServerInstance . Initialize ( ) ;
lock ( _servers )
{
_servers . Add ( ServerInstance ) ;
}
2018-05-05 16:36:26 -04:00
Logger . WriteVerbose ( $"{Utilities.CurrentLocalization.LocalizationIndex[" MANAGER_MONITORING_TEXT "]} {ServerInstance.Hostname}" ) ;
2018-04-26 02:13:04 -04:00
// add the start event for this server
2018-08-30 21:53:00 -04:00
var e = new GameEvent ( )
{
Type = GameEvent . EventType . Start ,
Data = $"{ServerInstance.GameName} started" ,
Owner = ServerInstance
} ;
Handler . AddEvent ( e ) ;
2019-02-24 20:35:59 -05:00
successServers + + ;
2018-04-16 16:31:14 -04:00
}
catch ( ServerException e )
{
2018-05-05 16:36:26 -04:00
Logger . WriteError ( $"{Utilities.CurrentLocalization.LocalizationIndex[" SERVER_ERROR_UNFIXABLE "]} [{Conf.IPAddress}:{Conf.Port}]" ) ;
2019-02-24 20:35:59 -05:00
2018-04-16 16:31:14 -04:00
if ( e . GetType ( ) = = typeof ( DvarException ) )
2018-11-25 21:00:36 -05:00
{
2018-05-05 16:36:26 -04:00
Logger . WriteDebug ( $"{Utilities.CurrentLocalization.LocalizationIndex[" SERVER_ERROR_DVAR "]} {(e as DvarException).Data[" dvar_name "]} ({Utilities.CurrentLocalization.LocalizationIndex[" SERVER_ERROR_DVAR_HELP "]})" ) ;
2018-11-25 21:00:36 -05:00
}
2019-02-24 20:35:59 -05:00
2018-04-16 16:31:14 -04:00
else if ( e . GetType ( ) = = typeof ( NetworkException ) )
{
Logger . WriteDebug ( e . Message ) ;
}
2019-02-24 20:35:59 -05:00
failedServers + + ;
lastException = e ;
2018-04-16 16:31:14 -04:00
}
}
await Task . WhenAll ( config . Servers . Select ( c = > Init ( c ) ) . ToArray ( ) ) ;
2019-02-24 20:35:59 -05:00
if ( failedServers > 0 & & successServers > 0 )
{
if ( ! Utilities . PromptBool ( Utilities . CurrentLocalization . LocalizationIndex [ "MANAGER_START_WITH_ERRORS" ] ) )
{
throw lastException ;
}
}
2018-07-29 15:43:42 -04:00
#endregion
2015-07-03 00:10:01 -04:00
}
2017-08-09 00:35:23 -04:00
2018-05-17 19:31:58 -04:00
private async Task SendHeartbeat ( object state )
2018-04-18 16:46:53 -04:00
{
2018-04-28 01:22:18 -04:00
var heartbeatState = ( HeartbeatState ) state ;
2018-05-16 00:57:37 -04:00
while ( Running )
2018-04-18 16:46:53 -04:00
{
2018-05-16 00:57:37 -04:00
if ( ! heartbeatState . Connected )
2018-04-18 16:46:53 -04:00
{
2018-05-16 00:57:37 -04:00
try
{
2018-05-17 19:31:58 -04:00
await Heartbeat . Send ( this , true ) ;
2018-05-16 00:57:37 -04:00
heartbeatState . Connected = true ;
}
2018-04-18 16:46:53 -04:00
2018-05-16 00:57:37 -04:00
catch ( Exception e )
{
heartbeatState . Connected = false ;
Logger . WriteWarning ( $"Could not connect to heartbeat server - {e.Message}" ) ;
}
2018-04-18 16:46:53 -04:00
}
2018-05-16 00:57:37 -04:00
else
2018-04-18 16:46:53 -04:00
{
2018-05-16 00:57:37 -04:00
try
{
2018-05-17 19:31:58 -04:00
await Heartbeat . Send ( this ) ;
2018-05-16 00:57:37 -04:00
}
2018-04-18 16:46:53 -04:00
2018-05-16 00:57:37 -04:00
catch ( System . Net . Http . HttpRequestException e )
{
Logger . WriteWarning ( $"Could not send heartbeat - {e.Message}" ) ;
}
2018-04-18 16:46:53 -04:00
2018-05-16 00:57:37 -04:00
catch ( AggregateException e )
2018-04-18 16:46:53 -04:00
{
2018-05-16 00:57:37 -04:00
Logger . WriteWarning ( $"Could not send heartbeat - {e.Message}" ) ;
var exceptions = e . InnerExceptions . Where ( ex = > ex . GetType ( ) = = typeof ( RestEase . ApiException ) ) ;
foreach ( var ex in exceptions )
2018-04-18 16:46:53 -04:00
{
2018-05-16 00:57:37 -04:00
if ( ( ( RestEase . ApiException ) ex ) . StatusCode = = System . Net . HttpStatusCode . Unauthorized )
{
heartbeatState . Connected = false ;
}
2018-04-18 16:46:53 -04:00
}
}
2018-05-16 00:57:37 -04:00
catch ( RestEase . ApiException e )
2018-04-18 16:46:53 -04:00
{
2018-05-16 00:57:37 -04:00
Logger . WriteWarning ( $"Could not send heartbeat - {e.Message}" ) ;
if ( e . StatusCode = = System . Net . HttpStatusCode . Unauthorized )
{
heartbeatState . Connected = false ;
}
}
catch ( Exception e )
{
Logger . WriteWarning ( $"Could not send heartbeat - {e.Message}" ) ;
2018-04-18 16:46:53 -04:00
}
2018-05-16 00:57:37 -04:00
}
2018-05-17 19:31:58 -04:00
await Task . Delay ( 30000 ) ;
2018-04-18 16:46:53 -04:00
}
}
2018-08-27 18:07:54 -04:00
public void Start ( )
2015-07-03 00:10:01 -04:00
{
2018-05-16 00:57:37 -04:00
// this needs to be run seperately from the main thread
2018-09-23 20:45:54 -04:00
var _ = Task . Run ( ( ) = > SendHeartbeat ( new HeartbeatState ( ) ) ) ;
_ = Task . Run ( ( ) = > UpdateServerStates ( ) ) ;
2018-05-08 00:58:46 -04:00
2018-04-28 17:39:45 -04:00
while ( Running )
2015-07-03 00:10:01 -04:00
{
2018-08-28 17:32:59 -04:00
OnQuit . Wait ( ) ;
OnQuit . Reset ( ) ;
2018-04-28 17:39:45 -04:00
}
_servers . Clear ( ) ;
2015-07-03 00:10:01 -04:00
}
2015-07-06 15:51:08 -04:00
2017-05-26 18:49:27 -04:00
public void Stop ( )
2015-07-06 15:51:08 -04:00
{
2017-05-26 18:49:27 -04:00
Running = false ;
2015-07-06 15:51:08 -04:00
}
2017-05-27 18:08:04 -04:00
2018-11-27 19:31:48 -05:00
public ILogger GetLogger ( long serverId )
2017-05-27 19:29:20 -04:00
{
2018-10-06 12:47:14 -04:00
if ( Loggers . ContainsKey ( serverId ) )
{
return Loggers [ serverId ] ;
}
else
{
Logger newLogger ;
if ( serverId = = 0 )
{
newLogger = new Logger ( "IW4MAdmin-Manager" ) ;
}
else
{
newLogger = new Logger ( $"IW4MAdmin-Server-{serverId}" ) ;
}
Loggers . Add ( serverId , newLogger ) ;
return newLogger ;
}
2017-05-27 19:29:20 -04:00
}
2017-05-31 01:31:56 -04:00
2017-06-19 13:58:01 -04:00
public IList < MessageToken > GetMessageTokens ( )
2017-05-31 01:31:56 -04:00
{
return MessageTokens ;
}
2017-06-12 13:50:00 -04:00
2018-11-25 21:00:36 -05:00
public IList < EFClient > GetActiveClients ( )
{
return _servers . SelectMany ( s = > s . Clients ) . Where ( p = > p ! = null ) . ToList ( ) ;
}
2017-08-17 19:28:08 -04:00
2018-11-25 21:00:36 -05:00
public ClientService GetClientService ( )
{
return ClientSvc ;
}
public AliasService GetAliasService ( )
{
return AliasSvc ;
}
public PenaltyService GetPenaltyService ( )
{
return PenaltySvc ;
}
public IConfigurationHandler < ApplicationConfiguration > GetApplicationSettings ( )
{
return ConfigHandler ;
}
public IDictionary < int , EFClient > GetPrivilegedClients ( )
{
return PrivilegedClients ;
}
public bool ShutdownRequested ( )
{
return ! Running ;
}
public IEventHandler GetEventHandler ( )
{
return Handler ;
}
2018-04-26 02:13:04 -04:00
public void SetHasEvent ( )
{
2018-08-28 17:32:59 -04:00
OnQuit . Set ( ) ;
2018-04-26 02:13:04 -04:00
}
2018-05-28 21:30:31 -04:00
2018-11-25 21:00:36 -05:00
public IList < Assembly > GetPluginAssemblies ( )
{
2019-02-16 18:18:50 -05:00
return SharedLibraryCore . Plugins . PluginImporter . PluginAssemblies . Union ( SharedLibraryCore . Plugins . PluginImporter . Assemblies ) . ToList ( ) ;
2018-11-25 21:00:36 -05:00
}
2018-08-03 18:10:20 -04:00
2018-11-25 21:00:36 -05:00
public IPageList GetPageList ( )
{
return PageList ;
}
2019-01-26 21:33:37 -05:00
2019-01-27 19:41:54 -05:00
public IRConParser GenerateDynamicRConParser ( )
{
return new DynamicRConParser ( ) ;
}
2019-01-26 21:33:37 -05:00
2019-01-27 19:41:54 -05:00
public IEventParser GenerateDynamicEventParser ( )
{
return new DynamicEventParser ( ) ;
}
2015-07-03 00:10:01 -04:00
}
}