public static void HandleChatMessage(ClientObject client, byte[] messageData) { ServerMessage newMessage = new ServerMessage(); newMessage.type = ServerMessageType.CHAT_MESSAGE; newMessage.data = messageData; using (MessageReader mr = new MessageReader(messageData)) { ChatMessageType messageType = (ChatMessageType)mr.Read <int>(); string fromPlayer = mr.Read <string>(); if (fromPlayer != client.playerName) { Messages.ConnectionEnd.SendConnectionEnd(client, "Kicked for sending a chat message for another player"); return; } switch (messageType) { case ChatMessageType.JOIN: { string joinChannel = mr.Read <string>(); if (!playerChatChannels.ContainsKey(fromPlayer)) { playerChatChannels.Add(fromPlayer, new List <string>()); } if (!playerChatChannels[fromPlayer].Contains(joinChannel)) { playerChatChannels[fromPlayer].Add(joinChannel); } DarkLog.Debug(fromPlayer + " joined channel: " + joinChannel); } ClientHandler.SendToAll(client, newMessage, true); break; case ChatMessageType.LEAVE: { string leaveChannel = mr.Read <string>(); if (playerChatChannels.ContainsKey(fromPlayer)) { if (playerChatChannels[fromPlayer].Contains(leaveChannel)) { playerChatChannels[fromPlayer].Remove(leaveChannel); } if (playerChatChannels[fromPlayer].Count == 0) { playerChatChannels.Remove(fromPlayer); } } DarkLog.Debug(fromPlayer + " left channel: " + leaveChannel); } ClientHandler.SendToAll(client, newMessage, true); break; case ChatMessageType.CHANNEL_MESSAGE: { string channel = mr.Read <string>(); string message = mr.Read <string>(); if (channel != "") { foreach (KeyValuePair <string, List <string> > playerEntry in playerChatChannels) { if (playerEntry.Value.Contains(channel)) { ClientObject findClient = ClientHandler.GetClientByName(playerEntry.Key); if (findClient != null) { ClientHandler.SendToClient(findClient, newMessage, true); } } } DarkLog.ChatMessage(fromPlayer + " -> #" + channel + ": " + message); } else { ClientHandler.SendToClient(client, newMessage, true); ClientHandler.SendToAll(client, newMessage, true); DarkLog.ChatMessage(fromPlayer + " -> #Global: " + message); } } break; case ChatMessageType.PRIVATE_MESSAGE: { string toPlayer = mr.Read <string>(); string message = mr.Read <string>(); if (toPlayer != Settings.settingsStore.consoleIdentifier) { ClientObject findClient = ClientHandler.GetClientByName(toPlayer); if (findClient != null) { ClientHandler.SendToClient(client, newMessage, true); ClientHandler.SendToClient(findClient, newMessage, true); DarkLog.ChatMessage(fromPlayer + " -> @" + toPlayer + ": " + message); } { DarkLog.ChatMessage(fromPlayer + " -X-> @" + toPlayer + ": " + message); } } else { ClientHandler.SendToClient(client, newMessage, true); DarkLog.ChatMessage(fromPlayer + " -> @" + toPlayer + ": " + message); } } break; case ChatMessageType.CONSOLE_MESSAGE: { string message = mr.Read <string>(); if (client.authenticated && DarkMultiPlayerServer.AdminSystem.fetch.IsAdmin(client.playerName)) { CommandHandler.HandleServerInput(message); } else { Messages.ConnectionEnd.SendConnectionEnd(client, "Kicked for sending a console command as a non-admin player."); } } break; } } }
public static void HandleScreenshotLibrary(ClientObject client, byte[] messageData) { string screenshotDirectory = Path.Combine(Server.universeDirectory, "Screenshots"); if (Settings.settingsStore.screenshotDirectory != "") { if (Directory.Exists(Settings.settingsStore.screenshotDirectory)) { screenshotDirectory = Settings.settingsStore.screenshotDirectory; } } if (!Directory.Exists(screenshotDirectory)) { Directory.CreateDirectory(screenshotDirectory); } ServerMessage newMessage = new ServerMessage(); newMessage.type = ServerMessageType.SCREENSHOT_LIBRARY; using (MessageReader mr = new MessageReader(messageData)) { ScreenshotMessageType messageType = (ScreenshotMessageType)mr.Read <int>(); string fromPlayer = mr.Read <string>(); switch (messageType) { case ScreenshotMessageType.SCREENSHOT: { if (Settings.settingsStore.screenshotsPerPlayer > -1) { string playerScreenshotDirectory = Path.Combine(screenshotDirectory, fromPlayer); if (!Directory.Exists(playerScreenshotDirectory)) { Directory.CreateDirectory(playerScreenshotDirectory); } string screenshotFile = Path.Combine(playerScreenshotDirectory, DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ".png"); DarkLog.Debug("Saving screenshot from " + fromPlayer); byte[] screenshotData = mr.Read <byte[]>(); File.WriteAllBytes(screenshotFile, screenshotData); if (Settings.settingsStore.screenshotsPerPlayer != 0) { while (Directory.GetFiles(playerScreenshotDirectory).Length > Settings.settingsStore.screenshotsPerPlayer) { string[] currentFiles = Directory.GetFiles(playerScreenshotDirectory); string deleteFile = currentFiles[0]; //Find oldest file foreach (string testFile in currentFiles) { if (File.GetCreationTime(testFile) < File.GetCreationTime(deleteFile)) { deleteFile = testFile; } } File.Delete(deleteFile); DarkLog.Debug("Removing old screenshot " + Path.GetFileName(deleteFile)); } } //Notify players that aren't watching that there's a new screenshot availabe. This only works if there's a file available on the server. //The server does not keep the screenshots in memory. ServerMessage notifyMessage = new ServerMessage(); notifyMessage.type = ServerMessageType.SCREENSHOT_LIBRARY; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)ScreenshotMessageType.NOTIFY); mw.Write(fromPlayer); notifyMessage.data = mw.GetMessageBytes(); ClientHandler.SendToAll(client, notifyMessage, false); } } if (!playerUploadedScreenshotIndex.ContainsKey(fromPlayer)) { playerUploadedScreenshotIndex.Add(fromPlayer, 0); } else { playerUploadedScreenshotIndex[fromPlayer]++; } if (!playerDownloadedScreenshotIndex.ContainsKey(fromPlayer)) { playerDownloadedScreenshotIndex.Add(fromPlayer, new Dictionary <string, int>()); } if (!playerDownloadedScreenshotIndex[fromPlayer].ContainsKey(fromPlayer)) { playerDownloadedScreenshotIndex[fromPlayer].Add(fromPlayer, playerUploadedScreenshotIndex[fromPlayer]); } else { playerDownloadedScreenshotIndex[fromPlayer][fromPlayer] = playerUploadedScreenshotIndex[fromPlayer]; } newMessage.data = messageData; foreach (KeyValuePair <string, string> entry in playerWatchScreenshot) { if (entry.Key != fromPlayer) { if (entry.Value == fromPlayer && entry.Key != client.playerName) { ClientObject toClient = ClientHandler.GetClientByName(entry.Key); if (toClient != null && toClient != client) { if (!playerDownloadedScreenshotIndex.ContainsKey(entry.Key)) { playerDownloadedScreenshotIndex.Add(entry.Key, new Dictionary <string, int>()); } if (!playerDownloadedScreenshotIndex[entry.Key].ContainsKey(fromPlayer)) { playerDownloadedScreenshotIndex[entry.Key].Add(fromPlayer, 0); } playerDownloadedScreenshotIndex[entry.Key][fromPlayer] = playerUploadedScreenshotIndex[fromPlayer]; DarkLog.Debug("Sending screenshot from " + fromPlayer + " to " + entry.Key); using (MessageWriter mw = new MessageWriter()) { ServerMessage sendStartMessage = new ServerMessage(); sendStartMessage.type = ServerMessageType.SCREENSHOT_LIBRARY; mw.Write <int>((int)ScreenshotMessageType.SEND_START_NOTIFY); mw.Write <string>(fromPlayer); sendStartMessage.data = mw.GetMessageBytes(); ClientHandler.SendToClient(toClient, sendStartMessage, true); } ClientHandler.SendToClient(toClient, newMessage, false); } } } } } break; case ScreenshotMessageType.WATCH: { newMessage.data = messageData; string watchPlayer = mr.Read <string>(); if (watchPlayer == "") { if (playerWatchScreenshot.ContainsKey(fromPlayer)) { DarkLog.Debug(fromPlayer + " is no longer watching screenshots from " + playerWatchScreenshot[fromPlayer]); playerWatchScreenshot.Remove(fromPlayer); } } else { DarkLog.Debug(fromPlayer + " is watching screenshots from " + watchPlayer); playerWatchScreenshot[fromPlayer] = watchPlayer; if (!playerDownloadedScreenshotIndex.ContainsKey(fromPlayer)) { playerDownloadedScreenshotIndex.Add(fromPlayer, new Dictionary <string, int>()); } string watchPlayerScreenshotDirectory = Path.Combine(screenshotDirectory, watchPlayer); //Find latest screenshot string sendFile = null; if (Directory.Exists(watchPlayerScreenshotDirectory)) { string[] playerScreenshots = Directory.GetFiles(watchPlayerScreenshotDirectory); if (playerScreenshots.Length > 0) { sendFile = playerScreenshots[0]; foreach (string testFile in playerScreenshots) { if (File.GetCreationTime(testFile) > File.GetCreationTime(sendFile)) { sendFile = testFile; } } if (!playerUploadedScreenshotIndex.ContainsKey(watchPlayer)) { playerUploadedScreenshotIndex.Add(watchPlayer, 0); } } } //Send screenshot if needed if (sendFile != null) { bool sendScreenshot = false; if (!playerDownloadedScreenshotIndex[fromPlayer].ContainsKey(watchPlayer)) { playerDownloadedScreenshotIndex[fromPlayer].Add(watchPlayer, playerUploadedScreenshotIndex[watchPlayer]); sendScreenshot = true; } else { if (playerDownloadedScreenshotIndex[fromPlayer][watchPlayer] != playerUploadedScreenshotIndex[watchPlayer]) { sendScreenshot = true; playerDownloadedScreenshotIndex[fromPlayer][watchPlayer] = playerUploadedScreenshotIndex[watchPlayer]; } } if (sendScreenshot) { ServerMessage sendStartMessage = new ServerMessage(); sendStartMessage.type = ServerMessageType.SCREENSHOT_LIBRARY; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)ScreenshotMessageType.SEND_START_NOTIFY); mw.Write <string>(fromPlayer); sendStartMessage.data = mw.GetMessageBytes(); } ServerMessage screenshotMessage = new ServerMessage(); screenshotMessage.type = ServerMessageType.SCREENSHOT_LIBRARY; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)ScreenshotMessageType.SCREENSHOT); mw.Write <string>(watchPlayer); mw.Write <byte[]>(File.ReadAllBytes(sendFile)); screenshotMessage.data = mw.GetMessageBytes(); } ClientObject toClient = ClientHandler.GetClientByName(fromPlayer); if (toClient != null) { DarkLog.Debug("Sending saved screenshot from " + watchPlayer + " to " + fromPlayer); ClientHandler.SendToClient(toClient, sendStartMessage, false); ClientHandler.SendToClient(toClient, screenshotMessage, false); } } } } //Relay the message ClientHandler.SendToAll(client, newMessage, false); } break; } } }
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); } }