/// <summary>
        /// Gets the byte array representing the next X Protocol frame that is stored in cache.
        /// </summary>
        /// <returns>A byte array representing an X Protocol frame.</returns>
        internal byte[] ReadNextBufferedMessage()
        {
            if (_multipleMessagesStream == null)
            {
                return(null);
            }

            var messageSizeBytes = new byte[4];

            _multipleMessagesStream.Read(messageSizeBytes, 0, messageSizeBytes.Length);
            byte messageType = (byte)_multipleMessagesStream.ReadByte();
            var  messageSize = BitConverter.ToInt32(messageSizeBytes, 0);
            var  data        = new byte[messageSize - 1];

            _multipleMessagesStream.Read(data, 0, data.Length);
            _lastCommunicationPacket = new CommunicationPacket(messageType, messageSize - 1, data);
            var message = new byte[messageSizeBytes.Length + 1 + data.Length];

            Buffer.BlockCopy(messageSizeBytes, 0, message, 0, messageSizeBytes.Length);
            Buffer.BlockCopy(new byte[] { messageType }, 0, message, messageSizeBytes.Length, 1);
            Buffer.BlockCopy(data, 0, message, messageSizeBytes.Length + 1, data.Length);

            if (_multipleMessagesStream.Position == _multipleMessagesStream.Length)
            {
                LastMessageContainsMultipleMessages = false;
                _multipleMessagesStream.Close();
                _multipleMessagesStream = null;
            }

            return(message);
        }
        /// <summary>
        /// Reads X Protocol frames incoming from the X Plugin.
        /// </summary>
        /// <returns>A <see cref="CommunicationPacket"/> instance representing the X Protocol frame that was read.</returns>
        public CommunicationPacket Read()
        {
            var compressionEnabled = CompressionController != null &&
                                     CompressionController.IsCompressionEnabled;

            if (compressionEnabled && CompressionController.LastMessageContainsMultipleMessages)
            {
                return(CompressionController.ReadNextBufferedMessageAsCommunicationPacket());
            }

            byte[] header = new byte[5];
            ReadFully(header, 0, 5);
            int length = BitConverter.ToInt32(header, 0);

            byte[] data = new byte[length - 1];
            ReadFully(data, 0, length - 1);

            // If compression is enabled and message is of type compression.
            if (compressionEnabled &&
                header[4] == 19)
            {
                var packet              = new CommunicationPacket(header[4], length - 1, data);
                var message             = Compression.Parser.ParseFrom(packet.Buffer);
                var payload             = message.Payload.ToByteArray();
                var decompressedPayload = CompressionController.Decompress(payload, (int)(message.UncompressedSize));
                data = new byte[decompressedPayload.Length - 5];
                for (int i = 0; i < data.Length; i++)
                {
                    data[i] = decompressedPayload[i + 5];
                }

                return(new CommunicationPacket(decompressedPayload[4], BitConverter.ToInt32(decompressedPayload, 0) - 1, data));
            }

            return(new CommunicationPacket(header[4], length - 1, data));
        }