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_));
        }
示例#2
0
        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_)));
            }
        }
示例#4
0
 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_));
        }