public void enqueuePluginInteropMessage(KLFCommon.PluginInteropMessageID id, byte[] data)
 {
     InteropMessage message = new InteropMessage();
     message.id = (int)id;
     message.data = data;
     interopInQueue.Enqueue(message);
 }
Beispiel #2
0
 protected override void SendClientInteropMessage(KLFCommon.ClientInteropMessageID id, byte[] data)
 {
     InteropMessage message = new InteropMessage();
     message.id = (int)id;
     message.data = data;
     InteropOutQueue.Enqueue(message);
 }
        protected override void messageReceived(KLFCommon.ServerMessageID id, byte[] data)
        {
            ServerMessage message;
            message.id = id;
            message.data = data;

            lock (serverMessageQueueLock)
            {
                serverMessageQueue.Enqueue(message);
            }
        }
Beispiel #4
0
        static void handleMessage(KLFCommon.ServerMessageID id, byte[] data)
        {
            ASCIIEncoding encoder = new ASCIIEncoding();

            switch (id)
            {
                case KLFCommon.ServerMessageID.HANDSHAKE:

                    Int32 protocol_version = KLFCommon.intFromBytes(data);
                    String server_version = encoder.GetString(data, 4, data.Length - 4);

                    Console.WriteLine("Handshake received. Server is running version: "+server_version);

                    //End the session if the protocol versions don't match
                    if (protocol_version != KLFCommon.NET_PROTOCOL_VERSION)
                    {
                        Console.WriteLine("Server version is incompatible with client version. Ending session.");
                        endSession = true;
                    }
                    else
                    {
                        tcpSendMutex.WaitOne();
                        sendHandshakeMessage(); //Reply to the handshake
                        tcpSendMutex.ReleaseMutex();
                    }

                    break;

                case KLFCommon.ServerMessageID.HANDSHAKE_REFUSAL:

                    String refusal_message = encoder.GetString(data, 0, data.Length);
                    Console.WriteLine("Server refused connection. Reason: " + refusal_message);
                    endSession = true;

                    break;

                case KLFCommon.ServerMessageID.SERVER_MESSAGE:

                    InTextMessage in_message = new InTextMessage();

                    in_message.fromServer = true;
                    in_message.message = encoder.GetString(data, 0, data.Length);

                    //Queue the message
                    textMessageQueueMutex.WaitOne();
                    enqueueTextMessage(in_message);
                    textMessageQueueMutex.ReleaseMutex();

                    break;

                case KLFCommon.ServerMessageID.TEXT_MESSAGE:

                    in_message = new InTextMessage();

                    in_message.fromServer = false;
                    in_message.message = encoder.GetString(data, 0, data.Length);

                    //Queue the message
                    textMessageQueueMutex.WaitOne();
                    enqueueTextMessage(in_message);
                    textMessageQueueMutex.ReleaseMutex();

                    break;

                case KLFCommon.ServerMessageID.PLUGIN_UPDATE:

                    //Add the update the queue
                    pluginUpdateInMutex.WaitOne();

                    pluginUpdateInQueue.Enqueue(data);

                    pluginUpdateInMutex.ReleaseMutex();

                    break;

                case KLFCommon.ServerMessageID.SERVER_SETTINGS:

                    serverSettingsMutex.WaitOne();
                    updateInterval = KLFCommon.intFromBytes(data, 0);
                    maxQueuedUpdates = KLFCommon.intFromBytes(data, 4);
                    serverSettingsMutex.ReleaseMutex();

                    break;
            }
        }
Beispiel #5
0
 //Messages
 private static void sendMessageHeader(KLFCommon.ClientMessageID id, int msg_length)
 {
     tcpClient.GetStream().Write(KLFCommon.intToBytes((int)id), 0, 4);
     tcpClient.GetStream().Write(KLFCommon.intToBytes(msg_length), 0, 4);
 }
Beispiel #6
0
 protected abstract void sendClientInteropMessage(KLFCommon.ClientInteropMessageID id, byte[] data);
