Exemple #1
0
        public async Task <ReadFixedHeaderResult> ReadFixedHeaderAsync(byte[] fixedHeaderBuffer, CancellationToken cancellationToken)
        {
            // The MQTT fixed header contains 1 byte of flags and at least 1 byte for the remaining data length.
            // So in all cases at least 2 bytes must be read for a complete MQTT packet.
            var buffer         = fixedHeaderBuffer;
            var totalBytesRead = 0;

            while (totalBytesRead < buffer.Length)
            {
                var bytesRead = await _channel.ReadAsync(buffer, totalBytesRead, buffer.Length - totalBytesRead, cancellationToken).ConfigureAwait(false);

                if (cancellationToken.IsCancellationRequested)
                {
                    return(null);
                }

                if (bytesRead == 0)
                {
                    return(new ReadFixedHeaderResult
                    {
                        ConnectionClosed = true
                    });
                }

                totalBytesRead += bytesRead;
            }

            var hasRemainingLength = buffer[1] != 0;

            if (!hasRemainingLength)
            {
                return(new ReadFixedHeaderResult
                {
                    FixedHeader = new MqttFixedHeader(buffer[0], 0, totalBytesRead)
                });
            }

            var bodyLength = await ReadBodyLengthAsync(buffer[1], cancellationToken).ConfigureAwait(false);

            if (!bodyLength.HasValue)
            {
                return(new ReadFixedHeaderResult
                {
                    ConnectionClosed = true
                });
            }

            totalBytesRead += bodyLength.Value;
            return(new ReadFixedHeaderResult
            {
                FixedHeader = new MqttFixedHeader(buffer[0], bodyLength.Value, totalBytesRead)
            });
        }
Exemple #2
0
        public static async Task <MqttFixedHeader> ReadFixedHeaderAsync(IMqttChannel channel, byte[] fixedHeaderBuffer, byte[] singleByteBuffer, CancellationToken cancellationToken)
        {
            // The MQTT fixed header contains 1 byte of flags and at least 1 byte for the remaining data length.
            // So in all cases at least 2 bytes must be read for a complete MQTT packet.
            // async/await is used here because the next packet is received in a couple of minutes so the performance
            // impact is acceptable according to a useless waiting thread.
            var buffer         = fixedHeaderBuffer;
            var totalBytesRead = 0;

            while (totalBytesRead < buffer.Length)
            {
                var bytesRead = await channel.ReadAsync(buffer, totalBytesRead, buffer.Length - totalBytesRead, cancellationToken).ConfigureAwait(false);

                if (bytesRead <= 0)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    ExceptionHelper.ThrowGracefulSocketClose();
                }

                totalBytesRead += bytesRead;
            }

            var hasRemainingLength = buffer[1] != 0;

            if (!hasRemainingLength)
            {
                return(new MqttFixedHeader(buffer[0], 0));
            }

            var bodyLength = ReadBodyLength(channel, buffer[1], singleByteBuffer, cancellationToken);

            return(new MqttFixedHeader(buffer[0], bodyLength));
        }
