|
3 | 3 | using System.IO;
|
4 | 4 | using System.Threading.Tasks;
|
5 | 5 | using MySql.Data.MySqlClient;
|
| 6 | +using MySqlConnector.Protocol.Payloads; |
6 | 7 | using MySqlConnector.Utilities;
|
7 | 8 |
|
8 | 9 | namespace MySqlConnector.Protocol.Serialization
|
@@ -417,38 +418,45 @@ private static ValueTask<Packet> ReadPacketAfterHeader(ArraySegment<byte> header
|
417 | 418 | {
|
418 | 419 | if (headerBytes.Count < 4)
|
419 | 420 | {
|
420 |
| - return protocolErrorBehavior == ProtocolErrorBehavior.Throw ? |
421 |
| - ValueTaskExtensions.FromException<Packet>(new EndOfStreamException("Expected to read 4 header bytes but only received {0}.".FormatInvariant(headerBytes.Count))) : |
422 |
| - default(ValueTask<Packet>); |
| 421 | + return protocolErrorBehavior == ProtocolErrorBehavior.Ignore ? default : |
| 422 | + ValueTaskExtensions.FromException<Packet>(new EndOfStreamException("Expected to read 4 header bytes but only received {0}.".FormatInvariant(headerBytes.Count))); |
423 | 423 | }
|
424 | 424 |
|
425 | 425 | var payloadLength = (int) SerializationUtility.ReadUInt32(headerBytes.Array, headerBytes.Offset, 3);
|
426 | 426 | int packetSequenceNumber = headerBytes.Array[headerBytes.Offset + 3];
|
427 | 427 |
|
| 428 | + Exception packetOutOfOrderException = null; |
428 | 429 | var expectedSequenceNumber = getNextSequenceNumber() % 256;
|
429 | 430 | if (expectedSequenceNumber != -1 && packetSequenceNumber != expectedSequenceNumber)
|
430 |
| - { |
431 |
| - if (protocolErrorBehavior == ProtocolErrorBehavior.Ignore) |
432 |
| - return default(ValueTask<Packet>); |
433 |
| - |
434 |
| - var exception = MySqlProtocolException.CreateForPacketOutOfOrder(expectedSequenceNumber, packetSequenceNumber); |
435 |
| - return ValueTaskExtensions.FromException<Packet>(exception); |
436 |
| - } |
| 431 | + packetOutOfOrderException = MySqlProtocolException.CreateForPacketOutOfOrder(expectedSequenceNumber, packetSequenceNumber); |
437 | 432 |
|
438 | 433 | var payloadBytesTask = bufferedByteReader.ReadBytesAsync(byteHandler, payloadLength, ioBehavior);
|
439 | 434 | if (payloadBytesTask.IsCompleted)
|
440 |
| - return CreatePacketFromPayload(payloadBytesTask.Result, payloadLength, protocolErrorBehavior); |
441 |
| - return AddContinuation(payloadBytesTask, payloadLength, protocolErrorBehavior); |
| 435 | + return CreatePacketFromPayload(payloadBytesTask.Result, payloadLength, protocolErrorBehavior, packetOutOfOrderException); |
| 436 | + return AddContinuation(payloadBytesTask, payloadLength, protocolErrorBehavior, packetOutOfOrderException); |
442 | 437 |
|
443 | 438 | // NOTE: use a local function (with no captures) to defer creation of lambda objects
|
444 |
| - ValueTask<Packet> AddContinuation(ValueTask<ArraySegment<byte>> payloadBytesTask_, int payloadLength_, ProtocolErrorBehavior protocolErrorBehavior_) |
445 |
| - => payloadBytesTask_.ContinueWith(x => CreatePacketFromPayload(x, payloadLength_, protocolErrorBehavior_)); |
| 439 | + ValueTask<Packet> AddContinuation(ValueTask<ArraySegment<byte>> payloadBytesTask_, int payloadLength_, ProtocolErrorBehavior protocolErrorBehavior_, Exception packetOutOfOrderException_) |
| 440 | + => payloadBytesTask_.ContinueWith(x => CreatePacketFromPayload(x, payloadLength_, protocolErrorBehavior_, packetOutOfOrderException_)); |
446 | 441 | }
|
447 | 442 |
|
448 |
| - private static ValueTask<Packet> CreatePacketFromPayload(ArraySegment<byte> payloadBytes, int payloadLength, ProtocolErrorBehavior protocolErrorBehavior) => |
449 |
| - payloadBytes.Count >= payloadLength ? new ValueTask<Packet>(new Packet(payloadBytes)) : |
| 443 | + private static ValueTask<Packet> CreatePacketFromPayload(ArraySegment<byte> payloadBytes, int payloadLength, ProtocolErrorBehavior protocolErrorBehavior, Exception exception) |
| 444 | + { |
| 445 | + if (exception is object) |
| 446 | + { |
| 447 | + if (protocolErrorBehavior == ProtocolErrorBehavior.Ignore) |
| 448 | + return default; |
| 449 | + |
| 450 | + if (payloadBytes.Count > 0 && payloadBytes.AsSpan()[0] == ErrorPayload.Signature) |
| 451 | + return new ValueTask<Packet>(new Packet(payloadBytes)); |
| 452 | + |
| 453 | + return ValueTaskExtensions.FromException<Packet>(exception); |
| 454 | + } |
| 455 | + |
| 456 | + return payloadBytes.Count >= payloadLength ? new ValueTask<Packet>(new Packet(payloadBytes)) : |
450 | 457 | protocolErrorBehavior == ProtocolErrorBehavior.Throw ? ValueTaskExtensions.FromException<Packet>(new EndOfStreamException("Expected to read {0} payload bytes but only received {1}.".FormatInvariant(payloadLength, payloadBytes.Count))) :
|
451 |
| - default(ValueTask<Packet>); |
| 458 | + default; |
| 459 | + } |
452 | 460 |
|
453 | 461 | public static ValueTask<ArraySegment<byte>> ReadPayloadAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func<int> getNextSequenceNumber, ArraySegmentHolder<byte> cache, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior)
|
454 | 462 | {
|
|
0 commit comments