Skip to content

Commit 1d3557c

Browse files
committed
Reword end-of-stream message to be more generic. Fixes #1383
Introduce MySqlEndOfStreamException which holds the expected and read byte counts; these are logged as an error and a more generic exception message is thrown.
1 parent b4238ce commit 1d3557c

File tree

6 files changed

+26
-4
lines changed

6 files changed

+26
-4
lines changed

src/MySqlConnector/Core/ServerSession.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,8 @@ public async ValueTask<PayloadData> ReceiveReplyAsync(IOBehavior ioBehavior, Can
925925
}
926926
catch (Exception ex)
927927
{
928+
if (ex is MySqlEndOfStreamException endOfStream)
929+
Log.ExpectedToReadMoreBytes(m_logger, Id, endOfStream.ExpectedByteCount, endOfStream.ReadByteCount);
928930
SetFailed(ex);
929931
throw;
930932
}

src/MySqlConnector/Logging/EventIds.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ internal static class EventIds
2222
public const int FailedInSendReplyAsync = 2007;
2323
public const int FailedInReceiveReplyAsync = 2008;
2424
public const int SettingStateToFailed = 2009;
25+
public const int ExpectedToReadMoreBytes = 2010;
2526
public const int ExpectedSessionState1 = 2011;
2627
public const int ExpectedSessionState6 = 2016;
2728

src/MySqlConnector/Logging/Log.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,9 @@ internal static partial class Log
282282
[LoggerMessage(EventIds.SettingStateToFailed, LogLevel.Debug, "Session {SessionId} setting state to Failed")]
283283
public static partial void SettingStateToFailed(ILogger logger, Exception exception, string sessionId);
284284

285+
[LoggerMessage(EventIds.ExpectedToReadMoreBytes, LogLevel.Error, "Session {SessionId} expected to read {ExpectedByteCount} bytes but only read {ReadByteCount}")]
286+
public static partial void ExpectedToReadMoreBytes(ILogger logger, string sessionId, int expectedByteCount, int readByteCount);
287+
285288
[LoggerMessage(EventIds.ErrorPayload, LogLevel.Debug, "Session {SessionId} got error payload: {ErrorCode}, {State}, {Message}")]
286289
public static partial void ErrorPayload(ILogger logger, string sessionId, int errorCode, string state, string message);
287290

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace MySqlConnector;
2+
3+
[Serializable]
4+
public sealed class MySqlEndOfStreamException : EndOfStreamException
5+
{
6+
internal MySqlEndOfStreamException(int expectedByteCount, int readByteCount)
7+
: base("An incomplete response was received from the server")
8+
{
9+
ExpectedByteCount = expectedByteCount;
10+
ReadByteCount = readByteCount;
11+
}
12+
13+
public int ExpectedByteCount { get; }
14+
public int ReadByteCount { get; }
15+
}

src/MySqlConnector/Protocol/Serialization/CompressedPayloadHandler.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ private async ValueTask<int> ReadBytesAsync(Memory<byte> buffer, ProtocolErrorBe
130130
} while (bytesRead > 0);
131131
#endif
132132
if (totalBytesRead != uncompressedLength && protocolErrorBehavior == ProtocolErrorBehavior.Throw)
133-
throw new InvalidOperationException($"Expected to read {uncompressedLength:d} uncompressed bytes but only read {totalBytesRead:d}");
133+
throw new MySqlEndOfStreamException(uncompressedLength, totalBytesRead);
134+
134135
m_remainingData = new(uncompressedData, 0, totalBytesRead);
135136
#else
136137
// check CMF (Compression Method and Flags) and FLG (Flags) bytes for expected values
@@ -160,7 +161,7 @@ private async ValueTask<int> ReadBytesAsync(Memory<byte> buffer, ProtocolErrorBe
160161
totalBytesRead += bytesRead;
161162
} while (bytesRead > 0);
162163
if (totalBytesRead != uncompressedLength && protocolErrorBehavior == ProtocolErrorBehavior.Throw)
163-
throw new InvalidOperationException($"Expected to read {uncompressedLength:d} uncompressed bytes but only read {totalBytesRead:d}");
164+
throw new MySqlEndOfStreamException(uncompressedLength, totalBytesRead);
164165
m_remainingData = new(uncompressedData, 0, totalBytesRead);
165166

166167
var checksum = Adler32.Calculate(uncompressedData.AsSpan(0, totalBytesRead));

src/MySqlConnector/Protocol/Serialization/ProtocolUtility.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ public static async ValueTask<ArraySegment<byte>> ReadPayloadAsync(BufferedByteR
422422
if (headerBytes.Count < 4)
423423
{
424424
return protocolErrorBehavior == ProtocolErrorBehavior.Ignore ? default :
425-
throw new EndOfStreamException($"Expected to read 4 header bytes but only received {headerBytes.Count:d}.");
425+
throw new MySqlEndOfStreamException(4, headerBytes.Count);
426426
}
427427

428428
// read values from the header before the memory is potentially overwritten by ReadBytesAsync
@@ -450,7 +450,7 @@ public static async ValueTask<ArraySegment<byte>> ReadPayloadAsync(BufferedByteR
450450
else
451451
{
452452
packet = payloadBytes.Count >= payloadLength ? new(payloadBytes) :
453-
protocolErrorBehavior == ProtocolErrorBehavior.Throw ? throw new EndOfStreamException($"Expected to read {payloadLength:d} payload bytes but only received {payloadBytes.Count:d}.") :
453+
protocolErrorBehavior == ProtocolErrorBehavior.Throw ? throw new MySqlEndOfStreamException(payloadLength, payloadBytes.Count) :
454454
default;
455455
}
456456

0 commit comments

Comments
 (0)