Exemple #3
0
        private async Task <ReceivedMqttPacket> ReceiveAsync(CancellationToken cancellationToken)
        {
            var fixedHeader = await MqttPacketReader.ReadFixedHeaderAsync(_channel, _fixedHeaderBuffer, _singleByteBuffer, cancellationToken).ConfigureAwait(false);

            try
            {
                ReadingPacketStarted?.Invoke(this, EventArgs.Empty);

                if (fixedHeader.RemainingLength == 0)
                {
                    return(new ReceivedMqttPacket(fixedHeader.Flags, null));
                }

                var body       = new byte[fixedHeader.RemainingLength];
                var bodyOffset = 0;
                var chunkSize  = Math.Min(ReadBufferSize, fixedHeader.RemainingLength);

                do
                {
                    var bytesLeft = body.Length - bodyOffset;
                    if (chunkSize > bytesLeft)
                    {
                        chunkSize = bytesLeft;
                    }

#if WINDOWS_UWP
                    var readBytes = await _channel.ReadAsync(body, bodyOffset, chunkSize, cancellationToken).ConfigureAwait(false);
#else
                    // async/await is not used to avoid the overhead of context switches. We assume that the reamining data
                    // has been sent from the sender directly after the initial bytes.
                    //var readBytes = _channel.ReadAsync(body, bodyOffset, chunkSize, cancellationToken).ConfigureAwait(false).GetAwaiter().GetResult();
                    var readBytes = AsyncContext.Run(async() => await _channel.ReadAsync(body, bodyOffset, chunkSize, cancellationToken).ConfigureAwait(false));
#endif

                    cancellationToken.ThrowIfCancellationRequested();
                    ExceptionHelper.ThrowIfGracefulSocketClose(readBytes);

                    bodyOffset += readBytes;
                } while (bodyOffset < body.Length);

                return(new ReceivedMqttPacket(fixedHeader.Flags, new MqttPacketBodyReader(body, 0, body.Length)));
            }
            finally
            {
                ReadingPacketCompleted?.Invoke(this, EventArgs.Empty);
            }
        }
        private async Task <ReceivedMqttPacket> ReceiveAsync(CancellationToken cancellationToken)
        {
            var readFixedHeaderResult = await _packetReader.ReadFixedHeaderAsync(_fixedHeaderBuffer, cancellationToken).ConfigureAwait(false);

            if (cancellationToken.IsCancellationRequested)
            {
                return(null);
            }

            try
            {
                if (readFixedHeaderResult.ConnectionClosed)
                {
                    return(null);
                }

                ReadingPacketStartedCallback?.Invoke();

                var fixedHeader = readFixedHeaderResult.FixedHeader;
                if (fixedHeader.RemainingLength == 0)
                {
                    return(new ReceivedMqttPacket(fixedHeader.Flags, null, 2));
                }

                var body       = new byte[fixedHeader.RemainingLength];
                var bodyOffset = 0;
                var chunkSize  = Math.Min(ReadBufferSize, fixedHeader.RemainingLength);

                do
                {
                    var bytesLeft = body.Length - bodyOffset;
                    if (chunkSize > bytesLeft)
                    {
                        chunkSize = bytesLeft;
                    }

                    var readBytes = await _channel.ReadAsync(body, bodyOffset, chunkSize, cancellationToken).ConfigureAwait(false);

                    if (cancellationToken.IsCancellationRequested)
                    {
                        return(null);
                    }

                    if (readBytes == 0)
                    {
                        return(null);
                    }

                    bodyOffset += readBytes;
                } while (bodyOffset < body.Length);

                var bodyReader = new MqttPacketBodyReader(body, 0, body.Length);
                return(new ReceivedMqttPacket(fixedHeader.Flags, bodyReader, fixedHeader.TotalLength));
            }
            finally
            {
                ReadingPacketCompletedCallback?.Invoke();
            }
        }
Exemple #5
0
        async Task <int> ReadBodyLengthAsync(byte initialEncodedByte, CancellationToken cancellationToken)
        {
            var offset      = 0;
            var multiplier  = 128;
            var value       = initialEncodedByte & 127;
            int encodedByte = initialEncodedByte;

            while ((encodedByte & 128) != 0)
            {
                offset++;
                if (offset > 3)
                {
                    throw new MqttProtocolViolationException("Remaining length is invalid.");
                }

                if (cancellationToken.IsCancellationRequested)
                {
                    return(0);
                }

                var readCount = await _channel.ReadAsync(_singleByteBuffer, 0, 1, cancellationToken).ConfigureAwait(false);

                if (cancellationToken.IsCancellationRequested)
                {
                    return(0);
                }

                if (readCount == 0)
                {
                    return(0);
                }

                _packetInspector?.FillReceiveBuffer(_singleByteBuffer);

                encodedByte = _singleByteBuffer[0];

                value      += (encodedByte & 127) * multiplier;
                multiplier *= 128;
            }

            return(value);
        }
Exemple #6
0
        private static byte ReadByte(IMqttChannel channel, byte[] singleByteBuffer, CancellationToken cancellationToken)
        {
            var readCount = channel.ReadAsync(singleByteBuffer, 0, 1, cancellationToken).GetAwaiter().GetResult();

            if (readCount <= 0)
            {
                cancellationToken.ThrowIfCancellationRequested();
                ExceptionHelper.ThrowGracefulSocketClose();
            }

            return(singleByteBuffer[0]);
        }