Beispiel #7
0
 protected void SendMessageTcp(KLFCommon.ClientMessageID id, byte[] data)
 {
     byte[] messageBytes = BuildMessageByteArray(id, data);
     lock (TcpSendLock)
     {
         try
         {
             TcpConnection.GetStream().Write(messageBytes, 0, messageBytes.Length);
         }
         catch (System.InvalidOperationException) {}
         catch (System.IO.IOException) {}
     }
     LastTcpMessageSendTime = ClientStopwatch.ElapsedMilliseconds;
 }
        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");
        }
Beispiel #9
0
    protected void handleMessage(KLFCommon.ServerMessageID id, byte[] data)
    {
        switch (id)
        {
            case KLFCommon.ServerMessageID.HANDSHAKE:

                Int32 protocol_version = KLFCommon.intFromBytes(data);

                if (data.Length >= 8)
                {
                    Int32 server_version_length = KLFCommon.intFromBytes(data, 4);

                    if (data.Length >= 12 + server_version_length)
                    {
                        String server_version = encoder.GetString(data, 8, server_version_length);
                        clientID = KLFCommon.intFromBytes(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 (protocol_version != KLFCommon.NET_PROTOCOL_VERSION)
                {
                    Console.WriteLine("Server version is incompatible with client version.");
                    endSession = true;
                    intentionalConnectionEnd = true;
                }
                else
                {
                    sendHandshakeMessage(); //Reply to the handshake
                    lock (udpTimestampLock)
                    {
                        lastUDPMessageSendTime = stopwatch.ElapsedMilliseconds;
                    }
                    handshakeCompleted = true;
                }

                break;

            case KLFCommon.ServerMessageID.HANDSHAKE_REFUSAL:

                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.SERVER_MESSAGE:
            case KLFCommon.ServerMessageID.TEXT_MESSAGE:

                if (data != null)
                {

                    InTextMessage in_message = new InTextMessage();

                    in_message.fromServer = (id == KLFCommon.ServerMessageID.SERVER_MESSAGE);
                    in_message.message = encoder.GetString(data, 0, data.Length);

                    //Queue the message
                    enqueueTextMessage(in_message);
                }

                break;

            case KLFCommon.ServerMessageID.PLUGIN_UPDATE:

            if (data != null)
                    sendClientInteropMessage(KLFCommon.ClientInteropMessageID.PLUGIN_UPDATE, data);

                break;

            case KLFCommon.ServerMessageID.SERVER_SETTINGS:

                lock (serverSettingsLock)
                {
                    if (data != null && data.Length >= KLFCommon.SERVER_SETTINGS_LENGTH && handshakeCompleted)
                    {

                        updateInterval = KLFCommon.intFromBytes(data, 0);
                        screenshotInterval = KLFCommon.intFromBytes(data, 4);

                        lock (clientDataLock)
                        {
                            int new_screenshot_height = KLFCommon.intFromBytes(data, 8);
                            if (screenshotSettings.maxHeight != new_screenshot_height)
                            {
                                screenshotSettings.maxHeight = new_screenshot_height;
                                lastClientDataChangeTime = stopwatch.ElapsedMilliseconds;
                                enqueueTextMessage("Screenshot Height has been set to " + screenshotSettings.maxHeight);
                            }

                            if (inactiveShipsPerUpdate != data[12])
                            {
                                inactiveShipsPerUpdate = data[12];
                                lastClientDataChangeTime = stopwatch.ElapsedMilliseconds;
                            }
                        }
                    }
                }

                break;

            case KLFCommon.ServerMessageID.SCREENSHOT_SHARE:
                if (data != null && data.Length > 0 && data.Length < screenshotSettings.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.SCREENSHOT_RECEIVE, data);
                }
                break;

            case KLFCommon.ServerMessageID.CONNECTION_END:

                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.UDP_ACKNOWLEDGE:
                lock (udpTimestampLock)
                {
                    lastUDPAckReceiveTime = stopwatch.ElapsedMilliseconds;
                }
                break;

            case KLFCommon.ServerMessageID.CRAFT_FILE:

                if (data != null && data.Length > 4)
                {
                    //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);

                        //Write the craft to a file
                        String filename = getCraftFilename(craft_name, craft_type);
                        if (filename != null)
                        {
                            try
                            {
                                File.WriteAllBytes(filename, craft_bytes);
                                enqueueTextMessage("Received craft file: " + craft_name);
                            }
                            catch
                            {
                                enqueueTextMessage("Error saving received craft file: " + craft_name);
                            }
                        }
                        else
                            enqueueTextMessage("Unable to save received craft file.");
                    }
                }

                break;

            case KLFCommon.ServerMessageID.PING_REPLY:
                if (pingStopwatch.IsRunning)
                {
                    enqueueTextMessage("Ping Reply: " + pingStopwatch.ElapsedMilliseconds + "ms");
                    pingStopwatch.Stop();
                    pingStopwatch.Reset();
                }
                break;
        }
    }
Beispiel #10
0
 protected void SendMessageUdp(KLFCommon.ClientMessageID id, byte[] data)
 {
     if (UdpSocket != null)
     {
         try
         {
             UdpSocket.Send(BuildMessageByteArray(id, data, KLFCommon.IntToBytes(ClientID)));
         }
         catch { }
         lock (UdpTimestampLock)
         {
             LastUdpMessageSendTime = ClientStopwatch.ElapsedMilliseconds;
         }
     }
 }
 public void queueOutgoingMessage(KLFCommon.ServerMessageID id, byte[] data)
 {
     queueOutgoingMessage(Server.buildMessageArray(id, data));
 }
Beispiel #12
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");
        }
