コード例 #1
0
 public static void SendDMPModMessageToAll(ClientObject excludeClient, string modName, byte[] messageData, bool highPriority)
 {
     ServerMessage newMessage = new ServerMessage();
     newMessage.type = ServerMessageType.MOD_DATA;
     using (MessageWriter mw = new MessageWriter())
     {
         mw.Write<string>(modName);
         mw.Write<byte[]>(messageData);
         newMessage.data = mw.GetMessageBytes();
     }
     ClientHandler.SendToAll(excludeClient, newMessage, highPriority);
 }
コード例 #2
0
        public override void OnMessageReceived(ClientObject client, ClientMessage message)
        {
            if (!client.authenticated)
            {
                //Only handle authenticated messages
                return;
            }

            if (message.type == ClientMessageType.SCENARIO_DATA)
            {
                HandleScenarioMessage(client, message);
                message.handled = true;
            }
        }
コード例 #3
0
 //Fire OnClientDisconnect
 public static void FireOnClientDisconnect(ClientObject client)
 {
     foreach (var plugin in loadedPlugins)
     {
         try
         {
             plugin.OnClientDisconnect(client);
         }
         catch (Exception e)
         {
             Type type = plugin.GetType();
             DarkLog.Debug("Error thrown in OnClientDisconnect event for " + type.FullName + " (" + type.Assembly.FullName + "), Exception: " + e);
         }
     }
 }
コード例 #4
0
ファイル: DarkChat.cs プロジェクト: JoshBlake/DarkChat
 public void OnMessageReceived(ClientObject client, ClientMessage message)
 {
     if (message.type == ClientMessageType.CHAT_MESSAGE)
     {
         using (MessageReader mr = new MessageReader(message.data, false))
         {
             ChatMessageType messageType = (ChatMessageType)mr.Read<int>();
             string fromPlayer = mr.Read<string>();
             if (messageType == ChatMessageType.CHANNEL_MESSAGE)
             {
                 string channel = mr.Read<string>();
                 string umessage = mr.Read<string>();
                 ircClient.Channels["#" + channel].SendMessage(String.Format("{0} -> {1}", fromPlayer, umessage));
             }
         }
     }
 }
コード例 #5
0
 private void SendCKANFileToClient(ClientObject client)
 {
     using (MessageWriter mw = new MessageWriter())
     {
         mw.Write<int>(CKAN_PROTOCOL_VERSION);
         if (!File.Exists(ckanFile))
         {
             mw.Write<bool>(false);
             byte[] sendData = mw.GetMessageBytes();
             DMPModInterface.SendDMPModMessageToClient(client, "DMPCkanPlugin", sendData, false);
             return;
         }
         mw.Write<bool>(true);
         mw.Write<string>(File.ReadAllText(ckanFile));
     }
     DarkLog.Debug("Sent CKAN file to " + client.playerName);
 }
コード例 #6
0
 public static void SendDMPModMessageToClient(ClientObject client, string modName, byte[] messageData, bool highPriority)
 {
     if (modName == null)
     {
         //Now that's just being silly :)
         return;
     }
     if (messageData == null)
     {
         DarkLog.Debug(modName + " attemped to send a null message");
         return;
     }
     ServerMessage newMessage = new ServerMessage();
     newMessage.type = ServerMessageType.MOD_DATA;
     using (MessageWriter mw = new MessageWriter())
     {
         mw.Write<string>(modName);
         mw.Write<byte[]>(messageData);
         newMessage.data = mw.GetMessageBytes();
     }
     ClientHandler.SendToClient(client, newMessage , highPriority);
 }
コード例 #7
0
 //Receive message data (PROTOCOL 1):
 //int ckan protocol version
 //int ckan request type:
 //1: CKAN metadata file
 //Send message data (PROTOCOL 1):
 //int ckan protocol version
 //bool ckan available (true/false)
 //if ckan available: UTF-8 string (ckan export data)
 private void OnCKANRequest(ClientObject client, byte[] messageData)
 {
     using (MessageReader mr = new MessageReader(messageData))
     {
         int clientProtocol = mr.Read<int>();
         if (clientProtocol != CKAN_PROTOCOL_VERSION)
         {
             DarkLog.Error("Client " + client.playerName + " connected with CKAN protocol " + clientProtocol + ", server version: " + CKAN_PROTOCOL_VERSION);
             return;
         }
         int requestType = mr.Read<int>();
         switch (requestType)
         {
             case 1:
                 SendCKANFileToClient(client);
                 break;
             default:
                 DarkLog.Error("Unknown CKAN request type: " + requestType);
                 break;
         }
     }
 }
コード例 #8
0
        //Fire OnMessageReceived
        public static void FireOnMessageReceived(ClientObject client, ClientMessage message)
        {
            bool handledByAny = false;
            foreach (var plugin in loadedPlugins)
            {
                try
                {
                    plugin.OnMessageReceived(client, message);

                    //prevent plugins from unhandling other plugin's handled requests
                    if (message.handled)
                    {
                        handledByAny = true;
                    }
                }
                catch (Exception e)
                {
                    Type type = plugin.GetType();
                    DarkLog.Debug("Error thrown in OnMessageReceived event for " + type.FullName + " (" + type.Assembly.FullName + "), Exception: " + e);
                }
            }
            message.handled = handledByAny;
        }
コード例 #9
0
        //Fire OnMessageReceived
        public static void FireOnMessageReceived(ClientObject client, ClientMessage message)
        {
            bool handledByAny = false;

            foreach (var plugin in loadedPlugins)
            {
                try
                {
                    plugin.OnMessageReceived(client, message);

                    //prevent plugins from unhandling other plugin's handled requests
                    if (message.handled)
                    {
                        handledByAny = true;
                    }
                }
                catch (Exception e)
                {
                    Type type = plugin.GetType();
                    DarkLog.Debug("Error thrown in OnMessageReceived event for " + type.FullName + " (" + type.Assembly.FullName + "), Exception: " + e);
                }
            }
            message.handled = handledByAny;
        }
