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(); } }
public async Task <MqttBasePacket> ReceivePacketAsync(TimeSpan timeout, CancellationToken cancellationToken) { var input = Connection.Transport.Input; try { while (!cancellationToken.IsCancellationRequested) { ReadResult readResult; var readTask = input.ReadAsync(cancellationToken); if (readTask.IsCompleted) { readResult = readTask.Result; } else { readResult = await readTask.ConfigureAwait(false); } var buffer = readResult.Buffer; var consumed = buffer.Start; var observed = buffer.Start; try { if (!buffer.IsEmpty) { if (PacketFormatterAdapter.TryDecode(_reader, buffer, out var packet, out consumed, out observed, out var received)) { BytesReceived += received; return(packet); } else { // we did receive something but the message is not yet complete ReadingPacketStartedCallback?.Invoke(); } } else if (readResult.IsCompleted) { throw new MqttCommunicationException("Connection Aborted"); } } finally { // The buffer was sliced up to where it was consumed, so we can just advance to the start. // We mark examined as buffer.End so that if we didn't receive a full frame, we'll wait for more data // before yielding the read again. input.AdvanceTo(consumed, observed); } }