Beispiel #13
0
 //Messages
 public void QueueClientMessage(int clientIndex, KLFCommon.ClientMessageID id, byte[] data)
 {
     ClientMessage message = new ClientMessage();
     message.ClientIndex = clientIndex;
     message.ID = id;
     message.Data = data;
     ClientMessageQueue.Enqueue(message);
 }
Beispiel #14
0
 public static byte[] BuildMessageArray(KLFCommon.ServerMessageID id, byte[] data)
 {
     //Construct the byte array for the message
     int messageDataLength = 0;
     if (data != null)
         messageDataLength = data.Length;
     byte[] messageBytes = new byte[KLFCommon.MessageHeaderLength + messageDataLength];
     KLFCommon.IntToBytes((int)id).CopyTo(messageBytes, 0);
     KLFCommon.IntToBytes(messageDataLength).CopyTo(messageBytes, 4);
     if (data != null)
         data.CopyTo(messageBytes, KLFCommon.MessageHeaderLength);
     return messageBytes;
 }
Beispiel #15
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());
 }
Beispiel #16
0
        //Messages
        public void queueClientMessage(int client_index, KLFCommon.ClientMessageID id, byte[] data)
        {
            ClientMessage message = new ClientMessage();
            message.clientIndex = client_index;
            message.id = id;
            message.data = data;

            clientMessageQueue.Enqueue(message);
        }
Beispiel #17
0
        private void enqueuePluginInteropMessage(KLFCommon.PluginInteropMessageID id, byte[] data)
        {
            int msg_data_length = 0;
            if (data != null)
                msg_data_length = data.Length;

            byte[] message_bytes = new byte[KLFCommon.INTEROP_MSG_HEADER_LENGTH + msg_data_length];

            KLFCommon.intToBytes((int)id).CopyTo(message_bytes, 0);
            KLFCommon.intToBytes(msg_data_length).CopyTo(message_bytes, 4);
            if (data != null)
                data.CopyTo(message_bytes, KLFCommon.INTEROP_MSG_HEADER_LENGTH);

            interopOutQueue.Enqueue(message_bytes);

            //Enforce max queue size
            while (interopOutQueue.Count > INTEROP_MAX_QUEUE_SIZE)
                interopOutQueue.Dequeue();
        }
