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) }); }
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)); }
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(); } }
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); }
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]); }
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; } }
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]); }
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); } }
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)); }
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) }); }