Example #1
0
        public void HandleMessage(int clientIndex, KLFCommon.ClientMessageID id, byte[] data)
        {
            if (!ValidClient(clientIndex))
                return;
            DebugConsoleWriteLine("Message id: " + id.ToString() + " data: " + (data != null ? data.Length.ToString() : "0"));
            UnicodeEncoding encoder = new UnicodeEncoding();

            switch (id)
            {
                case KLFCommon.ClientMessageID.Handshake:
                    if (data != null)
                    {
                        StringBuilder sb = new StringBuilder();
                        //Read username
                        Int32 usernameLength = KLFCommon.BytesToInt(data, 0);
                        String username = encoder.GetString(data, 4, usernameLength);
                        int offset = 4 + usernameLength;
                        String version = encoder.GetString(data, offset, data.Length - offset);
                        String usernameLower = username.ToLower();
                        bool accepted = true;
                        //Ensure no other players have the same username
                        for (int i = 0; i < Clients.Length; i++)
                        {
                            if (i != clientIndex && ClientIsReady(i) && Clients[i].Username.ToLower() == usernameLower)
                            {
                                //Disconnect the player
                                DisconnectClient(clientIndex, "Your username is already in use.");
                                StampedConsoleWriteLine("Rejected client due to duplicate username: "******"There is currently 1 other user on this server: ");
                            for (int i = 0; i < Clients.Length; i++)
                            {
                                if (i != clientIndex && ClientIsReady(i))
                                {
                                    sb.Append(Clients[i].Username);
                                    break;
                                }
                            }
                        }
                        else
                        {
                            sb.Append("There are currently ");
                            sb.Append(NumClients - 1);
                            sb.Append(" other users on this server.");
                            if (NumClients > 1)
                                sb.Append(" Enter /list to see them.");
                        }
                        Clients[clientIndex].Username = username;
                        Clients[clientIndex].ReceivedHandshake = true;
                        SendServerMessage(clientIndex, sb.ToString());
                        SendServerSettings(clientIndex);
                        StampedConsoleWriteLine(username + " ("+GetClientIP(clientIndex).ToString()+") has joined the server using client version " + version);
                        if (!Clients[clientIndex].MessagesThrottled)
                        {//Build join message
                            sb.Clear();
                            sb.Append("User ");
                            sb.Append(username);
                            sb.Append(" has joined the server.");
                            //Send the join message to all other Clients
                            SendServerMessageToAll(sb.ToString(), clientIndex);
                        }
                        MessageFloodIncrement(clientIndex);
                    }
                    break;

                case KLFCommon.ClientMessageID.PrimaryPluginUpdate:
                case KLFCommon.ClientMessageID.SecondaryPluginUpdate:
                    if (data != null && ClientIsReady(clientIndex))
                    {
            #if SEND_UPDATES_TO_SENDER
                        SendPluginUpdateToAll(data, id == KLFCommon.ClientMessageID.SecondaryPluginUpdate);
            #else
                        SendPluginUpdateToAll(data, id == KLFCommon.ClientMessageID.SecondaryPluginUpdate, clientIndex);
            #endif
                    }
                    break;

                case KLFCommon.ClientMessageID.TextMessage:
                    if (data != null && ClientIsReady(clientIndex))
                        HandleClientTextMessage(clientIndex, encoder.GetString(data, 0, data.Length));
                    break;

                case KLFCommon.ClientMessageID.ScreenWatchPlayer:
                    if(!ClientIsReady(clientIndex)
                    || data == null
                    || data.Length < 9)
                        break;
                    bool sendScreenshot = data[0] != 0;
                    int watchIndex = KLFCommon.BytesToInt(data, 1);
                    int currentIndex = KLFCommon.BytesToInt(data, 5);
                    String watchName = encoder.GetString(data, 9, data.Length - 9);
                    bool watchNameChanged = false;
                    lock (Clients[clientIndex].WatchPlayerNameLock)
                    {
                        if(watchName != Clients[clientIndex].WatchPlayerName
                        || watchIndex != Clients[clientIndex].WatchPlayerIndex)
                        {//Set the watch player name
                            Clients[clientIndex].WatchPlayerIndex = watchIndex;
                            Clients[clientIndex].WatchPlayerName = watchName;
                            watchNameChanged = true;
                        }
                    }

                    if (sendScreenshot && watchNameChanged && watchName.Length > 0)
                    {//Try to find the player the client is watching and send that player's current screenshot
                        int watchedIndex = GetClientIndexByName(watchName);
                        if (ClientIsReady(watchedIndex))
                        {
                            Screenshot screenshot = null;
                            lock (Clients[watchedIndex].ScreenshotLock)
                            {
                                screenshot = Clients[watchedIndex].GetScreenshot(watchIndex);
                                if (screenshot == null && watchIndex == -1)
                                    screenshot = Clients[watchedIndex].LastScreenshot;
                            }
                            if(screenshot != null
                            && screenshot.Index != currentIndex)
                                SendScreenshot(clientIndex, screenshot);
                        }
                    }
                    break;

                case KLFCommon.ClientMessageID.ScreenshotShare:
                    if (data != null && data.Length <= Configuration.ScreenshotSettings.MaxNumBytes && ClientIsReady(clientIndex))
                    {
                        if (!Clients[clientIndex].ScreenshotsThrottled)
                        {
                            StringBuilder sb = new StringBuilder();
                            Screenshot screenshot = new Screenshot();
                            screenshot.SetFromByteArray(data);
                            //Set the screenshot for the player
                            lock (Clients[clientIndex].ScreenshotLock)
                            {
                                Clients[clientIndex].PushScreenshot(screenshot);
                            }
                            sb.Append(Clients[clientIndex].Username);
                            sb.Append(" has shared a screenshot.");
                            SendTextMessageToAll(sb.ToString());
                            StampedConsoleWriteLine(sb.ToString());
                            //Send the screenshot to every client watching the player
                            SendScreenshotToWatchers(clientIndex, screenshot);
                            if (Configuration.SaveScreenshots)
                                saveScreenshot(screenshot, Clients[clientIndex].Username);
                        }
                        bool throttled = Clients[clientIndex].ScreenshotsThrottled;
                        Clients[clientIndex].ScreenshotFloodIncrement();
                        if (!throttled && Clients[clientIndex].ScreenshotsThrottled)
                        {
                            long throttleSeconds = Configuration.ScreenshotFloodThrottleTime / 1000;
                            SendServerMessage(clientIndex, "You have been restricted from sharing screenshots for " + throttleSeconds + " seconds.");
                            StampedConsoleWriteLine(Clients[clientIndex].Username + " has been restricted from sharing screenshots for " + throttleSeconds + " seconds.");
                        }
                        else if (Clients[clientIndex].CurrentThrottle.MessageFloodCounter == Configuration.ScreenshotFloodLimit - 1)
                            SendServerMessage(clientIndex, "Warning: You are sharing too many screenshots.");

                    }

                    break;

                case KLFCommon.ClientMessageID.ConnectionEnd:
                    String message = String.Empty;
                    if (data != null)
                        message = encoder.GetString(data, 0, data.Length); //Decode the message
                    DisconnectClient(clientIndex, message); //Disconnect the client
                    break;

                case KLFCommon.ClientMessageID.ShareCraftFile:
                    if(ClientIsReady(clientIndex)
                    && data != null
                    && data.Length > 5
                    && (data.Length - 5) <= KLFCommon.MaxCraftFileBytes)
                    {
                        if (Clients[clientIndex].MessagesThrottled)
                        {
                            MessageFloodIncrement(clientIndex);
                            break;
                        }
                        MessageFloodIncrement(clientIndex);

                        //Read craft name length
                        byte craftType = data[0];
                        int craftNameLength = KLFCommon.BytesToInt(data, 1);
                        if (craftNameLength < data.Length - 5)
                        {
                            //Read craft name
                            String craftName = encoder.GetString(data, 5, craftNameLength);
                            //Read craft bytes
                            byte[] craftBytes = new byte[data.Length - craftNameLength - 5];
                            Array.Copy(data, 5 + craftNameLength, craftBytes, 0, craftBytes.Length);

                            lock (Clients[clientIndex].SharedCraftLock)
                            {
                                Clients[clientIndex].SharedCraftName = craftName;
                                Clients[clientIndex].SharedCraftFile = craftBytes;
                                Clients[clientIndex].SharedCraftType = craftType;
                            }

                            //Send a message to players informing them that a craft has been shared
                            StringBuilder sb = new StringBuilder();
                            sb.Append(Clients[clientIndex].Username);
                            sb.Append(" shared ");
                            sb.Append(craftName);
                            switch (craftType)
                            {
                                case KLFCommon.CraftTypeVab:
                                    sb.Append(" (VAB)");
                                    break;
                                case KLFCommon.CraftTypeSph:
                                    sb.Append(" (SPH)");
                                    break;
                            }
                            StampedConsoleWriteLine(sb.ToString());
                            sb.Append(" . Enter " + KLFCommon.GetCraftCommand);
                            sb.Append(Clients[clientIndex].Username);
                            sb.Append(" to get it.");
                            SendTextMessageToAll(sb.ToString());
                        }
                    }
                    break;

                case KLFCommon.ClientMessageID.ActivityUpdateInFlight:
                    Clients[clientIndex].UpdateActivity(ServerClient.Activity.InFlight);
                    break;

                case KLFCommon.ClientMessageID.ActivityUpdateInGame:
                    Clients[clientIndex].UpdateActivity(ServerClient.Activity.InGame);
                    break;

                case KLFCommon.ClientMessageID.Ping:
                    Clients[clientIndex].QueueOutgoingMessage(KLFCommon.ServerMessageID.PingReply, null);
                    break;
            }
            DebugConsoleWriteLine("Handled message");
        }
Example #2
0
    protected void HandleMessage(KLFCommon.ServerMessageID id, byte[] data)
    {
        switch (id)
        {
        case KLFCommon.ServerMessageID.Handshake:
            Int32 protocolVersion = KLFCommon.BytesToInt(data);
            if (data.Length >= 8)
            {
                Int32 server_version_length = KLFCommon.BytesToInt(data, 4);
                if (data.Length >= 12 + server_version_length)
                {
                    String server_version = Encoder.GetString(data, 8, server_version_length);
                    ClientID = KLFCommon.BytesToInt(data, 8 + server_version_length);
                    Console.WriteLine("Handshake received. Server is running version: " + server_version);
                }
            }
            //End the session if the protocol versions don't match
            if (protocolVersion != KLFCommon.NetProtocolVersion)
            {
                Console.WriteLine("Server version is incompatible with client version.");
                EndSession = true;
                IntentionalConnectionEnd = true;
            }
            else
            {
                SendHandshakeMessage(); //Reply to the handshake
                lock (UdpTimestampLock)
                {
                    LastUdpMessageSendTime = ClientStopwatch.ElapsedMilliseconds;
                }
                HandshakeComplete = true;
            }
            break;

        case KLFCommon.ServerMessageID.HandshakeRefusal:
            String refusal_message = Encoder.GetString(data, 0, data.Length);
            EndSession = true;
            IntentionalConnectionEnd = true;
            EnqueuePluginChatMessage("Server refused connection. Reason: " + refusal_message, true);
            break;

        case KLFCommon.ServerMessageID.ServerMessage:
        case KLFCommon.ServerMessageID.TextMessage:
            if (data != null)
            {
                InTextMessage inMessage = new InTextMessage();
                inMessage.FromServer = (id == KLFCommon.ServerMessageID.ServerMessage);
                inMessage.message = Encoder.GetString(data, 0, data.Length);
                //Queue the message
                EnqueueTextMessage(inMessage);
            }
            break;

        case KLFCommon.ServerMessageID.PluginUpdate:
            if (data != null)
                SendClientInteropMessage(KLFCommon.ClientInteropMessageID.PluginUpdate, data);
            break;

        case KLFCommon.ServerMessageID.ServerSettings:
            lock (ServerSettingsLock)
            {
                if (data != null && data.Length >= KLFCommon.ServerSettingsLength && HandshakeComplete)
                {
                    UpdateInterval = KLFCommon.BytesToInt(data, 0);
                    ScreenshotInterval = KLFCommon.BytesToInt(data, 4);
                    lock (ClientDataLock)
                    {
                        int new_screenshot_height = KLFCommon.BytesToInt(data, 8);
                        if (ScreenshotConfiguration.MaxHeight != new_screenshot_height)
                        {
                            ScreenshotConfiguration.MaxHeight = new_screenshot_height;
                            LastClientDataChangeTime = ClientStopwatch.ElapsedMilliseconds;
                            EnqueueTextMessage("Screenshot Height has been set to " + ScreenshotConfiguration.MaxHeight);
                        }
                        if (InactiveShipsPerUpdate != data[12])
                        {
                            InactiveShipsPerUpdate = data[12];
                            LastClientDataChangeTime = ClientStopwatch.ElapsedMilliseconds;
                        }
                    }
                }
            }
            break;

        case KLFCommon.ServerMessageID.ScreenshotShare:
            if (data != null
            && data.Length > 0
            && data.Length < ScreenshotConfiguration.MaxNumBytes
            && WatchPlayerName.Length > 0)
            {
                //Cache the screenshot
                Screenshot screenshot = new Screenshot();
                screenshot.SetFromByteArray(data);
                CacheScreenshot(screenshot);
                //Send the screenshot to the client
                SendClientInteropMessage(KLFCommon.ClientInteropMessageID.ScreenshotReceive, data);
            }
            break;

        case KLFCommon.ServerMessageID.ConnectionEnd:
            if (data != null)
            {
                String message = Encoder.GetString(data, 0, data.Length);
                EndSession = true;
                //If the reason is not a timeout, connection end is intentional
                IntentionalConnectionEnd = message.ToLower() != "timeout";
                EnqueuePluginChatMessage("Server closed the connection: " + message, true);
            }

            break;

        case KLFCommon.ServerMessageID.UdpAcknowledge:
            lock (UdpTimestampLock)
            {
                LastUdpAckReceiveTime = ClientStopwatch.ElapsedMilliseconds;
            }
            break;

        case KLFCommon.ServerMessageID.CraftFile:
            if (data != null && data.Length > 4)
            {
                //Read craft name length
                byte craftType = data[0];
                int craftName_length = KLFCommon.BytesToInt(data, 1);
                if (craftName_length < data.Length - 5)
                {
                    //Read craft name
                    String craftName = Encoder.GetString(data, 5, craftName_length);
                    //Read craft bytes
                    byte[] craft_bytes = new byte[data.Length - craftName_length - 5];
                    Array.Copy(data, 5 + craftName_length, craft_bytes, 0, craft_bytes.Length);
                    //Write the craft to a file
                    String filename = GetCraftFilename(craftName, craftType);
                    if (filename != null)
                    {
                        try
                        {
                            File.WriteAllBytes(filename, craft_bytes);
                            EnqueueTextMessage("Received craft file: " + craftName);
                        }
                        catch
                        {
                            EnqueueTextMessage("Error saving received craft file: " + craftName);
                        }
                    }
                    else
                        EnqueueTextMessage("Unable to save received craft file.");
                }
            }
            break;

        case KLFCommon.ServerMessageID.PingReply:
            if (PingStopwatch.IsRunning)
            {
                EnqueueTextMessage("Ping Reply: " + PingStopwatch.ElapsedMilliseconds + "ms");
                PingStopwatch.Stop();
                PingStopwatch.Reset();
            }
            break;
        }
    }