Beispiel #18
0
    protected void sendMessageTCP(KLFCommon.ClientMessageID id, byte[] data)
    {
        byte[] message_bytes = buildMessageByteArray(id, data);

        lock (tcpSendLock)
        {
            try
            {
                //Send message
                tcpClient.GetStream().Write(message_bytes, 0, message_bytes.Length);
            }
            catch (System.InvalidOperationException) { }
            catch (System.IO.IOException) { }

        }

        lastTCPMessageSendTime = stopwatch.ElapsedMilliseconds;
    }
Beispiel #19
0
        private void handleInteropMessage(KLFCommon.ClientInteropMessageID id, byte[] data)
        {
            switch (id)
            {
                case KLFCommon.ClientInteropMessageID.CHAT_RECEIVE:

                    if (data != null)
                    {
                        KLFChatDisplay.enqueueChatLine(encoder.GetString(data));
                    }

                    break;

                case KLFCommon.ClientInteropMessageID.CLIENT_DATA:

                    if (data != null && data.Length > 9)
                    {
                        //Read inactive vessels per update count
                        inactiveVesselsPerUpdate = data[0];

                        //Read screenshot height
                        KLFScreenshotDisplay.screenshotSettings.maxHeight = KLFCommon.intFromBytes(data, 1);

                        updateInterval = ((float)KLFCommon.intFromBytes(data, 5))/1000.0f;

                        //Read username
                        playerName = encoder.GetString(data, 9, data.Length - 9);
                    }

                    break;

                case KLFCommon.ClientInteropMessageID.PLUGIN_UPDATE:
                    if (data != null)
                    {
                        //De-serialize and handle the update
                        handleUpdate(KSP.IO.IOUtils.DeserializeFromBinary(data));
                    }
                    break;

                case KLFCommon.ClientInteropMessageID.SCREENSHOT_RECEIVE:
                    if (data != null)
                    {
                        Debug.Log("Received screenshot");
                        KLFScreenshotDisplay.screenshot.setFromByteArray(data);

                        if (KLFScreenshotDisplay.screenshot.image.Length <= KLFScreenshotDisplay.screenshotSettings.maxNumBytes)
                        {
                            if (KLFScreenshotDisplay.texture == null)
                                KLFScreenshotDisplay.texture = new Texture2D(4, 4, TextureFormat.RGB24, false, true);

                            if (KLFScreenshotDisplay.texture.LoadImage(KLFScreenshotDisplay.screenshot.image))
                            {
                                KLFScreenshotDisplay.texture.Apply();

                                //Make sure the screenshot texture does not exceed the size limits
                                if (KLFScreenshotDisplay.texture.width > KLFScreenshotDisplay.screenshotSettings.maxWidth
                                    || KLFScreenshotDisplay.texture.height > KLFScreenshotDisplay.screenshotSettings.maxHeight)
                                {
                                    KLFScreenshotDisplay.screenshot.clear();
                                }
                            }
                            else
                            {
                                KLFScreenshotDisplay.screenshot.clear();
                            }

                            KLFScreenshotDisplay.screenshot.image = null;
                        }
                    }
                    break;
            }
        }
Beispiel #20
0
    protected byte[] buildMessageByteArray(KLFCommon.ClientMessageID id, byte[] data, byte[] prefix = null)
    {
        int prefix_length = 0;
        if (prefix != null)
            prefix_length = prefix.Length;

        int msg_data_length = 0;
        if (data != null)
            msg_data_length = data.Length;

        byte[] message_bytes = new byte[KLFCommon.MSG_HEADER_LENGTH + msg_data_length + prefix_length];

        int index = 0;

        if (prefix != null)
        {
            prefix.CopyTo(message_bytes, index);
            index += 4;
        }

        KLFCommon.intToBytes((int)id).CopyTo(message_bytes, index);
        index += 4;

        KLFCommon.intToBytes(msg_data_length).CopyTo(message_bytes, index);
        index += 4;

        if (data != null)
        {
            data.CopyTo(message_bytes, index);
            index += data.Length;
        }

        return message_bytes;
    }
 //Messages
 private void messageReceived(KLFCommon.ClientMessageID id, byte[] data)
 {
     parent.queueClientMessage(clientIndex, id, data);
 }
