Пример #1
0
 private void SendMessageHeaderDirect(TcpClient client, KLFCommon.ServerMessageID id, int msgLength)
 {
     client.GetStream().Write(KLFCommon.IntToBytes((int)id), 0, 4);
     client.GetStream().Write(KLFCommon.IntToBytes(msgLength), 0, 4);
     DebugConsoleWriteLine("Sending message: " + id.ToString());
 }
Пример #2
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");
        }
Пример #3
0
        public void handleMessage(int client_index, KLFCommon.ClientMessageID id, byte[] data)
        {
            if (!clientIsValid(client_index))
            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 username_length = KLFCommon.intFromBytes(data, 0);
                String username = encoder.GetString(data, 4, username_length);

                int offset = 4 + username_length;

                String version = encoder.GetString(data, offset, data.Length - offset);

                String username_lower = username.ToLower();

                bool accepted = true;

                //Ensure no other players have the same username
                for (int i = 0; i < clients.Length; i++)
                {
                    if (i != client_index && clientIsReady(i) && clients[i].username.ToLower() == username_lower)
                    {
                        //Disconnect the player
                        disconnectClient(client_index, "Your username is already in use.");
                        stampedConsoleWriteLine("Rejected client due to duplicate username: "******"Your Client is Outdated Please Update");
                        stampedConsoleWriteLine("Rejected client due to wrong version : " + version + " New "+ KLFCommon.PROGRAM_VERSION);
                        accepted = false;
                        break;
                }
                if (!accepted)
                    break;

                //Send the active user count to the client
                if (numClients == 2)
                {
                    //Get the username of the other user on the server
                    sb.Append("There is currently 1 other user on this server: ");
                    for (int i = 0; i < clients.Length; i++)
                    {
                        if (i != client_index && 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[client_index].username = username;
                clients[client_index].receivedHandshake = true;

                sendServerMessage(client_index, sb.ToString());
                sendServerSettings(client_index);

                stampedConsoleWriteLine(username + " ("+getClientIP(client_index).ToString()+") has joined the server using client version " + version);

                if (!clients[client_index].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(), client_index);
                }

                messageFloodIncrement(client_index);

            }

            break;

            case KLFCommon.ClientMessageID.PRIMARY_PLUGIN_UPDATE:
            case KLFCommon.ClientMessageID.SECONDARY_PLUGIN_UPDATE:

            if (data != null && clientIsReady(client_index))
            {
            #if SEND_UPDATES_TO_SENDER
                sendPluginUpdateToAll(data, id == KLFCommon.ClientMessageID.SECONDARY_PLUGIN_UPDATE);
            #else
                sendPluginUpdateToAll(data, id == KLFCommon.ClientMessageID.SECONDARY_PLUGIN_UPDATE, client_index);
            #endif
            }

            break;

            case KLFCommon.ClientMessageID.TEXT_MESSAGE:

            if (data != null && clientIsReady(client_index))
                handleClientTextMessage(client_index, encoder.GetString(data, 0, data.Length));

            break;

            case KLFCommon.ClientMessageID.SCREEN_WATCH_PLAYER:

            if (!clientIsReady(client_index) || data == null || data.Length < 9)
                break;

            bool send_screenshot = data[0] != 0;
            int watch_index = KLFCommon.intFromBytes(data, 1);
            int current_index = KLFCommon.intFromBytes(data, 5);
            String watch_name = encoder.GetString(data, 9, data.Length - 9);

            bool watch_name_changed = false;

            lock (clients[client_index].watchPlayerNameLock)
            {
                if (watch_name != clients[client_index].watchPlayerName || watch_index != clients[client_index].watchPlayerIndex)
                {
                    //Set the watch player name
                    clients[client_index].watchPlayerIndex = watch_index;
                    clients[client_index].watchPlayerName = watch_name;
                    watch_name_changed = true;
                }
            }

            if (send_screenshot && watch_name_changed && watch_name.Length > 0)
            {
                //Try to find the player the client is watching and send that player's current screenshot
                int watched_index = getClientIndexByName(watch_name);
                if (clientIsReady(watched_index))
                {
                    Screenshot screenshot = null;
                    lock (clients[watched_index].screenshotLock)
                    {
                        screenshot = clients[watched_index].getScreenshot(watch_index);
                        if (screenshot == null && watch_index == -1)
                            screenshot = clients[watched_index].lastScreenshot;
                    }

                    if (screenshot != null && screenshot.index != current_index)
                    {
                        sendScreenshot(client_index, screenshot);
                    }
                }
            }

            break;

            case KLFCommon.ClientMessageID.SCREENSHOT_SHARE:

            if (data != null && data.Length <= settings.screenshotSettings.maxNumBytes && clientIsReady(client_index))
            {
                if (!clients[client_index].screenshotsThrottled)
                {
                    StringBuilder sb = new StringBuilder();

                    Screenshot screenshot = new Screenshot();
                    screenshot.setFromByteArray(data);

                    //Set the screenshot for the player
                    lock (clients[client_index].screenshotLock)
                    {
                        clients[client_index].pushScreenshot(screenshot);
                    }

                    sb.Append(clients[client_index].username);
                    sb.Append(" has shared a screenshot.");

                    sendTextMessageToAll(sb.ToString());
                    stampedConsoleWriteLine(sb.ToString());

                    //Send the screenshot to every client watching the player
                    sendScreenshotToWatchers(client_index, screenshot);

                    if (settings.saveScreenshots)
                        saveScreenshot(screenshot, clients[client_index].username);
                    SHARED_SCREEN_SHOTS += 1;
                }

                bool was_throttled = clients[client_index].screenshotsThrottled;

                clients[client_index].screenshotFloodIncrement();

                if (!was_throttled && clients[client_index].screenshotsThrottled)
                {
                    long throttle_secs = settings.screenshotFloodThrottleTime / 1000;
                    sendServerMessage(client_index, "You have been restricted from sharing screenshots for " + throttle_secs + " seconds.");
                    stampedConsoleWriteLine(clients[client_index].username + " has been restricted from sharing screenshots for " + throttle_secs + " seconds.");
                }
                else if (clients[client_index].throttleState.messageFloodCounter == settings.screenshotFloodLimit - 1)
                    sendServerMessage(client_index, "Warning: You are sharing too many screenshots.");

            }

            break;

            case KLFCommon.ClientMessageID.CONNECTION_END:

            String message = String.Empty;
            if (data != null)
                message = encoder.GetString(data, 0, data.Length); //Decode the message

            disconnectClient(client_index, message); //Disconnect the client
            break;

            case KLFCommon.ClientMessageID.SHARE_CRAFT_FILE:

            if (clientIsReady(client_index) && data != null
                    && data.Length > 5 && (data.Length - 5) <= KLFCommon.MAX_CRAFT_FILE_BYTES)
            {
                if (clients[client_index].messagesThrottled)
                {
                    messageFloodIncrement(client_index);
                    break;
                }

                messageFloodIncrement(client_index);

                //Read craft name length
                byte craft_type = data[0];
                int craft_name_length = KLFCommon.intFromBytes(data, 1);
                if (craft_name_length < data.Length - 5)
                {
                    //Read craft name
                    String craft_name = encoder.GetString(data, 5, craft_name_length);

                    //Read craft bytes
                    byte[] craft_bytes = new byte[data.Length - craft_name_length - 5];
                    Array.Copy(data, 5 + craft_name_length, craft_bytes, 0, craft_bytes.Length);

                    lock (clients[client_index].sharedCraftLock)
                    {
                        clients[client_index].sharedCraftName = craft_name;
                        clients[client_index].sharedCraftFile = craft_bytes;
                        clients[client_index].sharedCraftType = craft_type;
                    }

                    //Send a message to players informing them that a craft has been shared
                    StringBuilder sb = new StringBuilder();
                    sb.Append(clients[client_index].username);
                    sb.Append(" shared ");
                    sb.Append(craft_name);

                    switch (craft_type)
                    {
                    case KLFCommon.CRAFT_TYPE_VAB:
                        sb.Append(" (VAB)");
                        break;

                    case KLFCommon.CRAFT_TYPE_SPH:
                        sb.Append(" (SPH)");
                        break;
                    }

                    stampedConsoleWriteLine(sb.ToString());

                    sb.Append(" . Enter !getcraft ");
                    sb.Append(clients[client_index].username);
                    sb.Append(" to get it.");
                    sendTextMessageToAll(sb.ToString());
                }
            }
            break;

            case KLFCommon.ClientMessageID.ACTIVITY_UPDATE_IN_FLIGHT:
            clients[client_index].updateActivityLevel(ServerClient.ActivityLevel.IN_FLIGHT);
            break;

            case KLFCommon.ClientMessageID.ACTIVITY_UPDATE_IN_GAME:
            clients[client_index].updateActivityLevel(ServerClient.ActivityLevel.IN_GAME);
            break;

            case KLFCommon.ClientMessageID.PING:
            clients[client_index].queueOutgoingMessage(KLFCommon.ServerMessageID.PING_REPLY, null);
            break;

            }

            debugConsoleWriteLine("Handled message");
        }