/// <summary> /// Runs the restart logic /// </summary> public static void Restart() { //Perform Backups BackupSystem.PerformBackups(CancellationTokenSrc.Token); LunaLog.Normal("Restarting... Please wait until all threads are finished"); ServerContext.Shutdown("Server is restarting"); CancellationTokenSrc.Cancel(); Task.WaitAll(TaskContainer.ToArray()); QuitEvent.Set(); //Start new server var serverExePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\Server.exe"; var newProcLmpServer = new ProcessStartInfo { FileName = serverExePath }; Process.Start(newProcLmpServer); }
/// <summary> /// We receive the console inputs with a pipe /// </summary> public static async void ThreadMain() { try { while (ServerContext.ServerRunning) { var input = Console.ReadLine(); if (input == null) { LunaLog.Normal("End of stdin, stopping command listener"); break; } if (!string.IsNullOrEmpty(input)) { LunaLog.Normal($"Command input: {input}"); if (!string.IsNullOrEmpty(input)) { if (input.StartsWith("/")) { HandleServerInput(input.Substring(1)); } else { Commands["say"].Func(input); } } } //We only accept a command once every 500ms await Task.Delay(500); } } catch (Exception e) { if (ServerContext.ServerRunning && !(e is ThreadAbortException)) { LunaLog.Fatal($"Error in command handler thread, Exception: {e}"); throw; } } }
//Changes selected server option private static void ChangeServerSettings(string settingName, string newValue, StreamReader streamReader, XmlDocument document, string settingsPath) { //Set message var msgSettingNameInfo = Environment.NewLine + "Setting name error:" + Environment.NewLine + "'" + settingName + "'" + Environment.NewLine + "is not a valid setting name." + Environment.NewLine + "Setting name is case sensitive."; //Load document document.Load(streamReader); //Try to find the xml node and save the new value to setting file try { //Get node var nodeSetting = document.SelectSingleNode("//" + settingName); //Return if null if (nodeSetting == null) { LunaLog.Error(msgSettingNameInfo); return; } //Change node inner text if (newValue == "-") { nodeSetting.InnerText = ""; } else { nodeSetting.InnerText = newValue; } //Save document SaveDocument(streamReader, document, settingsPath); //Send info message that setting has changed LunaLog.Normal(Environment.NewLine + "Setting changes saved." + Environment.NewLine + "You may need to restart the server for the changes to take effect."); } catch (Exception) { LunaLog.Error(msgSettingNameInfo); return; } }
public void HandleHandshakeResponse(ClientStructure client, HandshakeResponseMsgData data) { var valid = CheckServerFull(client); valid &= valid && CheckUsernameLength(client, data.PlayerName); valid &= valid && CheckUsernameCharacters(client, data.PlayerName); valid &= valid && CheckWhitelist(client, data.PlayerName); valid &= valid && CheckPlayerIsAlreadyConnected(client, data.PlayerName); valid &= valid && CheckUsernameIsReserved(client, data.PlayerName); valid &= valid && CheckPlayerIsBanned(client, data.PlayerName, client.Endpoint.Address.ToString(), data.PublicKey); valid &= valid && CheckKey(client, data.PlayerName, data.PublicKey, data.ChallengeSignature); if (!valid) { LunaLog.Normal($"Client {data.PlayerName} failed to handshake: {Reason}. Disconnecting"); client.DisconnectClient = true; ClientConnectionHandler.DisconnectClient(client, Reason); } else { client.PlayerName = data.PlayerName; client.PublicKey = data.PublicKey; client.Id = Guid.NewGuid(); client.Authenticated = true; LmpPluginHandler.FireOnClientAuthenticated(client); LunaLog.Normal($"Client {data.PlayerName} handshook successfully, Version: {data.MajorVersion}.{data.MinorVersion}.{data.BuildVersion}"); CreatePlayerScenarioFiles(client, data.PlayerName); HandshakeSystemSender.SendHandshakeReply(client, HandshakeReply.HandshookSuccessfully, "success"); var msgData = ServerContext.ServerMessageFactory.CreateNewMessageData <PlayerConnectionJoinMsgData>(); msgData.PlayerName = client.PlayerName; MessageQueuer.RelayMessage <PlayerConnectionSrvMsg>(client, msgData); LunaLog.Debug($"Online Players: {ServerContext.PlayerCount}, connected: {ClientRetriever.GetClients().Length}"); } }
private static void SendNetworkMessage(ClientStructure client, IServerMessageBase message) { if (client.ConnectionStatus == ConnectionStatus.CONNECTED) { try { ServerContext.LidgrenServer.SendMessageToClient(client, message); } catch (Exception e) { ClientException.HandleDisconnectException("Send network message error: ", client, e); return; } } else { LunaLog.Normal($"Tried to send a message to client {client.PlayerName}, with connection status: {client.ConnectionStatus}"); } LmpPluginHandler.FireOnMessageSent(client, message); }
private static void CheckMasterServerListed() { var ownAddress = LunaNetUtils.GetOwnExternalIpAddress(); if (ownAddress != null) { var ownEndpoint = new IPEndPoint(ownAddress, Port); if (!MasterServerRetriever.MasterServers.Contains(ownEndpoint)) { LunaLog.Error($"You're not listed in the master servers list ({RepoConstants.MasterServersListShortUrl}). Clients/Servers won't see you"); } else { LunaLog.Normal("You're correctly listed in the master servers list"); } } else { LunaLog.Error("Could not retrieve own external IP address, master server likely won't function properly"); } }
private static void RemoveExpiredServers() { Task.Run(async() => { while (RunServer) { var serversIdsToRemove = ServerDictionary .Where(s => LunaNetworkTime.UtcNow.Ticks - s.Value.LastRegisterTime > TimeSpan.FromMilliseconds(ServerMsTimeout).Ticks || BannedIpsRetriever.IsBanned(s.Value.ExternalEndpoint)) .ToArray(); foreach (var serverId in serversIdsToRemove) { LunaLog.Normal($"REMOVING SERVER: {serverId.Value.ExternalEndpoint}"); ServerDictionary.TryRemove(serverId.Key, out _); } await Task.Delay(ServerRemoveMsCheckInterval); } }); }
public override void HandleMessage(ClientStructure client, IClientMessageBase message) { var data = (FacilityBaseMsgData)message.Data; switch (data.FacilityMessageType) { case FacilityMessageType.Upgrade: var upgradeMsg = (FacilityUpgradeMsgData)message.Data; LunaLog.Normal($"{client.PlayerName} UPGRADED facility {upgradeMsg.ObjectId} to level: {upgradeMsg.Level}"); break; case FacilityMessageType.Repair: LunaLog.Normal($"{client.PlayerName} REPAIRED facility {data.ObjectId}"); break; case FacilityMessageType.Collapse: LunaLog.Normal($"{client.PlayerName} DESTROYED facility {data.ObjectId}"); break; default: throw new ArgumentOutOfRangeException(); } //We don't do anything on the server side with this messages so just relay them. MessageQueuer.RelayMessage<FacilitySrvMsg>(client, message.Data); }
public override void Execute(string commandArgs) { CommandSystemHelperMethods.SplitCommand(commandArgs, out var ip, out var reason); reason = string.IsNullOrEmpty(reason) ? "No reason specified" : reason; if (IPAddress.TryParse(ip, out var ipAddress)) { var player = ClientRetriever.GetClientByIp(ipAddress); if (player != null) { MessageQueuer.SendConnectionEnd(player, $"You were banned from the server: {reason}"); } Add(ipAddress.ToString()); LunaLog.Normal($"IP Address '{ip}' was banned from the server: {reason}"); } else { LunaLog.Normal($"{ip} is not a valid IP address"); } }
public override void Execute(string commandArgs) { CommandSystemHelperMethods.SplitCommand(commandArgs, out var playerName, out var reason); reason = string.IsNullOrEmpty(reason) ? "No reason specified" : reason; if (!string.IsNullOrEmpty(playerName)) { var player = ClientRetriever.GetClientByName(playerName); if (player != null) { MessageQueuer.SendConnectionEnd(player, $"You were banned from the server: {reason}"); } Add(playerName); LunaLog.Normal($"Player '{playerName}' was banned from the server: {reason}"); } else { LunaLog.Normal($"Player: {playerName} not found"); } }
public override void HandleMessage(ClientStructure client, IClientMessageBase message) { var data = (FacilityBaseMsgData)message.Data; switch (data.FacilityMessageType) { case FacilityMessageType.Repair: LunaLog.Normal($"{client.PlayerName} REPAIRED facility {data.ObjectId}"); ScenarioDataUpdater.WriteRepairedDestroyedDataToFile(data.ObjectId, true); break; case FacilityMessageType.Collapse: LunaLog.Normal($"{client.PlayerName} DESTROYED facility {data.ObjectId}"); ScenarioDataUpdater.WriteRepairedDestroyedDataToFile(data.ObjectId, false); break; default: throw new ArgumentOutOfRangeException(); } //We don't do anything on the server side with this messages so just relay them. MessageQueuer.RelayMessage <FacilitySrvMsg>(client, message.Data); }
private static void LoadSettingsAndGroups() { LunaLog.Normal("Loading groups..."); GroupSystem.LoadGroups(); LunaLog.Normal("Loading settings..."); SettingsHandler.LoadSettings(); ServerContext.ConfigsLoaded = true; SettingsHandler.ValidateDifficultySettings(); if (GeneralSettings.SettingsStore.ModControl) { LunaLog.Normal("Loading mod control..."); ModFileSystem.LoadModFile(); } if (Common.PlatformIsWindows()) { Console.Title += $" ({GeneralSettings.SettingsStore.ServerName})"; #if DEBUG Console.Title += " DEBUG"; #endif } }
public override void HandleCommand(string commandArgs) { CommandSystemHelperMethods.SplitCommand(commandArgs, out var func, out var playerName); switch (func) { default: LunaLog.Normal("Undefined function. Usage: /admin [add|del] playername or /admin show"); break; case "add": AdminAddCommand.Execute(playerName); break; case "del": AdminRemoveCommand.Execute(playerName); break; case "show": AdminShowCommand.Execute(""); break; } }
public override void Execute(string commandArgs) { CommandSystemHelperMethods.SplitCommand(commandArgs, out var playerName, out var reason); reason = string.IsNullOrEmpty(reason) ? "No reason specified" : reason; if (playerName != "") { var player = ClientRetriever.GetClientByName(playerName); if (player != null) { LunaLog.Normal($"Kicking {playerName} from the server"); MessageQueuer.SendConnectionEnd(player, $"Kicked from the server: {reason}"); } else { LunaLog.Normal($"Player: {playerName} not found"); } } else { LunaLog.Error("Syntax error. Usage: /kick playername [reason]"); } }
public override void HandleCommand(string commandArgs) { SplitCommand(commandArgs, out var type, out var data, out var reason); switch (type) { default: LunaLog.Normal("Undefined function. Usage: /ban [key|ip|username] Data [reason]"); break; case "ip": BanIpCommand.Execute($"{data} {reason}"); break; case "key": BanKeyCommand.Execute($"{data} {reason}"); break; case "username": BanPlayerCommand.Execute($"{data} {reason}"); break; } }
//Removes all matching vessels private static void RunRemove(string vesselType, string vesselSituation, string vesselSplashed, string vesselName, string orbName) { //Declare variables var removalCount = 0; var vesselList = VesselStoreSystem.CurrentVesselsInXmlFormat.ToArray(); //Cycle vesselList foreach (var vesselKeyVal in vesselList) { //Check if vessel can be found if (IsVesselFound(vesselKeyVal.Value, vesselType, vesselSituation, vesselSplashed, vesselName, orbName)) { //Send a vessel remove server console message LunaLog.Normal($"Removing vessel: {vesselKeyVal.Key}"); //Remove vessel from universe VesselStoreSystem.RemoveVessel(vesselKeyVal.Key); //Send a vessel remove message to all clients var msgData = ServerContext.ServerMessageFactory.CreateNewMessageData <VesselRemoveMsgData>(); msgData.VesselId = vesselKeyVal.Key; MessageQueuer.SendToAllClients <VesselSrvMsg>(msgData); //Increase counter removalCount++; } } //Send message remove info if (removalCount > 0) { LunaLog.Normal($"Removed {removalCount} vessel(s) ..."); } else { LunaLog.Normal($"Removed nothing ..."); } }
public override void Execute(string commandArgs) { var splittedCommand = commandArgs.Trim().Split(' '); if (splittedCommand.Length == 2) { var playerName = splittedCommand[0]; var client = ClientRetriever.GetAuthenticatedClients().FirstOrDefault(p => p.PlayerName == playerName); if (client != null) { var msgData = ServerContext.ServerMessageFactory.CreateNewMessageData <ChatPrivateMsgData>(); msgData.From = GeneralSettings.SettingsStore.ConsoleIdentifier; msgData.To = client.PlayerName; msgData.Text = commandArgs.Substring(client.PlayerName.Length + 1); MessageQueuer.SendToClient <ChatSrvMsg>(client, msgData); } else { LunaLog.Normal("Player not found!"); } } }
public static void Main() { try { Console.Title = $"LMPServer {LmpVersioning.CurrentVersion}"; #if DEBUG Console.Title += " DEBUG"; #endif Console.OutputEncoding = Encoding.Unicode; ServerContext.StartTime = LunaTime.UtcNow.Ticks; if (!Common.PlatformIsWindows()) { LunaLog.Warning("Remember! Quit the server by using Control+C so the vessels are saved to the hard drive!"); } if (Common.PlatformIsWindows()) { ExitSignal.Exit += (sender, args) => Exit(); } else { //Register the ctrl+c event and exit signal if we are on linux Console.CancelKeyPress += (sender, args) => Exit(); } //We disable quick edit as otherwise when you select some text for copy/paste then you can't write to the console and server freezes //This just happens on windows.... if (Common.PlatformIsWindows()) { ConsoleUtil.DisableConsoleQuickEdit(); } //We cannot run more than 6 instances ofd servers + clients as otherwise the sync time will fail (30 seconds / 5 seconds = 6) but we use 3 for safety if (GetRunningInstances() > 3) { throw new HandledException("Cannot run more than 3 servers at a time!"); } //Start the server clock ServerContext.ServerClock.Start(); //Set the last player activity time to server start ServerContext.LastPlayerActivity = ServerContext.ServerClock.ElapsedMilliseconds; ServerContext.ServerStarting = true; //Set day for log change ServerContext.Day = LunaTime.Now.Day; LunaLog.Normal($"Starting Luna Server version: {LmpVersioning.CurrentVersion}"); Universe.CheckUniverse(); LoadSettingsAndGroups(); VesselStoreSystem.LoadExistingVessels(); ScenarioSystem.GenerateDefaultScenarios(); ScenarioStoreSystem.LoadExistingScenarios(); LmpPluginHandler.LoadPlugins(); WarpSystem.Reset(); LunaLog.Normal($"Starting {GeneralSettings.SettingsStore.WarpMode} server on Port {GeneralSettings.SettingsStore.Port}... "); LunaLog.Normal($"Server name: '{GeneralSettings.SettingsStore.ServerName}'..."); LunaLog.Normal($"Server location: '{Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)}'..."); ServerContext.ServerRunning = true; LidgrenServer.SetupLidgrenServer(); //Do not add the command handler thread to the TaskContainer as it's a blocking task LongRunTaskFactory.StartNew(() => new CommandHandler().ThreadMain(), CancellationTokenSrc.Token); TaskContainer.Add(LongRunTaskFactory.StartNew(LogThread.RunLogThread, CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(() => new ClientMainThread().ThreadMain(), CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(() => BackupSystem.PerformBackups(CancellationTokenSrc.Token), CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(LidgrenServer.StartReceiveingMessages, CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(LidgrenMasterServer.RefreshMasterServersList, CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(LidgrenMasterServer.RegisterWithMasterServer, CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(VesselRelaySystem.RelayOldVesselMessages, CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(VersionChecker.RefreshLatestVersion, CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(VersionChecker.DisplayNewVersionMsg, CancellationTokenSrc.Token)); while (ServerContext.ServerStarting) { Thread.Sleep(500); } LunaLog.Normal("All systems up and running. Поехали!"); LmpPluginHandler.FireOnServerStart(); QuitEvent.WaitOne(); LmpPluginHandler.FireOnServerStop(); LunaLog.Normal("So long and thanks for all the fish!"); } catch (Exception e) { if (e is HandledException) { LunaLog.Fatal(e.Message); } else { LunaLog.Fatal($"Error in main server thread, Exception: {e}"); } Console.ReadLine(); //Avoid closing automatically } }
public static void Main() { try { ServerContext.StartTime = DateTime.UtcNow.Ticks; //Start the server clock ServerContext.ServerClock.Start(); //Set the last player activity time to server start ServerContext.LastPlayerActivity = ServerContext.ServerClock.ElapsedMilliseconds; //Register the ctrl+c event Console.CancelKeyPress += CatchExit; ServerContext.ServerStarting = true; LunaLog.Debug("Loading settings..."); if (GeneralSettings.SettingsStore.GameDifficulty == GameDifficulty.Custom) { GameplaySettings.Reset(); GameplaySettings.Load(); } //Set day for log change ServerContext.Day = DateTime.Now.Day; //Load plugins LmpPluginHandler.LoadPlugins(); Console.Title = $"LMPServer v{VersionInfo.VersionNumber}"; while (ServerContext.ServerStarting || ServerContext.ServerRestarting) { if (ServerContext.ServerRestarting) { LunaLog.Debug("Reloading settings..."); GeneralSettings.Reset(); GeneralSettings.Load(); if (GeneralSettings.SettingsStore.GameDifficulty == GameDifficulty.Custom) { LunaLog.Debug("Reloading gameplay settings..."); GameplaySettings.Reset(); GameplaySettings.Load(); } } ServerContext.ServerRestarting = false; LunaLog.Normal($"Starting Luna Server v{VersionInfo.FullVersionNumber}"); if (GeneralSettings.SettingsStore.GameDifficulty == GameDifficulty.Custom) { //Generate the config file by accessing the object. LunaLog.Debug("Loading gameplay settings..."); GameplaySettings.Load(); } //Load universe LunaLog.Normal("Loading universe... "); Universe.CheckUniverse(); LunaLog.Normal($"Starting {GeneralSettings.SettingsStore.WarpMode} server on Port {GeneralSettings.SettingsStore.Port}... "); ServerContext.ServerRunning = true; var commandThread = Task.Run(() => new CommandHandler().ThreadMain()); var clientThread = Task.Run(() => new ClientMainThread().ThreadMain()); ServerContext.LidgrenServer.SetupLidgrenServer(); Task.Run(() => ServerContext.LidgrenServer.StartReceiveingMessages()); Task.Run(() => ServerContext.LidgrenServer.RegisterWithMasterServer()); var vesselRelayThread = Task.Run(() => VesselRelaySystem.RelayOldVesselMessages()); var vesselRelayFarThread = Task.Run(() => VesselUpdateRelaySystem.RelayToFarPlayers()); var vesselRelayMediumThread = Task.Run(() => VesselUpdateRelaySystem.RelayToMediumDistancePlayers()); var vesselRelayCloseThread = Task.Run(() => VesselUpdateRelaySystem.RelayToClosePlayers()); while (ServerContext.ServerStarting) { Thread.Sleep(500); } LunaLog.Normal("Ready!"); LmpPluginHandler.FireOnServerStart(); while (ServerContext.ServerRunning) { //Run the log expire function every 10 minutes if (ServerContext.ServerClock.ElapsedMilliseconds - _lastLogExpiredCheck > 600000) { _lastLogExpiredCheck = ServerContext.ServerClock.ElapsedMilliseconds; LogExpire.ExpireLogs(); } // Check if the day has changed, every minute if (ServerContext.ServerClock.ElapsedMilliseconds - _lastDayCheck > 60000) { _lastDayCheck = ServerContext.ServerClock.ElapsedMilliseconds; if (ServerContext.Day != DateTime.Now.Day) { LunaLog.LogFilename = Path.Combine(LunaLog.LogFolder, $"lmpserver {DateTime.Now:yyyy-MM-dd HH-mm-ss}.log"); LunaLog.WriteToLog($"Continued from logfile {DateTime.Now:yyyy-MM-dd HH-mm-ss}.log"); ServerContext.Day = DateTime.Now.Day; } } Thread.Sleep(500); } LmpPluginHandler.FireOnServerStop(); commandThread.Wait(); clientThread.Wait(); vesselRelayThread.Wait(); vesselRelayFarThread.Wait(); vesselRelayMediumThread.Wait(); vesselRelayCloseThread.Wait(); } LunaLog.Normal("Goodbye and thanks for all the fish!"); Environment.Exit(0); } catch (Exception e) { LunaLog.Fatal($"Error in main server thread, Exception: {e}"); throw; } }
public static void StartReceivingMessages() { while (ServerContext.ServerRunning) { var msg = Server.WaitMessage(ServerContext.PlayerCount > 0 ? IntervalSettings.SettingsStore.SendReceiveThreadTickMs : int.MaxValue); if (msg != null) { try { ClientStructure client = null; if (msg.SenderConnection != null) { ServerContext.Clients.TryGetValue(msg.SenderConnection.RemoteEndPoint, out client); } switch (msg.MessageType) { case NetIncomingMessageType.ConnectionApproval: if (ServerContext.UsePassword) { if (msg.ReadString() != GeneralSettings.SettingsStore.Password) { msg.SenderConnection.Deny("Invalid password"); break; } } msg.SenderConnection.Approve(); break; case NetIncomingMessageType.Data: MessageReceiver.ReceiveCallback(client, msg); if (client == null) { break; } client.BytesReceived += (uint)msg.LengthBytes; break; case NetIncomingMessageType.WarningMessage: LunaLog.Warning(msg.ReadString()); break; case NetIncomingMessageType.DebugMessage: LunaLog.NetworkDebug(msg.ReadString()); break; case NetIncomingMessageType.ConnectionLatencyUpdated: case NetIncomingMessageType.VerboseDebugMessage: LunaLog.NetworkVerboseDebug(msg.ReadString()); break; case NetIncomingMessageType.ErrorMessage: case NetIncomingMessageType.Error: LunaLog.Error(msg.ReadString()); break; case NetIncomingMessageType.StatusChanged: switch ((NetConnectionStatus)msg.ReadByte()) { case NetConnectionStatus.Connected: var endpoint = msg.SenderConnection.RemoteEndPoint; LunaLog.Normal($"New client Connection from {endpoint.Address}:{endpoint.Port}"); ClientConnectionHandler.ConnectClient(msg.SenderConnection); break; case NetConnectionStatus.Disconnected: if (client != null) { ClientConnectionHandler.DisconnectClient(client, msg.ReadString()); } break; } break; default: LunaLog.Warning($"Unhandled Lidgren Message: {msg.MessageType} -- {msg.ReadString()}"); break; } } catch (Exception e) { LunaLog.Error($"ERROR in networking thread! Details: {e}"); } } } }
private static void HandleMessage(IMasterServerMessageBase message, NetIncomingMessage netMsg, NetPeer peer) { if (BannedIpsRetriever.IsBanned(netMsg.SenderEndPoint)) { LunaLog.Debug($"Ignoring BANNED ip: {netMsg.SenderEndPoint}"); return; } try { switch ((message?.Data as MsBaseMsgData)?.MasterServerMessageSubType) { case MasterServerMessageSubType.RegisterServer: RegisterServer(message, netMsg); break; case MasterServerMessageSubType.RequestServers: LunaLog.Normal($"LIST REQUEST from: {netMsg.SenderEndPoint}"); SendServerLists(netMsg, peer); break; case MasterServerMessageSubType.Introduction: var msgData = (MsIntroductionMsgData)message.Data; if (ServerDictionary.TryGetValue(msgData.Id, out var server)) { _ = Task.Run(() => { if (!server.InternalEndpoint6.Address.Equals(IPAddress.IPv6Loopback) && !server.InternalEndpoint6.Address.Equals(IPAddress.IPv6Loopback)) { // Both client and server are listening on IPv6, try an IPv6 firewall punchthrough // This also triggers a first punchthrough on IPv4 with the public addresses LunaLog.Normal( $"INTRODUCTION request from: {msgData.InternalEndpoint6} to server: {server.InternalEndpoint6}"); peer.Introduce(server.InternalEndpoint6, server.ExternalEndpoint, msgData.InternalEndpoint6, // client internal netMsg.SenderEndPoint, // client external msgData.Token); // request token // Give the first introduction attempt some time Thread.Sleep(50); } LunaLog.Normal( $"INTRODUCTION request from: {netMsg.SenderEndPoint} to server: {server.ExternalEndpoint}"); peer.Introduce(server.InternalEndpoint, server.ExternalEndpoint, msgData.InternalEndpoint, // client internal netMsg.SenderEndPoint, // client external msgData.Token); // request token }); } else { LunaLog.Warning($"Client {netMsg.SenderEndPoint} requested introduction to non listed host!"); } break; } } catch (Exception e) { LunaLog.Error($"Error handling message. Details: {e}"); } }
public override void Execute(string commandArgs) { LunaLog.Normal($"Online Players: {ServerContext.PlayerCount}"); }
public static void PerformGCNow() { LunaLog.Normal("Performing a GarbageCollection..."); GC.Collect(); }
public static async void RegisterWithMasterServer() { if (!MasterServerSettings.SettingsStore.RegisterWithMasterServer) { return; } LunaLog.Normal("Registering with master servers"); var adr4 = LunaNetUtils.GetOwnInternalIPv4Address(); // As of right now the internal endpoint for IPv4 is mandatory, because if there is none, there is no // IPv4 connectivity at all, which is required to connect to the master servers (so they can determine // the public IPv4 address). if (adr4 == null) { return; } var endpoint4 = new IPEndPoint(adr4, ServerContext.Config.Port); // Only send IPv6 address if actually listening on IPv6, otherwise send loopback with means "none". IPAddress adr6; IPEndPoint endpoint6; if (LidgrenServer.Server.Socket.AddressFamily == AddressFamily.InterNetworkV6) { adr6 = LunaNetUtils.GetOwnInternalIPv6Address(); endpoint6 = new IPEndPoint(adr6, ServerContext.Config.Port); } else { endpoint6 = new IPEndPoint(IPAddress.IPv6Loopback, ServerContext.Config.Port); } while (ServerContext.ServerRunning) { var msgData = ServerContext.ServerMessageFactory.CreateNewMessageData <MsRegisterServerMsgData>(); msgData.Id = LidgrenServer.Server.UniqueIdentifier; msgData.Password = !string.IsNullOrEmpty(GeneralSettings.SettingsStore.Password); msgData.Cheats = GeneralSettings.SettingsStore.Cheats; msgData.Description = GeneralSettings.SettingsStore.Description; msgData.CountryCode = GeneralSettings.SettingsStore.CountryCode; msgData.Website = GeneralSettings.SettingsStore.Website; msgData.WebsiteText = GeneralSettings.SettingsStore.WebsiteText; msgData.RainbowEffect = DedicatedServerSettings.SettingsStore.UseRainbowEffect; msgData.Color = new[] { DedicatedServerSettings.SettingsStore.Red, DedicatedServerSettings.SettingsStore.Green, DedicatedServerSettings.SettingsStore.Blue }; msgData.GameMode = (int)GeneralSettings.SettingsStore.GameMode; msgData.InternalEndpoint = endpoint4; msgData.InternalEndpoint6 = endpoint6; msgData.MaxPlayers = GeneralSettings.SettingsStore.MaxPlayers; msgData.ModControl = GeneralSettings.SettingsStore.ModControl; msgData.PlayerCount = ServerContext.Clients.Count; msgData.ServerName = GeneralSettings.SettingsStore.ServerName; msgData.ServerVersion = LmpVersioning.CurrentVersion.ToString(3); msgData.VesselPositionUpdatesMsInterval = IntervalSettings.SettingsStore.VesselUpdatesMsInterval; msgData.SecondaryVesselPositionUpdatesMsInterval = IntervalSettings.SettingsStore.SecondaryVesselUpdatesMsInterval; msgData.WarpMode = (int)WarpSettings.SettingsStore.WarpMode; msgData.TerrainQuality = (int)GeneralSettings.SettingsStore.TerrainQuality; msgData.Description = msgData.Description.Length > 200 ? msgData.Description.Substring(0, 200) : msgData.Description; msgData.CountryCode = msgData.CountryCode.Length > 2 ? msgData.CountryCode.Substring(0, 2) : msgData.CountryCode; msgData.Website = msgData.Website.Length > 60 ? msgData.Website.Substring(0, 60) : msgData.Website; msgData.WebsiteText = msgData.WebsiteText.Length > 15 ? msgData.WebsiteText.Substring(0, 15) : msgData.WebsiteText; msgData.ServerName = msgData.ServerName.Length > 30 ? msgData.ServerName.Substring(0, 30) : msgData.ServerName; IPEndPoint[] masterServers; if (string.IsNullOrEmpty(DebugSettings.SettingsStore.CustomMasterServer)) { masterServers = MasterServerRetriever.MasterServers.GetValues; } else { masterServers = new[] { LunaNetUtils.CreateEndpointFromString(DebugSettings.SettingsStore.CustomMasterServer) }; } foreach (var masterServer in masterServers) { RegisterWithMasterServer(msgData, masterServer); } await Task.Delay(MasterServerRegistrationMsInterval); } }
public void RegisterWithMasterServer() { if (!GeneralSettings.SettingsStore.RegisterWithMasterServer) { return; } var adr = NetUtility.GetMyAddress(out var _); var endpoint = new IPEndPoint(adr, ServerContext.Config.Port); if (MasterServerEndpoints == null || !MasterServerEndpoints.Any()) { MasterServerEndpoints = MasterServerRetriever.RetrieveWorkingMasterServersEndpoints() .Select(Common.CreateEndpointFromString) .ToArray(); } LunaLog.Normal("Registering with master servers..."); while (ServerContext.ServerRunning) { var msgData = new MsRegisterServerMsgData { Id = Server.UniqueIdentifier, Cheats = GeneralSettings.SettingsStore.Cheats, ShowVesselsInThePast = GeneralSettings.SettingsStore.ShowVesselsInThePast, Description = GeneralSettings.SettingsStore.Description, DropControlOnExit = GeneralSettings.SettingsStore.Cheats, DropControlOnExitFlight = GeneralSettings.SettingsStore.Cheats, DropControlOnVesselSwitching = GeneralSettings.SettingsStore.Cheats, GameMode = (int)GeneralSettings.SettingsStore.GameMode, InternalEndpoint = $"{endpoint.Address}:{endpoint.Port}", MaxPlayers = GeneralSettings.SettingsStore.MaxPlayers, ModControl = (int)GeneralSettings.SettingsStore.ModControl, PlayerCount = ServerContext.Clients.Count, ServerName = GeneralSettings.SettingsStore.ServerName, ServerVersion = VersionInfo.VersionNumber, VesselUpdatesSendMsInterval = GeneralSettings.SettingsStore.VesselUpdatesSendMsInterval, SecondaryVesselUpdatesSendMsInterval = GeneralSettings.SettingsStore.SecondaryVesselUpdatesSendMsInterval, WarpMode = (int)GeneralSettings.SettingsStore.WarpMode }; msgData.Description = msgData.Description.Length > 200 ? msgData.Description.Substring(0, 200) : msgData.Description; msgData.ServerName = msgData.ServerName.Length > 30 ? msgData.ServerName.Substring(0, 30) : msgData.ServerName; var msg = ServerContext.MasterServerMessageFactory.CreateNew <MainMstSrvMsg>(msgData); var msgBytes = ServerContext.MasterServerMessageFactory.Serialize(msg); foreach (var masterServer in MasterServerEndpoints) { try { var outMsg = Server.CreateMessage(msgBytes.Length); outMsg.Write(msgBytes); Server.SendUnconnectedMessage(outMsg, masterServer); Server.FlushSendQueue(); } catch (Exception) { // ignored } } Thread.Sleep(MasterServerRegistrationMsInterval); } }
public static async void StartReceiveingMessages() { try { while (ServerContext.ServerRunning) { var msg = Server.ReadMessage(); if (msg != null) { var client = TryGetClient(msg); switch (msg.MessageType) { case NetIncomingMessageType.ConnectionApproval: if (ServerContext.UsePassword) { var password = msg.ReadString(); if (password != GeneralSettings.SettingsStore.Password) { msg.SenderConnection.Deny("Invalid password"); break; } } msg.SenderConnection.Approve(); break; case NetIncomingMessageType.Data: ClientMessageReceiver.ReceiveCallback(client, msg); break; case NetIncomingMessageType.WarningMessage: LunaLog.Warning(msg.ReadString()); break; case NetIncomingMessageType.DebugMessage: LunaLog.NetworkDebug(msg.ReadString()); break; case NetIncomingMessageType.ConnectionLatencyUpdated: case NetIncomingMessageType.VerboseDebugMessage: LunaLog.NetworkVerboseDebug(msg.ReadString()); break; case NetIncomingMessageType.Error: LunaLog.Error(msg.ReadString()); break; case NetIncomingMessageType.StatusChanged: switch ((NetConnectionStatus)msg.ReadByte()) { case NetConnectionStatus.Connected: var endpoint = msg.SenderConnection.RemoteEndPoint; LunaLog.Normal($"New client Connection from {endpoint.Address}:{endpoint.Port}"); ClientConnectionHandler.ConnectClient(msg.SenderConnection); break; case NetConnectionStatus.Disconnected: var reason = msg.ReadString(); if (client != null) { ClientConnectionHandler.DisconnectClient(client, reason); } break; } break; default: var details = msg.PeekString(); LunaLog.Debug($"Lidgren: {msg.MessageType.ToString().ToUpper()} -- {details}"); break; } } else { await Task.Delay(IntervalSettings.SettingsStore.SendReceiveThreadTickMs); } } } catch (Exception e) { LunaLog.Fatal($"ERROR in thread receive! Details: {e}"); } }
public void StartReceiveingMessages() { try { while (ServerContext.ServerRunning) { var msg = Server.ReadMessage(); if (msg != null) { var client = TryGetClient(msg); switch (msg.MessageType) { case NetIncomingMessageType.ConnectionApproval: msg.SenderConnection.Approve(); break; case NetIncomingMessageType.Data: ClientMessageReceiver.ReceiveCallback(client, msg); break; case NetIncomingMessageType.WarningMessage: LunaLog.Error($"Lidgren WARNING: {msg.ReadString()}"); break; case NetIncomingMessageType.DebugMessage: case NetIncomingMessageType.VerboseDebugMessage: LunaLog.Debug($"Lidgren DEBUG: {msg.MessageType}-- {msg.PeekString()}"); break; case NetIncomingMessageType.StatusChanged: switch ((NetConnectionStatus)msg.ReadByte()) { case NetConnectionStatus.Connected: var endpoint = msg.SenderConnection.RemoteEndPoint; LunaLog.Normal($"New client Connection from {endpoint.Address}:{endpoint.Port}"); ClientConnectionHandler.ConnectClient(msg.SenderConnection); break; case NetConnectionStatus.Disconnected: var reason = msg.ReadString(); if (client != null) { ClientConnectionHandler.DisconnectClient(client, reason); } break; } break; default: var details = msg.PeekString(); LunaLog.Debug($"Lidgren: {msg.MessageType.ToString().ToUpper()} -- {details}"); break; } } else { Thread.Sleep(GeneralSettings.SettingsStore.SendReceiveThreadTickMs); } } } catch (Exception e) { LunaLog.Fatal($"ERROR in thread receive! Details: {e}"); } }
public static void Main() { try { Console.Title = $"LMPServer {LmpVersioning.CurrentVersion}"; #if DEBUG Console.Title += " DEBUG"; #endif Console.OutputEncoding = Encoding.Unicode; ServerContext.StartTime = LunaTime.UtcNow.Ticks; //We disable quick edit as otherwise when you select some text for copy/paste then you can't write to the console and server freezes //This just happens on windows.... if (Common.PlatformIsWindows()) { ConsoleUtil.DisableConsoleQuickEdit(); } //We cannot run more than 6 instances ofd servers + clients as otherwise the sync time will fail (30 seconds / 5 seconds = 6) but we use 3 for safety if (GetRunningInstances() > 3) { throw new HandledException("Cannot run more than 3 servers at a time!"); } //Start the server clock ServerContext.ServerClock.Start(); //Set the last player activity time to server start ServerContext.LastPlayerActivity = ServerContext.ServerClock.ElapsedMilliseconds; //Register the ctrl+c event Console.CancelKeyPress += CatchExit; ServerContext.ServerStarting = true; //Set day for log change ServerContext.Day = LunaTime.Now.Day; LunaLog.Normal($"Starting Luna Server version: {LmpVersioning.CurrentVersion}"); Universe.CheckUniverse(); LoadSettingsAndGroups(); LmpPluginHandler.LoadPlugins(); WarpSystem.Reset(); ChatSystem.Reset(); LunaLog.Normal($"Starting {GeneralSettings.SettingsStore.WarpMode} server on Port {GeneralSettings.SettingsStore.Port}... "); ServerContext.ServerRunning = true; ServerContext.LidgrenServer.SetupLidgrenServer(); Task.Run(() => new CommandHandler().ThreadMain()); Task.Run(() => new ClientMainThread().ThreadMain()); Task.Run(() => ServerContext.LidgrenServer.StartReceiveingMessages()); Task.Run(() => ServerContext.LidgrenServer.RefreshMasterServersList()); Task.Run(() => ServerContext.LidgrenServer.RegisterWithMasterServer()); Task.Run(() => LogThread.RunLogThread()); Task.Run(() => VesselRelaySystem.RelayOldVesselMessages()); Task.Run(() => VesselUpdateRelaySystem.RelayToFarPlayers()); Task.Run(() => VesselUpdateRelaySystem.RelayToMediumDistancePlayers()); Task.Run(() => VesselUpdateRelaySystem.RelayToClosePlayers()); Task.Run(() => VersionChecker.CheckForNewVersions()); while (ServerContext.ServerStarting) { Thread.Sleep(500); } LunaLog.Normal("All systems up and running. Поехали!"); LmpPluginHandler.FireOnServerStart(); QuitEvent.WaitOne(); WarpSystem.SaveSubspacesToFile(); LmpPluginHandler.FireOnServerStop(); LunaLog.Normal("Goodbye and thanks for all the fish!"); } catch (Exception e) { if (e is HandledException) { LunaLog.Fatal(e.Message); } else { LunaLog.Fatal($"Error in main server thread, Exception: {e}"); } Console.ReadLine(); //Avoid closing automatically } }
public static void Main() { try { Console.Title = $"LMP {LmpVersioning.CurrentVersion}"; Console.OutputEncoding = Encoding.Unicode; ServerContext.StartTime = LunaNetworkTime.UtcNow.Ticks; LunaLog.Info("Remember! Quit the server by using 'Control + C' so a backup is properly made before closing!"); if (Common.PlatformIsWindows()) { ExitSignal.Exit += (sender, args) => Exit(); } else { //Register the ctrl+c event and exit signal if we are on linux Console.CancelKeyPress += (sender, args) => Exit(); } //We disable quick edit as otherwise when you select some text for copy/paste then you can't write to the console and server freezes //This just happens on windows.... if (Common.PlatformIsWindows()) { ConsoleUtil.DisableConsoleQuickEdit(); } //We cannot run more than 6 instances ofd servers + clients as otherwise the sync time will fail (30 seconds / 5 seconds = 6) but we use 3 for safety if (GetRunningInstances() > 3) { throw new HandledException("Cannot run more than 3 servers at a time!"); } //Start the server clock ServerContext.ServerClock.Start(); ServerContext.ServerStarting = true; //Set day for log change ServerContext.Day = LunaNetworkTime.Now.Day; LunaLog.Normal($"Luna Server version: {LmpVersioning.CurrentVersion} ({Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)})"); Universe.CheckUniverse(); LoadSettingsAndGroups(); VesselStoreSystem.LoadExistingVessels(); var scenariosCreated = ScenarioSystem.GenerateDefaultScenarios(); ScenarioStoreSystem.LoadExistingScenarios(scenariosCreated); LmpPluginHandler.LoadPlugins(); WarpSystem.Reset(); LunaLog.Normal($"Starting '{GeneralSettings.SettingsStore.ServerName}' on Port {ConnectionSettings.SettingsStore.Port}... "); LidgrenServer.SetupLidgrenServer(); LmpPortMapper.OpenLmpPort().Wait(); LmpPortMapper.OpenWebPort().Wait(); ServerContext.ServerRunning = true; WebServer.StartWebServer(); //Do not add the command handler thread to the TaskContainer as it's a blocking task LongRunTaskFactory.StartNew(CommandHandler.ThreadMain, CancellationTokenSrc.Token); TaskContainer.Add(LongRunTaskFactory.StartNew(WebServer.RefreshWebServerInformation, CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(LmpPortMapper.RefreshUpnpPort, CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(LogThread.RunLogThread, CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(ClientMainThread.ThreadMain, CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(() => BackupSystem.PerformBackups(CancellationTokenSrc.Token), CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(LidgrenServer.StartReceivingMessages, CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(LidgrenMasterServer.RegisterWithMasterServer, CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(VersionChecker.RefreshLatestVersion, CancellationTokenSrc.Token)); TaskContainer.Add(LongRunTaskFactory.StartNew(VersionChecker.DisplayNewVersionMsg, CancellationTokenSrc.Token)); while (ServerContext.ServerStarting) { Thread.Sleep(500); } LunaLog.Normal("All systems up and running. Поехали!"); LmpPluginHandler.FireOnServerStart(); QuitEvent.WaitOne(); LmpPluginHandler.FireOnServerStop(); LunaLog.Normal("So long and thanks for all the fish!"); } catch (Exception e) { LunaLog.Fatal(e is HandledException ? e.Message : $"Error in main server thread, Exception: {e}"); Console.ReadLine(); //Avoid closing automatically } }
public override bool Execute(string commandArgs) { LunaLog.Normal($"Online Players: {ServerContext.PlayerCount}"); return(true); }