Esempio n. 1
0
        public static string GetClientAlertSubject(ClientMessageType alertType, Job job)
        {
            string subject = String.Empty;

            switch (alertType)
            {
            case ClientMessageType.Estimate:
                subject = "Estimate for Work Request - No. " + job.JobId.ToString();
                break;

            case ClientMessageType.JobCanceled:
                subject = "Notice of Job Cancellation - Job No. " + job.JobId.ToString();
                break;

            case ClientMessageType.JobCompleted:
                subject = "Notice of Job Completion - Job No. " + job.JobId.ToString();
                break;

            case ClientMessageType.JobDeclined:
                subject = "Unable to Accept Work Request - No. " + job.JobId.ToString();
                break;

            case ClientMessageType.General:
                subject = "Notice Regarding Job No. " + job.JobId.ToString();
                break;
            }

            return(subject);
        }
Esempio n. 2
0
        /// <summary>
        /// Called when replying to messages recieved from the client
        /// </summary>
        private void SendReplyMessage(NetConnection netConnection, ClientMessageType messageType, int feedback, string jsonBody = null)
        {
            //Determine how to send the data
            DetermineMethodandChannel(messageType, out NetDeliveryMethod deliverymethod, out int?sequenceChannel);

            //Send the message
            lidgrenServer.SendMessage(false, (byte)messageType, netConnection, deliverymethod, feedback, sequenceChannel, jsonBody);
        }
 /// <summary>
 /// Sends data over the connection asynchronously.
 /// </summary>
 /// <param name="buffer">The buffer to be sent over the connection.</param>
 /// <param name="messageType">TIndicates whether the application is sending a binary or text message.</param>
 /// <param name="endOfMessage">Indicates whether the data in "buffer" is the last part of a message.</param>
 /// <param name="cancellationToken">The token that propagates the notification that operations should be canceled.</param>
 /// <returns>Task.</returns>
 public Task SendAsync(ArraySegment <byte> buffer, ClientMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
 {
     return(_webSocket.SendAsync(
                buffer,
                messageType.ToWebSocketMessageType(),
                endOfMessage,
                cancellationToken));
 }
Esempio n. 4
0
        /// <summary>
        /// Called when creating a new message from the server
        /// </summary>
        private void SendNewMessage(ClientMessageType messageType, string jsonBody = null)
        {
            //Determine how to send the data
            DetermineMethodandChannel(messageType, out NetDeliveryMethod deliverymethod, out int?sequenceChannel);

            //Send the message
            lidgrenClient.SendMessage(true, (byte)messageType, deliverymethod, null, sequenceChannel, jsonBody);
        }
 public TestClientSettings(string host, int concurrentClients, int totalClients, int requestsPerClient, ClientMessageType messageType)
 {
     Host = host;
     ConcurrentClients = concurrentClients;
     TotalClients = totalClients;
     RequestsPerClient = requestsPerClient;
     MessageType = messageType;
 }
Esempio n. 6
0
        public void SendBytes(ClientMessageType type, byte[] msg)
        {
            byte[] buffer = new byte[msg.Length + 1];
            buffer[0] = (byte)type;
            msg.CopyTo(buffer, 1);

            stream.Write(buffer, 0, buffer.Length);
        }
Esempio n. 7
0
 public static Offset <ClientMessage> CreateClientMessage(FlatBufferBuilder builder,
                                                          ushort clientId            = 0,
                                                          ClientMessageType msg_type = ClientMessageType.NONE,
                                                          int msgOffset = 0)
 {
     builder.StartObject(3);
     ClientMessage.AddMsg(builder, msgOffset);
     ClientMessage.AddClientId(builder, clientId);
     ClientMessage.AddMsgType(builder, msg_type);
     return(ClientMessage.EndClientMessage(builder));
 }
Esempio n. 8
0
        /// <summary>
        /// Messages from client to server.
        /// </summary>
        /// <param name="message"></param>
        private void OnClientDispatch(object sender, NetworkMessageEventArgs e)
        {
            ClientMessageType clientMessageType = (ClientMessageType)e.Message.Type;

            switch (clientMessageType)
            {
            case ClientMessageType.GameAction:
                DispatchGameAction(e.Message);
                break;
            }
        }
        /// <summary>
        /// Sends data over the connection asynchronously.
        /// </summary>
        /// <param name="buffer">The buffer to be sent over the connection.</param>
        /// <param name="messageType">TIndicates whether the application is sending a binary or text message.</param>
        /// <param name="endOfMessage">Indicates whether the data in "buffer" is the last part of a message.</param>
        /// <param name="cancellationToken">The token that propagates the notification that operations should be canceled.</param>
        /// <returns>Task.</returns>
        public Task SendAsync(ArraySegment <byte> buffer, ClientMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
        {
            var message = new MockClientMessage(buffer.ToArray(), messageType, endOfMessage);

            lock (_outgoingMessageQueue)
            {
                _outgoingMessageQueue.Enqueue(message);
            }

            return(Task.CompletedTask);
        }
Esempio n. 10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MockClientMessage" /> class.
 /// </summary>
 /// <param name="data">The data.</param>
 /// <param name="messageType">Type of the message.</param>
 /// <param name="isEndOfMessage">The is end of message.</param>
 /// <param name="closeStatus">The close status.</param>
 /// <param name="closeDescription">The close description.</param>
 public MockClientMessage(
     byte[] data,
     ClientMessageType messageType,
     bool isEndOfMessage = false,
     ClientConnectionCloseStatus?closeStatus = null,
     string closeDescription = null)
 {
     this.Data                   = data;
     this.MessageType            = messageType;
     this.CloseStatus            = closeStatus;
     this.CloseStatusDescription = closeDescription;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="MockClientMessageResult" /> class.
 /// </summary>
 /// <param name="byteCount">The byte count.</param>
 /// <param name="messageType">Type of the message.</param>
 /// <param name="isEndOfMessage">The is end of message.</param>
 /// <param name="closeStatus">The close status.</param>
 /// <param name="closeDescription">The close description.</param>
 public MockClientMessageResult(
     int byteCount,
     ClientMessageType messageType,
     bool isEndOfMessage = false,
     ClientConnectionCloseStatus?closeStatus = null,
     string closeDescription = null)
 {
     this.Count                  = byteCount;
     this.MessageType            = messageType;
     this.CloseStatus            = closeStatus;
     this.CloseStatusDescription = closeDescription;
     this.EndOfMessage           = isEndOfMessage;
 }
Esempio n. 12
0
 public void RecordSend(byte[] data, ClientMessageType messageType)
 {
     if (!active)
     {
         return;
     }
     using (MessageWriter mw = new MessageWriter())
     {
         mw.Write <int>((int)messageType);
         mw.Write <int>(data.Length);
         byte[] headerData = mw.GetMessageBytes();
         recording.Write(headerData, 0, headerData.Length);
     }
     recording.Write(data, 0, data.Length);
 }
Esempio n. 13
0
        public ClientMessage(ClientMessageType Type)
        {
            MessageType = Type;

            if (MyAPIGateway.Multiplayer != null && !MyAPIGateway.Multiplayer.IsServer)
            {
                if (MyAPIGateway.Session.LocalHumanPlayer == null)
                {
                    return;
                }

                IdentityID    = MySession.Static?.LocalHumanPlayer?.Identity?.IdentityId ?? 0;
                SteamID       = MySession.Static?.LocalHumanPlayer?.Id.SteamId ?? 0;
                PluginVersion = SeamlessClient.Version;
            }
        }
        /// <summary>
        /// Sends data to the <see cref="INetworkSender"/>. This method is thread-safe.
        /// </summary>
        /// <param name="sender">The <see cref="INetworkSender"/> to use to send the data.</param>
        /// <param name="data">BitStream containing the data to send to the User.</param>
        /// <param name="messageType">The <see cref="ClientMessageType"/> to use for sending the <paramref name="data"/>.</param>
        public static void Send(this INetworkSender sender, BitStream data, ClientMessageType messageType)
        {
            if (!sender.IsConnected)
            {
                const string errmsg = "Send to `{0}` failed - not connected.";
                if (log.IsErrorEnabled)
                    log.ErrorFormat(errmsg, sender);
                Debug.Fail(string.Format(errmsg, sender));
                return;
            }

            NetDeliveryMethod method;
            int seqChannel;
            messageType.GetDeliveryMethod(out method, out seqChannel);

            sender.Send(data, method, seqChannel);
        }
    public byte[] ConstructClientGoodbye(ClientMessageType type, ushort clientId)
    {
        fbBuilder.Clear();

        ClientGoodbye.StartClientGoodbye(fbBuilder);
        Offset <ClientGoodbye> clientGoodbyeOffset = ClientGoodbye.EndClientGoodbye(fbBuilder);

        ClientMessage.StartClientMessage(fbBuilder);
        //var clientIdOffset = clientId;
        ClientMessage.AddClientId(fbBuilder, clientId);
        ClientMessage.AddMsgType(fbBuilder, type);
        ClientMessage.AddMsg(fbBuilder, clientGoodbyeOffset.Value);
        Offset <ClientMessage> clientMessageOffset = ClientMessage.EndClientMessage(fbBuilder);

        ClientMessage.FinishClientMessageBuffer(fbBuilder, clientMessageOffset);

        return(fbBuilder.SizedByteArray());
    }
Esempio n. 16
0
 public void RecordSend(ByteArray data, ClientMessageType messageType, Guid vesselID)
 {
     if (!active)
     {
         return;
     }
     if (HighLogic.LoadedSceneIsFlight && FlightGlobals.fetch != null && FlightGlobals.fetch.activeVessel != null && FlightGlobals.fetch.activeVessel.id == vesselID)
     {
         using (MessageWriter mw = new MessageWriter())
         {
             mw.Write <int>((int)messageType);
             mw.Write <int>(data.Length);
             byte[] headerData = mw.GetMessageBytes();
             recording.Write(headerData, 0, headerData.Length);
         }
         recording.Write(data.data, 0, data.Length);
     }
 }
    public byte[] ConstructTickAck(ClientMessageType type, ushort clientId, uint tick)
    {
        fbBuilder.Clear();

        TickAck.StartTickAck(fbBuilder);
        TickAck.AddTick(fbBuilder, tick);
        Offset <TickAck> tickAckOffset = TickAck.EndTickAck(fbBuilder);

        ClientMessage.StartClientMessage(fbBuilder);
        //var clientIdOffset = clientId;
        ClientMessage.AddClientId(fbBuilder, clientId);
        ClientMessage.AddMsgType(fbBuilder, type);
        ClientMessage.AddMsg(fbBuilder, tickAckOffset.Value);
        Offset <ClientMessage> clientMessageOffset = ClientMessage.EndClientMessage(fbBuilder);

        ClientMessage.FinishClientMessageBuffer(fbBuilder, clientMessageOffset);

        return(fbBuilder.SizedByteArray());
    }
        /* Documentation on Delivery Methods
         * Unreliable              This is just UDP. Messages can be lost or received more than once.
         *                      Messages may not be received in the same order as they were sent.
         *
         * UnreliableSequenced     Using this delivery method messages can still be lost; but you're protected against duplicated messages.
         *                      If a message arrives late; that is, if a message sent after this one has already been received - it will be dropped.
         *                      This means you will never receive "older" data than what you already have received.
         *
         * ReliableUnordered       This delivery method ensures that every message sent will be eventually received.
         *                      It does not however guarantee what order they will be received in; late messages may be delivered before newer ones.
         *
         * ReliableSequenced       This delivery method is similar to UnreliableSequenced; except that it guarantees that SOME messages will be received
         *                      - if you only send one message - it will be received.
         *                      If you sent two messages quickly, and they get reordered in transit, only the newest message will be received
         *                      - but at least ONE of them will be received.
         *
         * ReliableOrdered         This delivery method guarantees that messages will always be received in the exact order they were sent.
         */

        public static void DetermineMethodandChannel(ClientMessageType messageType, out NetDeliveryMethod deliverymethod, out int?sequenceChannel)
        {
            //Determine the delivery type and if needed, the sequence channel
            sequenceChannel = null;

            switch (messageType)
            {
            case ClientMessageType.Beat:
                throw new Exception("Shouldn't be sending beats this way (Specific beat function that recycles message)");

            case ClientMessageType.SendName:
                deliverymethod  = NetDeliveryMethod.ReliableOrdered;
                sequenceChannel = 0;
                break;

            default:
                throw new Exception("Could not determine datatype");
            }
        }
Esempio n. 19
0
        void ILidgrenClientEvents.HandleReplyMessage(ClientMessageType messageType, int feedback, string jsonBody)
        {
            try
            {
                //Switch on the message type and have it handled by specific methods so as to not clutter this area
                switch (messageType)
                {
                case ClientMessageType.SendName:
                    SendNameReply?.Invoke(feedback, jsonBody);
                    break;

                default:
                    throw new Exception($"Unhandled message type {messageType}");
                }
            }
            catch (Exception ex)
            {
                LogMessage($"Error handling reply message type {messageType} with feedback {feedback}, error: {ex.Message}");
            }
        }
Esempio n. 20
0
        /// <summary>
        /// Sends data to the <see cref="INetworkSender"/>. This method is thread-safe.
        /// </summary>
        /// <param name="sender">The <see cref="INetworkSender"/> to use to send the data.</param>
        /// <param name="data">BitStream containing the data to send to the User.</param>
        /// <param name="messageType">The <see cref="ClientMessageType"/> to use for sending the <paramref name="data"/>.</param>
        public static void Send(this INetworkSender sender, BitStream data, ClientMessageType messageType)
        {
            if (!sender.IsConnected)
            {
                const string errmsg = "Send to `{0}` failed - not connected.";
                if (log.IsErrorEnabled)
                {
                    log.ErrorFormat(errmsg, sender);
                }
                Debug.Fail(string.Format(errmsg, sender));
                return;
            }

            NetDeliveryMethod method;
            int seqChannel;

            messageType.GetDeliveryMethod(out method, out seqChannel);

            sender.Send(data, method, seqChannel);
        }
    public byte[] ConstructClientHello(ClientMessageType type, ushort clientId, string playerName)
    {
        fbBuilder.Clear();

        StringOffset playerNameOffset = fbBuilder.CreateString(playerName);

        ClientHello.StartClientHello(fbBuilder);
        ClientHello.AddPlayerName(fbBuilder, playerNameOffset);
        Offset <ClientHello> clientHelloOffset = ClientHello.EndClientHello(fbBuilder);

        ClientMessage.StartClientMessage(fbBuilder);
        //var clientIdOffset = clientId;
        ClientMessage.AddClientId(fbBuilder, clientId);
        ClientMessage.AddMsgType(fbBuilder, type);
        ClientMessage.AddMsg(fbBuilder, clientHelloOffset.Value);
        Offset <ClientMessage> clientMessageOffset = ClientMessage.EndClientMessage(fbBuilder);

        ClientMessage.FinishClientMessageBuffer(fbBuilder, clientMessageOffset);

        return(fbBuilder.SizedByteArray());
    }
Esempio n. 22
0
        public override bool Handle(ClientMessageType messageType, uint clientId, byte[] buffer, int count)
        {
            if (!_messageTypeMapping.TryGetValue(messageType, out var clientMessageType))
            {
                return(false);
            }

            if (!_handlerMethods.TryGetValue(messageType, out var handlerMethod))
            {
                return(false);
            }

            var buff          = new ArraySegment <byte>(buffer, 1, count).ToArray();
            var gcHandle      = GCHandle.Alloc(buff, GCHandleType.Pinned);
            var clientMessage = (IClientMessage)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), clientMessageType);

            gcHandle.Free();

            handlerMethod.Invoke(clientId, clientMessage);
            return(true);
        }
    public byte[] ConstructClientInputState(ClientMessageType type, ushort clientId, uint tick, Vector3 desiredMove, bool isTurbo)
    {
        fbBuilder.Clear();


        ClientInputState.StartClientInputState(fbBuilder);
        ClientInputState.AddTick(fbBuilder, tick);
        ClientInputState.AddDesiredMove(fbBuilder, Vec2.CreateVec2(fbBuilder, desiredMove.x, desiredMove.y));
        ClientInputState.AddIsTurbo(fbBuilder, isTurbo);
        Offset <ClientInputState> clientInputStateOffset = ClientInputState.EndClientInputState(fbBuilder);

        ClientMessage.StartClientMessage(fbBuilder);
        //var clientIdOffset = clientId;
        ClientMessage.AddClientId(fbBuilder, clientId);
        ClientMessage.AddMsgType(fbBuilder, type);
        ClientMessage.AddMsg(fbBuilder, clientInputStateOffset.Value);
        Offset <ClientMessage> clientMessageOffset = ClientMessage.EndClientMessage(fbBuilder);

        ClientMessage.FinishClientMessageBuffer(fbBuilder, clientMessageOffset);

        return(fbBuilder.SizedByteArray());
    }
 public void ToClientMessageType(WebSocketMessageType messageType, ClientMessageType expectedType)
 {
     Assert.AreEqual(expectedType, messageType.ToClientMessageType());
 }
Esempio n. 25
0
 public ClientMessage(ClientMessageType type, params string[] messages) : this()
 {
     MessageType = type;
     Messages.AddRange(messages.Where(x => !x.IsNullOrEmpty()));
 }
Esempio n. 26
0
 public ClientMessageTypeAttribute(ClientMessageType clientMessageType)
 {
     ClientMessageType = clientMessageType;
 }
Esempio n. 27
0
        /// <summary>
        /// Handles data messages (reads the message and outputs to interface)
        /// </summary>
        /// <param name="incomingMessage"></param>
        private void HandleMessageData(NetIncomingMessage incomingMessage)
        {
            //Determine if it is a new message from the client network object (true) or a reply to a message from the server (false)
            bool newMessage = incomingMessage.ReadBoolean();

            //Determine if there is a body to read
            bool bodyToRead = incomingMessage.ReadBoolean();

            //Consume the pad bits
            incomingMessage.ReadPadBits();

            //Determine the message type
            int messageType = incomingMessage.ReadByte();

            //If a beat then do nothing
            if (messageType == 0)
            {
                //Log the message
                lidgrenConsoleOutputGUI.WriteConsole($"Received beat", LogLevel.Everything);

                //Abort further processing
                return;
            }

            int?feedback = null;

            //If it is a reply message
            if (!newMessage)
            {
                //Read the feedback
                feedback = incomingMessage.ReadByte();
            }

            string jsonBody = null;

            //If there is a body
            if (bodyToRead)
            {
                int bodylength = incomingMessage.ReadInt32();

                //Read the body
                byte[] bodyBytes = incomingMessage.ReadBytes(bodylength);

                //Decode the body
                jsonBody = Encoding.UTF8.GetString(bodyBytes);
            }

            //Handle the message type accordingly
            if (newMessage)
            {
                //Cast to the enum
                ServerMessageType serverMessageType = (ServerMessageType)messageType;

                //Log the message
                if (jsonBody == null)
                {
                    lidgrenConsoleOutputGUI.WriteConsole($"Received new message with type {serverMessageType} and no body", LogLevel.High);
                }
                else
                {
                    lidgrenConsoleOutputGUI.WriteConsole($"Received new message with type {serverMessageType} and body {jsonBody}", LogLevel.High);
                }

                //Activate the event
                lidgrenClientEvents.HandleNewMessage(serverMessageType, jsonBody);
            }
            else
            {
                //Cast to the enum
                ClientMessageType clientMessageType = (ClientMessageType)messageType;

                //Log the message
                if (jsonBody == null)
                {
                    lidgrenConsoleOutputGUI.WriteConsole($"Received reply message with type {clientMessageType} and feedback {feedback} and no body", LogLevel.High);
                }
                else
                {
                    lidgrenConsoleOutputGUI.WriteConsole($"Received reply message with type {clientMessageType} and feedback {feedback} and body {jsonBody}", LogLevel.High);
                }

                if (feedback == null)
                {
                    //Log the message
                    lidgrenConsoleOutputGUI.WriteConsole($"Aborting processing of message type {clientMessageType} as feedback is null", LogLevel.Medium);

                    //Don't handle any further
                    return;
                }

                //Activate the event
                lidgrenClientEvents.HandleReplyMessage(clientMessageType, (int)feedback, jsonBody);
            }
        }
Esempio n. 28
0
        /// <summary>
        /// Sends a message using the lidgren connection
        /// </summary>
        /// <param name="newMessageFromClient">Set to true when it is a new message from the client and not a reply</param>
        /// <param name="messageType">Based on the enum in the owner class (Note: limited to 256 types)</param>
        /// <param name="deliverymethod">The delivery method to use</param>
        /// <param name="feedback">This is required if it is a reply type message</param>
        /// <param name="sequenceChannel"></param>
        /// <param name="body"></param>
        void ILidgrenClient.SendMessage(bool newMessageFromClient,
                                        byte messageType,
                                        NetDeliveryMethod deliverymethod,
                                        int?feedback,
                                        int?sequenceChannel,
                                        string jsonBody)
        {
            //Log the message
            if (newMessageFromClient)
            {
                //Cast to the enum
                ClientMessageType clientMessageType = (ClientMessageType)messageType;

                //Log the message
                if (jsonBody == null)
                {
                    lidgrenConsoleOutputGUI.WriteConsole($"Sending new message with type {clientMessageType} and no body", LogLevel.High);
                }
                else
                {
                    lidgrenConsoleOutputGUI.WriteConsole($"Sending new message with type {clientMessageType} and body {jsonBody}", LogLevel.High);
                }
            }
            else
            {
                //Cast to the enum
                ServerMessageType serverMessageType = (ServerMessageType)messageType;

                lidgrenConsoleOutputGUI.WriteConsole($"Sending reply message with type {serverMessageType} and feedback {feedback} and body {jsonBody}", LogLevel.High);
            }

            //If there is a jsonBody then convert it to a byte array body, otherwise set to null
            byte[] body = jsonBody == null ? null : Encoding.UTF8.GetBytes(jsonBody);

            //Create a new message
            NetOutgoingMessage outgoingMessage = netClient.CreateMessage();

            //Write whether it is a new message from the client (true) or a reply to a message from the server (false)
            outgoingMessage.Write(newMessageFromClient);

            //Write true if a body exists to read
            outgoingMessage.Write(body != null);

            //Pad so that future reading is easily done
            outgoingMessage.WritePadBits();

            //Write the message type (note it's been squished to 8 bits therefore max 256 message types)
            outgoingMessage.Write(messageType);

            //If it is a reply message
            if (!newMessageFromClient)
            {
                if (feedback != null)
                {
                    //Write the feedback (note again 8 bit so max 256 types)
                    outgoingMessage.Write((byte)feedback);
                }
                else
                {
                    throw new Exception("Feedback not provided but is necessary for reply type message!");
                }
            }

            //If a body exists
            if (body != null)
            {
                //Write the body length
                outgoingMessage.Write(body.Length);

                //Write the body
                outgoingMessage.Write(body);
            }

            /*
             * There is an override for SendMessage() which takes an integer called 'sequenceChannel'
             * - this can be used for certain delivery methods, namely UnreliableSequenced, ReliableSequenced and ReliableOrdered.
             *
             * The sequence channel is a number between 0 and (NetConstants.NetChannelsPerDeliveryMethod - 1) - currently 31.
             * The reason for this limitation is to reduce the amount of overhead per message.Note that there are this amount of channels per delivery method, not in total.
             *
             * Messages sent in a certain sequence channel will be dropped/withheld independently of messages sent in a different sequence channel.
             */

            switch (deliverymethod)
            {
            case NetDeliveryMethod.UnreliableSequenced:
            case NetDeliveryMethod.ReliableSequenced:
            case NetDeliveryMethod.ReliableOrdered:
                if (sequenceChannel != null)
                {
                    netClient.SendMessage(outgoingMessage, deliverymethod, (int)sequenceChannel);
                }
                else
                {
                    throw new Exception("Trying to send a message without specifying the required sequence channel");
                }

                break;

            default:
                netClient.SendMessage(outgoingMessage, deliverymethod);
                break;
            }
        }
Esempio n. 29
0
		protected ClientMessage(ClientMessageType type)
		{
			this.MessageType = type;
		}
Esempio n. 30
0
        public void StartPlayback()
        {
            int       messagesLoaded = 0;
            bool      firstMessage   = true;
            ByteArray headerBytes    = ByteRecycler.GetObject(8);

            using (FileStream fs = new FileStream(recordPath, FileMode.Open))
            {
                while (fs.Position < fs.Length)
                {
                    messagesLoaded++;
                    fs.Read(headerBytes.data, 0, 8);
                    using (MessageReader mr = new MessageReader(headerBytes.data))
                    {
                        ClientMessageType messageType = (ClientMessageType)mr.Read <int>();
                        int       length    = mr.Read <int>();
                        ByteArray dataBytes = ByteRecycler.GetObject(length);
                        fs.Read(dataBytes.data, 0, length);
                        using (MessageReader timeReader = new MessageReader(dataBytes.data))
                        {
                            //Planet time is the first part of the message for the three types we care about here
                            double planetTime = timeReader.Read <double>();
                            lastTime = planetTime;
                            if (firstMessage)
                            {
                                firstTime    = planetTime;
                                firstMessage = false;
                                Planetarium.SetUniversalTime(planetTime - 5d);
                                warpWorker.SendNewSubspace();
                            }
                        }
                        using (MessageReader mrignore = new MessageReader(dataBytes.data))
                        {
                            //Planet time, don't care here
                            mrignore.Read <double>();
                            string vesselID = mrignore.Read <string>();
                            vesselWorker.IgnoreVessel(new Guid(vesselID));
                        }
                        switch (messageType)
                        {
                        case ClientMessageType.VESSEL_PROTO:
                            HandleProtoUpdate(dataBytes);
                            break;

                        case ClientMessageType.VESSEL_UPDATE:
                            HandleVesselUpdate(dataBytes, false);
                            break;

                        case ClientMessageType.VESSEL_REMOVE:
                            HandleVesselRemove(dataBytes);
                            break;

                        default:
                            break;
                        }
                        ByteRecycler.ReleaseObject(dataBytes);
                    }
                }
                ByteRecycler.ReleaseObject(headerBytes);
            }

            playbackQueue = new Queue <VesselUpdate>();
            using (FileStream fs = new FileStream(recordVectorPath, FileMode.Open))
            {
                while (fs.Position < fs.Length)
                {
                    fs.Read(headerBytesInt, 0, 4);
                    if (BitConverter.IsLittleEndian)
                    {
                        Array.Reverse(headerBytesInt);
                    }
                    int       updateLength = BitConverter.ToInt32(headerBytesInt, 0);
                    ByteArray updateBytes  = ByteRecycler.GetObject(updateLength);
                    fs.Read(updateBytes.data, 0, updateLength);
                    VesselUpdate vu = networkWorker.VeselUpdateFromBytes(updateBytes.data, false);
                    playbackQueue.Enqueue(vu);
                    ByteRecycler.ReleaseObject(updateBytes);
                }
            }

            ScreenMessages.PostScreenMessage("Loaded " + messagesLoaded + " saved updates.", 5f, ScreenMessageStyle.UPPER_CENTER);
            screenMessage = ScreenMessages.PostScreenMessage("Playback 0 / " + (int)(lastTime - firstTime) + " seconds.", float.MaxValue, ScreenMessageStyle.UPPER_CENTER);
            playback      = true;
        }
Esempio n. 31
0
        private void SplitAndRewriteMessage(ref ClientMessage message)
        {
            if (message == null)
            {
                return;
            }
            if (message.data == null)
            {
                return;
            }
            if (message.data.Length > Common.SPLIT_MESSAGE_LENGTH)
            {
                lastSplitMessageType = message.type;
                ClientMessage newSplitMessage = new ClientMessage();
                newSplitMessage.type = ClientMessageType.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();
                    sendMessageQueueSplit.Enqueue(newSplitMessage);
                }

                while (splitBytesLeft > 0)
                {
                    ClientMessage currentSplitMessage = new ClientMessage();
                    currentSplitMessage.type = ClientMessageType.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;
                    sendMessageQueueSplit.Enqueue(currentSplitMessage);
                }
                message = sendMessageQueueSplit.Dequeue();
            }
        }