コード例 #10
0
 private static void SendSetSubspace(ClientObject client)
 {
     if (!Settings.settingsStore.keepTickingWhileOffline && clients.Count == 1)
     {
         DarkLog.Debug("Reverting server time to last player connection");
         long currentTime = DateTime.UtcNow.Ticks;
         foreach (KeyValuePair<int, Subspace> subspace in subspaces)
         {
             subspace.Value.serverClock = currentTime;
             subspace.Value.subspaceSpeed = 1f;
             SaveLatestSubspace();
         }
     }
     int targetSubspace = -1;
     if (Settings.settingsStore.sendPlayerToLatestSubspace || !playerSubspace.ContainsKey(client.playerName))
     {
         DarkLog.Debug("Sending " + client.playerName + " to the latest subspace " + targetSubspace);
         targetSubspace = GetLatestSubspace();
     }
     else
     {
         DarkLog.Debug("Sending " + client.playerName + " to the previous subspace " + targetSubspace);
         targetSubspace = playerSubspace[client.playerName];
     }
     client.subspace = targetSubspace;
     ServerMessage newMessage = new ServerMessage();
     newMessage.type = ServerMessageType.SET_SUBSPACE;
     using (MessageWriter mw = new MessageWriter())
     {
         mw.Write<int>(targetSubspace);
         newMessage.data = mw.GetMessageBytes();
     }
     SendToClient(client, newMessage, true);
 }
コード例 #11
0
 private static void SendAllSubspaces(ClientObject client)
 {
     //Send all the locks.
     foreach (KeyValuePair<int, Subspace> subspace in subspaces)
     {
         ServerMessage newMessage = new ServerMessage();
         newMessage.type = ServerMessageType.WARP_CONTROL;
         using (MessageWriter mw = new MessageWriter())
         {
             mw.Write<int>((int)WarpMessageType.NEW_SUBSPACE);
             mw.Write<string>("");
             mw.Write<int>(subspace.Key);
             mw.Write<long>(subspace.Value.serverClock);
             mw.Write<double>(subspace.Value.planetTime);
             mw.Write<float>(subspace.Value.subspaceSpeed);
             newMessage.data = mw.GetMessageBytes();
         }
         SendToClient(client, newMessage, true);
     }
     //Tell the player "when" everyone is.
     foreach (ClientObject otherClient in clients)
     {
         if (otherClient.authenticated && (otherClient.playerName != client.playerName))
         {
             ServerMessage newMessage = new ServerMessage();
             newMessage.type = ServerMessageType.WARP_CONTROL;
             using (MessageWriter mw = new MessageWriter())
             {
                 mw.Write<int>((int)WarpMessageType.CHANGE_SUBSPACE);
                 mw.Write<string>(otherClient.playerName);
                 mw.Write<int>(otherClient.subspace);
                 newMessage.data = mw.GetMessageBytes();
             }
             SendToClient(client, newMessage, true);
         }
     }
 }
コード例 #12
0
 private static void SendScenarioModules(ClientObject client)
 {
     int numberOfScenarioModules = Directory.GetFiles(Path.Combine(Server.universeDirectory, "Scenarios", client.playerName)).Length;
     int currentScenarioModule = 0;
     string[] scenarioNames = new string[numberOfScenarioModules];
     byte[][] scenarioDataArray = new byte[numberOfScenarioModules][];
     foreach (string file in Directory.GetFiles(Path.Combine(Server.universeDirectory, "Scenarios", client.playerName)))
     {
         //Remove the .txt part for the name
         scenarioNames[currentScenarioModule] = Path.GetFileNameWithoutExtension(file);
         scenarioDataArray[currentScenarioModule] = File.ReadAllBytes(file);
         currentScenarioModule++;
     }
     ServerMessage newMessage = new ServerMessage();
     newMessage.type = ServerMessageType.SCENARIO_DATA;
     using (MessageWriter mw = new MessageWriter())
     {
         mw.Write<string[]>(scenarioNames);
         foreach (byte[] scenarioData in scenarioDataArray)
         {
             mw.Write<byte[]>(scenarioData);
         }
         newMessage.data = mw.GetMessageBytes();
     }
     SendToClient(client, newMessage, true);
 }
コード例 #13
0
 private static void DisconnectClient(ClientObject client)
 {
     lock (client.disconnectLock)
     {
         if (client.connectionStatus != ConnectionStatus.DISCONNECTED)
         {
             DMPPluginHandler.FireOnClientDisconnect(client);
             if (client.playerName != null)
             {
                 if (playerChatChannels.ContainsKey(client.playerName))
                 {
                     playerChatChannels.Remove(client.playerName);
                 }
                 if (playerDownloadedScreenshotIndex.ContainsKey(client.playerName))
                 {
                     playerDownloadedScreenshotIndex.Remove(client.playerName);
                 }
                 if (playerUploadedScreenshotIndex.ContainsKey(client.playerName))
                 {
                     playerUploadedScreenshotIndex.Remove(client.playerName);
                 }
                 if (playerWatchScreenshot.ContainsKey(client.playerName))
                 {
                     playerWatchScreenshot.Remove(client.playerName);
                 }
             }
             client.connectionStatus = ConnectionStatus.DISCONNECTED;
             if (client.authenticated)
             {
                 ServerMessage newMessage = new ServerMessage();
                 newMessage.type = ServerMessageType.PLAYER_DISCONNECT;
                 using (MessageWriter mw = new MessageWriter())
                 {
                     mw.Write<string>(client.playerName);
                     newMessage.data = mw.GetMessageBytes();
                 }
                 SendToAll(client, newMessage, true);
                 lockSystem.ReleasePlayerLocks(client.playerName);
             }
             deleteClients.Enqueue(client);
             try
             {
                 if (client.connection != null)
                 {
                     client.connection.GetStream().Close();
                     client.connection.Close();
                 }
             }
             catch (Exception e)
             {
                 DarkLog.Debug("Error closing client connection: " + e.Message);
             }
             Server.lastPlayerActivity = Server.serverClock.ElapsedMilliseconds;
         }
     }
 }