Exemple #7
0
        private static async Task <byte> ReadByteAsync(IMqttChannel channel, byte[] singleByteBuffer, CancellationToken cancellationToken)
        {
            var readCount = await channel.ReadAsync(singleByteBuffer, 0, 1, cancellationToken).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            if (readCount <= 0)
            {
                ExceptionHelper.ThrowGracefulSocketClose();
            }

            return(singleByteBuffer[0]);
        }
        async Task ReadAsync(int iterations, int size)
        {
            await Task.Yield();

            var  expected = iterations * size;
            long read     = 0;

            while (read < expected)
            {
                var readresult = await _clientChannel.ReadAsync(new byte[size], 0, size, CancellationToken.None).ConfigureAwait(false);

                read += readresult;
            }
        }
Exemple #9
0
        private static byte ReadByte(IMqttChannel channel, byte[] singleByteBuffer, CancellationToken cancellationToken)
        {
            //var readCount = channel.ReadAsync(singleByteBuffer, 0, 1, cancellationToken).ConfigureAwait(false).GetAwaiter().GetResult();
            var readCount = AsyncContext.Run(async() => await channel.ReadAsync(singleByteBuffer, 0, 1, cancellationToken).ConfigureAwait(false));

            cancellationToken.ThrowIfCancellationRequested();

            if (readCount <= 0)
            {
                ExceptionHelper.ThrowGracefulSocketClose();
            }

            return(singleByteBuffer[0]);
        }
Exemple #10
0
        private async Task <MqttReceivedPacket> ReceiveAsync(CancellationToken cancellationToken)
        {
            var fixedHeader = await MqttPacketReader.ReadFixedHeaderAsync(_channel, _fixedHeaderBuffer, _singleByteBuffer, cancellationToken).ConfigureAwait(false);

            try
            {
                ReadingPacketStarted?.Invoke(this, EventArgs.Empty);

                if (fixedHeader.RemainingLength == 0)
                {
                    return(new MqttReceivedPacket(fixedHeader.Flags, null));
                }

                var body       = new byte[fixedHeader.RemainingLength];
                var bodyOffset = 0;
                var chunkSize  = Math.Min(ReadBufferSize, fixedHeader.RemainingLength);

                do
                {
                    var bytesLeft = body.Length - bodyOffset;
                    if (chunkSize > bytesLeft)
                    {
                        chunkSize = bytesLeft;
                    }


                    //async/await不用于避免上下文切换的开销。我们假设扩孔数据已从发件人直接发送到初始字节之后。
                    var readBytes = _channel.ReadAsync(body, bodyOffset, chunkSize, cancellationToken).ConfigureAwait(false).GetAwaiter().GetResult();


                    cancellationToken.ThrowIfCancellationRequested();
                    ExceptionHelper.ThrowIfGracefulSocketClose(readBytes);

                    bodyOffset += readBytes;
                } while (bodyOffset < body.Length);

                return(new MqttReceivedPacket(fixedHeader.Flags, new MqttPacketBodyReader(body, 0, body.Length)));
            }
            finally
            {
                ReadingPacketCompleted?.Invoke(this, EventArgs.Empty);
            }
        }
Exemple #11
0
        public static async Task <MqttFixedHeader> ReadFixedHeaderAsync(IMqttChannel channel, byte[] fixedHeaderBuffer, byte[] singleByteBuffer, CancellationToken cancellationToken)
        {
            // The MQTT fixed header contains 1 byte of flags and at least 1 byte for the remaining data length.
            // So in all cases at least 2 bytes must be read for a complete MQTT packet.
            // async/await is used here because the next packet is received in a couple of minutes so the performance
            // impact is acceptable according to a useless waiting thread.
            var buffer         = fixedHeaderBuffer;
            var totalBytesRead = 0;

            while (totalBytesRead < buffer.Length)
            {
                var bytesRead = await channel.ReadAsync(buffer, totalBytesRead, buffer.Length - totalBytesRead, cancellationToken).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();
                ExceptionHelper.ThrowIfGracefulSocketClose(bytesRead);

                totalBytesRead += bytesRead;
            }

            var hasRemainingLength = buffer[1] != 0;

            if (!hasRemainingLength)
            {
                return(new MqttFixedHeader(buffer[0], 0));
            }

#if WINDOWS_UWP
            // UWP will have a dead lock when calling this not async.
            var bodyLength = await ReadBodyLengthAsync(channel, buffer[1], singleByteBuffer, cancellationToken).ConfigureAwait(false);
#else
            // Here the async/await pattern is not used becuase the overhead of context switches
            // is too big for reading 1 byte in a row. We expect that the remaining data was sent
            // directly after the initial bytes. If the client disconnects just in this moment we
            // will get an exception anyway.
            var bodyLength = ReadBodyLength(channel, buffer[1], singleByteBuffer, cancellationToken);
#endif

            return(new MqttFixedHeader(buffer[0], bodyLength));
        }