Esempio n. 32
0
 protected PromptMessageBase(ClientMessageType messageType) : base(messageType)
 {
     this.Id = Interlocked.Increment(ref PromptMessageBase.id);
 }
Esempio n. 33
0
 protected ClientMessage(ClientMessageType type)
 {
     this.MessageType = type;
 }
Esempio n. 34
0
        /// <summary>
        /// Gets the <see cref="NetDeliveryMethod"/> and sequence channel to use for a given <see cref="ClientMessageType"/>.
        /// </summary>
        /// <param name="msgType">The <see cref="ClientMessageType"/>.</param>
        /// <param name="method">The <see cref="NetDeliveryMethod"/> to use for the <paramref name="msgType"/>.</param>
        /// <param name="seqChannel">The sequence channel to use for the <paramref name="msgType"/>.</param>
        public static void GetDeliveryMethod(this ClientMessageType msgType, out NetDeliveryMethod method, out int seqChannel)
        {
            /* Some important things to keep in mind:
             *
             *  - Sequence numbers are unique per NetDeliveryMethod. That is, seqChannel=1 for ReliableOrder is not
             *      the same as seqChannel=1 for UnreliableSequenced.
             *
             *  - Sequence numbers are not used on Unreliable and ReliableUnordered. For these channels, always use seqChannel=0.
             *
             *  - The max sequence number is defined by NetConstants.NetChannelsPerDeliveryMethod.
             *
             *  - All sequences are created equally. They just provide a way to, when using ordering/sequencing, not have to
             *      stall on messages that are irrelevant. For example, say Chat and MapEffect were on the same channel. Then
             *      you send a huge chat message, then a MapEffect message shortly after. For some reason, the chat message gets
             *      lost in the network and has to be retransmitted while the MapEffect arrived very quickly. Even though they are
             *      logically irrelevant, since they use the same channel, the MapEffect will not be handled until that chat message
             *      was received. Putting them on a different sequence channel resolves this issue.
             *
             *  - Unreliable messages are just raw UDP. Not only can they be lost forever, they can arrive out-of-order and duplicate
             *      copies can arrive.
             *
             *  - It is perfectly fine, and even recommended, to use the same method and channel for multiple message types. Even if there
             *      is no important distinction on the network layer, it keeps them logically separated in the upper layer. This makes it
             *      very easy to change them on the network layer if needed.
             *
             *  - Never create or use a message type based on the underlying delivery method and/or sequence channel. How it arrives should
             *      be irrelevant on the upper layer.
             *
             *  - A delivery method and (when applicable) sequence number should be specified for every message type. Never just rely
             *      on the default behavior.
             *
             * If you update this comment block, please also update it in the server under:
             *      ServerMessageTypeExtensions.GetDeliveryMethod().
             */

#if true
            // NOTE: For now, we use a very simple and straight-forward approach. In the future, we will use more complex deliveries.

            method     = NetDeliveryMethod.ReliableOrdered;
            seqChannel = 0;
#else
            // Listing of the used sequence numbers, grouped by delivery method
            const int chRO_General = 0;
            const int chRO_Chat    = 1;

            // FUTURE: Can start dividing stuff up for the client into different channels in the future. For now, it shouldn't be important.

            switch (msgType)
            {
            case ClientMessageType.CharacterMove:
            case ClientMessageType.CharacterInteract:
            case ClientMessageType.General:
            case ClientMessageType.GUI:
            case ClientMessageType.GUIItems:
            case ClientMessageType.System:
                method     = NetDeliveryMethod.ReliableOrdered;
                seqChannel = chRO_General;
                break;

            case ClientMessageType.Chat:
                method     = NetDeliveryMethod.ReliableOrdered;
                seqChannel = chRO_Chat;
                break;

            default:
                const string errmsg =
                    "ClientMessageType `{0}` does not explicitly define a delivery method and sequence channel." +
                    " All message types should define this explicitly. Falling back to ClientMessageType.General.";
                if (log.IsErrorEnabled)
                {
                    log.ErrorFormat(errmsg, msgType);
                }
                GetDeliveryMethod(ClientMessageType.General, out method, out seqChannel);
                break;
            }
#endif
        }
Esempio n. 35
0
		protected PromptMessageBase(ClientMessageType messageType) : base(messageType)
		{
			this.Id = Interlocked.Increment(ref PromptMessageBase.id);
		}