コード例 #14
0
 public virtual void OnClientAuthenticated(ClientObject client)
 {
 }
コード例 #15
0
        private static void SplitAndRewriteMessage(ClientObject client, ref ServerMessage message)
        {
            if (message == null)
            {
                return;
            }
            if (message.data == null)
            {
                return;
            }
            if (message.data.Length > Common.SPLIT_MESSAGE_LENGTH)
            {
                ServerMessage newSplitMessage = new ServerMessage();
                newSplitMessage.type = ServerMessageType.SPLIT_MESSAGE;
                int splitBytesLeft = message.data.Length;
                using (MessageWriter mw = new MessageWriter())
                {
                    mw.Write<int>((int)message.type);
                    mw.Write<int>(message.data.Length);
                    byte[] firstSplit = new byte[Common.SPLIT_MESSAGE_LENGTH];
                    Array.Copy(message.data, 0, firstSplit, 0, Common.SPLIT_MESSAGE_LENGTH);
                    mw.Write<byte[]>(firstSplit);
                    splitBytesLeft -= Common.SPLIT_MESSAGE_LENGTH;
                    newSplitMessage.data = mw.GetMessageBytes();
                    //SPLIT_MESSAGE adds a 12 byte header.
                    client.bytesQueuedOut += 12;
                    client.sendMessageQueueSplit.Enqueue(newSplitMessage);
                }


                while (splitBytesLeft > 0)
                {
                    ServerMessage currentSplitMessage = new ServerMessage();
                    currentSplitMessage.type = ServerMessageType.SPLIT_MESSAGE;
                    currentSplitMessage.data = new byte[Math.Min(splitBytesLeft, Common.SPLIT_MESSAGE_LENGTH)];
                    Array.Copy(message.data, message.data.Length - splitBytesLeft, currentSplitMessage.data, 0, currentSplitMessage.data.Length);
                    splitBytesLeft -= currentSplitMessage.data.Length;
                    //Add the SPLIT_MESSAGE header to the out queue count.
                    client.bytesQueuedOut += 12;
                    client.sendMessageQueueSplit.Enqueue(currentSplitMessage);
                }
                client.sendMessageQueueSplit.TryDequeue(out message);
            }
        }
コード例 #16
0
 private static void StartReceivingIncomingMessages(ClientObject client)
 {
     client.lastReceiveTime = Server.serverClock.ElapsedMilliseconds;
     //Allocate byte for header
     client.receiveMessage = new ClientMessage();
     client.receiveMessage.data = new byte[8];
     client.receiveMessageBytesLeft = client.receiveMessage.data.Length;
     try
     {
         client.connection.GetStream().BeginRead(client.receiveMessage.data, client.receiveMessage.data.Length - client.receiveMessageBytesLeft, client.receiveMessageBytesLeft, new AsyncCallback(ReceiveCallback), client);
     }
     catch (Exception e)
     {
         HandleDisconnectException("Start Receive", client, e);
     }
 }
コード例 #17
0
 private static void SendConnectionEnd(ClientObject client, string reason)
 {
     ServerMessage newMessage = new ServerMessage();
     newMessage.type = ServerMessageType.CONNECTION_END;
     using (MessageWriter mw = new MessageWriter())
     {
         mw.Write<string>(reason);
         newMessage.data = mw.GetMessageBytes();
     }
     SendToClient(client, newMessage, true);
 }
コード例 #18
0
 private static void StartSendingOutgoingMessages(ClientObject client)
 {
     Thread clientSendThread = new Thread(new ParameterizedThreadStart(SendOutgoingMessages));
     clientSendThread.IsBackground = true;
     clientSendThread.Start(client);
 }
コード例 #19
0
 private static void SendVessel(ClientObject client, byte[] vesselData)
 {
     ServerMessage newMessage = new ServerMessage();
     newMessage.type = ServerMessageType.VESSEL_PROTO;
     using (MessageWriter mw = new MessageWriter())
     {
         mw.Write<double>(0);
         mw.Write<byte[]>(vesselData);
         newMessage.data = mw.GetMessageBytes();
     }
     SendToClient(client, newMessage, false);
 }
コード例 #20
0
        private static void SendMotdReply(ClientObject client)
        {
            ServerMessage newMessage = new ServerMessage();
            newMessage.type = ServerMessageType.MOTD_REPLY;

            string newMotd = Settings.settingsStore.serverMotd;
            newMotd = newMotd.Replace("%name%", client.playerName);
            newMotd = newMotd.Replace(@"\n", Environment.NewLine);

            using (MessageWriter mw = new MessageWriter())
            {
                mw.Write<string>(newMotd);
                newMessage.data = mw.GetMessageBytes();
            }
            SendToClient(client, newMessage, true);
        }
コード例 #21
0
 private static void SendKerbal(ClientObject client, string kerbalName, byte[] kerbalData)
 {
     ServerMessage newMessage = new ServerMessage();
     newMessage.type = ServerMessageType.KERBAL_REPLY;
     using (MessageWriter mw = new MessageWriter())
     {
         //Send the vessel with a send time of 0 so it instantly loads on the client.
         mw.Write<double>(0);
         mw.Write<string>(kerbalName);
         mw.Write<byte[]>(kerbalData);
         newMessage.data = mw.GetMessageBytes();
     }
     SendToClient(client, newMessage, false);
 }
コード例 #22
0
 private static void SendAllReportedSkewRates(ClientObject client)
 {
     foreach (ClientObject otherClient in clients)
     {
         if (otherClient.authenticated)
         {
             if (otherClient != client)
             {
                 ServerMessage newMessage = new ServerMessage();
                 newMessage.type = ServerMessageType.WARP_CONTROL;
                 using (MessageWriter mw = new MessageWriter())
                 {
                     mw.Write<int>((int)WarpMessageType.REPORT_RATE);
                     mw.Write<string>(otherClient.playerName);
                     mw.Write<float>(otherClient.subspace);
                     mw.Write<float>(otherClient.subspaceRate);
                     newMessage.data = mw.GetMessageBytes();
                 }
                 SendToClient(client, newMessage, true);
             }
         }
     }
 }
