private static void queueOutgoingUDPMessage(KMPCommon.ClientMessageID id, byte[] data)
 {
     byte[] message_bytes = buildMessageByteArray(id, data, KMPCommon.intToBytes(clientID));
     queuedOutUDPMessages.Enqueue (message_bytes);
 }
        private static void sendShareCraftMessage(String craft_name, byte[] data, KMPCommon.CraftType type)
        {
            //Encode message
            byte[] name_bytes = encoder.GetBytes(craft_name);

            byte[] bytes = new byte[8 + name_bytes.Length + data.Length];

            //Check size of data to make sure it's not too large
            if ((name_bytes.Length + data.Length) <= KMPCommon.MAX_CRAFT_FILE_BYTES)
            {
                //Copy data
                KMPCommon.intToBytes((int)type).CopyTo(bytes, 0);
                KMPCommon.intToBytes(name_bytes.Length).CopyTo(bytes, 4);
                name_bytes.CopyTo(bytes, 8);
                data.CopyTo(bytes, 8 + name_bytes.Length);

                queueOutgoingMessage(KMPCommon.ClientMessageID.SHARE_CRAFT_FILE, bytes);
            }
            else
                enqueueTextMessage("Craft file is too large to send.", false, true);
        }
        private static void sendMessageUDP(KMPCommon.ClientMessageID id, byte[] data)
        {
            if (udpSocket != null)
            {
                //Send the packet
                try
                {
                    udpSocket.Send(buildMessageByteArray(id, data, KMPCommon.intToBytes(clientID)));
                }
                catch { }

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

            }
        }
 private static void queueOutgoingMessage(KMPCommon.ClientMessageID id, byte[] data)
 {
     //Figure out if this is a high or low priority message
     byte[] message_bytes = buildMessageByteArray(id, data);
     switch (id) {
         case KMPCommon.ClientMessageID.HANDSHAKE:
         case KMPCommon.ClientMessageID.TEXT_MESSAGE:
         case KMPCommon.ClientMessageID.KEEPALIVE:
         case KMPCommon.ClientMessageID.UDP_PROBE:
         case KMPCommon.ClientMessageID.PING:
             queuedOutMessagesHighPriority.Enqueue (message_bytes);
             break;
         default:
             queuedOutMessages.Enqueue (message_bytes);
             break;
     }
 }
Exemple #5
0
 public void queueOutgoingMessage(KMPCommon.ServerMessageID id, byte[] data)
 {
     queueOutgoingMessage(Server.buildMessageArray(id, data));
 }
        private void enqueuePluginInteropMessage(KMPCommon.PluginInteropMessageID id, byte[] data)
        {
            int msg_data_length = 0;
            if (data != null)
                msg_data_length = data.Length;

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

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

            interopOutQueue.Enqueue(message_bytes);

            //Enforce max queue size
            while (interopOutQueue.Count > INTEROP_MAX_QUEUE_SIZE)
                interopOutQueue.Dequeue();
        }
        private static void sendMessageUDP(KMPCommon.ClientMessageID id, byte[] data)
        {
            if (udpSocket != null)
            {
                //Send the packet
                try
                {
                    udpSocket.Send(buildMessageByteArray(id, data, KMPCommon.intToBytes(clientID)));
                }
                catch (Exception e) {
                    KMP.Log.Debug("Exception thrown in sendMessageUDP(), catch 1, Exception: {0}", e.ToString());
                }

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

            }
        }
        static String findCraftFilename(String craft_name, ref KMPCommon.CraftType craft_type)
        {
            String vab_filename = getCraftFilename(craft_name, KMPCommon.CraftType.VAB);
            if (vab_filename != null && System.IO.File.Exists(vab_filename))
            {
                craft_type = KMPCommon.CraftType.VAB;
                return vab_filename;
            }

            String sph_filename = getCraftFilename(craft_name, KMPCommon.CraftType.SPH);
            if (sph_filename != null && System.IO.File.Exists(sph_filename))
            {
                craft_type = KMPCommon.CraftType.SPH;
                return sph_filename;
            }

            String subassembly_filename = getCraftFilename(craft_name, KMPCommon.CraftType.SUBASSEMBLY);
            if (subassembly_filename != null && System.IO.File.Exists(subassembly_filename))
            {
                craft_type = KMPCommon.CraftType.SUBASSEMBLY;
                return subassembly_filename;
            }

            return null;
        }