Beispiel #22
0
        public static byte[] buildMessageArray(KLFCommon.ServerMessageID id, byte[] data)
        {
            //Construct the byte array for the message
            int msg_data_length = 0;
            if (data != null)
            msg_data_length = data.Length;

            byte[] message_bytes = new byte[KLFCommon.MSG_HEADER_LENGTH + msg_data_length];

            KLFCommon.intToBytes((int)id).CopyTo(message_bytes, 0);
            KLFCommon.intToBytes(msg_data_length).CopyTo(message_bytes, 4);
            if (data != null)
            data.CopyTo(message_bytes, KLFCommon.MSG_HEADER_LENGTH);

            return message_bytes;
        }
Beispiel #23
0
    protected void sendMessageUDP(KLFCommon.ClientMessageID id, byte[] data)
    {
        if (udpSocket != null)
        {
            //Send the packet
            try
            {
                udpSocket.Send(buildMessageByteArray(id, data, KLFCommon.intToBytes(clientID)));
            }
            catch { }

            lock (udpTimestampLock)
            {
                lastUDPMessageSendTime = stopwatch.ElapsedMilliseconds;
            }

        }
    }
        private void handleInteropMessage(KLFCommon.ClientInteropMessageID id, byte[] data)
        {
            switch (id)
            {
                case KLFCommon.ClientInteropMessageID.CHAT_RECEIVE:

                    if (data != null)
                    {
                        string NNmessage = encoder.GetString(data);
                        if (!KLFGlobalSettings.instance.chatWindowEnabled || !KLFInfoDisplay.infoDisplayActive)
                        {
                            KLF_Button.SetTexture(KLF_button_alert); KLF_button_alert_anim = 1;
                            if (KLFGlobalSettings.instance.SendNotifications)
                            {
                                MessageSystem.Message m = new MessageSystem.Message("Kerbal Live Feed Activity", NNmessage, MessageSystemButton.MessageButtonColor.YELLOW, MessageSystemButton.ButtonIcons.MESSAGE);
                                MessageSystem.Instance.AddMessage(m);
                            }
                        }
                        KLFChatDisplay.enqueueChatLine(NNmessage);
                    }

                    break;

                case KLFCommon.ClientInteropMessageID.CLIENT_DATA:

                    if (data != null && data.Length > 9)
                    {
                        //Read inactive vessels per update count
                        inactiveVesselsPerUpdate = data[0];

                        //Read screenshot height
                        KLFScreenshotDisplay.screenshotSettings.maxHeight = KLFCommon.intFromBytes(data, 1);

                        updateInterval = ((float)KLFCommon.intFromBytes(data, 5)) / 1000.0f;

                        //Read username
                        playerName = encoder.GetString(data, 9, data.Length - 9);
                    }

                    break;

                case KLFCommon.ClientInteropMessageID.PLUGIN_UPDATE:
                    if (data != null)
                    {
                        //De-serialize and handle the update
                        handleUpdate(KSP.IO.IOUtils.DeserializeFromBinary(data));
                    }
                    break;

                case KLFCommon.ClientInteropMessageID.SCREENSHOT_RECEIVE:
                    if (data != null)
                    {
                        Debug.Log("Received screenshot");
                        KLFScreenshotDisplay.screenshot.setFromByteArray(data);

                        if (KLFScreenshotDisplay.screenshot.image.Length <= KLFScreenshotDisplay.screenshotSettings.maxNumBytes)
                        {
                            if (KLFScreenshotDisplay.texture == null)
                                KLFScreenshotDisplay.texture = new Texture2D(4, 4, TextureFormat.RGB24, false, true);

                            if (KLFScreenshotDisplay.texture.LoadImage(KLFScreenshotDisplay.screenshot.image))
                            {
                                KLFScreenshotDisplay.texture.Apply();

                                //Make sure the screenshot texture does not exceed the size limits
                                if (KLFScreenshotDisplay.texture.width > KLFScreenshotDisplay.screenshotSettings.maxWidth
                                    || KLFScreenshotDisplay.texture.height > KLFScreenshotDisplay.screenshotSettings.maxHeight)
                                {
                                    KLFScreenshotDisplay.screenshot.clear();
                                }
                                else
                                {
                                    KLFScreenshotDisplay.watchPlayerIndex = KLFScreenshotDisplay.screenshot.index;
                                }
                            }
                            else
                            {
                                KLFScreenshotDisplay.screenshot.clear();
                            }

                            KLFScreenshotDisplay.screenshot.image = null;
                        }
                    }
                    break;
            }
        }
