/// <summary>
        /// Process a received command.
        /// (A ack command is processed by a receive thread, other commands is dispatched in a rendering thread.)
        /// </summary>
        private void ExecuteReceiveCommand(IncomingCommand command)
        {
            if (_udpSocket.State != SocketState.Connected)
            {
                return;
            }

            switch (command.Type)
            {
            case CommandType.Acknowledge:
                // Already process a acknowledge command in a receive thread.
                return;

            case CommandType.Disconnect:
                byte[] payload = command.GetPayload();
                int    offset  = 0;

                DisconnectReason disconnectType = (DisconnectReason)ByteRead.GetInt(payload, ref offset);

                var detailMessage = ByteRead.GetString <int>(payload, ref offset, Encoding.UTF8);
                Log(LogLevel.Error, "Disconnect this client[{0}] : {1}", disconnectType, detailMessage);

                Disconnect(disconnectType, false);

                return;

            case CommandType.Reliable:
            case CommandType.Unreliable:
                EnqueueIncomingCommand(command);
                return;

            case CommandType.Fragmented:
                if (command.FragmentNumber > command.FragmentCount ||
                    command.FragmentOffset >= command.TotalLength ||
                    command.FragmentOffset + command.GetPayload().Length > command.TotalLength)
                {
                    Log(LogLevel.Error, "Received fragment has bad size: {0}", command);
                    return;
                }

                if (EnqueueIncomingCommand(command))
                {
                    UdpChannel udpChannel = _channels[command.Channel];

                    ReliableReceiveQueue reliableReceiveQueue = udpChannel.ReliableReceiveQueue as ReliableReceiveQueue;
                    if (reliableReceiveQueue != null)
                    {
                        reliableReceiveQueue.ReceiveFragmentCommand(command);
                    }
                }
                return;

            default:
                Log(LogLevel.Error, "Unknown command received {0}", command.Type);
                return;
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Fetch a payload. If a incoming command is invalid, return null.
        /// </summary>
        /// <returns>A payload in a incoming command.</returns>
        private IByteBuffer FetchPayload(IncomingCommand command)
        {
            if (false == command.IsPayloadAvailable())
            {
                return(null);
            }

            // The length of InitialResponse is 2. Thus payload length should be bigger then 2.
            if (command.GetPayload().Length < 2)
            {
                Log(LogLevel.Error, "Incoming UDP data is too short; Length [{0}] ", command.GetPayload().Length);
                return(null);
            }

            if (command.IsEncrypted)
            {
                try
                {
                    command.SetPayload(_cipher.Decrypt(command.GetPayload()));
                }
                catch (Exception)
                {
                    Log(LogLevel.Error, "Invalid encrypted data");
                    return(null);
                }
            }

            var payload = ByteBufferFactory.NewBuffer(command.GetPayload());

            byte serializerVersion = payload.ReadByte();

            if (serializerVersion != DataSerializer.Version)
            {
                Log(LogLevel.Error, "Unknown serializer Version");
                return(null);
            }

            return(payload);
        }