コード例 #23
0
 public virtual void OnClientDisconnect(ClientObject client)
 {
 }
コード例 #24
0
 public virtual void OnMessageSent(ClientObject client, ServerMessage messageData)
 {
 }
コード例 #25
0
 public virtual void OnMessageReceived(ClientObject client, ClientMessage messageData)
 {
 }
コード例 #26
0
 private static void SendVesselList(ClientObject client)
 {
     ServerMessage newMessage = new ServerMessage();
     newMessage.type = ServerMessageType.VESSEL_LIST;
     string[] vesselFiles = Directory.GetFiles(Path.Combine(Server.universeDirectory, "Vessels"));
     string[] vesselObjects = new string[vesselFiles.Length];
     for (int i = 0; i < vesselFiles.Length; i++)
     {
         vesselObjects[i] = Common.CalculateSHA256Hash(vesselFiles[i]);
     }
     using (MessageWriter mw = new MessageWriter())
     {
         mw.Write<string[]>(vesselObjects);
         newMessage.data = mw.GetMessageBytes();
     }
     SendToClient(client, newMessage, false);
 }
コード例 #27
0
 private static void StartSendingOutgoingMessages(ClientObject client)
 {
     Thread clientSendThread = new Thread(new ParameterizedThreadStart(SendOutgoingMessages));
     clientSendThread.IsBackground = true;
     clientSendThread.Start(client);
 }
コード例 #28
0
 private static void SendKerbalsComplete(ClientObject client)
 {
     ServerMessage newMessage = new ServerMessage();
     newMessage.type = ServerMessageType.KERBAL_COMPLETE;
     SendToClient(client, newMessage, false);
     //Send vessel list needed for sync to the client
     SendVesselList(client);
 }
コード例 #29
0
 public void SendUnordered(ClientObject client, IMessage aMessage)
 {
     m_server.SendTo(aMessage, client.Id, GameServer.SendType.KUnordered);
 }
コード例 #30
0
 private static void SendVesselsComplete(ClientObject client)
 {
     ServerMessage newMessage = new ServerMessage();
     newMessage.type = ServerMessageType.VESSEL_COMPLETE;
     SendToClient(client, newMessage, false);
 }
コード例 #31
0
 public void SendUnreliable(ClientObject client, IMessage aMessage)
 {
     m_server.SendTo(aMessage, client.Id, GameServer.SendType.KUnreliable);
 }
コード例 #32
0
 private static void SetupClient(TcpClient newClientConnection)
 {
     ClientObject newClientObject = new ClientObject();
     newClientObject.subspace = GetLatestSubspace();
     newClientObject.playerStatus = new PlayerStatus();
     newClientObject.connectionStatus = ConnectionStatus.CONNECTED;
     newClientObject.endpoint = newClientConnection.Client.RemoteEndPoint.ToString();
     newClientObject.ipAddress = (newClientConnection.Client.RemoteEndPoint as IPEndPoint).Address;
     //Keep the connection reference
     newClientObject.connection = newClientConnection;
     StartReceivingIncomingMessages(newClientObject);
     StartSendingOutgoingMessages(newClientObject);
     DMPPluginHandler.FireOnClientConnect(newClientObject);
     SendHandshakeChallange(newClientObject);
     addClients.Enqueue(newClientObject);
 }
コード例 #33
0
 private static void SendNetworkMessage(ClientObject client, ServerMessage message)
 {
     //Write the send times down in SYNC_TIME_REPLY packets
     if (message.type == ServerMessageType.SYNC_TIME_REPLY)
     {
         try
         {
             using (MessageWriter mw = new MessageWriter())
             {
                 using (MessageReader mr = new MessageReader(message.data))
                 {
                     client.bytesQueuedOut += 8;
                     //Client send time
                     mw.Write <long>(mr.Read <long>());
                     //Server receive time
                     mw.Write <long>(mr.Read <long>());
                     //Server send time
                     mw.Write <long>(DateTime.UtcNow.Ticks);
                     message.data = mw.GetMessageBytes();
                 }
             }
         }
         catch (Exception e)
         {
             DarkLog.Debug("Error rewriting SYNC_TIME packet, Exception " + e);
         }
     }
     //Continue sending
     byte[] messageBytes = Common.PrependNetworkFrame((int)message.type, message.data);
     client.lastSendTime    = Server.serverClock.ElapsedMilliseconds;
     client.bytesQueuedOut -= messageBytes.Length;
     client.bytesSent      += messageBytes.Length;
     if (client.connectionStatus == ConnectionStatus.CONNECTED)
     {
         try
         {
             client.connection.GetStream().Write(messageBytes, 0, messageBytes.Length);
         }
         catch (Exception e)
         {
             HandleDisconnectException("Send Network Message", client, e);
             return;
         }
     }
     DMPPluginHandler.FireOnMessageSent(client, message);
     if (message.type == ServerMessageType.CONNECTION_END)
     {
         using (MessageReader mr = new MessageReader(message.data))
         {
             string reason = mr.Read <string>();
             DarkLog.Normal("Disconnecting client " + client.playerName + ", sent CONNECTION_END (" + reason + ") to endpoint " + client.endpoint);
             client.disconnectClient = true;
             DisconnectClient(client);
         }
     }
     if (message.type == ServerMessageType.HANDSHAKE_REPLY)
     {
         using (MessageReader mr = new MessageReader(message.data))
         {
             int    response = mr.Read <int>();
             string reason   = mr.Read <string>();
             if (response != 0)
             {
                 DarkLog.Normal("Disconnecting client " + client.playerName + ", sent HANDSHAKE_REPLY (" + reason + ") to endpoint " + client.endpoint);
                 client.disconnectClient = true;
                 DisconnectClient(client);
             }
         }
     }
 }
