public static ValueTask <Packet> ReadPacketAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int> getNextSequenceNumber, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { var headerBytesTask = bufferedByteReader.ReadBytesAsync(byteHandler, 4, ioBehavior); if (headerBytesTask.IsCompleted) { return(ReadPacketAfterHeader(headerBytesTask.Result, bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior)); } return(AddContinuation(headerBytesTask, bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior)); // NOTE: use a local function (with no captures) to defer creation of lambda objects ValueTask <Packet> AddContinuation(ValueTask <ArraySegment <byte> > headerBytes_, BufferedByteReader bufferedByteReader_, IByteHandler byteHandler_, Func <int> getNextSequenceNumber_, ProtocolErrorBehavior protocolErrorBehavior_, IOBehavior ioBehavior_) => headerBytes_.ContinueWith(x => ReadPacketAfterHeader(x, bufferedByteReader_, byteHandler_, getNextSequenceNumber_, protocolErrorBehavior_, ioBehavior_)); }
public static ValueTask <Packet> ReadPacketAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int> getNextSequenceNumber, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { return(bufferedByteReader.ReadBytesAsync(byteHandler, 4, ioBehavior) .ContinueWith(headerBytes => { if (headerBytes.Count < 4) { return protocolErrorBehavior == ProtocolErrorBehavior.Throw ? ValueTaskExtensions.FromException <Packet>(new EndOfStreamException()) : default(ValueTask <Packet>); } var payloadLength = (int)SerializationUtility.ReadUInt32(headerBytes.Array, headerBytes.Offset, 3); int packetSequenceNumber = headerBytes.Array[headerBytes.Offset + 3]; var expectedSequenceNumber = getNextSequenceNumber() % 256; if (packetSequenceNumber != expectedSequenceNumber) { if (protocolErrorBehavior == ProtocolErrorBehavior.Ignore) { return default(ValueTask <Packet>); } var exception = new InvalidOperationException("Packet received out-of-order. Expected {0}; got {1}.".FormatInvariant(expectedSequenceNumber, packetSequenceNumber)); return ValueTaskExtensions.FromException <Packet>(exception); } return bufferedByteReader.ReadBytesAsync(byteHandler, payloadLength, ioBehavior) .ContinueWith(payloadBytes => { if (payloadBytes.Count < payloadLength) { return protocolErrorBehavior == ProtocolErrorBehavior.Throw ? ValueTaskExtensions.FromException <Packet>(new EndOfStreamException()) : default(ValueTask <Packet>); } return new ValueTask <Packet>(new Packet(packetSequenceNumber, payloadBytes)); }); })); }
private static ValueTask <ArraySegment <byte> > DoReadPayloadAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int> getNextSequenceNumber, ArraySegmentHolder <byte> previousPayloads, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { var readPacketTask = ReadPacketAsync(bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior); while (readPacketTask.IsCompleted) { if (HasReadPayload(previousPayloads, readPacketTask.Result, protocolErrorBehavior, out var result)) { return(result); } readPacketTask = ReadPacketAsync(bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior); } return(AddContinuation(readPacketTask, bufferedByteReader, byteHandler, getNextSequenceNumber, previousPayloads, protocolErrorBehavior, ioBehavior)); // NOTE: use a local function (with no captures) to defer creation of lambda objects ValueTask <ArraySegment <byte> > AddContinuation(ValueTask <Packet> readPacketTask_, BufferedByteReader bufferedByteReader_, IByteHandler byteHandler_, Func <int> getNextSequenceNumber_, ArraySegmentHolder <byte> previousPayloads_, ProtocolErrorBehavior protocolErrorBehavior_, IOBehavior ioBehavior_) { return(readPacketTask_.ContinueWith(packet => HasReadPayload(previousPayloads_, packet, protocolErrorBehavior_, out var result_) ? result_ : DoReadPayloadAsync(bufferedByteReader_, byteHandler_, getNextSequenceNumber_, previousPayloads_, protocolErrorBehavior_, ioBehavior_))); } }
public static ValueTask <ArraySegment <byte> > ReadPayloadAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int> getNextSequenceNumber, ArraySegment <byte> previousPayloads, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { return(ReadPacketAsync(bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior).ContinueWith(packet => ContinueRead(bufferedByteReader, byteHandler, getNextSequenceNumber, previousPayloads, packet, protocolErrorBehavior, ioBehavior))); }
public static ValueTask <ArraySegment <byte> > ReadPayloadAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int> getNextSequenceNumber, ArraySegmentHolder <byte> cache, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { cache.Clear(); return(DoReadPayloadAsync(bufferedByteReader, byteHandler, getNextSequenceNumber, cache, protocolErrorBehavior, ioBehavior)); }
private static ValueTask <Packet> ReadPacketAfterHeader(ArraySegment <byte> headerBytes, BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int> getNextSequenceNumber, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { if (headerBytes.Count < 4) { return(protocolErrorBehavior == ProtocolErrorBehavior.Throw ? ValueTaskExtensions.FromException <Packet>(new EndOfStreamException()) : default(ValueTask <Packet>)); } var payloadLength = (int)SerializationUtility.ReadUInt32(headerBytes.Array, headerBytes.Offset, 3); int packetSequenceNumber = headerBytes.Array[headerBytes.Offset + 3]; var expectedSequenceNumber = getNextSequenceNumber() % 256; if (expectedSequenceNumber != -1 && packetSequenceNumber != expectedSequenceNumber) { if (protocolErrorBehavior == ProtocolErrorBehavior.Ignore) { return(default(ValueTask <Packet>)); } var exception = MySqlProtocolException.CreateForPacketOutOfOrder(expectedSequenceNumber, packetSequenceNumber); return(ValueTaskExtensions.FromException <Packet>(exception)); } var payloadBytesTask = bufferedByteReader.ReadBytesAsync(byteHandler, payloadLength, ioBehavior); if (payloadBytesTask.IsCompleted) { return(CreatePacketFromPayload(payloadBytesTask.Result, payloadLength, protocolErrorBehavior)); } return(AddContinuation(payloadBytesTask, payloadLength, protocolErrorBehavior)); // NOTE: use a local function (with no captures) to defer creation of lambda objects ValueTask <Packet> AddContinuation(ValueTask <ArraySegment <byte> > payloadBytesTask_, int payloadLength_, ProtocolErrorBehavior protocolErrorBehavior_) => payloadBytesTask_.ContinueWith(x => CreatePacketFromPayload(x, payloadLength_, protocolErrorBehavior_)); }