Exemple #9
0
 private void asyncReceive(IAsyncResult ar)
 {
     try {
         // Retrieve the state object and the client socket
         // from the asynchronous state object.
         StateObject state     = (StateObject)ar.AsyncState;
         TcpClient   client    = state.workClient;
         int         bytesRead = client.GetStream().EndRead(ar); // Read data from the remote device directly into the message buffer.
         updateReceiveTimestamp();
         currentBytesToReceive -= bytesRead;                     //Decrement how many bytes we have read.
         if (bytesRead > 0)                                      //This is just a shortcut really
         {
             if (!currentMessageHeaderRecieved)
             {
                 //We are receiving just the header
                 if (currentBytesToReceive == 0)
                 {
                     //We have recieved the full message header, lets process it.
                     currentMessageID      = (KMPCommon.ClientMessageID)BitConverter.ToInt32(currentMessage, 0);
                     currentBytesToReceive = BitConverter.ToInt32(currentMessage, 4);
                     if (currentBytesToReceive == 0)
                     {
                         //We received the header of a empty message, process it and reset the buffers.
                         messageReceived(currentMessageID, null);
                         currentMessageID      = KMPCommon.ClientMessageID.NULL;
                         currentBytesToReceive = KMPCommon.MSG_HEADER_LENGTH;
                         currentMessage        = new byte[currentBytesToReceive];
                     }
                     else
                     {
                         //We received the header of a non-empty message, Let's give it a buffer and read again.
                         currentMessage = new byte[currentBytesToReceive];
                         currentMessageHeaderRecieved = true;
                     }
                 }
             }
             else
             {
                 if (currentBytesToReceive == 0)
                 {
                     //We have received all the message data, lets decompress and process it
                     byte[] decompressedData = KMPCommon.Decompress(currentMessage);
                     messageReceived(currentMessageID, decompressedData);
                     currentMessageHeaderRecieved = false;
                     currentMessageID             = KMPCommon.ClientMessageID.NULL;
                     currentBytesToReceive        = KMPCommon.MSG_HEADER_LENGTH;
                     currentMessage = new byte[currentBytesToReceive];
                 }
             }
         }
         if (currentBytesToReceive < 0)
         {
             throw new System.IO.IOException("You somehow managed to read more bytes then we asked for. Good for you. Open this up on the bugtracker now.");
         }
         if (client != null)
         {
             client.GetStream().BeginRead(currentMessage, currentMessage.Length - currentBytesToReceive, currentBytesToReceive, new AsyncCallback(asyncReceive), state);
         }
     }
     catch (Exception e) {
         //Basically, If anything goes wrong at all the stream is broken and there is no way to recover from it.
         Log.Debug("Exception thrown in ReceiveCallback(), catch 1, Exception: {0}", e.ToString());
     }
 }
        private static void sendMessageTCP(KMPCommon.ClientMessageID id, byte[] data)
        {
            lock (tcpSendLock)
            {
                byte[] message_bytes = buildMessageByteArray(id, data);
                int send_bytes_actually_sent = 0;
                while (send_bytes_actually_sent < message_bytes.Length)
                {
                    try
                    {
                        //Send message
                        send_bytes_actually_sent += tcpSocket.Send(message_bytes, send_bytes_actually_sent, message_bytes.Length - send_bytes_actually_sent, SocketFlags.None);
                    //					Just do a blocking send
                    //					tcpSocket.BeginSend(message_bytes, 0, message_bytes.Length, SocketFlags.None,
                    //      					new AsyncCallback(SendCallback), tcpSocket);
                    }
                    catch (System.InvalidOperationException e) {
                        KMP.Log.Debug("Exception thrown in sendMessageTCP(), catch 1, Exception: {0}", e.ToString());
                    }
                    catch (KSP.IO.IOException e) {
                        KMP.Log.Debug("Exception thrown in sendMessageTCP(), catch 2, Exception: {0}", e.ToString());
                    }

                }
            }
            lastTCPMessageSendTime = stopwatch.ElapsedMilliseconds;
        }