コード例 #34
0
 private static void CheckHeartBeat(ClientObject client)
 {
     long currentTime = Server.serverClock.ElapsedMilliseconds;
     if ((currentTime - client.lastReceiveTime) > Common.CONNECTION_TIMEOUT)
     {
         //Heartbeat timeout
         DarkLog.Normal("Disconnecting client " + client.playerName + ", endpoint " + client.endpoint + ", Connection timed out");
         DisconnectClient(client);
     }
     else
     {
         if (client.sendMessageQueueHigh.Count == 0 && client.sendMessageQueueSplit.Count == 0 && client.sendMessageQueueLow.Count == 0)
         {
             if ((currentTime - client.lastSendTime) > Common.HEART_BEAT_INTERVAL)
             {
                 SendHeartBeat(client);
             }
         }
     }
 }
コード例 #35
0
        private static void ReceiveCallback(IAsyncResult ar)
        {
            ClientObject client    = (ClientObject)ar.AsyncState;
            int          bytesRead = 0;

            try
            {
                bytesRead = client.connection.GetStream().EndRead(ar);
            }
            catch (Exception e)
            {
                HandleDisconnectException("ReceiveCallback", client, e);
                return;
            }
            if (bytesRead == 0)
            {
                DarkLog.Normal("Disconnected " + client.endpoint);
                DisconnectClient(client);
                return;
            }
            client.bytesReceived           += bytesRead;
            client.receiveMessageBytesLeft -= bytesRead;
            if (client.receiveMessageBytesLeft == 0)
            {
                //We either have the header or the message data, let's do something
                if (!client.isReceivingMessage)
                {
                    //We have the header
                    using (MessageReader mr = new MessageReader(client.receiveMessage.data))
                    {
                        int messageType   = mr.Read <int>();
                        int messageLength = mr.Read <int>();
                        if (messageType < 0 || messageType > (Enum.GetNames(typeof(ClientMessageType)).Length - 1))
                        {
                            //Malformed message, most likely from a non DMP-client.
                            Messages.ConnectionEnd.SendConnectionEnd(client, "Invalid DMP message. Disconnected.");
                            DarkLog.Normal("Invalid DMP message from " + client.endpoint);
                            //Returning from ReceiveCallback will break the receive loop and stop processing any further messages.
                            return;
                        }
                        client.receiveMessage.type = (ClientMessageType)messageType;
                        if (messageLength == 0)
                        {
                            //Null message, handle it.
                            client.receiveMessage.data = null;
                            HandleMessage(client, client.receiveMessage);
                            client.receiveMessage.type     = 0;
                            client.receiveMessage.data     = new byte[8];
                            client.receiveMessageBytesLeft = client.receiveMessage.data.Length;
                        }
                        else
                        {
                            if (messageLength > 0 && messageLength < Common.MAX_MESSAGE_SIZE)
                            {
                                client.isReceivingMessage      = true;
                                client.receiveMessage.data     = new byte[messageLength];
                                client.receiveMessageBytesLeft = client.receiveMessage.data.Length;
                            }
                            else
                            {
                                //Malformed message, most likely from a non DMP-client.
                                Messages.ConnectionEnd.SendConnectionEnd(client, "Invalid DMP message. Disconnected.");
                                DarkLog.Normal("Invalid DMP message from " + client.endpoint);
                                //Returning from ReceiveCallback will break the receive loop and stop processing any further messages.
                                return;
                            }
                        }
                    }
                }
                else
                {
                    //We have the message data to a non-null message, handle it
                    client.isReceivingMessage = false;
#if !DEBUG
                    try
                    {
#endif
                    HandleMessage(client, client.receiveMessage);
#if !DEBUG
                }
                catch (Exception e)
                {
                    HandleDisconnectException("ReceiveCallback", client, e);
                    return;
                }
#endif
                    client.receiveMessage.type     = 0;
                    client.receiveMessage.data     = new byte[8];
                    client.receiveMessageBytesLeft = client.receiveMessage.data.Length;
                }
            }
            if (client.connectionStatus == ConnectionStatus.CONNECTED)
            {
                client.lastReceiveTime = Server.serverClock.ElapsedMilliseconds;
                try
                {
                    client.connection.GetStream().BeginRead(client.receiveMessage.data, client.receiveMessage.data.Length - client.receiveMessageBytesLeft, client.receiveMessageBytesLeft, new AsyncCallback(ReceiveCallback), client);
                }
                catch (Exception e)
                {
                    HandleDisconnectException("ReceiveCallback", client, e);
                    return;
                }
            }
        }
コード例 #36
0
 private static void SendOutgoingMessages(ClientObject client)
 {
     while (client.connectionStatus == ConnectionStatus.CONNECTED)
     {
         ServerMessage message = null;
         if (message == null && client.sendMessageQueueHigh.Count > 0)
         {
             client.sendMessageQueueHigh.TryDequeue(out message);
         }
         //Don't send low or split during server shutdown.
         if (Server.serverRunning)
         {
             if (message == null && client.sendMessageQueueSplit.Count > 0)
             {
                 client.sendMessageQueueSplit.TryDequeue(out message);
             }
             if (message == null && client.sendMessageQueueLow.Count > 0)
             {
                 client.sendMessageQueueLow.TryDequeue(out message);
                 //Splits large messages to higher priority messages can get into the queue faster
                 SplitAndRewriteMessage(client, ref message);
             }
         }
         if (message != null)
         {
             SendNetworkMessage(client, message);
         }
         else
         {
             //Give the chance for the thread to terminate
             client.sendEvent.WaitOne(1000);
         }
     }
 }