Beispiel #25
0
    protected void handleInteropMessage(KLFCommon.PluginInteropMessageID id, byte[] data)
    {
        switch (id)
        {

            case KLFCommon.PluginInteropMessageID.CHAT_SEND:

                if (data != null)
                {
                    String line = encoder.GetString(data);

                    InTextMessage message = new InTextMessage();
                    message.fromServer = false;
                    message.message = "[" + clientSettings.username + "] " + line;
                    enqueueTextMessage(message, false);

                    handleChatInput(line);
                }

                break;

            case KLFCommon.PluginInteropMessageID.PLUGIN_DATA:

                String new_watch_player_name = String.Empty;

                if (data != null && data.Length >= 9)
                {
                    UnicodeEncoding encoder = new UnicodeEncoding();
                    int index = 0;

                    //Read current activity status
                    bool in_flight = data[index] != 0;
                    index++;

                    //Read current game title
                    int current_game_title_length = KLFCommon.intFromBytes(data, index);
                    index += 4;

                    currentGameTitle = encoder.GetString(data, index, current_game_title_length);
                    index += current_game_title_length;

                    //Send the activity status to the server
                    if (in_flight)
                        sendMessageTCP(KLFCommon.ClientMessageID.ACTIVITY_UPDATE_IN_FLIGHT, null);
                    else
                        sendMessageTCP(KLFCommon.ClientMessageID.ACTIVITY_UPDATE_IN_GAME, null);
                }
                break;

            case KLFCommon.PluginInteropMessageID.PRIMARY_PLUGIN_UPDATE:
                sendPluginUpdate(data, true);
                break;

            case KLFCommon.PluginInteropMessageID.SECONDARY_PLUGIN_UPDATE:
                sendPluginUpdate(data, false);
                break;

            case KLFCommon.PluginInteropMessageID.SCREENSHOT_SHARE:

                if (data != null)
                {
                    lock (screenshotOutLock)
                    {
                        queuedOutScreenshot = data;
                    }
                }

                break;

            case KLFCommon.PluginInteropMessageID.SCREENSHOT_WATCH_UPDATE:
                if (data != null && data.Length >= 8)
                {
                    int index = KLFCommon.intFromBytes(data, 0);
                    int current_index = KLFCommon.intFromBytes(data, 4);
                    String name = encoder.GetString(data, 8, data.Length - 8);

                    if (watchPlayerName != name || watchPlayerIndex != index)
                    {
                        watchPlayerName = name;
                        watchPlayerIndex = index;

                        //Look in the screenshot cache for the requested screenshot
                        Screenshot cached = getCachedScreenshot(watchPlayerIndex, watchPlayerName);
                        if (cached != null)
                            sendClientInteropMessage(KLFCommon.ClientInteropMessageID.SCREENSHOT_RECEIVE, cached.toByteArray());

                        sendScreenshotWatchPlayerMessage((cached == null), current_index, watchPlayerIndex, watchPlayerName);
                    }
                }
                break;

        }
    }
Beispiel #26
0
        private static void messageReceived(KLFCommon.ServerMessageID id, byte[] data)
        {
            ServerMessage message;
            message.id = id;
            message.data = data;

            receivedMessageQueue.Enqueue(message);
        }
Beispiel #27
0
 protected abstract void messageReceived(KLFCommon.ServerMessageID id, byte[] data);
