public static void SendAllPlayerColors(ClientObject client) { Dictionary <string, float[]> sendColors = new Dictionary <string, float[]>(); foreach (ClientObject otherClient in ClientHandler.GetClients()) { if (otherClient.authenticated && otherClient.playerColor != null) { if (otherClient != client) { sendColors[otherClient.playerName] = otherClient.playerColor; } } } ServerMessage newMessage = new ServerMessage(); newMessage.type = ServerMessageType.PLAYER_COLOR; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)PlayerColorMessageType.LIST); mw.Write <int>(sendColors.Count); foreach (KeyValuePair <string, float[]> kvp in sendColors) { mw.Write <string>(kvp.Key); mw.Write <float[]>(kvp.Value); } newMessage.data = mw.GetMessageBytes(); } ClientHandler.SendToClient(client, newMessage, true); }
private static void HandleReportRate(ClientObject client, float newSubspaceRate) { int reportedSubspace = client.subspace; client.subspaceRate = newSubspaceRate; //Get minimum rate foreach (ClientObject otherClient in ClientHandler.GetClients()) { if (otherClient.authenticated && otherClient.subspace == reportedSubspace) { if (otherClient.subspaceRate < newSubspaceRate) { newSubspaceRate = otherClient.subspaceRate; } } } //Bound the rate if (newSubspaceRate < 0.3f) { newSubspaceRate = 0.3f; } if (newSubspaceRate > 1f) { newSubspaceRate = 1f; } //Relock the subspace if the rate is more than 3% out of the average if (Math.Abs(subspaces[reportedSubspace].subspaceSpeed - newSubspaceRate) > 0.03f) { //Update the subspace's epoch to now, so we have a new time to lock from. UpdateSubspace(reportedSubspace); //Change the subspace speed and report it to the clients subspaces[reportedSubspace].subspaceSpeed = newSubspaceRate; ServerMessage relockMessage = new ServerMessage(); relockMessage.type = ServerMessageType.WARP_CONTROL; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)WarpMessageType.RELOCK_SUBSPACE); mw.Write <int>(reportedSubspace); mw.Write <long>(subspaces[reportedSubspace].serverClock); mw.Write <double>(subspaces[reportedSubspace].planetTime); mw.Write <float>(subspaces[reportedSubspace].subspaceSpeed); relockMessage.data = mw.GetMessageBytes(); } ClientHandler.SendToAll(null, relockMessage, true); //Save to disk SaveLatestSubspace(); } //Tell other players about the reported rate ServerMessage reportMessage = new ServerMessage(); reportMessage.type = ServerMessageType.WARP_CONTROL; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)WarpMessageType.REPORT_RATE); mw.Write <string>(client.playerName); mw.Write <float>(client.subspaceRate); reportMessage.data = mw.GetMessageBytes(); } ClientHandler.SendToAll(client, reportMessage, true); }
public static void SendSetSubspaceToAll(int subspace) { DarkLog.Debug("Sending everyone to subspace " + subspace); ServerMessage newMessage = new ServerMessage(); newMessage.type = ServerMessageType.SET_SUBSPACE; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>(subspace); newMessage.data = mw.GetMessageBytes(); } ClientHandler.SendToAll(null, newMessage, true); //Tell everyone else they changed foreach (ClientObject otherClient in ClientHandler.GetClients()) { if (otherClient.authenticated) { ServerMessage changeMessage = new ServerMessage(); changeMessage.type = ServerMessageType.WARP_CONTROL; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)WarpMessageType.CHANGE_SUBSPACE); mw.Write <string>(otherClient.playerName); mw.Write <int>(subspace); changeMessage.data = mw.GetMessageBytes(); } ClientHandler.SendToAll(otherClient, changeMessage, true); } } }
public static void SendSetSubspace(ClientObject client) { if (!Settings.settingsStore.keepTickingWhileOffline && ClientHandler.GetClients().Length == 1) { DarkLog.Debug("Reverting server time to last player connection"); long currentTime = DateTime.UtcNow.Ticks; foreach (KeyValuePair <int, Subspace> subspace in subspaces) { subspace.Value.serverClock = currentTime; subspace.Value.subspaceSpeed = 1f; } SaveLatestSubspace(); } int targetSubspace = -1; if (Settings.settingsStore.sendPlayerToLatestSubspace || !offlinePlayerSubspaces.ContainsKey(client.playerName)) { targetSubspace = GetLatestSubspace(); } else { DarkLog.Debug("Sending " + client.playerName + " to the previous subspace " + targetSubspace); targetSubspace = offlinePlayerSubspaces[client.playerName]; } SendSetSubspace(client, targetSubspace); }
public void TestGetClientsReturnTwoClients() { ClientHandler _sut = new ClientHandler(); int actual = _sut.GetClients(true).Count; Assert.AreEqual(2, actual); }
public void TestGetClientsReturnListOfClientM() { ClientHandler _sut = new ClientHandler(); Type expected = typeof(ClientM); Type actual = _sut.GetClients(true)[0].GetType(); Assert.AreEqual(expected, actual); }
public static void SendConsoleMessageToAdmins(string message) { foreach (ClientObject client in ClientHandler.GetClients()) { if (client.authenticated && DarkMultiPlayerServer.AdminSystem.fetch.IsAdmin(client.playerName)) { SendConsoleMessageToClient(client, message); } } }
public static void SendConnectionEndToAll(string reason) { foreach (ClientObject client in ClientHandler.GetClients()) { if (client.authenticated) { SendConnectionEnd(client, reason); } } }
public static void SendSetSubspaceToAll(int subspace) { DarkLog.Debug("Sending everyone to subspace " + subspace); foreach (ClientObject otherClient in ClientHandler.GetClients()) { if (otherClient.authenticated) { SendSetSubspace(otherClient, subspace); } } }
private static void HandleLowestRateChange(ClientObject client) { string newWarpMaster = null; PlayerWarpRate lowestRate = null; if (warpMaster != null && warpList.ContainsKey(warpMaster)) { newWarpMaster = warpMaster; lowestRate = warpList[warpMaster]; } else { newWarpMaster = client.playerName; lowestRate = warpList[client.playerName]; } foreach (ClientObject testClient in ClientHandler.GetClients()) { if (!warpList.ContainsKey(testClient.playerName)) { newWarpMaster = null; break; } PlayerWarpRate pwr = warpList[testClient.playerName]; if (pwr.rateIndex == 0) { newWarpMaster = null; break; } if (pwr.isPhysWarp != lowestRate.isPhysWarp) { newWarpMaster = null; break; } if (pwr.rateIndex < lowestRate.rateIndex) { newWarpMaster = testClient.playerName; lowestRate = pwr; } } if (newWarpMaster != warpMaster) { //No expire time SendSetController(newWarpMaster, long.MinValue); warpMaster = newWarpMaster; } }
public static void SendAllReportedSkewRates(ClientObject client) { foreach (ClientObject otherClient in ClientHandler.GetClients()) { if (otherClient.authenticated) { if (otherClient != client) { ServerMessage newMessage = new ServerMessage(); newMessage.type = ServerMessageType.WARP_CONTROL; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)WarpMessageType.REPORT_RATE); mw.Write <string>(otherClient.playerName); mw.Write <float>(otherClient.subspaceRate); newMessage.data = mw.GetMessageBytes(); } ClientHandler.SendToClient(client, newMessage, true); } } } }
public static void SendAllPlayerStatus(ClientObject client) { foreach (ClientObject otherClient in ClientHandler.GetClients()) { if (otherClient.authenticated) { if (otherClient != client) { ServerMessage newMessage = new ServerMessage(); newMessage.type = ServerMessageType.PLAYER_STATUS; using (MessageWriter mw = new MessageWriter()) { mw.Write <string>(otherClient.playerName); mw.Write <string>(otherClient.playerStatus.vesselText); mw.Write <string>(otherClient.playerStatus.statusText); newMessage.data = mw.GetMessageBytes(); } ClientHandler.SendToClient(client, newMessage, true); } } } }
public static void SendAllSubspaces(ClientObject client) { //Send all the locks. foreach (KeyValuePair <int, Subspace> subspace in subspaces) { ServerMessage newMessage = new ServerMessage(); newMessage.type = ServerMessageType.WARP_CONTROL; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)WarpMessageType.NEW_SUBSPACE); mw.Write <string>(""); mw.Write <int>(subspace.Key); mw.Write <long>(subspace.Value.serverClock); mw.Write <double>(subspace.Value.planetTime); mw.Write <float>(subspace.Value.subspaceSpeed); newMessage.data = mw.GetMessageBytes(); } ClientHandler.SendToClient(client, newMessage, true); } //Tell the player "when" everyone is. foreach (ClientObject otherClient in ClientHandler.GetClients()) { if (otherClient.authenticated && (otherClient.playerName != client.playerName)) { ServerMessage newMessage = new ServerMessage(); newMessage.type = ServerMessageType.WARP_CONTROL; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)WarpMessageType.CHANGE_SUBSPACE); mw.Write <string>(otherClient.playerName); mw.Write <int>(otherClient.subspace); newMessage.data = mw.GetMessageBytes(); } ClientHandler.SendToClient(client, newMessage, true); } } }
public static void SendSetSubspace(ClientObject client) { if (!Settings.settingsStore.keepTickingWhileOffline && ClientHandler.GetClients().Length == 1) { DarkLog.Debug("Reverting server time to last player connection"); long currentTime = DateTime.UtcNow.Ticks; foreach (KeyValuePair <int, Subspace> subspace in subspaces) { subspace.Value.serverClock = currentTime; subspace.Value.subspaceSpeed = 1f; SaveLatestSubspace(); } } int targetSubspace = -1; if (Settings.settingsStore.sendPlayerToLatestSubspace || !playerSubspace.ContainsKey(client.playerName)) { DarkLog.Debug("Sending " + client.playerName + " to the latest subspace " + targetSubspace); targetSubspace = GetLatestSubspace(); } else { DarkLog.Debug("Sending " + client.playerName + " to the previous subspace " + targetSubspace); targetSubspace = playerSubspace[client.playerName]; } client.subspace = targetSubspace; ServerMessage newMessage = new ServerMessage(); newMessage.type = ServerMessageType.SET_SUBSPACE; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>(targetSubspace); newMessage.data = mw.GetMessageBytes(); } ClientHandler.SendToClient(client, newMessage, true); }
public static void HandleWarpControl(ClientObject client, byte[] messageData) { ServerMessage newMessage = new ServerMessage(); newMessage.type = ServerMessageType.WARP_CONTROL; newMessage.data = messageData; using (MessageReader mr = new MessageReader(messageData)) { WarpMessageType warpType = (WarpMessageType)mr.Read <int>(); string fromPlayer = mr.Read <string>(); if (fromPlayer == client.playerName) { if (warpType == WarpMessageType.NEW_SUBSPACE) { int newSubspaceID = mr.Read <int>(); if (subspaces.ContainsKey(newSubspaceID)) { DarkLog.Debug("Kicked for trying to create an existing subspace"); Messages.ConnectionEnd.SendConnectionEnd(client, "Kicked for trying to create an existing subspace"); return; } else { Subspace newSubspace = new Subspace(); newSubspace.serverClock = mr.Read <long>(); newSubspace.planetTime = mr.Read <double>(); newSubspace.subspaceSpeed = mr.Read <float>(); subspaces.Add(newSubspaceID, newSubspace); client.subspace = newSubspaceID; SaveLatestSubspace(); } } if (warpType == WarpMessageType.CHANGE_SUBSPACE) { client.subspace = mr.Read <int>(); } if (warpType == WarpMessageType.REPORT_RATE) { int reportedSubspace = mr.Read <int>(); if (client.subspace != reportedSubspace) { DarkLog.Debug("Warning, setting client " + client.playerName + " to subspace " + client.subspace); client.subspace = reportedSubspace; } float newSubspaceRate = mr.Read <float>(); client.subspaceRate = newSubspaceRate; foreach (ClientObject otherClient in ClientHandler.GetClients()) { if (otherClient.authenticated && otherClient.subspace == reportedSubspace) { if (newSubspaceRate > otherClient.subspaceRate) { newSubspaceRate = otherClient.subspaceRate; } } } if (newSubspaceRate < 0.3f) { newSubspaceRate = 0.3f; } if (newSubspaceRate > 1f) { newSubspaceRate = 1f; } //Relock the subspace if the rate is more than 3% out of the average if (Math.Abs(subspaces[reportedSubspace].subspaceSpeed - newSubspaceRate) > 0.03f) { UpdateSubspace(reportedSubspace); subspaces[reportedSubspace].subspaceSpeed = newSubspaceRate; ServerMessage relockMessage = new ServerMessage(); relockMessage.type = ServerMessageType.WARP_CONTROL; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)WarpMessageType.RELOCK_SUBSPACE); mw.Write <string>(Settings.settingsStore.consoleIdentifier); mw.Write <int>(reportedSubspace); mw.Write <long>(subspaces[reportedSubspace].serverClock); mw.Write <double>(subspaces[reportedSubspace].planetTime); mw.Write <float>(subspaces[reportedSubspace].subspaceSpeed); relockMessage.data = mw.GetMessageBytes(); } SaveLatestSubspace(); //DarkLog.Debug("Subspace " + client.subspace + " locked to " + newSubspaceRate + "x speed."); ClientHandler.SendToClient(client, relockMessage, true); ClientHandler.SendToAll(client, relockMessage, true); } } } else { DarkLog.Debug(client.playerName + " tried to send an update for " + fromPlayer + ", kicking."); Messages.ConnectionEnd.SendConnectionEnd(client, "Kicked for sending an update for another player"); return; } } ClientHandler.SendToAll(client, newMessage, true); }
public static void HandleHandshakeResponse(ClientObject client, byte[] messageData) { int protocolVersion; string playerName = ""; string playerPublicKey; byte[] playerChallangeSignature; string clientVersion = ""; string reason = ""; Regex regex = new Regex(@"[\""<>|$]"); // Regex to detect quotation marks, and other illegal characters //0 - Success HandshakeReply handshakeReponse = HandshakeReply.HANDSHOOK_SUCCESSFULLY; try { using (MessageReader mr = new MessageReader(messageData)) { protocolVersion = mr.Read <int>(); playerName = mr.Read <string>(); playerPublicKey = mr.Read <string>(); playerChallangeSignature = mr.Read <byte[]>(); clientVersion = mr.Read <string>(); try { client.compressionEnabled = mr.Read <bool>(); } catch { //This is safe to ignore. We want to tell people about version mismatches still. client.compressionEnabled = false; } } } catch (Exception e) { DarkLog.Debug("Error in HANDSHAKE_REQUEST from " + client.playerName + ": " + e); SendHandshakeReply(client, HandshakeReply.MALFORMED_HANDSHAKE, "Malformed handshake"); return; } if (regex.IsMatch(playerName)) { // Invalid username handshakeReponse = HandshakeReply.INVALID_PLAYERNAME; reason = "Invalid username"; } if (playerName.Contains("/") || playerName.Contains(@"\") || playerName.Contains("\n") || playerName.Contains("\r")) { handshakeReponse = HandshakeReply.INVALID_PLAYERNAME; reason = "Invalid username"; } if (protocolVersion != Common.PROTOCOL_VERSION) { //Protocol mismatch handshakeReponse = HandshakeReply.PROTOCOL_MISMATCH; reason = "Protocol mismatch"; } if (handshakeReponse == HandshakeReply.HANDSHOOK_SUCCESSFULLY) { //Check client isn't already connected ClientObject testClient = ClientHandler.GetClientByName(playerName); if (testClient != null) { Messages.Heartbeat.Send(testClient); Thread.Sleep(1000); } if (ClientHandler.ClientConnected(testClient)) { handshakeReponse = HandshakeReply.ALREADY_CONNECTED; reason = "Client already connected"; } } if (handshakeReponse == HandshakeReply.HANDSHOOK_SUCCESSFULLY) { bool reserveKick = false; //Check the client isn't using a reserved name if (playerName == "Initial") { reserveKick = true; } if (playerName == Settings.settingsStore.consoleIdentifier) { reserveKick = true; } if (reserveKick) { handshakeReponse = HandshakeReply.RESERVED_NAME; reason = "Kicked for using a reserved name"; } } if (handshakeReponse == HandshakeReply.HANDSHOOK_SUCCESSFULLY) { //Check the client matches any database entry string storedPlayerFile = Path.Combine(Server.universeDirectory, "Players", playerName + ".txt"); string storedPlayerPublicKey = ""; if (File.Exists(storedPlayerFile)) { storedPlayerPublicKey = File.ReadAllText(storedPlayerFile); if (playerPublicKey != storedPlayerPublicKey) { handshakeReponse = HandshakeReply.INVALID_KEY; reason = "Invalid key for user"; } else { using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024)) { rsa.PersistKeyInCsp = false; rsa.FromXmlString(playerPublicKey); bool result = rsa.VerifyData(client.challange, CryptoConfig.CreateFromName("SHA256"), playerChallangeSignature); if (!result) { handshakeReponse = HandshakeReply.INVALID_KEY; reason = "Public/private key mismatch"; } } } } else { try { File.WriteAllText(storedPlayerFile, playerPublicKey); DarkLog.Debug("Client " + playerName + " registered!"); } catch { handshakeReponse = HandshakeReply.INVALID_PLAYERNAME; reason = "Invalid username"; } } } client.playerName = playerName; client.publicKey = playerPublicKey; client.clientVersion = clientVersion; if (handshakeReponse == HandshakeReply.HANDSHOOK_SUCCESSFULLY) { if (BanSystem.fetch.IsPlayerNameBanned(client.playerName) || BanSystem.fetch.IsIPBanned(client.ipAddress) || BanSystem.fetch.IsPublicKeyBanned(client.publicKey)) { handshakeReponse = HandshakeReply.PLAYER_BANNED; reason = "You were banned from the server!"; } } if (handshakeReponse == HandshakeReply.HANDSHOOK_SUCCESSFULLY) { if (ClientHandler.GetActiveClientCount() >= Settings.settingsStore.maxPlayers) { handshakeReponse = HandshakeReply.SERVER_FULL; reason = "Server is full"; } } if (handshakeReponse == HandshakeReply.HANDSHOOK_SUCCESSFULLY) { if (Settings.settingsStore.whitelisted && !WhitelistSystem.fetch.IsWhitelisted(client.playerName)) { handshakeReponse = HandshakeReply.NOT_WHITELISTED; reason = "You are not on the whitelist"; } } if (handshakeReponse == HandshakeReply.HANDSHOOK_SUCCESSFULLY) { client.authenticated = true; string devClientVersion = ""; DMPPluginHandler.FireOnClientAuthenticated(client); if (client.clientVersion.Length == 40) { devClientVersion = client.clientVersion.Substring(0, 7); } else { devClientVersion = client.clientVersion; } DarkLog.Normal("Client " + playerName + " handshook successfully, version: " + devClientVersion); if (!Directory.Exists(Path.Combine(Server.universeDirectory, "Scenarios", client.playerName))) { Directory.CreateDirectory(Path.Combine(Server.universeDirectory, "Scenarios", client.playerName)); foreach (string file in Directory.GetFiles(Path.Combine(Server.universeDirectory, "Scenarios", "Initial"))) { File.Copy(file, Path.Combine(Server.universeDirectory, "Scenarios", playerName, Path.GetFileName(file))); } } SendHandshakeReply(client, handshakeReponse, "success"); Server.playerCount = ClientHandler.GetActiveClientCount(); Server.players = ClientHandler.GetActivePlayerNames(); DarkLog.Debug("Online players is now: " + Server.playerCount + ", connected: " + ClientHandler.GetClients().Length); } else { DarkLog.Normal("Client " + playerName + " failed to handshake: " + reason); SendHandshakeReply(client, handshakeReponse, reason); } }