コード例 #37
0
        internal static void HandleMessage(ClientObject client, ClientMessage message)
        {
            //Prevent plugins from dodging SPLIT_MESSAGE. If they are modified, every split message will be broken.
            if (message.type != ClientMessageType.SPLIT_MESSAGE)
            {
                DMPPluginHandler.FireOnMessageReceived(client, message);

                if (message.handled)
                {
                    //a plugin has handled this message and requested suppression of the default DMP behavior
                    return;
                }
            }

            //Clients can only send HEARTBEATS, HANDSHAKE_REQUEST or CONNECTION_END's until they are authenticated.
            if (!client.authenticated && !(message.type == ClientMessageType.HEARTBEAT || message.type == ClientMessageType.HANDSHAKE_RESPONSE || message.type == ClientMessageType.CONNECTION_END))
            {
                Messages.ConnectionEnd.SendConnectionEnd(client, "You must authenticate before attempting to send a " + message.type.ToString() + " message");
                return;
            }

#if !DEBUG
            try
            {
#endif
            switch (message.type)
            {
            case ClientMessageType.HEARTBEAT:
                //Don't do anything for heartbeats, they just keep the connection alive
                break;

            case ClientMessageType.HANDSHAKE_RESPONSE:
                Messages.Handshake.HandleHandshakeResponse(client, message.data);
                break;

            case ClientMessageType.CHAT_MESSAGE:
                Messages.Chat.HandleChatMessage(client, message.data);
                break;

            case ClientMessageType.PLAYER_STATUS:
                Messages.PlayerStatus.HandlePlayerStatus(client, message.data);
                break;

            case ClientMessageType.PLAYER_COLOR:
                Messages.PlayerColor.HandlePlayerColor(client, message.data);
                break;

            case ClientMessageType.GROUP:
                Messages.GroupMessage.HandleMessage(client, message.data);
                break;

            case ClientMessageType.SCENARIO_DATA:
                Messages.ScenarioData.HandleScenarioModuleData(client, message.data);
                break;

            case ClientMessageType.SYNC_TIME_REQUEST:
                Messages.SyncTimeRequest.HandleSyncTimeRequest(client, message.data);
                break;

            case ClientMessageType.KERBALS_REQUEST:
                Messages.KerbalsRequest.HandleKerbalsRequest(client);
                break;

            case ClientMessageType.KERBAL_PROTO:
                Messages.KerbalProto.HandleKerbalProto(client, message.data);
                break;

            case ClientMessageType.VESSELS_REQUEST:
                Messages.VesselRequest.HandleVesselsRequest(client, message.data);
                break;

            case ClientMessageType.VESSEL_PROTO:
                Messages.VesselProto.HandleVesselProto(client, message.data);
                break;

            case ClientMessageType.VESSEL_UPDATE:
                Messages.VesselUpdate.HandleVesselUpdate(client, message.data);
                break;

            case ClientMessageType.VESSEL_REMOVE:
                Messages.VesselRemove.HandleVesselRemoval(client, message.data);
                break;

            case ClientMessageType.PERMISSION:
                Messages.PermissionMessage.HandleMessage(client, message.data);
                break;

            case ClientMessageType.CRAFT_LIBRARY:
                Messages.CraftLibrary.HandleCraftLibrary(client, message.data);
                break;

            case ClientMessageType.SCREENSHOT_LIBRARY:
                Messages.ScreenshotLibrary.HandleScreenshotLibrary(client, message.data);
                break;

            case ClientMessageType.FLAG_SYNC:
                Messages.FlagSync.HandleFlagSync(client, message.data);
                break;

            case ClientMessageType.PING_REQUEST:
                Messages.PingRequest.HandlePingRequest(client, message.data);
                break;

            case ClientMessageType.MOTD_REQUEST:
                Messages.MotdRequest.HandleMotdRequest(client);
                break;

            case ClientMessageType.WARP_CONTROL:
                Messages.WarpControl.HandleWarpControl(client, message.data);
                break;

            case ClientMessageType.LOCK_SYSTEM:
                Messages.LockSystem.HandleLockSystemMessage(client, message.data);
                break;

            case ClientMessageType.MOD_DATA:
                Messages.ModData.HandleModDataMessage(client, message.data);
                break;

            case ClientMessageType.KERBAL_REMOVE:
                Messages.VesselRemove.HandleKerbalRemoval(client, message.data);
                break;

            case ClientMessageType.SPLIT_MESSAGE:
                Messages.SplitMessage.HandleSplitMessage(client, message.data);
                break;

            case ClientMessageType.CONNECTION_END:
                Messages.ConnectionEnd.HandleConnectionEnd(client, message.data);
                break;

            case ClientMessageType.MODPACK_DATA:
                Messages.Modpack.HandleModpackMessage(client, message.data);
                break;

            default:
                DarkLog.Debug("Unhandled message type " + message.type);
                Messages.ConnectionEnd.SendConnectionEnd(client, "Unhandled message type " + message.type);
#if DEBUG
                throw new NotImplementedException("Message type not implemented");
#else
                break;
#endif
            }
#if !DEBUG
        }

        catch (Exception e)
        {
            DarkLog.Debug("Error handling " + message.type + " from " + client.playerName + ", exception: " + e);
            Messages.ConnectionEnd.SendConnectionEnd(client, "Server failed to process " + message.type + " message");
        }
#endif
        }