Beispiel #28
0
        static void enqueueClientInteropMessage(KLFCommon.ClientInteropMessageID id, byte[] data)
        {
            int msg_data_length = 0;
            if (data != null)
                msg_data_length = data.Length;

            byte[] message_bytes = new byte[KLFCommon.INTEROP_MSG_HEADER_LENGTH + msg_data_length];

            KLFCommon.intToBytes((int)id).CopyTo(message_bytes, 0);
            KLFCommon.intToBytes(msg_data_length).CopyTo(message_bytes, 4);
            if (data != null)
                data.CopyTo(message_bytes, KLFCommon.INTEROP_MSG_HEADER_LENGTH);

            interopOutQueue.Enqueue(message_bytes);

            //Enforce max queue size
            while (interopOutQueue.Count > INTEROP_MAX_QUEUE_SIZE)
            {
                byte[] bytes;
                if (!interopOutQueue.TryDequeue(out bytes))
                    break;
            }
        }
    protected override void sendClientInteropMessage(KLFCommon.ClientInteropMessageID id, byte[] data)
    {
        InteropMessage message = new InteropMessage();
        message.id = (int)id;
        message.data = data;

        interopOutQueue.Enqueue(message);

        //Enforce max queue size
        while (interopOutQueue.Count > INTEROP_MAX_QUEUE_SIZE)
        {
            if (!interopOutQueue.TryDequeue(out message))
                break;
        }
    }
Beispiel #30
0
        static void handleInteropMessage(KLFCommon.PluginInteropMessageID id, byte[] data)
        {
            switch (id)
            {

                case KLFCommon.PluginInteropMessageID.CHAT_SEND:

                    if (data != null)
                    {
                        String line = encoder.GetString(data);

                        InTextMessage message = new InTextMessage();
                        message.fromServer = false;
                        message.message = "[" + username + "] " + line;
                        enqueueTextMessage(message, false);

                        handleChatInput(line);
                    }

                    break;

                case KLFCommon.PluginInteropMessageID.PLUGIN_DATA:

                    String new_watch_player_name = String.Empty;

                    if (data != null && data.Length >= 9)
                    {
                        UnicodeEncoding encoder = new UnicodeEncoding();
                        int index = 0;

                        //Read current activity status
                        bool in_flight = data[index] != 0;
                        index++;

                        //Read current game title
                        int current_game_title_length = KLFCommon.intFromBytes(data, index);
                        index += 4;

                        currentGameTitle = encoder.GetString(data, index, current_game_title_length);
                        index += current_game_title_length;

                        //Read the watch player name
                        int watch_player_name_length = KLFCommon.intFromBytes(data, index);
                        index += 4;

                        new_watch_player_name = encoder.GetString(data, index, watch_player_name_length);
                        index += watch_player_name_length;

                        //Send the activity status to the server
                        if (in_flight)
                            sendMessageTCP(KLFCommon.ClientMessageID.ACTIVITY_UPDATE_IN_FLIGHT, null);
                        else
                            sendMessageTCP(KLFCommon.ClientMessageID.ACTIVITY_UPDATE_IN_GAME, null);
                    }

                    if (watchPlayerName != new_watch_player_name)
                    {
                        watchPlayerName = new_watch_player_name;

                        if (watchPlayerName == username && lastSharedScreenshot != null)
                            enqueueClientInteropMessage(KLFCommon.ClientInteropMessageID.SCREENSHOT_RECEIVE, lastSharedScreenshot);

                        sendScreenshotWatchPlayerMessage(watchPlayerName);
                    }
                    break;

                case KLFCommon.PluginInteropMessageID.PRIMARY_PLUGIN_UPDATE:
                    sendPluginUpdate(data, true);
                    break;

                case KLFCommon.PluginInteropMessageID.SECONDARY_PLUGIN_UPDATE:
                    sendPluginUpdate(data, false);
                    break;

                case KLFCommon.PluginInteropMessageID.SCREENSHOT_SHARE:

                    if (data != null)
                    {
                        lock (screenshotOutLock)
                        {
                            queuedOutScreenshot = data;
                        }
                    }

                    break;

            }
        }