Exemple #11
0
 //Messages
 private void messageReceived(KMPCommon.ClientMessageID id, byte[] data)
 {
     if (id == KMPCommon.ClientMessageID.SPLIT_MESSAGE) {
                 if (splitMessageReceiveIndex == 0) {
                     //New split message
                         int split_message_length = KMPCommon.intFromBytes (data, 4);
                         splitMessageData = new byte[8 + split_message_length];
                         data.CopyTo (splitMessageData, 0);
                         splitMessageReceiveIndex = data.Length;
                 } else {
                         //Continued split message
                         data.CopyTo (splitMessageData, splitMessageReceiveIndex);
                         splitMessageReceiveIndex = splitMessageReceiveIndex + data.Length;
                 }
                 //Check if we have filled the byte array, if so, handle the message.
                 if (splitMessageReceiveIndex == splitMessageData.Length) {
                         //Parse the message and feed it into the client queue
                         KMPCommon.ClientMessageID joined_message_id = (KMPCommon.ClientMessageID)KMPCommon.intFromBytes (splitMessageData, 0);
                         int joined_message_length = KMPCommon.intFromBytes (splitMessageData, 4);
                         byte[] joined_message_data = new byte[joined_message_length];
                         Array.Copy (splitMessageData, 8, joined_message_data, 0, joined_message_length);
                         byte[] joined_message_data_decompressed = KMPCommon.Decompress (joined_message_data);
                         parent.queueClientMessage (this, joined_message_id, joined_message_data_decompressed);
                         splitMessageReceiveIndex = 0;
                 }
         } else {
                 parent.queueClientMessage (this, id, data);
         }
 }
        private void handleReceive()
        {
            while (receiveHandleIndex < receiveIndex)
            {
                //Read header bytes
                if (currentMessageHeaderIndex < KMPCommon.MSG_HEADER_LENGTH)
                {
                    //Determine how many header bytes can be read
                    int bytes_to_read = Math.Min(receiveIndex - receiveHandleIndex, KMPCommon.MSG_HEADER_LENGTH - currentMessageHeaderIndex);

                    //Read header bytes
                    Array.Copy(receiveBuffer, receiveHandleIndex, currentMessageHeader, currentMessageHeaderIndex, bytes_to_read);

                    //Advance buffer indices
                    currentMessageHeaderIndex += bytes_to_read;
                    receiveHandleIndex        += bytes_to_read;

                    //Handle header
                    if (currentMessageHeaderIndex >= KMPCommon.MSG_HEADER_LENGTH)
                    {
                        int id_int = KMPCommon.intFromBytes(currentMessageHeader, 0);

                        //Make sure the message id section of the header is a valid value
                        if (id_int >= 0 && id_int < Enum.GetValues(typeof(KMPCommon.ClientMessageID)).Length)
                        {
                            currentMessageID = (KMPCommon.ClientMessageID)id_int;
                        }
                        else
                        {
                            currentMessageID = KMPCommon.ClientMessageID.NULL;
                        }

                        int data_length = KMPCommon.intFromBytes(currentMessageHeader, 4);

                        if (data_length > 0)
                        {
                            //Init message data buffer
                            currentMessageData      = new byte[data_length];
                            currentMessageDataIndex = 0;
                        }
                        else
                        {
                            currentMessageData = null;
                            //Handle received message
                            messageReceived(currentMessageID, null);

                            //Prepare for the next header read
                            currentMessageHeaderIndex = 0;
                        }
                    }
                }

                if (currentMessageData != null)
                {
                    //Read data bytes
                    if (currentMessageDataIndex < currentMessageData.Length)
                    {
                        //Determine how many data bytes can be read
                        int bytes_to_read = Math.Min(receiveIndex - receiveHandleIndex, currentMessageData.Length - currentMessageDataIndex);

                        //Read data bytes
                        Array.Copy(receiveBuffer, receiveHandleIndex, currentMessageData, currentMessageDataIndex, bytes_to_read);

                        //Advance buffer indices
                        currentMessageDataIndex += bytes_to_read;
                        receiveHandleIndex      += bytes_to_read;

                        //Handle data
                        if (currentMessageDataIndex >= currentMessageData.Length)
                        {
                            //Handle received message
                            messageReceived(currentMessageID, currentMessageData);

                            currentMessageData = null;

                            //Prepare for the next header read
                            currentMessageHeaderIndex = 0;
                        }
                    }
                }
            }

            //Once all receive bytes have been handled, reset buffer indices to use the whole buffer again
            receiveHandleIndex = 0;
            receiveIndex       = 0;
        }
        static void handleMessage(KMPCommon.ServerMessageID id, byte[] data)
        {
            //LogAndShare("Message ID: " + id.ToString() + " data: " + (data == null ? "0" : System.Text.Encoding.ASCII.GetString(data)));
            switch (id)
            {
                case KMPCommon.ServerMessageID.HANDSHAKE:
                    Int32 protocol_version = KMPCommon.intFromBytes(data);

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

                        if (data.Length >= 12 + server_version_length)
                        {
                            String server_version = encoder.GetString(data, 8, server_version_length);
                            clientID = KMPCommon.intFromBytes(data, 8 + server_version_length);

                            SetMessage("Handshake received. Server version: " + server_version);
                        }
                    }

                    //End the session if the protocol versions don't match
                    if (protocol_version != KMPCommon.NET_PROTOCOL_VERSION)
                    {
                        endSession = true;
                        intentionalConnectionEnd = true;
                    }
                    else
                    {
                        sendHandshakeMessage(); //Reply to the handshake
                        lock (udpTimestampLock)
                        {
                            lastUDPMessageSendTime = stopwatch.ElapsedMilliseconds;
                        }
                        handshakeCompleted = true;
                    }

                    break;

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

                    if (data != null)
                    {

                        InTextMessage in_message = new InTextMessage();

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

                        //Queue the message
                        enqueueTextMessage(in_message);
                    }

                    break;

                case KMPCommon.ServerMessageID.PLUGIN_UPDATE:

                    if (data != null)
                        enqueueClientInteropMessage(KMPCommon.ClientInteropMessageID.PLUGIN_UPDATE, data);

                    break;

                case KMPCommon.ServerMessageID.SERVER_SETTINGS:

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

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

                            lock (clientDataLock)
                            {
                                int new_screenshot_height = KMPCommon.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;
                                }
                            }

                            receivedSettings = true;
                            /*
                            UnityEngine.Debug.Log("Update interval: " + updateInterval);
                            UnityEngine.Debug.Log("Screenshot interval: " + screenshotInterval);
                            UnityEngine.Debug.Log("Inactive ships per update: " + inactiveShipsPerUpdate);
                             */
                        }
                    }

                    break;

                case KMPCommon.ServerMessageID.SCREENSHOT_SHARE:

                    if (data != null && data.Length > 0 && data.Length < screenshotSettings.maxNumBytes
                        && watchPlayerName.Length > 0 && watchPlayerName != username)
                    {
                        enqueueClientInteropMessage(KMPCommon.ClientInteropMessageID.SCREENSHOT_RECEIVE, data);
                    }
                    break;

                case KMPCommon.ServerMessageID.CONNECTION_END:

                    gameManager.disconnect();
                    if (data != null)
                    {
                        String message = encoder.GetString(data, 0, data.Length);

                        endSession = true;
                        handshakeCompleted = false;
                        receivedSettings = false;
                        //If the reason is not a timeout, connection end is intentional
                        intentionalConnectionEnd = message.ToLower() != "timeout";
                        enqueuePluginChatMessage("Server closed the connection: " + message, true);
                        clearConnectionState();
                        SetMessage("Disconnected from server: " + message);
                        gameManager.disconnect(message);
                    }
                    else
                    {
                        clearConnectionState();
                        SetMessage("Disconnected from server");
                        gameManager.disconnect();
                    }

                    break;

                case KMPCommon.ServerMessageID.UDP_ACKNOWLEDGE:
                    lock (udpTimestampLock)
                    {
                        lastUDPAckReceiveTime = stopwatch.ElapsedMilliseconds;
                    }
                    break;

                case KMPCommon.ServerMessageID.CRAFT_FILE:

                    if (data != null && data.Length > 4)
                    {
                        //Read craft name length
                        byte craft_type = data[0];
                        int craft_name_length = KMPCommon.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
                                {
                                    //KSP.IO.File.WriteAllBytes<KMPClientMain>(craft_bytes, filename);
                                    System.IO.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 KMPCommon.ServerMessageID.PING_REPLY:
                    if (pingStopwatch.IsRunning)
                    {
                        enqueueTextMessage("Ping Reply: " + pingStopwatch.ElapsedMilliseconds + "ms");
                        lastPing = pingStopwatch.ElapsedMilliseconds;
                        pingStopwatch.Stop();
                        pingStopwatch.Reset();
                    }
                    break;

                case KMPCommon.ServerMessageID.SYNC:
                    if (data != null) gameManager.targetTick = BitConverter.ToDouble(data,0) + Convert.ToDouble(lastPing);

                    break;
                case KMPCommon.ServerMessageID.SYNC_COMPLETE:
                    gameManager.HandleSyncCompleted();
                    break;
            }
        }
        private static byte[] buildMessageByteArray(KMPCommon.ClientMessageID id, byte[] data, byte[] prefix = null)
        {
            byte[] compressed_data = null;
            int prefix_length = 0;
            if (prefix != null)
                prefix_length = prefix.Length;

            int msg_data_length = 0;
            if (data != null)
            {
                compressed_data = KMPCommon.Compress(data);
                if (compressed_data == null) compressed_data = KMPCommon.Compress(data, true);
                msg_data_length = compressed_data.Length;
            }

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

            int index = 0;

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

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

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

            if (compressed_data != null)
            {
                compressed_data.CopyTo(message_bytes, index);
                index += compressed_data.Length;
            }
            return message_bytes;
        }
        private void enqueuePluginInteropMessage(KMPCommon.PluginInteropMessageID id, byte[] data)
        {
            int msg_data_length = 0;
            if (data != null)
                msg_data_length = data.Length;

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

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

            KMPClientMain.acceptPluginInterop (message_bytes);
        }
        static void enqueueClientInteropMessage(KMPCommon.ClientInteropMessageID id, byte[] data)
        {
            int msg_data_length = 0;
            if (data != null)
                msg_data_length = data.Length;

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

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

            lock (interopOutQueueLock)
            {
                gameManager.acceptClientInterop (message_bytes);
            }
        }
        static void handleInteropMessage(KMPCommon.PluginInteropMessageID id, byte[] data)
        {
            switch (id)
            {

                case KMPCommon.PluginInteropMessageID.CHAT_SEND:
                    if (data != null)
                    {
                        String line = encoder.GetString(data);

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

                        handleChatInput(line);
                    }

                    break;

                case KMPCommon.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 = KMPCommon.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 = KMPCommon.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)
                            queueOutgoingMessage(KMPCommon.ClientMessageID.ACTIVITY_UPDATE_IN_FLIGHT, null);
                        else
                            queueOutgoingMessage(KMPCommon.ClientMessageID.ACTIVITY_UPDATE_IN_GAME, null);
                    }

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

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

                        sendScreenshotWatchPlayerMessage(watchPlayerName);
                    }
                    break;

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

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

                case KMPCommon.PluginInteropMessageID.SCENARIO_UPDATE:
                    sendScenarioUpdate(data);
                    break;

                case KMPCommon.PluginInteropMessageID.SCREENSHOT_SHARE:
                    if (data != null)
                    {
                        lock (screenshotOutLock)
                        {
                            queuedOutScreenshot = data;
                        }
                    }

                    break;
                case KMPCommon.PluginInteropMessageID.WARPING:
                    queueOutgoingMessage(KMPCommon.ClientMessageID.WARPING, data);
                    break;
                case KMPCommon.PluginInteropMessageID.SSYNC:
                    queueOutgoingMessage(KMPCommon.ClientMessageID.SSYNC, data);
                    break;
            }
        }
        static String getCraftFilename(String craft_name, KMPCommon.CraftType craft_type)
        {
            //Filter the craft name for illegal characters
            String filtered_craft_name = KMPCommon.filteredFileName(craft_name.Replace('.', '_'));

            if (currentGameTitle.Length <= 0 || filtered_craft_name.Length <= 0)
                return null;

            switch (craft_type)
            {
                case KMPCommon.CraftType.VAB:
                    return "saves/" + currentGameTitle + "/Ships/VAB/" + filtered_craft_name + CRAFT_FILE_EXTENSION;

                case KMPCommon.CraftType.SPH:
                    return "saves/" + currentGameTitle + "/Ships/SPH/" + filtered_craft_name + CRAFT_FILE_EXTENSION;

                case KMPCommon.CraftType.SUBASSEMBLY:
                    return "saves/" + currentGameTitle + "/Subassemblies/" + filtered_craft_name + CRAFT_FILE_EXTENSION;

            }

            return null;
        }
        static void handleMessage(KMPCommon.ServerMessageID id, byte[] data)
        {
            //LogAndShare("Message ID: " + id.ToString() + " data: " + (data == null ? "0" : System.Text.Encoding.ASCII.GetString(data)));
            switch (id)
            {
                case KMPCommon.ServerMessageID.HANDSHAKE:
                    Int32 protocol_version = KMPCommon.intFromBytes(data);

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

                        if (data.Length >= 12 + server_version_length)
                        {
                            String server_version = encoder.GetString(data, 8, server_version_length);
                            clientID = KMPCommon.intFromBytes(data, 8 + server_version_length);
                            gameManager.gameMode = KMPCommon.intFromBytes(data, 12 + server_version_length);
                            int kmpModControl_length = KMPCommon.intFromBytes(data, 16 + server_version_length);
                            kmpModControl_bytes = new byte[kmpModControl_length];
                            Array.Copy(data, 20 + server_version_length, kmpModControl_bytes, 0, kmpModControl_length);

                            SetMessage("Handshake received. Server version: " + server_version);
                        }
                    }

                    //End the session if the protocol versions don't match
                    if (protocol_version != KMPCommon.NET_PROTOCOL_VERSION)
                    {
                        endSession = true;
                        intentionalConnectionEnd = true;
                        gameManager.disconnect("Your client is incompatible with this server");
                    }
                    else
                    {
                        if (!modCheck(kmpModControl_bytes))
                        {
                            endSession = true;
                            intentionalConnectionEnd = true;
                            gameManager.disconnect(modMismatchError);
                        }
                        else
                        {
                            sendHandshakeMessage(); //Reply to the handshake
                            lock (udpTimestampLock)
                            {
                                lastUDPMessageSendTime = stopwatch.ElapsedMilliseconds;
                            }
                            handshakeCompleted = true;
                        }
                    }

                    break;

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

                    if (data != null)
                    {

                        InTextMessage in_message = new InTextMessage();

                        in_message.fromServer = (id == KMPCommon.ServerMessageID.SERVER_MESSAGE);
                        in_message.isMOTD = (id == KMPCommon.ServerMessageID.MOTD_MESSAGE);
                        in_message.message = encoder.GetString(data, 0, data.Length);
                        if (in_message.message.Contains(" has shared a screenshot.")) {
                            int screenshotSharePlayerNameIndex = in_message.message.IndexOf(" has shared a screenshot.");
                            string screenshotSharePlayerName = in_message.message.Substring(0, screenshotSharePlayerNameIndex);
                            if (screenshotSharePlayerName != username) {
                                bool listPlayerNameInScreenshotsWaiting = false;
                                foreach (string listPlayer in screenshotsWaiting)
                                {
                                    if (listPlayer == screenshotSharePlayerName) {
                                        listPlayerNameInScreenshotsWaiting = true;
                                    }
                                }
                                if (listPlayerNameInScreenshotsWaiting == false)
                                {
                                    screenshotsWaiting.Add(screenshotSharePlayerName);
                                }
                            }
                        }

                        if (in_message.message.Contains(" has disconnected : ")) {
                            int quitPlayerNameIndex = in_message.message.IndexOf(" has disconnected : ");
                            string quitPlayerName = in_message.message.Substring(0, quitPlayerNameIndex);
                            if (quitPlayerName != username) {
                                bool listPlayerNameInScreenshotsWaiting = false;
                                foreach (string listPlayer in screenshotsWaiting)
                                {
                                    if (listPlayer == quitPlayerName) {
                                        listPlayerNameInScreenshotsWaiting = true;
                                    }
                                }
                                if (listPlayerNameInScreenshotsWaiting)
                                {
                                    screenshotsWaiting.Remove(quitPlayerName);
                                }
                            }
                        }

                        //Queue the message
                        enqueueTextMessage(in_message);
                    }

                    break;

                case KMPCommon.ServerMessageID.MOTD_MESSAGE:

                    if (data != null)
                    {
                        InTextMessage in_message = new InTextMessage();
                        in_message.fromServer = (id == KMPCommon.ServerMessageID.SERVER_MESSAGE);
                        in_message.isMOTD = (id == KMPCommon.ServerMessageID.MOTD_MESSAGE);
                        in_message.message = encoder.GetString(data, 0, data.Length);

                        enqueueTextMessage(in_message);
                    }

                    break;

                case KMPCommon.ServerMessageID.PLUGIN_UPDATE:

                    if (data != null)
                        enqueueClientInteropMessage(KMPCommon.ClientInteropMessageID.PLUGIN_UPDATE, data);

                    break;

                case KMPCommon.ServerMessageID.SCENARIO_UPDATE:

                    if (data != null)
                        enqueueClientInteropMessage(KMPCommon.ClientInteropMessageID.SCENARIO_UPDATE, data);

                    break;

                case KMPCommon.ServerMessageID.SERVER_SETTINGS:

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

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

                            lock (clientDataLock)
                            {
                                int new_screenshot_height = KMPCommon.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);
                                }

                                gameManager.safetyBubbleRadius = BitConverter.ToDouble(data, 12);

                                if (inactiveShipsPerUpdate != data[20])
                                {
                                    inactiveShipsPerUpdate = data[20];
                                    lastClientDataChangeTime = stopwatch.ElapsedMilliseconds;
                                }
                                gameManager.gameCheatsEnabled = Convert.ToBoolean(data[21]);
                                gameManager.gameArrr = Convert.ToBoolean(data[22]);
                                //partList, requiredModList, shaList, resourceList and resourceControlMode

                            }

                            receivedSettings = true;
                            /*
                            Log.Debug("Update interval: " + updateInterval);
                            Log.Debug("Screenshot interval: " + screenshotInterval);
                            Log.Debug("Inactive ships per update: " + inactiveShipsPerUpdate);
                             */
                        }
                    }

                    break;

                case KMPCommon.ServerMessageID.SCREENSHOT_SHARE:

                    if (data != null && data.Length > 0 && data.Length < screenshotSettings.maxNumBytes
                        && watchPlayerName.Length > 0 && watchPlayerName != username)
                    {
                        enqueueClientInteropMessage(KMPCommon.ClientInteropMessageID.SCREENSHOT_RECEIVE, data);
                    }
                    break;

                case KMPCommon.ServerMessageID.CONNECTION_END:
                    if (data != null)
                    {
                        String message = encoder.GetString(data, 0, data.Length);

                        gameManager.disconnect(message);
                        clearConnectionState();

                        //If the reason is not a timeout, connection end is intentional
                        intentionalConnectionEnd = message.ToLower() != "timeout";
                        enqueuePluginChatMessage("Server closed the connection: " + message, true);

                        SetMessage("Disconnected from server: " + message);
                    }
                    else
                    {
                        gameManager.disconnect();
                        clearConnectionState();
                        SetMessage("Disconnected from server");
                    }

                    break;

                case KMPCommon.ServerMessageID.UDP_ACKNOWLEDGE:
                    lock (udpTimestampLock)
                    {
                        lastUDPAckReceiveTime = stopwatch.ElapsedMilliseconds;
                    }
                    break;

                case KMPCommon.ServerMessageID.CRAFT_FILE:

                    if (data != null && data.Length > 8)
                    {
                        //Read craft name length
                        KMPCommon.CraftType craft_type = (KMPCommon.CraftType)KMPCommon.intFromBytes(data, 0);
                        int craft_name_length = KMPCommon.intFromBytes(data, 4);
                        if (craft_name_length < data.Length - 8)
                        {
                            //Read craft name
                            String craft_name = encoder.GetString(data, 8, craft_name_length);

                            //Read craft bytes
                            byte[] craft_bytes = new byte[data.Length - craft_name_length - 8];
                            Array.Copy(data, 8 + 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
                                {
                                    //KSP.IO.File.WriteAllBytes<KMPClientMain>(craft_bytes, filename);
                                    System.IO.File.WriteAllBytes(filename, craft_bytes);
                                    enqueueTextMessage("Received craft file: " + craft_name);
                                }
                                catch (Exception e)
                                {
                                    Log.Debug("Exception thrown in handleMessage(), catch 1, Exception: {0}", e.ToString());
                                    enqueueTextMessage("Error saving received craft file: " + craft_name);
                                }
                            }
                            else
                                enqueueTextMessage("Unable to save received craft file.");
                        }
                    }

                    break;

                case KMPCommon.ServerMessageID.PING_REPLY:
                    if (pingStopwatch.IsRunning)
                    {
                        enqueueTextMessage("Ping Reply: " + pingStopwatch.ElapsedMilliseconds + "ms");
                        lastPing = pingStopwatch.ElapsedMilliseconds;
                        pingStopwatch.Stop();
                        pingStopwatch.Reset();
                    }
                    break;

                case KMPCommon.ServerMessageID.SYNC:
                    if (data != null) gameManager.targetTick = BitConverter.ToDouble(data, 0) + Convert.ToDouble(lastPing);

                    break;
                case KMPCommon.ServerMessageID.SYNC_COMPLETE:
                    gameManager.HandleSyncCompleted();
                    break;
                case KMPCommon.ServerMessageID.SPLIT_MESSAGE:
            handleSplitMessage(data);
                    break;
            }
        }