コード例 #38
0
 private static void SendNetworkMessage(ClientObject client, ServerMessage message)
 {
     //Write the send times down in SYNC_TIME_REPLY packets
     if (message.type == ServerMessageType.SYNC_TIME_REPLY)
     {
         try
         {
             using (MessageWriter mw = new MessageWriter())
             {
                 using (MessageReader mr = new MessageReader(message.data, false))
                 {
                     client.bytesQueuedOut += 8;
                     //Client send time
                     mw.Write<long>(mr.Read<long>());
                     //Server receive time
                     mw.Write<long>(mr.Read<long>());
                     //Server send time
                     mw.Write<long>(DateTime.UtcNow.Ticks);
                     message.data = mw.GetMessageBytes();
                 }
             }
         }
         catch (Exception e)
         {
             DarkLog.Debug("Error rewriting SYNC_TIME packet, Exception " + e);
         }
     }
     //Continue sending
     byte[] messageBytes;
     using (MessageWriter mw = new MessageWriter((int)message.type))
     {
         if (message.data != null)
         {
             mw.Write<byte[]>(message.data);
         }
         messageBytes = mw.GetMessageBytes();
     }
     client.lastSendTime = Server.serverClock.ElapsedMilliseconds;
     client.bytesQueuedOut -= messageBytes.Length;
     client.bytesSent += messageBytes.Length;
     if (client.connectionStatus == ConnectionStatus.CONNECTED)
     {
         try
         {
             client.connection.GetStream().Write(messageBytes, 0, messageBytes.Length);
         }
         catch (Exception e)
         {
             HandleDisconnectException("Send Network Message", client, e);
             return;
         }
     }
     if (message.type == ServerMessageType.CONNECTION_END)
     {
         using (MessageReader mr = new MessageReader(message.data, false))
         {
             string reason = mr.Read<string>();
             DarkLog.Normal("Disconnecting client " + client.playerName + ", sent CONNECTION_END (" + reason + ") to endpoint " + client.endpoint);
             client.disconnectClient = true;
             DisconnectClient(client);
         }
     }
     if (message.type == ServerMessageType.HANDSHAKE_REPLY)
     {
         using (MessageReader mr = new MessageReader(message.data, false))
         {
             int response = mr.Read<int>();
             string reason = mr.Read<string>();
             if (response != 0)
             {
                 DarkLog.Normal("Disconnecting client " + client.playerName + ", sent HANDSHAKE_REPLY (" + reason + ") to endpoint " + client.endpoint);
                 client.disconnectClient = true;
                 DisconnectClient(client);
             }
         }
     }
 }
コード例 #39
0
        public static void SendToClient(ClientObject client, ServerMessage message, bool highPriority)
        {
            //Because we dodge the queue, we need to lock it up again...
            lock (client.sendLock)
            {
                if (message == null)
                {
                    return;
                }
                //All messages have an 8 byte header
                client.bytesQueuedOut += 8;
                if (message.data != null)
                {
                    //Count the payload if we have one.
                    client.bytesQueuedOut += message.data.Length;
                }
                if (highPriority)
                {
                    client.sendMessageQueueHigh.Enqueue(message);
                }
                else
                {
                    client.sendMessageQueueLow.Enqueue(message);
                    //If we need to optimize
                    if (client.bytesQueuedOut > OPTIMIZE_QUEUE_LIMIT)
                    {
                        //And we haven't optimized in the last 5 seconds
                        long currentTime    = DateTime.UtcNow.Ticks;
                        long optimizedBytes = 0;
                        if ((currentTime - client.lastQueueOptimizeTime) > 50000000)
                        {
                            client.lastQueueOptimizeTime = currentTime;
                            DarkLog.Debug("Optimizing " + client.playerName + " (" + client.bytesQueuedOut + " bytes queued)");

                            //Create a temporary filter list
                            List <ServerMessage> oldClientMessagesToSend = new List <ServerMessage>();
                            List <ServerMessage> newClientMessagesToSend = new List <ServerMessage>();
                            //Steal all the messages from the queue and put them into a list
                            ServerMessage stealMessage = null;
                            while (client.sendMessageQueueLow.TryDequeue(out stealMessage))
                            {
                                oldClientMessagesToSend.Add(stealMessage);
                            }
                            //Clear the client send queue
                            List <string> seenProtovesselUpdates = new List <string>();
                            List <string> seenPositionUpdates    = new List <string>();
                            //Iterate backwards over the list
                            oldClientMessagesToSend.Reverse();
                            foreach (ServerMessage currentMessage in oldClientMessagesToSend)
                            {
                                if (currentMessage.type != ServerMessageType.VESSEL_PROTO && currentMessage.type != ServerMessageType.VESSEL_UPDATE)
                                {
                                    //Message isn't proto or position, don't skip it.
                                    newClientMessagesToSend.Add(currentMessage);
                                }
                                else
                                {
                                    //Message is proto or position
                                    if (currentMessage.type == ServerMessageType.VESSEL_PROTO)
                                    {
                                        using (MessageReader mr = new MessageReader(currentMessage.data))
                                        {
                                            //Don't care about the send time, it's already the latest in the queue.
                                            mr.Read <double>();
                                            string vesselID = mr.Read <string>();
                                            if (!seenProtovesselUpdates.Contains(vesselID))
                                            {
                                                seenProtovesselUpdates.Add(vesselID);
                                                newClientMessagesToSend.Add(currentMessage);
                                            }
                                            else
                                            {
                                                optimizedBytes += 8 + currentMessage.data.Length;
                                            }
                                        }
                                    }

                                    if (currentMessage.type == ServerMessageType.VESSEL_UPDATE)
                                    {
                                        using (MessageReader mr = new MessageReader(currentMessage.data))
                                        {
                                            //Don't care about the send time, it's already the latest in the queue.
                                            mr.Read <double>();
                                            string vesselID = mr.Read <string>();
                                            if (!seenPositionUpdates.Contains(vesselID))
                                            {
                                                seenPositionUpdates.Add(vesselID);
                                                newClientMessagesToSend.Add(currentMessage);
                                            }
                                            else
                                            {
                                                //8 byte message header plus payload
                                                optimizedBytes += 8 + currentMessage.data.Length;
                                            }
                                        }
                                    }
                                }
                            }
                            //Flip it back to the right order
                            newClientMessagesToSend.Reverse();
                            foreach (ServerMessage putBackMessage in newClientMessagesToSend)
                            {
                                client.sendMessageQueueLow.Enqueue(putBackMessage);
                            }
                            float optimizeTime = (DateTime.UtcNow.Ticks - currentTime) / 10000f;
                            client.bytesQueuedOut -= optimizedBytes;
                            DarkLog.Debug("Optimized " + optimizedBytes + " bytes in " + Math.Round(optimizeTime, 3) + " ms.");
                        }
                    }
                }
                client.sendEvent.Set();
            }
        }
