internal void SetVesselGroupCommand(string commandText) { if (editVessel == Guid.Empty) { DarkLog.Normal("Set /editvessel first"); } if (!vesselPermissions.ContainsKey(editVessel)) { DarkLog.Normal("Set /vesselowner first"); return; } if (commandText == null || commandText == "") { DarkLog.Normal(editVessel + " no longer belongs to a group"); } else { DarkLog.Normal(editVessel + " now belongs to group: " + commandText); } SetVesselGroup(editVessel, commandText); }
internal void ShowGroupsCommand(string commandText) { lock (playerGroups) { foreach (KeyValuePair <string, List <string> > kvp in playerGroups) { DarkLog.Normal(kvp.Key + ":"); foreach (string group in kvp.Value) { if (PlayerIsAdmin(kvp.Key, group)) { DarkLog.Normal(group + " (Admin)"); } else { DarkLog.Normal(group); } } } } }
public void Update() { try { m_clients.Flush(); // TODO: Save subspace if player leaves and count == 0 m_server.Run(); // Dispatch events Run(); //Check timers NukeKSC.CheckTimer(); Dekessler.CheckTimer(); //Run plugin update DMPPluginHandler.FireOnUpdate(); } catch (Exception e) { DarkLog.Error("Fatal error thrown, exception: " + e); Server.ShutDown("Crashed!"); } }
//Fire OnMessageReceived public static bool FireOnMessageReceived(IMessage message) { bool handledByAny = false; foreach (var plugin in loadedPlugins) { try { //prevent plugins from unhandling other plugin's handled requests if (plugin.OnMessageReceived(message)) { handledByAny = true; } } catch (Exception e) { Type type = plugin.GetType(); DarkLog.Debug("Error thrown in OnMessageReceived event for " + type.FullName + " (" + type.Assembly.FullName + "), Exception: " + e); } } return(handledByAny); }
public void PMCommand(string commandArgs) { ClientObject pmPlayer = null; int matchedLength = 0; m_clients.Iterate(x => { //Only search authenticated players if (x.authenticated) { //Try to match the longest player name if (commandArgs.StartsWith(x.playerName) && x.playerName.Length > matchedLength) { //Double check there is a space after the player name if ((commandArgs.Length > (x.playerName.Length + 1)) ? commandArgs[x.playerName.Length] == ' ' : false) { pmPlayer = x; matchedLength = x.playerName.Length; } } } }); if (pmPlayer != null) { string messageText = commandArgs.Substring(pmPlayer.playerName.Length + 1); Messages.ServerClient_ChatMessageSend msg = new Messages.ServerClient_ChatMessageSend(); msg.type = (byte)ChatMessageType.PRIVATE_MESSAGE; msg.name = Settings.settingsStore.consoleIdentifier; msg.channel = pmPlayer.playerName; msg.message = messageText; SendUnordered(pmPlayer, msg); } else { DarkLog.Normal("Player not found!"); } }
public void SaveBans() { try { if (File.Exists(banlistFile)) { File.SetAttributes(banlistFile, FileAttributes.Normal); } using (StreamWriter sw = new StreamWriter(banlistFile)) { foreach (string name in bannedNames) { sw.WriteLine("{0}", name); } } using (StreamWriter sw = new StreamWriter(ipBanlistFile)) { foreach (IPAddress ip in bannedIPs) { sw.WriteLine("{0}", ip); } } using (StreamWriter sw = new StreamWriter(publicKeyBanlistFile)) { foreach (string publicKey in bannedPublicKeys) { sw.WriteLine("{0}", publicKey); } } } catch (Exception e) { DarkLog.Error("Error saving bans!, Exception: " + e); } }
public static void ConvertSettings(string oldSettings, string newSettings) { if (!File.Exists(oldSettings)) { return; } using (StreamWriter sw = new StreamWriter(newSettings)) { using (StreamReader sr = new StreamReader(oldSettings)) { string currentLine; while ((currentLine = sr.ReadLine()) != null) { string trimmedLine = currentLine.Trim(); if (!trimmedLine.Contains(",") || trimmedLine.StartsWith("#") || trimmedLine == string.Empty) { continue; } int seperatorIndex = trimmedLine.IndexOf(","); string keyPart = trimmedLine.Substring(0, seperatorIndex).Trim(); string valuePart = trimmedLine.Substring(seperatorIndex + 1).Trim(); string realKey = keyPart; foreach (FieldInfo fieldInfo in typeof(SettingsStore).GetFields()) { if (fieldInfo.Name.ToLower() == keyPart.ToLower()) { realKey = fieldInfo.Name; break; } } sw.WriteLine(realKey + "=" + valuePart); } } } File.Delete(oldSettings); DarkLog.Debug("Converted settings to DMP v0.2.1.0 format"); }
private void SaveAdmins() { DarkLog.Debug("Saving admins"); try { if (File.Exists(adminListFile)) { File.SetAttributes(adminListFile, FileAttributes.Normal); } using (StreamWriter sw = new StreamWriter(adminListFile)) { foreach (string user in serverAdmins) { sw.WriteLine(user); } } } catch (Exception e) { DarkLog.Error("Error saving admin list!, Exception: " + e); } }
public static void SendDMPModMessageToClient(ClientObject client, string modName, byte[] messageData, bool highPriority) { if (modName == null) { //Now that's just being silly :) return; } if (messageData == null) { DarkLog.Debug(modName + " attemped to send a null message"); return; } ServerMessage newMessage = new ServerMessage(); newMessage.type = ServerMessageType.MOD_DATA; using (MessageWriter mw = new MessageWriter()) { mw.Write <string>(modName); mw.Write <byte[]>(messageData); newMessage.data = mw.GetMessageBytes(); } ClientHandler.SendToClient(client, newMessage, highPriority); }
private static void SetupClient(TcpClient newClientConnection) { ClientObject newClientObject = new ClientObject(); newClientObject.subspace = Messages.WarpControl.GetLatestSubspace(); newClientObject.playerStatus = new PlayerStatus(); newClientObject.connectionStatus = ConnectionStatus.CONNECTED; newClientObject.endpoint = newClientConnection.Client.RemoteEndPoint.ToString(); newClientObject.ipAddress = (newClientConnection.Client.RemoteEndPoint as IPEndPoint).Address; //Keep the connection reference newClientObject.connection = newClientConnection; StartReceivingIncomingMessages(newClientObject); StartSendingOutgoingMessages(newClientObject); DMPPluginHandler.FireOnClientConnect(newClientObject); Messages.Handshake.SendHandshakeChallange(newClientObject); lock (clients) { List<ClientObject> newList = new List<ClientObject>(clients); newList.Add(newClientObject); clients = newList.AsReadOnly(); Server.playerCount = GetActiveClientCount(); Server.players = GetActivePlayerNames(); DarkLog.Debug("Online players is now: " + Server.playerCount + ", connected: " + clients.Count); } }
//Fire OnMessageReceived public static void FireOnMessageReceived(ClientObject client, ClientMessage message) { bool handledByAny = false; foreach (var plugin in loadedPlugins) { try { plugin.OnMessageReceived(client, message); //prevent plugins from unhandling other plugin's handled requests if (message.handled) { handledByAny = true; } } catch (Exception e) { Type type = plugin.GetType(); DarkLog.Debug("Error thrown in OnMessageReceived event for " + type.FullName + " (" + type.Assembly.FullName + "), Exception: " + e); } } message.handled = handledByAny; }
public bool SaveModObject(byte[] data, string sha256sum) { if (data == null) { data = new byte[0]; } if (Common.CalculateSHA256Hash(data) != sha256sum) { return(false); } string tryWrite = null; try { foreach (KeyValuePair <string, string> kvp in clientData) { tryWrite = Path.Combine(modpackPath, kvp.Key); if (kvp.Value == sha256sum) { clientReceived++; new FileInfo(tryWrite).Directory.Create(); if (File.Exists(tryWrite)) { File.Delete(tryWrite); } File.WriteAllBytes(tryWrite, data); } } } catch (Exception e) { DarkLog.Error("Cannot write file " + tryWrite + ", error: " + e); return(false); } return(true); }
public static void FixKerbals() { string kerbalPath = Path.Combine(Server.universeDirectory, "Kerbals"); int kerbalCount = 0; while (File.Exists(Path.Combine(kerbalPath, kerbalCount + ".txt"))) { string oldKerbalFile = Path.Combine(kerbalPath, kerbalCount + ".txt"); string kerbalName = null; using (StreamReader sr = new StreamReader(oldKerbalFile)) { string fileLine; while ((fileLine = sr.ReadLine()) != null) { if (fileLine.StartsWith("name = ")) { kerbalName = fileLine.Substring(fileLine.IndexOf("name = ") + 7); break; } } } if (!String.IsNullOrEmpty(kerbalName)) { DarkLog.Debug("Renaming kerbal " + kerbalCount + " to " + kerbalName); File.Move(oldKerbalFile, Path.Combine(kerbalPath, kerbalName + ".txt")); } kerbalCount++; } if (kerbalCount != 0) { DarkLog.Normal("Kerbal database upgraded to 0.24 format"); } }
public static void Main() { try { //Start the server clock serverClock = new Stopwatch(); serverClock.Start(); //Set the last player activity time to server start lastPlayerActivity = serverClock.ElapsedMilliseconds; //Periodic garbage collection long lastGarbageCollect = 0; //Periodic screenshot check long lastScreenshotExpiredCheck = 0; //Set universe directory and modfile path universeDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Universe"); modFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DMPModControl.txt"); CommandHandler commandHandler = new CommandHandler(); //Register the server commands commandHandler.RegisterCommand("exit", Server.ShutDown, "Shuts down the server"); commandHandler.RegisterCommand("quit", Server.ShutDown, "Shuts down the server"); commandHandler.RegisterCommand("shutdown", Server.ShutDown, "Shuts down the server"); commandHandler.RegisterCommand("restart", Server.Restart, "Restarts the server"); commandHandler.RegisterCommand("kick", x => WorldManager.Instance.KickPlayer(x), "Kicks a player from the server"); commandHandler.RegisterCommand("ban", x => WorldManager.Instance.BanPlayer(x), "Bans a player from the server"); commandHandler.RegisterCommand("banip", x => WorldManager.Instance.BanIP(x), "Bans an IP Address from the server"); commandHandler.RegisterCommand("bankey", x => WorldManager.Instance.BanPublicKey(x), "Bans a Guid from the server"); commandHandler.RegisterCommand("pm", x => WorldManager.Instance.PMCommand(x), "Sends a message to a player"); commandHandler.RegisterCommand("admin", x => WorldManager.Instance.AdminCommand(x), "Sets a player as admin/removes admin from the player"); commandHandler.RegisterCommand("whitelist", x => WorldManager.Instance.WhitelistCommand(x), "Change the server whitelist"); //Register the ctrl+c event Console.CancelKeyPress += new ConsoleCancelEventHandler(CatchExit); serverStarting = true; //Fix kerbals from 0.23.5 to 0.24 (Now indexed by string, thanks Squad! BackwardsCompatibility.FixKerbals(); //Remove player tokens BackwardsCompatibility.RemoveOldPlayerTokens(); //Load plugins DMPPluginHandler.LoadPlugins(); Console.Title = "DMPServer " + Common.PROGRAM_VERSION + ", protocol " + Common.PROTOCOL_VERSION; while (serverStarting || serverRestarting) { serverRestarting = false; DarkLog.Normal("Starting DMPServer " + Common.PROGRAM_VERSION + ", protocol " + Common.PROTOCOL_VERSION); //Load settings DarkLog.Normal("Loading universe... "); CheckUniverse(); DarkLog.Normal("Done!"); DarkLog.Normal("Loading settings... "); Settings.Load(); DarkLog.Normal("Done!"); DarkLog.Normal("Starting " + Settings.settingsStore.warpMode + " server on port " + Settings.settingsStore.port + "... "); serverRunning = true; DarkLog.Normal("Done!"); StartHTTPServer(); DarkLog.Normal("Done!"); DMPPluginHandler.FireOnServerStart(); while (serverRunning) { WorldManager.Instance.Update(); commandHandler.Run(); //Run a garbage collection every 2 minutes. if ((serverClock.ElapsedMilliseconds - lastGarbageCollect) > 12000) { lastGarbageCollect = serverClock.ElapsedMilliseconds; GC.Collect(); } //Run the screenshot expire function every 10 minutes if ((serverClock.ElapsedMilliseconds - lastScreenshotExpiredCheck) > 600000) { lastScreenshotExpiredCheck = serverClock.ElapsedMilliseconds; ScreenshotExpire.ExpireCache(); } Thread.Sleep(10); } DMPPluginHandler.FireOnServerStop(); } DarkLog.Normal("Goodbye!"); Environment.Exit(0); } catch (Exception e) { DarkLog.Fatal("Error in main server thread, Exception: " + e); throw; } }
public static void LoadPlugins() { DarkLog.Debug("Loading plugins!"); //Load all the assemblies just in case they depend on each other during instantation List <Assembly> loadedAssemblies = new List <Assembly>(); string[] pluginFiles = Directory.GetFiles(Server.pluginDirectory, "*", SearchOption.AllDirectories); foreach (string pluginFile in pluginFiles) { if (Path.GetExtension(pluginFile).ToLower() == ".dll") { try { Assembly loadedAssembly = Assembly.LoadFile(pluginFile); loadedAssemblies.Add(loadedAssembly); DarkLog.Debug("Loaded " + pluginFile); } catch { DarkLog.Debug("Error loading " + pluginFile); } } } //Add all the event types pluginEvents.Add(typeof(DMPUpdate), new List <Delegate>()); pluginEvents.Add(typeof(DMPOnServerStart), new List <Delegate>()); pluginEvents.Add(typeof(DMPOnServerStop), new List <Delegate>()); pluginEvents.Add(typeof(DMPOnClientConnect), new List <Delegate>()); pluginEvents.Add(typeof(DMPOnClientAuthenticated), new List <Delegate>()); pluginEvents.Add(typeof(DMPOnClientDisconnect), new List <Delegate>()); pluginEvents.Add(typeof(DMPOnMessageReceived), new List <Delegate>()); //Iterate through the assemblies looking for the DMPPlugin attribute foreach (Assembly loadedAssembly in loadedAssemblies) { Type[] loadedTypes = loadedAssembly.GetExportedTypes(); foreach (Type loadedType in loadedTypes) { if (loadedType.IsDefined(typeof(DMPPluginAttribute), false)) { DarkLog.Debug("Loading " + loadedType.Name); object pluginInstance = Activator.CreateInstance(loadedType); MethodInfo[] methodInfos = loadedType.GetMethods(BindingFlags.Public | BindingFlags.Instance); foreach (MethodInfo methodInfo in methodInfos) { try { foreach (Type evT in pluginEvents.Keys) { if (evT.Name.Substring(3) == methodInfo.Name) { DarkLog.Debug("Event registered : " + evT.Name); Delegate deg = Delegate.CreateDelegate(evT, pluginInstance, methodInfo); DMPEventInfo info = new DMPEventInfo(); info.loadedAssembly = loadedAssembly.FullName; info.loadedType = loadedType.Name; delegateInfo.Add(deg, info); pluginEvents[evT].Add(deg); } } } catch (Exception e) { DarkLog.Error("Error loading " + methodInfo.Name + " from " + loadedType.Name + ", Exception: " + e.Message); } } } } } DarkLog.Debug("Done!"); }
private static void Load() { DarkLog.Debug("Loading settings"); FieldInfo[] settingFields = typeof(SettingsStore).GetFields(); if (!File.Exists(settingsFile)) { try { if (System.Net.Sockets.Socket.OSSupportsIPv6) { //Default to listening on IPv4 and IPv6 if possible. settingsStore.address = "::"; } } catch { //May throw on Windows XP } Save(); } using (FileStream fs = new FileStream(settingsFile, FileMode.Open)) { using (StreamReader sr = new StreamReader(fs)) { string currentLine; string trimmedLine; string currentKey; string currentValue; while (true) { currentLine = sr.ReadLine(); if (currentLine == null) { break; } trimmedLine = currentLine.Trim(); if (!String.IsNullOrEmpty(trimmedLine)) { if (trimmedLine.Contains(",") && !trimmedLine.StartsWith("#")) { currentKey = trimmedLine.Substring(0, trimmedLine.IndexOf(",")); currentValue = trimmedLine.Substring(trimmedLine.IndexOf(",") + 1); foreach (FieldInfo settingField in settingFields) { if (settingField.Name.ToLower() == currentKey) { if (settingField.FieldType == typeof(string)) { settingField.SetValue(settingsStore, currentValue); } if (settingField.FieldType == typeof(int)) { int intValue = Int32.Parse(currentValue); settingField.SetValue(settingsStore, (int)intValue); } if (settingField.FieldType == typeof(double)) { double doubleValue = Double.Parse(currentValue); settingField.SetValue(settingsStore, (double)doubleValue); } if (settingField.FieldType == typeof(bool)) { if (currentValue == "1") { settingField.SetValue(settingsStore, true); } else { settingField.SetValue(settingsStore, false); } } if (settingField.FieldType.IsEnum) { int intValue = Int32.Parse(currentValue); Array enumValues = settingField.FieldType.GetEnumValues(); if (intValue <= enumValues.Length) { settingField.SetValue(settingsStore, enumValues.GetValue(intValue)); } } //DarkLog.Debug(settingField.Name + ": " + currentValue); } } } } } } } Save(); }
public static void Main() { #if !DEBUG try { #endif //Start the server clock serverClock = new Stopwatch(); serverClock.Start(); Settings.Reset(); //Set the last player activity time to server start lastPlayerActivity = serverClock.ElapsedMilliseconds; //Periodic garbage collection long lastGarbageCollect = 0; //Periodic screenshot check long lastScreenshotExpiredCheck = 0; //Periodic log check long lastLogExpiredCheck = 0; //Periodic day check long lastDayCheck = 0; //Set universe directory and modfile path universeDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Universe"); modFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DMPModControl.txt"); if (!Directory.Exists(configDirectory)) { Directory.CreateDirectory(configDirectory); } string oldSettingsFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DMPServerSettings.txt"); string newSettingsFile = Path.Combine(Server.configDirectory, "Settings.txt"); string oldGameplayFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DMPGameplaySettings.txt"); string newGameplayFile = Path.Combine(Server.configDirectory, "GameplaySettings.txt"); // Run the conversion BackwardsCompatibility.ConvertSettings(oldSettingsFile, newSettingsFile); if (File.Exists(oldGameplayFile)) { if (!File.Exists(newGameplayFile)) { File.Move(oldGameplayFile, newGameplayFile); } File.Delete(oldGameplayFile); } //Register the server commands CommandHandler.RegisterCommand("exit", Server.ShutDown, "Shuts down the server"); CommandHandler.RegisterCommand("quit", Server.ShutDown, "Shuts down the server"); CommandHandler.RegisterCommand("shutdown", Server.ShutDown, "Shuts down the server"); CommandHandler.RegisterCommand("restart", Server.Restart, "Restarts the server"); CommandHandler.RegisterCommand("kick", KickCommand.KickPlayer, "Kicks a player from the server"); CommandHandler.RegisterCommand("ban", BanSystem.fetch.BanPlayer, "Bans a player from the server"); CommandHandler.RegisterCommand("banip", BanSystem.fetch.BanIP, "Bans an IP Address from the server"); CommandHandler.RegisterCommand("bankey", BanSystem.fetch.BanPublicKey, "Bans a Guid from the server"); CommandHandler.RegisterCommand("pm", PMCommand.HandleCommand, "Sends a message to a player"); CommandHandler.RegisterCommand("admin", AdminCommand.HandleCommand, "Sets a player as admin/removes admin from the player"); CommandHandler.RegisterCommand("whitelist", WhitelistCommand.HandleCommand, "Change the server whitelist"); //Register the ctrl+c event Console.CancelKeyPress += new ConsoleCancelEventHandler(CatchExit); serverStarting = true; //Fix kerbals from 0.23.5 to 0.24 (Now indexed by string, thanks Squad! BackwardsCompatibility.FixKerbals(); //Remove player tokens BackwardsCompatibility.RemoveOldPlayerTokens(); //Add new stock parts BackwardsCompatibility.UpdateModcontrolPartList(); if (System.Net.Sockets.Socket.OSSupportsIPv6) { Settings.settingsStore.address = "::"; } DarkLog.Debug("Loading settings..."); Settings.Load(); if (Settings.settingsStore.gameDifficulty == GameDifficulty.CUSTOM) { GameplaySettings.Reset(); GameplaySettings.Load(); } //Test compression if (Settings.settingsStore.compressionEnabled) { long testTime = Compression.TestSysIOCompression(); Compression.compressionEnabled = true; DarkLog.Debug("System.IO compression works: " + Compression.sysIOCompressionWorks + ", test time: " + testTime + " ms."); } //Set day for log change day = DateTime.Now.Day; //Load plugins DMPPluginHandler.LoadPlugins(); Console.Title = "DMPServer " + Common.PROGRAM_VERSION + ", protocol " + Common.PROTOCOL_VERSION; while (serverStarting || serverRestarting) { if (serverRestarting) { DarkLog.Debug("Reloading settings..."); Settings.Reset(); Settings.Load(); if (Settings.settingsStore.gameDifficulty == GameDifficulty.CUSTOM) { DarkLog.Debug("Reloading gameplay settings..."); GameplaySettings.Reset(); GameplaySettings.Load(); } } serverRestarting = false; DarkLog.Normal("Starting DMPServer " + Common.PROGRAM_VERSION + ", protocol " + Common.PROTOCOL_VERSION); if (Settings.settingsStore.gameDifficulty == GameDifficulty.CUSTOM) { //Generate the config file by accessing the object. DarkLog.Debug("Loading gameplay settings..."); GameplaySettings.Load(); } //Load universe DarkLog.Normal("Loading universe... "); CheckUniverse(); DarkLog.Normal("Starting " + Settings.settingsStore.warpMode + " server on port " + Settings.settingsStore.port + "... "); serverRunning = true; Thread commandThread = new Thread(new ThreadStart(CommandHandler.ThreadMain)); Thread clientThread = new Thread(new ThreadStart(ClientHandler.ThreadMain)); commandThread.Start(); clientThread.Start(); while (serverStarting) { Thread.Sleep(500); } StartHTTPServer(); DarkLog.Normal("Ready!"); DMPPluginHandler.FireOnServerStart(); while (serverRunning) { //Run a garbage collection every 30 seconds. if ((serverClock.ElapsedMilliseconds - lastGarbageCollect) > 30000) { lastGarbageCollect = serverClock.ElapsedMilliseconds; GC.Collect(); } //Run the screenshot expire function every 10 minutes if ((serverClock.ElapsedMilliseconds - lastScreenshotExpiredCheck) > 600000) { lastScreenshotExpiredCheck = serverClock.ElapsedMilliseconds; ScreenshotExpire.ExpireScreenshots(); } //Run the log expire function every 10 minutes if ((serverClock.ElapsedMilliseconds - lastLogExpiredCheck) > 600000) { lastLogExpiredCheck = serverClock.ElapsedMilliseconds; LogExpire.ExpireLogs(); } // Check if the day has changed, every minute if ((serverClock.ElapsedMilliseconds - lastDayCheck) > 60000) { lastDayCheck = serverClock.ElapsedMilliseconds; if (day != DateTime.Now.Day) { DarkLog.LogFilename = Path.Combine(DarkLog.LogFolder, "dmpserver " + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ".log"); DarkLog.WriteToLog("Continued from logfile " + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ".log"); day = DateTime.Now.Day; } } Thread.Sleep(500); } DMPPluginHandler.FireOnServerStop(); commandThread.Abort(); clientThread.Join(); } DarkLog.Normal("Goodbye!"); Environment.Exit(0); #if !DEBUG } catch (Exception e) { DarkLog.Fatal("Error in main server thread, Exception: " + e); throw; } #endif }
public static void Load() { FieldInfo[] settingFields = typeof(SettingsStore).GetFields(); if (!File.Exists(Path.Combine(serverPath, SETTINGS_FILE_NAME))) { Save(); } using (FileStream fs = new FileStream(settingsFile, FileMode.Open)) { using (StreamReader sr = new StreamReader(fs)) { string currentLine; string trimmedLine; string currentKey; string currentValue; while (true) { currentLine = sr.ReadLine(); if (currentLine == null) { break; } trimmedLine = currentLine.Trim(); if (!String.IsNullOrEmpty(trimmedLine)) { if (trimmedLine.Contains(",") && !trimmedLine.StartsWith("#")) { currentKey = trimmedLine.Substring(0, trimmedLine.IndexOf(",")); currentValue = trimmedLine.Substring(trimmedLine.IndexOf(",") + 1); foreach (FieldInfo settingField in settingFields) { if (settingField.Name.ToLower() == currentKey) { if (settingField.FieldType == typeof(string)) { settingField.SetValue(settingsStore, currentValue); } if (settingField.FieldType == typeof(int)) { int intValue = Int32.Parse(currentValue); settingField.SetValue(settingsStore, (int)intValue); } if (settingField.FieldType == typeof(bool)) { if (currentValue == "1") { settingField.SetValue(settingsStore, true); } else { settingField.SetValue(settingsStore, false); } } if (settingField.FieldType.IsEnum) { int intValue = Int32.Parse(currentValue); Array enumValues = settingField.FieldType.GetEnumValues(); if (intValue <= enumValues.Length) { settingField.SetValue(settingsStore, enumValues.GetValue(intValue)); } } DarkLog.Debug(settingField.Name + ": " + currentValue); } } } } } } } Save(); }
public static void SendToClient(ClientObject client, ServerMessage message, bool highPriority) { //Because we dodge the queue, we need to lock it up again... lock (client.sendLock) { if (message == null) { return; } //All messages have an 8 byte header client.bytesQueuedOut += 8; if (message.data != null) { //Count the payload if we have one. client.bytesQueuedOut += message.data.Length; } if (highPriority) { client.sendMessageQueueHigh.Enqueue(message); } else { client.sendMessageQueueLow.Enqueue(message); //If we need to optimize if (client.bytesQueuedOut > OPTIMIZE_QUEUE_LIMIT) { //And we haven't optimized in the last 5 seconds long currentTime = DateTime.UtcNow.Ticks; long optimizedBytes = 0; if ((currentTime - client.lastQueueOptimizeTime) > 50000000) { client.lastQueueOptimizeTime = currentTime; DarkLog.Debug("Optimizing " + client.playerName + " (" + client.bytesQueuedOut + " bytes queued)"); //Create a temporary filter list List <ServerMessage> oldClientMessagesToSend = new List <ServerMessage>(); List <ServerMessage> newClientMessagesToSend = new List <ServerMessage>(); //Steal all the messages from the queue and put them into a list ServerMessage stealMessage = null; while (client.sendMessageQueueLow.TryDequeue(out stealMessage)) { oldClientMessagesToSend.Add(stealMessage); } //Clear the client send queue List <string> seenProtovesselUpdates = new List <string>(); List <string> seenPositionUpdates = new List <string>(); //Iterate backwards over the list oldClientMessagesToSend.Reverse(); foreach (ServerMessage currentMessage in oldClientMessagesToSend) { if (currentMessage.type != ServerMessageType.VESSEL_PROTO && currentMessage.type != ServerMessageType.VESSEL_UPDATE) { //Message isn't proto or position, don't skip it. newClientMessagesToSend.Add(currentMessage); } else { //Message is proto or position if (currentMessage.type == ServerMessageType.VESSEL_PROTO) { using (MessageReader mr = new MessageReader(currentMessage.data)) { //Don't care about the send time, it's already the latest in the queue. mr.Read <double>(); string vesselID = mr.Read <string>(); if (!seenProtovesselUpdates.Contains(vesselID)) { seenProtovesselUpdates.Add(vesselID); newClientMessagesToSend.Add(currentMessage); } else { optimizedBytes += 8 + currentMessage.data.Length; } } } if (currentMessage.type == ServerMessageType.VESSEL_UPDATE) { using (MessageReader mr = new MessageReader(currentMessage.data)) { //Don't care about the send time, it's already the latest in the queue. mr.Read <double>(); string vesselID = mr.Read <string>(); if (!seenPositionUpdates.Contains(vesselID)) { seenPositionUpdates.Add(vesselID); newClientMessagesToSend.Add(currentMessage); } else { //8 byte message header plus payload optimizedBytes += 8 + currentMessage.data.Length; } } } } } //Flip it back to the right order newClientMessagesToSend.Reverse(); foreach (ServerMessage putBackMessage in newClientMessagesToSend) { client.sendMessageQueueLow.Enqueue(putBackMessage); } float optimizeTime = (DateTime.UtcNow.Ticks - currentTime) / 10000f; client.bytesQueuedOut -= optimizedBytes; DarkLog.Debug("Optimized " + optimizedBytes + " bytes in " + Math.Round(optimizeTime, 3) + " ms."); } } } client.sendEvent.Set(); } }
public void AdminCommand(string commandArgs) { string func = ""; string playerName = ""; func = commandArgs; if (commandArgs.Contains(" ")) { func = commandArgs.Substring(0, commandArgs.IndexOf(" ")); if (commandArgs.Substring(func.Length).Contains(" ")) { playerName = commandArgs.Substring(func.Length + 1); } } switch (func) { default: DarkLog.Normal("Undefined function. Usage: /admin [add|del] playername or /admin show"); break; case "add": if (File.Exists(Path.Combine(Server.universeDirectory, "Players", playerName + ".txt"))) { if (!serverAdmins.Contains(playerName)) { DarkLog.Debug("Added '" + playerName + "' to admin list."); serverAdmins.Add(playerName); //Notify all players an admin has been added Messages.ServerClient_AdminAddSend msg = new Messages.ServerClient_AdminAddSend(); msg.name = playerName; Broadcast(msg); } else { DarkLog.Normal("'" + playerName + "' is already an admin."); } } else { DarkLog.Normal("'" + playerName + "' does not exist."); } break; case "del": if (serverAdmins.Contains(playerName)) { DarkLog.Normal("Removed '" + playerName + "' from the admin list."); serverAdmins.Remove(playerName); //Notify all players an admin has been removed Messages.ServerClient_AdminRemoveSend msg = new Messages.ServerClient_AdminRemoveSend(); msg.name = playerName; Broadcast(msg); } else { DarkLog.Normal("'" + playerName + "' is not an admin."); } break; case "show": foreach (string player in serverAdmins) { DarkLog.Normal(player); } break; } }
private static void ReceiveCallback(IAsyncResult ar) { ClientObject client = (ClientObject)ar.AsyncState; int bytesRead = 0; try { bytesRead = client.connection.GetStream().EndRead(ar); } catch (Exception e) { HandleDisconnectException("ReceiveCallback", client, e); return; } if (bytesRead == 0) { DarkLog.Normal("Disconnected " + client.endpoint); DisconnectClient(client); return; } client.bytesReceived += bytesRead; client.receiveMessageBytesLeft -= bytesRead; if (client.receiveMessageBytesLeft == 0) { //We either have the header or the message data, let's do something if (!client.isReceivingMessage) { //We have the header using (MessageReader mr = new MessageReader(client.receiveMessage.data)) { int messageType = mr.Read <int>(); int messageLength = mr.Read <int>(); if (messageType < 0 || messageType > (Enum.GetNames(typeof(ClientMessageType)).Length - 1)) { //Malformed message, most likely from a non DMP-client. Messages.ConnectionEnd.SendConnectionEnd(client, "Invalid DMP message. Disconnected."); DarkLog.Normal("Invalid DMP message from " + client.endpoint); //Returning from ReceiveCallback will break the receive loop and stop processing any further messages. return; } client.receiveMessage.type = (ClientMessageType)messageType; if (messageLength == 0) { //Null message, handle it. client.receiveMessage.data = null; HandleMessage(client, client.receiveMessage); client.receiveMessage.type = 0; client.receiveMessage.data = new byte[8]; client.receiveMessageBytesLeft = client.receiveMessage.data.Length; } else { if (messageLength > 0 && messageLength < Common.MAX_MESSAGE_SIZE) { client.isReceivingMessage = true; client.receiveMessage.data = new byte[messageLength]; client.receiveMessageBytesLeft = client.receiveMessage.data.Length; } else { //Malformed message, most likely from a non DMP-client. Messages.ConnectionEnd.SendConnectionEnd(client, "Invalid DMP message. Disconnected."); DarkLog.Normal("Invalid DMP message from " + client.endpoint); //Returning from ReceiveCallback will break the receive loop and stop processing any further messages. return; } } } } else { //We have the message data to a non-null message, handle it client.isReceivingMessage = false; #if !DEBUG try { #endif HandleMessage(client, client.receiveMessage); #if !DEBUG } catch (Exception e) { HandleDisconnectException("ReceiveCallback", client, e); return; } #endif client.receiveMessage.type = 0; client.receiveMessage.data = new byte[8]; client.receiveMessageBytesLeft = client.receiveMessage.data.Length; } } if (client.connectionStatus == ConnectionStatus.CONNECTED) { client.lastReceiveTime = Server.serverClock.ElapsedMilliseconds; try { client.connection.GetStream().BeginRead(client.receiveMessage.data, client.receiveMessage.data.Length - client.receiveMessageBytesLeft, client.receiveMessageBytesLeft, new AsyncCallback(ReceiveCallback), client); } catch (Exception e) { HandleDisconnectException("ReceiveCallback", client, e); return; } } }
private static void SendNetworkMessage(ClientObject client, ServerMessage message) { //Write the send times down in SYNC_TIME_REPLY packets if (message.type == ServerMessageType.SYNC_TIME_REPLY) { try { using (MessageWriter mw = new MessageWriter()) { using (MessageReader mr = new MessageReader(message.data)) { client.bytesQueuedOut += 8; //Client send time mw.Write <long>(mr.Read <long>()); //Server receive time mw.Write <long>(mr.Read <long>()); //Server send time mw.Write <long>(DateTime.UtcNow.Ticks); message.data = mw.GetMessageBytes(); } } } catch (Exception e) { DarkLog.Debug("Error rewriting SYNC_TIME packet, Exception " + e); } } //Continue sending byte[] messageBytes = Common.PrependNetworkFrame((int)message.type, message.data); client.lastSendTime = Server.serverClock.ElapsedMilliseconds; client.bytesQueuedOut -= messageBytes.Length; client.bytesSent += messageBytes.Length; if (client.connectionStatus == ConnectionStatus.CONNECTED) { try { client.connection.GetStream().Write(messageBytes, 0, messageBytes.Length); } catch (Exception e) { HandleDisconnectException("Send Network Message", client, e); return; } } DMPPluginHandler.FireOnMessageSent(client, message); if (message.type == ServerMessageType.CONNECTION_END) { using (MessageReader mr = new MessageReader(message.data)) { string reason = mr.Read <string>(); DarkLog.Normal("Disconnecting client " + client.playerName + ", sent CONNECTION_END (" + reason + ") to endpoint " + client.endpoint); client.disconnectClient = true; DisconnectClient(client); } } if (message.type == ServerMessageType.HANDSHAKE_REPLY) { using (MessageReader mr = new MessageReader(message.data)) { int response = mr.Read <int>(); string reason = mr.Read <string>(); if (response != 0) { DarkLog.Normal("Disconnecting client " + client.playerName + ", sent HANDSHAKE_REPLY (" + reason + ") to endpoint " + client.endpoint); client.disconnectClient = true; DisconnectClient(client); } } } }
public static void ThreadMain() { try { clients = new List <ClientObject>().AsReadOnly(); Messages.WarpControl.Reset(); Messages.Chat.Reset(); Messages.ScreenshotLibrary.Reset(); SetupTCPServer(); while (Server.serverRunning) { //Process current clients foreach (ClientObject client in clients) { Messages.Heartbeat.CheckHeartBeat(client); } ModpackSystem.fetch.SendFilesToClients(); //Check timers NukeKSC.CheckTimer(); Dekessler.CheckTimer(); Messages.WarpControl.CheckTimer(); //Run plugin update DMPPluginHandler.FireOnUpdate(); Thread.Sleep(10); } } catch (Exception e) { DarkLog.Error("Fatal error thrown, exception: " + e); Server.ShutDown("Crashed!"); } try { long disconnectTime = DateTime.UtcNow.Ticks; bool sendingHighPriotityMessages = true; while (sendingHighPriotityMessages) { if ((DateTime.UtcNow.Ticks - disconnectTime) > 50000000) { DarkLog.Debug("Shutting down with " + Server.playerCount + " players, " + clients.Count + " connected clients"); break; } sendingHighPriotityMessages = false; foreach (ClientObject client in clients) { if (client.authenticated && (client.sendMessageQueueHigh.Count > 0)) { sendingHighPriotityMessages = true; } } Thread.Sleep(10); } ShutdownTCPServer(); } catch (Exception e) { DarkLog.Fatal("Fatal error thrown during shutdown, exception: " + e); throw; } }
private static void Say(string sayText) { DarkLog.Normal("Broadcasting " + sayText); ClientHandler.SendChatMessageToAll(sayText); }
public static void ThreadMain() { try { //Register commands CommandHandler.RegisterCommand("help", CommandHandler.DisplayHelp, "Displays this help"); CommandHandler.RegisterCommand("say", CommandHandler.Say, "Broadcasts a message to clients"); CommandHandler.RegisterCommand("dekessler", Dekessler.RunDekessler, "Clears out debris from the server"); CommandHandler.RegisterCommand("nukeksc", NukeKSC.RunNukeKSC, "Clears ALL vessels from KSC and the Runway"); CommandHandler.RegisterCommand("listclients", ListClients, "Lists connected clients"); CommandHandler.RegisterCommand("countclients", CountClients, "Counts connected clients"); CommandHandler.RegisterCommand("connectionstats", ConnectionStats, "Displays network traffic usage"); CommandHandler.RegisterCommand("editgroup", Groups.fetch.EditGroupCommand, "Sets the group to edit"); CommandHandler.RegisterCommand("addplayer", Groups.fetch.AddPlayerToGroupCommand, "Adds player to group, first player becomes admin"); CommandHandler.RegisterCommand("removeplayer", Groups.fetch.RemovePlayerFromGroupCommand, "Removes player from group"); CommandHandler.RegisterCommand("addadmin", Groups.fetch.AddPlayerAdminCommand, "Adds admin to group"); CommandHandler.RegisterCommand("removeadmin", Groups.fetch.RemovePlayerAdminCommand, "Removes admin from group"); CommandHandler.RegisterCommand("showgroups", Groups.fetch.ShowGroupsCommand, "Shows group database"); CommandHandler.RegisterCommand("editvessel", Permissions.fetch.EditVesselCommand, "Edits vessel permissions, takes same ID from Universe/Vessels/"); CommandHandler.RegisterCommand("vesselowner", Permissions.fetch.SetVesselOwnerCommand, "Sets a vessel owner"); CommandHandler.RegisterCommand("vesselgroup", Permissions.fetch.SetVesselGroupCommand, "Sets a vessels group"); CommandHandler.RegisterCommand("vesselprotection", Permissions.fetch.SetVesselProtectionCommand, "Sets vessel protection level. Valid levels: public, group, private."); CommandHandler.RegisterCommand("showvessels", Permissions.fetch.ShowVesselsCommand, "Shows vessel protection database"); //Main loop while (Server.serverRunning) { string input = ""; try { input = Console.ReadLine(); if (input == null) { DarkLog.Debug("Terminal may be not attached or broken, Exiting out of command handler"); return; } } catch { if (Server.serverRunning) { DarkLog.Debug("Ignored mono Console.ReadLine() bug"); } Thread.Sleep(500); } DarkLog.Normal("Command input: " + input); if (input.StartsWith("/", StringComparison.Ordinal)) { HandleServerInput(input.Substring(1)); } else { if (input != "") { commands["say"].func(input); } } } } catch (Exception e) { if (Server.serverRunning) { DarkLog.Fatal("Error in command handler thread, Exception: " + e); throw; } } }
internal static void HandleMessage(ClientObject client, ClientMessage message) { //Prevent plugins from dodging SPLIT_MESSAGE. If they are modified, every split message will be broken. if (message.type != ClientMessageType.SPLIT_MESSAGE) { DMPPluginHandler.FireOnMessageReceived(client, message); if (message.handled) { //a plugin has handled this message and requested suppression of the default DMP behavior return; } } //Clients can only send HEARTBEATS, HANDSHAKE_REQUEST or CONNECTION_END's until they are authenticated. if (!client.authenticated && !(message.type == ClientMessageType.HEARTBEAT || message.type == ClientMessageType.HANDSHAKE_RESPONSE || message.type == ClientMessageType.CONNECTION_END)) { Messages.ConnectionEnd.SendConnectionEnd(client, "You must authenticate before attempting to send a " + message.type.ToString() + " message"); return; } #if !DEBUG try { #endif switch (message.type) { case ClientMessageType.HEARTBEAT: //Don't do anything for heartbeats, they just keep the connection alive break; case ClientMessageType.HANDSHAKE_RESPONSE: Messages.Handshake.HandleHandshakeResponse(client, message.data); break; case ClientMessageType.CHAT_MESSAGE: Messages.Chat.HandleChatMessage(client, message.data); break; case ClientMessageType.PLAYER_STATUS: Messages.PlayerStatus.HandlePlayerStatus(client, message.data); break; case ClientMessageType.PLAYER_COLOR: Messages.PlayerColor.HandlePlayerColor(client, message.data); break; case ClientMessageType.GROUP: Messages.GroupMessage.HandleMessage(client, message.data); break; case ClientMessageType.SCENARIO_DATA: Messages.ScenarioData.HandleScenarioModuleData(client, message.data); break; case ClientMessageType.SYNC_TIME_REQUEST: Messages.SyncTimeRequest.HandleSyncTimeRequest(client, message.data); break; case ClientMessageType.KERBALS_REQUEST: Messages.KerbalsRequest.HandleKerbalsRequest(client); break; case ClientMessageType.KERBAL_PROTO: Messages.KerbalProto.HandleKerbalProto(client, message.data); break; case ClientMessageType.VESSELS_REQUEST: Messages.VesselRequest.HandleVesselsRequest(client, message.data); break; case ClientMessageType.VESSEL_PROTO: Messages.VesselProto.HandleVesselProto(client, message.data); break; case ClientMessageType.VESSEL_UPDATE: Messages.VesselUpdate.HandleVesselUpdate(client, message.data); break; case ClientMessageType.VESSEL_REMOVE: Messages.VesselRemove.HandleVesselRemoval(client, message.data); break; case ClientMessageType.PERMISSION: Messages.PermissionMessage.HandleMessage(client, message.data); break; case ClientMessageType.CRAFT_LIBRARY: Messages.CraftLibrary.HandleCraftLibrary(client, message.data); break; case ClientMessageType.SCREENSHOT_LIBRARY: Messages.ScreenshotLibrary.HandleScreenshotLibrary(client, message.data); break; case ClientMessageType.FLAG_SYNC: Messages.FlagSync.HandleFlagSync(client, message.data); break; case ClientMessageType.PING_REQUEST: Messages.PingRequest.HandlePingRequest(client, message.data); break; case ClientMessageType.MOTD_REQUEST: Messages.MotdRequest.HandleMotdRequest(client); break; case ClientMessageType.WARP_CONTROL: Messages.WarpControl.HandleWarpControl(client, message.data); break; case ClientMessageType.LOCK_SYSTEM: Messages.LockSystem.HandleLockSystemMessage(client, message.data); break; case ClientMessageType.MOD_DATA: Messages.ModData.HandleModDataMessage(client, message.data); break; case ClientMessageType.KERBAL_REMOVE: Messages.VesselRemove.HandleKerbalRemoval(client, message.data); break; case ClientMessageType.SPLIT_MESSAGE: Messages.SplitMessage.HandleSplitMessage(client, message.data); break; case ClientMessageType.CONNECTION_END: Messages.ConnectionEnd.HandleConnectionEnd(client, message.data); break; case ClientMessageType.MODPACK_DATA: Messages.Modpack.HandleModpackMessage(client, message.data); break; default: DarkLog.Debug("Unhandled message type " + message.type); Messages.ConnectionEnd.SendConnectionEnd(client, "Unhandled message type " + message.type); #if DEBUG throw new NotImplementedException("Message type not implemented"); #else break; #endif } #if !DEBUG } catch (Exception e) { DarkLog.Debug("Error handling " + message.type + " from " + client.playerName + ", exception: " + e); Messages.ConnectionEnd.SendConnectionEnd(client, "Server failed to process " + message.type + " message"); } #endif }
public static void ThreadMain() { try { //Register commands CommandHandler.RegisterCommand("help", CommandHandler.DisplayHelp, "Displays this help"); CommandHandler.RegisterCommand("say", CommandHandler.Say, "Broadcasts a message to clients"); CommandHandler.RegisterCommand("dekessler", Dekessler.RunDekessler, "Clears out debris from the server"); CommandHandler.RegisterCommand("nukeksc", NukeKSC.RunNukeKSC, "Clears ALL vessels from KSC and the Runway"); CommandHandler.RegisterCommand("listclients", ListClients, "Clears out debris from the server"); CommandHandler.RegisterCommand("countclients", CountClients, "Clears out debris from the server"); //Main loop while (Server.serverRunning) { string input = ""; try { input = Console.ReadLine(); } catch { if (Server.serverRunning) { DarkLog.Debug("Ignored mono Console.ReadLine() bug"); } Thread.Sleep(500); } DarkLog.Normal("Command input: " + input); if (input.StartsWith("/")) { string commandPart = input.Substring(1); string argumentPart = ""; if (commandPart.Contains(" ")) { if (commandPart.Length > commandPart.IndexOf(' ') + 1) { argumentPart = commandPart.Substring(commandPart.IndexOf(' ') + 1); } commandPart = commandPart.Substring(0, commandPart.IndexOf(' ')); } if (commandPart.Length > 0) { if (commands.ContainsKey(commandPart)) { try { commands[commandPart].func(argumentPart); } catch (Exception e) { DarkLog.Error("Error handling command " + commandPart + ", Exception " + e); } } else { DarkLog.Normal("Unknown command: " + commandPart); } } } else { if (input != "") { commands["say"].func(input); } } } } catch (Exception e) { if (Server.serverRunning) { DarkLog.Fatal("Error in command handler thread, Exception: " + e); throw; } } }
private static void Say(string sayText) { DarkLog.Normal("Broadcasting " + sayText); Messages.Chat.SendChatMessageToAll(sayText); }
private static void CountClients(string commandArgs) { DarkLog.Normal("Online players: " + Server.playerCount); }
public static void LoadPlugins() { string pluginDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins"); if (!Directory.Exists(pluginDirectory)) { Directory.CreateDirectory(pluginDirectory); } DarkLog.Debug("Loading plugins!"); //Load all the assemblies just in case they depend on each other during instantation List <Assembly> loadedAssemblies = new List <Assembly>(); string[] pluginFiles = Directory.GetFiles(pluginDirectory, "*", SearchOption.AllDirectories); foreach (string pluginFile in pluginFiles) { if (Path.GetExtension(pluginFile).ToLower() == ".dll") { try { //UnsafeLoadFrom will not throw an exception if the dll is marked as unsafe, such as downloaded from internet in Windows //See http://stackoverflow.com/a/15238782 Assembly loadedAssembly = Assembly.UnsafeLoadFrom(pluginFile); loadedAssemblies.Add(loadedAssembly); DarkLog.Debug("Loaded " + pluginFile); } catch (NotSupportedException) { //This should only occur if using Assembly.LoadFrom() above instead of Assembly.UnsafeLoadFrom() DarkLog.Debug("Can't load dll, perhaps it is blocked: " + pluginFile); } catch { DarkLog.Debug("Error loading " + pluginFile); } } } //Iterate through the assemblies looking for classes that have the IDMPPlugin interface Type dmpInterfaceType = typeof(IDMPPlugin); foreach (Assembly loadedAssembly in loadedAssemblies) { Type[] loadedTypes = loadedAssembly.GetExportedTypes(); foreach (Type loadedType in loadedTypes) { Type[] typeInterfaces = loadedType.GetInterfaces(); bool containsDMPInterface = false; foreach (Type typeInterface in typeInterfaces) { if (typeInterface == dmpInterfaceType) { containsDMPInterface = true; } } if (containsDMPInterface) { DarkLog.Debug("Loading plugin: " + loadedType.FullName); try { IDMPPlugin pluginInstance = ActivatePluginType(loadedType); if (pluginInstance != null) { DarkLog.Debug("Loaded plugin: " + loadedType.FullName); loadedPlugins.Add(pluginInstance); } } catch (Exception ex) { DarkLog.Error("Error loading plugin " + loadedType.FullName + "(" + loadedType.Assembly.FullName + ") Exception: " + ex.ToString()); } } } } DarkLog.Debug("Done!"); }