예제 #1
0
        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;
                }
            }
        }
예제 #2
0
        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;
                }
            }
        }
예제 #3
0
        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);
            }
        }