コード例 #40
0
 private static void HandleDisconnectException(string location, ClientObject client, Exception e)
 {
     lock (client.disconnectLock)
     {
         if (!client.disconnectClient && client.connectionStatus != ConnectionStatus.DISCONNECTED)
         {
             if (e.InnerException != null)
             {
                 DarkLog.Normal("Client " + client.playerName + " disconnected in " + location + ", endpoint " + client.endpoint + ", error: " + e.Message + " (" + e.InnerException.Message + ")");
             }
             else
             {
                 DarkLog.Normal("Client " + client.playerName + " disconnected in " + location + ", endpoint " + client.endpoint + ", error: " + e.Message);
             }
         }
         DisconnectClient(client);
     }
 }
コード例 #41
0
 public static bool ClientConnected(ClientObject client)
 {
     return(clients.Contains(client));
 }
コード例 #42
0
        private static void HandleMessage(ClientObject client, ClientMessage message)
        {
            //Prevent plugins from dodging SPLIT_MESSAGE. If they are modified, every split message will be broken.
            if (message.type != ClientMessageType.SPLIT_MESSAGE)
            {
                DMPPluginHandler.FireOnMessageReceived(client, message);

                if (message.handled)
                {
                    //a plugin has handled this message and requested suppression of the default DMP behavior
                    return;
                }
            }

            //Clients can only send HEARTBEATS, HANDSHAKE_REQUEST or CONNECTION_END's until they are authenticated.
            if (!client.authenticated && !(message.type == ClientMessageType.HEARTBEAT || message.type == ClientMessageType.HANDSHAKE_RESPONSE || message.type == ClientMessageType.CONNECTION_END))
            {
                SendConnectionEnd(client, "You must authenticate before attempting to send a " + message.type.ToString() + " message");
                return;
            }

            try
            {
                switch (message.type)
                {
                    case ClientMessageType.HEARTBEAT:
                        //Don't do anything for heartbeats, they just keep the connection alive
                        break;
                    case ClientMessageType.HANDSHAKE_RESPONSE:
                        HandleHandshakeResponse(client, message.data);
                        break;
                    case ClientMessageType.CHAT_MESSAGE:
                        HandleChatMessage(client, message.data);
                        break;
                    case ClientMessageType.PLAYER_STATUS:
                        HandlePlayerStatus(client, message.data);
                        break;
                    case ClientMessageType.PLAYER_COLOR:
                        HandlePlayerColor(client, message.data);
                        break;
                    case ClientMessageType.SCENARIO_DATA:
                        HandleScenarioModuleData(client, message.data);
                        break;
                    case ClientMessageType.SYNC_TIME_REQUEST:
                        HandleSyncTimeRequest(client, message.data);
                        break;
                    case ClientMessageType.KERBALS_REQUEST:
                        HandleKerbalsRequest(client);
                        break;
                    case ClientMessageType.KERBAL_PROTO:
                        HandleKerbalProto(client, message.data);
                        break;
                    case ClientMessageType.VESSELS_REQUEST:
                        HandleVesselsRequest(client, message.data);
                        break;
                    case ClientMessageType.VESSEL_PROTO:
                        HandleVesselProto(client, message.data);
                        break;
                    case ClientMessageType.VESSEL_UPDATE:
                        HandleVesselUpdate(client, message.data);
                        break;
                    case ClientMessageType.VESSEL_REMOVE:
                        HandleVesselRemoval(client, message.data);
                        break;
                    case ClientMessageType.CRAFT_LIBRARY:
                        HandleCraftLibrary(client, message.data);
                        break;
                    case ClientMessageType.SCREENSHOT_LIBRARY:
                        HandleScreenshotLibrary(client, message.data);
                        break;
                    case ClientMessageType.FLAG_SYNC:
                        HandleFlagSync(client, message.data);
                        break;
                    case ClientMessageType.PING_REQUEST:
                        HandlePingRequest(client, message.data);
                        break;
                    case ClientMessageType.MOTD_REQUEST:
                        HandleMotdRequest(client);  
                        break;
                    case ClientMessageType.WARP_CONTROL:
                        HandleWarpControl(client, message.data);
                        break;
                    case ClientMessageType.LOCK_SYSTEM:
                        HandleLockSystemMessage(client, message.data);
                        break;
                    case ClientMessageType.MOD_DATA:
                        HandleModDataMessage(client, message.data);
                        break;
                    case ClientMessageType.SPLIT_MESSAGE:
                        HandleSplitMessage(client, message.data);
                        break;
                    case ClientMessageType.CONNECTION_END:
                        HandleConnectionEnd(client, message.data);
                        break;
                    default:
                        DarkLog.Debug("Unhandled message type " + message.type);
                        SendConnectionEnd(client, "Unhandled message type " + message.type);
                        break;
                }
            }
            catch (Exception e)
            {
                DarkLog.Debug("Error handling " + message.type + " from " + client.playerName + ", exception: " + e);
                SendConnectionEnd(client, "Server failed to process " + message.type + " message");
            }
        }
コード例 #43
0
 private static void SendAllPlayerStatus(ClientObject client)
 {
     foreach (ClientObject otherClient in clients)
     {
         if (otherClient.authenticated)
         {
             if (otherClient != client)
             {
                 ServerMessage newMessage = new ServerMessage();
                 newMessage.type = ServerMessageType.PLAYER_STATUS;
                 using (MessageWriter mw = new MessageWriter())
                 {
                     mw.Write<string>(otherClient.playerName);
                     mw.Write<string>(otherClient.playerStatus.vesselText);
                     mw.Write<string>(otherClient.playerStatus.statusText);
                     newMessage.data = mw.GetMessageBytes();
                 }
                 SendToClient(client, newMessage, true);
             }
         }
     }
 }