Exemple #12
0
        async Task <ReceivedMqttPacket> ReceiveAsync(CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(null);
            }

            var readFixedHeaderResult = await ReadFixedHeaderAsync(cancellationToken).ConfigureAwait(false);

            if (cancellationToken.IsCancellationRequested)
            {
                return(null);
            }

            if (readFixedHeaderResult.ConnectionClosed)
            {
                return(null);
            }

            try
            {
                IsReadingPacket = true;

                var fixedHeader = readFixedHeaderResult.FixedHeader;
                if (fixedHeader.RemainingLength == 0)
                {
                    return(new ReceivedMqttPacket(fixedHeader.Flags, new MqttPacketBodyReader(new byte[0], 0, 0), 2));
                }

                var bodyLength = fixedHeader.RemainingLength;
                var body       = new byte[bodyLength];

                var bodyOffset = 0;
                var chunkSize  = Math.Min(ReadBufferSize, bodyLength);

                do
                {
                    var bytesLeft = body.Length - bodyOffset;
                    if (chunkSize > bytesLeft)
                    {
                        chunkSize = bytesLeft;
                    }

                    var readBytes = await _channel.ReadAsync(body, bodyOffset, chunkSize, cancellationToken).ConfigureAwait(false);

                    if (cancellationToken.IsCancellationRequested)
                    {
                        return(null);
                    }

                    if (readBytes == 0)
                    {
                        return(null);
                    }

                    bodyOffset += readBytes;
                } while (bodyOffset < bodyLength);

                _packetInspectorHandler.FillReceiveBuffer(body);

                var bodyReader = new MqttPacketBodyReader(body, 0, bodyLength);
                return(new ReceivedMqttPacket(fixedHeader.Flags, bodyReader, fixedHeader.TotalLength));
            }
            finally
            {
                IsReadingPacket = false;
            }
        }
        public async Task <ReadFixedHeaderResult> ReadFixedHeaderAsync(byte[] fixedHeaderBuffer, CancellationToken cancellationToken)
        {
            // The MQTT fixed header contains 1 byte of flags and at least 1 byte for the remaining data length.
            // So in all cases at least 2 bytes must be read for a complete MQTT packet.
            // async/await is used here because the next packet is received in a couple of minutes so the performance
            // impact is acceptable according to a useless waiting thread.
            var buffer         = fixedHeaderBuffer;
            var totalBytesRead = 0;

            while (totalBytesRead < buffer.Length)
            {
                var bytesRead = await _channel.ReadAsync(buffer, totalBytesRead, buffer.Length - totalBytesRead, cancellationToken).ConfigureAwait(false);

                if (cancellationToken.IsCancellationRequested)
                {
                    return(null);
                }

                if (bytesRead == 0)
                {
                    return(new ReadFixedHeaderResult
                    {
                        ConnectionClosed = true
                    });
                }

                totalBytesRead += bytesRead;
            }

            var hasRemainingLength = buffer[1] != 0;

            if (!hasRemainingLength)
            {
                return(new ReadFixedHeaderResult
                {
                    FixedHeader = new MqttFixedHeader(buffer[0], 0, totalBytesRead)
                });
            }

#if WINDOWS_UWP
            // UWP will have a dead lock when calling this not async.
            var bodyLength = await ReadBodyLengthAsync(buffer[1], cancellationToken).ConfigureAwait(false);
#else
            // Here the async/await pattern is not used because the overhead of context switches
            // is too big for reading 1 byte in a row. We expect that the remaining data was sent
            // directly after the initial bytes. If the client disconnects just in this moment we
            // will get an exception anyway.
            var bodyLength = ReadBodyLength(buffer[1], cancellationToken);
#endif

            if (!bodyLength.HasValue)
            {
                return(new ReadFixedHeaderResult
                {
                    ConnectionClosed = true
                });
            }

            totalBytesRead += bodyLength.Value;
            return(new ReadFixedHeaderResult
            {
                FixedHeader = new MqttFixedHeader(buffer[0], bodyLength.Value, totalBytesRead)
            });
        }