public void LogFileReplay() { var mgr = A.Fake <IManager>(); A.CallTo(() => mgr.GetLogger(A <long> .Ignored)).Returns(logger); var server = new IW4MServer(mgr, new SharedLibraryCore.Configuration.ServerConfiguration() { IPAddress = "127.0.0.1", Port = 28960 }, A.Fake <ITranslationLookup>(), A.Fake <IRConConnectionFactory>(), A.Fake <IGameLogReaderFactory>(), A.Fake <IMetaService>()); var parser = new BaseEventParser(A.Fake <IParserRegexFactory>(), A.Fake <ILogger>(), A.Fake <ApplicationConfiguration>()); parser.Configuration.GuidNumberStyle = System.Globalization.NumberStyles.Integer; var log = System.IO.File.ReadAllLines("Files\\T6Game.log"); long lastEventId = 0; foreach (string line in log) { var e = parser.GenerateGameEvent(line); server.Logger.WriteInfo($"{e.GameTime}"); if (e.Origin != null) { e.Origin.CurrentServer = server; } server.ExecuteEvent(e).Wait(); lastEventId = e.Id; } Assert.GreaterOrEqual(lastEventId, log.Length); }
public GameLogEventDetection(ILogger <GameLogEventDetection> logger, IW4MServer server, Uri[] gameLogUris, IGameLogReaderFactory gameLogReaderFactory) { _reader = gameLogReaderFactory.CreateGameLogReader(gameLogUris, server.EventParser); _server = server; _ignoreBots = server?.Manager.GetApplicationSettings().Configuration().IgnoreBots ?? false; _logger = logger; }
public void GameTimeFalseQuitTest() { var mgr = A.Fake <IManager>(); var server = new IW4MServer(mgr, new SharedLibraryCore.Configuration.ServerConfiguration() { IPAddress = "127.0.0.1", Port = 28960 }, A.Fake <ITranslationLookup>(), A.Fake <IRConConnectionFactory>(), A.Fake <IGameLogReaderFactory>(), A.Fake <IMetaService>()); var parser = new BaseEventParser(A.Fake <IParserRegexFactory>(), A.Fake <ILogger>(), A.Fake <ApplicationConfiguration>()); parser.Configuration.GuidNumberStyle = System.Globalization.NumberStyles.Integer; var log = System.IO.File.ReadAllLines("Files\\T6MapRotation.log"); foreach (string line in log) { var e = parser.GenerateGameEvent(line); if (e.Origin != null) { e.Origin.CurrentServer = server; } server.ExecuteEvent(e).Wait(); } }
public void Test_GenerateLogPath_Basic() { string expected = "C:\\Game\\main\\log.log"; var info = new LogPathGeneratorInfo() { BasePathDirectory = "C:\\Game", GameDirectory = "main", LogFile = "log.log" }; string generated = IW4MServer.GenerateLogPath(info); Assert.AreEqual(expected, generated); }
public void Test_GenerateLogPath_FixWineDriveMangling() { string expected = "/opt/server/game/log.log"; var info = new LogPathGeneratorInfo() { BasePathDirectory = "Z:\\opt\\server", GameDirectory = "game", LogFile = "log.log", IsWindows = false }; string generated = IW4MServer.GenerateLogPath(info).Replace('\\', '/'); Assert.AreEqual(expected, generated); }
public void Test_GenerateLogPath_WithBaseGameAndMod() { string expected = "C:\\GameAlt\\mods\\mod\\log.log"; var info = new LogPathGeneratorInfo() { BaseGameDirectory = "C:\\GameAlt", BasePathDirectory = "C:\\Game", GameDirectory = "main", ModDirectory = "mods\\mod", LogFile = "log.log" }; string generated = IW4MServer.GenerateLogPath(info); Assert.AreEqual(expected, generated); }
public void Setup() { serviceProvider = new ServiceCollection() .BuildBase() .AddSingleton <ActionController>() .AddSingleton <IManagerCommand, BanCommand>() .AddSingleton <IManagerCommand, TempBanCommand>() .AddSingleton <IManagerCommand, UnbanCommand>() .AddSingleton <IManagerCommand, KickCommand>() .AddSingleton <IManagerCommand, FlagClientCommand>() .AddSingleton <IManagerCommand, UnflagClientCommand>() .AddSingleton <IManagerCommand, SayCommand>() .AddSingleton <IManagerCommand, SetLevelCommand>() .BuildServiceProvider() .SetupTestHooks(); contextFactory = serviceProvider.GetRequiredService <IDatabaseContextFactory>(); server = serviceProvider.GetRequiredService <IW4MServer>(); manager = serviceProvider.GetRequiredService <IManager>(); A.CallTo(() => manager.GetServers()) .Returns(new[] { server }); A.CallTo(() => manager.GetActiveClients()) .Returns(new[] { ClientGenerators.CreateBasicClient(server) }); }
public async Task Init() { #region DATABASE var ipList = (await ClientSvc.Find(c => c.Level > Player.Permission.Trusted)) .Select(c => new { c.Password, c.PasswordSalt, c.ClientId, c.Level, c.Name }); foreach (var a in ipList) { try { PrivilegedClients.Add(a.ClientId, new Player() { Name = a.Name, ClientId = a.ClientId, Level = a.Level, PasswordSalt = a.PasswordSalt, Password = a.Password }); } catch (ArgumentException) { continue; } } #endregion #region CONFIG var config = ConfigHandler.Configuration(); // copy over default config if it doesn't exist if (config == null) { 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); newConfig.Servers = new List <ServerConfiguration>(); do { newConfig.Servers.Add((ServerConfiguration) new ServerConfiguration().Generate()); } while (Utilities.PromptBool(Utilities.CurrentLocalization.LocalizationSet["SETUP_SERVER_SAVE"])); config = newConfig; await ConfigHandler.Save(); } } else if (config != null) { if (string.IsNullOrEmpty(config.Id)) { config.Id = Guid.NewGuid().ToString(); await ConfigHandler.Save(); } if (string.IsNullOrEmpty(config.WebfrontBindUrl)) { config.WebfrontBindUrl = "http://127.0.0.1:1624"; await ConfigHandler.Save(); } } else if (config.Servers.Count == 0) { throw new ServerException("A server configuration in IW4MAdminSettings.json is invalid"); } Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); Utilities.EncodingType = Encoding.GetEncoding(!string.IsNullOrEmpty(config.CustomParserEncoding) ? config.CustomParserEncoding : "windows-1252"); #endregion #region PLUGINS SharedLibraryCore.Plugins.PluginImporter.Load(this); foreach (var Plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins) { try { await Plugin.OnLoadAsync(this); } catch (Exception e) { Logger.WriteError($"An error occured loading plugin {Plugin.Name}"); Logger.WriteDebug($"Exception: {e.Message}"); Logger.WriteDebug($"Stack Trace: {e.StackTrace}"); } } #endregion #region COMMANDS if (ClientSvc.GetOwners().Result.Count == 0) { Commands.Add(new COwner()); } 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()); 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()); Commands.Add(new CMask()); Commands.Add(new CPruneAdmins()); Commands.Add(new CKillServer()); Commands.Add(new CSetPassword()); Commands.Add(new CPing()); foreach (Command C in SharedLibraryCore.Plugins.PluginImporter.ActiveCommands) { Commands.Add(C); } #endregion #region INIT async Task Init(ServerConfiguration Conf) { try { var ServerInstance = new IW4MServer(this, Conf); await ServerInstance.Initialize(); lock (_servers) { _servers.Add(ServerInstance); } Logger.WriteVerbose($"Now monitoring {ServerInstance.Hostname}"); // this way we can keep track of execution time and see if problems arise. var Status = new AsyncStatus(ServerInstance, UPDATE_FREQUENCY); lock (TaskStatuses) { TaskStatuses.Add(Status); } } catch (ServerException e) { Logger.WriteError($"Not monitoring server {Conf.IPAddress}:{Conf.Port} due to uncorrectable errors"); if (e.GetType() == typeof(DvarException)) { Logger.WriteDebug($"Could not get the dvar value for {(e as DvarException).Data["dvar_name"]} (ensure the server has a map loaded)"); } else if (e.GetType() == typeof(NetworkException)) { Logger.WriteDebug(e.Message); } // throw the exception to the main method to stop before instantly exiting throw e; } } await Task.WhenAll(config.Servers.Select(c => Init(c)).ToArray()); #endregion Running = true; }
public async Task Init() { Running = true; ExternalIPAddress = await Utilities.GetExternalIP(); #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 #region CONFIG var config = ConfigHandler.Configuration(); // copy over default config if it doesn't exist if (config == null) { var defaultConfig = new BaseConfigurationHandler <DefaultConfiguration>("DefaultSettings").Configuration(); ConfigHandler.Set((ApplicationConfiguration) new ApplicationConfiguration().Generate()); var newConfig = ConfigHandler.Configuration(); newConfig.AutoMessages = defaultConfig.AutoMessages; newConfig.GlobalRules = defaultConfig.GlobalRules; newConfig.Maps = defaultConfig.Maps; newConfig.DisallowedClientNames = defaultConfig.DisallowedClientNames; newConfig.QuickMessages = defaultConfig.QuickMessages; if (newConfig.Servers == null) { ConfigHandler.Set(newConfig); newConfig.Servers = new List <ServerConfiguration>(); do { 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()); } while (Utilities.PromptBool(Utilities.CurrentLocalization.LocalizationIndex["SETUP_SERVER_SAVE"])); config = newConfig; await ConfigHandler.Save(); } } else { if (string.IsNullOrEmpty(config.Id)) { config.Id = Guid.NewGuid().ToString(); await ConfigHandler.Save(); } if (string.IsNullOrEmpty(config.WebfrontBindUrl)) { config.WebfrontBindUrl = "http://0.0.0.0:1624"; await ConfigHandler.Save(); } foreach (var serverConfig in config.Servers) { Migration.ConfigurationMigration.ModifyLogPath020919(serverConfig); 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(); } await ConfigHandler.Save(); } } if (config.Servers.Count == 0) { throw new ServerException("A server configuration in IW4MAdminSettings.json is invalid"); } Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); Utilities.EncodingType = Encoding.GetEncoding(!string.IsNullOrEmpty(config.CustomParserEncoding) ? config.CustomParserEncoding : "windows-1252"); #endregion #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 #region COMMANDS if (ClientSvc.GetOwners().Result.Count == 0) { Commands.Add(new COwner()); } 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()); Commands.Add(new CUnflag()); 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()); Commands.Add(new CMask()); Commands.Add(new CPruneAdmins()); Commands.Add(new CKillServer()); Commands.Add(new CSetPassword()); Commands.Add(new CPing()); Commands.Add(new CSetGravatar()); Commands.Add(new CNextMap()); Commands.Add(new RequestTokenCommand()); foreach (Command C in SharedLibraryCore.Plugins.PluginImporter.ActiveCommands) { Commands.Add(C); } #endregion #region META async Task <List <ProfileMeta> > getProfileMeta(int clientId, int offset, int count, DateTime?startAt) { var metaList = new List <ProfileMeta>(); // we don't want to return anything because it means we're trying to retrieve paged meta data if (count > 1) { return(metaList); } var lastMapMeta = await _metaService.GetPersistentMeta("LastMapPlayed", new EFClient() { ClientId = clientId }); if (lastMapMeta != null) { metaList.Add(new ProfileMeta() { Id = lastMapMeta.MetaId, Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_LAST_MAP"], Value = lastMapMeta.Value, Show = true, Type = ProfileMeta.MetaType.Information, }); } var lastServerMeta = await _metaService.GetPersistentMeta("LastServerPlayed", new EFClient() { ClientId = clientId }); if (lastServerMeta != null) { metaList.Add(new ProfileMeta() { Id = lastServerMeta.MetaId, Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_LAST_SERVER"], Value = lastServerMeta.Value, Show = true, Type = ProfileMeta.MetaType.Information }); } var client = await GetClientService().Get(clientId); metaList.Add(new ProfileMeta() { Id = client.ClientId, Key = $"{Utilities.CurrentLocalization.LocalizationIndex["GLOBAL_TIME_HOURS"]} {Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_PLAYER"]}", Value = Math.Round(client.TotalConnectionTime / 3600.0, 1).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Show = true, Column = 1, Order = 0, Type = ProfileMeta.MetaType.Information }); metaList.Add(new ProfileMeta() { Id = client.ClientId, Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_FSEEN"], Value = Utilities.GetTimePassed(client.FirstConnection, false), Show = true, Column = 1, Order = 1, Type = ProfileMeta.MetaType.Information }); metaList.Add(new ProfileMeta() { Id = client.ClientId, Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_LSEEN"], Value = Utilities.GetTimePassed(client.LastConnection, false), Show = true, Column = 1, Order = 2, Type = ProfileMeta.MetaType.Information }); metaList.Add(new ProfileMeta() { Id = client.ClientId, Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_CONNECTIONS"], Value = client.Connections.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Show = true, Column = 1, Order = 3, Type = ProfileMeta.MetaType.Information }); metaList.Add(new ProfileMeta() { Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_MASKED"], Value = client.Masked ? Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_TRUE"] : Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_FALSE"], Sensitive = true, Column = 1, Order = 4, Type = ProfileMeta.MetaType.Information }); return(metaList); } async Task <List <ProfileMeta> > getPenaltyMeta(int clientId, int offset, int count, DateTime?startAt) { if (count <= 1) { return(new List <ProfileMeta>()); } var penalties = await GetPenaltyService().GetClientPenaltyForMetaAsync(clientId, count, offset, startAt); return(penalties.Select(_penalty => new ProfileMeta() { Id = _penalty.Id, Type = _penalty.PunisherId == clientId ? ProfileMeta.MetaType.Penalized : ProfileMeta.MetaType.ReceivedPenalty, Value = _penalty, When = _penalty.TimePunished, Sensitive = _penalty.Sensitive }) .ToList()); } MetaService.AddRuntimeMeta(getProfileMeta); MetaService.AddRuntimeMeta(getPenaltyMeta); #endregion #region INIT int failedServers = 0; int successServers = 0; Exception lastException = null; async Task Init(ServerConfiguration Conf) { // setup the event handler after the class is initialized Handler = new GameEventHandler(this); try { var ServerInstance = new IW4MServer(this, Conf); await ServerInstance.Initialize(); lock (_servers) { _servers.Add(ServerInstance); } Logger.WriteVerbose(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_MONITORING_TEXT"].FormatExt(ServerInstance.Hostname)); // add the start event for this server var e = new GameEvent() { Type = GameEvent.EventType.Start, Data = $"{ServerInstance.GameName} started", Owner = ServerInstance }; Handler.AddEvent(e); successServers++; } catch (ServerException e) { Logger.WriteError(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_UNFIXABLE"].FormatExt($"[{Conf.IPAddress}:{Conf.Port}]")); if (e.GetType() == typeof(DvarException)) { Logger.WriteDebug($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_DVAR"].FormatExt((e as DvarException).Data["dvar_name"])} ({Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_DVAR_HELP"]})"); } else if (e.GetType() == typeof(NetworkException)) { Logger.WriteDebug(e.Message); } failedServers++; lastException = e; } } await Task.WhenAll(config.Servers.Select(c => Init(c)).ToArray()); if (successServers - failedServers <= 0) { if (!Utilities.PromptBool(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_START_WITH_ERRORS"])) { throw lastException; } } #endregion }
public void TestKDR() { var mgr = A.Fake <IManager>(); var config = A.Fake <IConfigurationHandler <StatsConfiguration> >(); var plugin = serviceProvider.GetRequiredService <IW4MAdmin.Plugins.Stats.Plugin>(); A.CallTo(() => config.Configuration()) .Returns(new StatsConfiguration() { EnableAntiCheat = true }); A.CallTo(() => handlerFactory.GetConfigurationHandler <StatsConfiguration>(A <string> .Ignored)) .Returns(config); A.CallTo(() => mgr.GetLogger(A <long> .Ignored)) .Returns(logger); var server = new IW4MServer(mgr, new SharedLibraryCore.Configuration.ServerConfiguration() { IPAddress = "127.0.0.1", Port = 28960 }, A.Fake <ITranslationLookup>(), A.Fake <IRConConnectionFactory>(), A.Fake <IGameLogReaderFactory>(), A.Fake <IMetaService>()); var parser = new BaseEventParser(A.Fake <IParserRegexFactory>(), A.Fake <ILogger>(), A.Fake <ApplicationConfiguration>()); parser.Configuration.GuidNumberStyle = System.Globalization.NumberStyles.Integer; var log = System.IO.File.ReadAllLines("Files\\T6GameStats.log"); plugin.OnLoadAsync(mgr).Wait(); plugin.OnEventAsync(new SharedLibraryCore.GameEvent() { Type = SharedLibraryCore.GameEvent.EventType.Start, Owner = server }, server).Wait(); var clientList = new Dictionary <long, EFClient>(); foreach (string line in log) { var e = parser.GenerateGameEvent(line); if (e.Origin != null) { //if (!clientList.ContainsKey(e.Origin.NetworkId)) //{ // clientList.Add(e.Origin.NetworkId, e.Origin); //} //else //{ // e.Origin = clientList[e.Origin.NetworkId]; //} e.Origin = server.GetClientsAsList().FirstOrDefault(_client => _client.NetworkId == e.Origin.NetworkId) ?? e.Origin; e.Origin.CurrentServer = server; } if (e.Target != null) { //if (!clientList.ContainsKey(e.Target.NetworkId)) //{ // clientList.Add(e.Target.NetworkId, e.Target); //} //else //{ // e.Target = clientList[e.Target.NetworkId]; //} e.Target = server.GetClientsAsList().FirstOrDefault(_client => _client.NetworkId == e.Target.NetworkId) ?? e.Target; e.Target.CurrentServer = server; } server.ExecuteEvent(e).Wait(); plugin.OnEventAsync(e, server).Wait(); } var client = server.GetClientsAsList().First(_client => _client?.NetworkId == 2028755667); var stats = client.GetAdditionalProperty <EFClientStatistics>("ClientStats"); }