Exemple #20
0
 //Messages
 private void messageReceived(KMPCommon.ClientMessageID id, byte[] data)
 {
     parent.queueClientMessage(this, id, data);
 }
 private static void messageReceived(KMPCommon.ServerMessageID id, byte[] data)
 {
     ServerMessage message;
     message.id = id;
     message.data = data;
     if (id != KMPCommon.ServerMessageID.NULL) receivedMessageQueue.Enqueue(message);
 }
Exemple #22
0
        private void handleInteropMessage(KMPCommon.ClientInteropMessageID id, byte[] data)
        {
            try
            {
                switch (id)
                {
                    case KMPCommon.ClientInteropMessageID.CHAT_RECEIVE:
                        if (data != null)
                        {
                            KMPChatDisplay.enqueueChatLine(encoder.GetString(data));
                            KMPChatDX.enqueueChatLine(encoder.GetString(data));
                            chatMessagesWaiting++;
                        }
                        break;

                    case KMPCommon.ClientInteropMessageID.CLIENT_DATA:

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

                            //Read screenshot height
                            KMPScreenshotDisplay.screenshotSettings.maxHeight = KMPCommon.intFromBytes(data, 1);

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

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

                        break;

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

                    case KMPCommon.ClientInteropMessageID.SCREENSHOT_RECEIVE:
                        if (data != null)
                        {
                            //Read description length
                            int description_length = KMPCommon.intFromBytes(data, 0);

                            //Read description
                            String description = encoder.GetString(data, 4, description_length);

                            //Read data
                            byte[] image_data = new byte[data.Length - 4 - description_length];
                            Array.Copy(data, 4 + description_length, image_data, 0, image_data.Length);
                            if (image_data.Length <= KMPScreenshotDisplay.screenshotSettings.maxNumBytes)
                            {
                                KMPScreenshotDisplay.description = description;
                                StartCoroutine(applyScreenshotTexture(image_data));
                            }
                        }
                        break;
                }
            } catch (Exception e) { KMPClientMain.DebugLog(e.Message); }
        }
        private static void sendMessageTCP(KMPCommon.ClientMessageID id, byte[] data)
        {
            byte[] message_bytes = buildMessageByteArray(id, data);

            lock (tcpSendLock)
            {
                try
                {
                    //Send message
                    tcpSocket.Send(message_bytes, message_bytes.Length, SocketFlags.None);
            //					Just do a blocking send
            //					tcpSocket.BeginSend(message_bytes, 0, message_bytes.Length, SocketFlags.None,
            //      					new AsyncCallback(SendCallback), tcpSocket);
                }
                catch (System.InvalidOperationException) { }
                catch (KSP.IO.IOException) { }

            }

            lastTCPMessageSendTime = stopwatch.ElapsedMilliseconds;
        }