@@ -171,12 +171,14 @@ public static Memory<byte> GetHeartbeatFrame()
171
171
public readonly FrameType Type ;
172
172
public readonly int Channel ;
173
173
public readonly ReadOnlyMemory < byte > Payload ;
174
+ private readonly byte [ ] _rentedArray ;
174
175
175
- private InboundFrame ( FrameType type , int channel , ReadOnlyMemory < byte > payload )
176
+ private InboundFrame ( FrameType type , int channel , ReadOnlyMemory < byte > payload , byte [ ] rentedArray )
176
177
{
177
178
Type = type ;
178
179
Channel = channel ;
179
180
Payload = payload ;
181
+ _rentedArray = rentedArray ;
180
182
}
181
183
182
184
private static void ProcessProtocolHeader ( Stream reader )
@@ -210,17 +212,12 @@ private static void ProcessProtocolHeader(Stream reader)
210
212
}
211
213
}
212
214
213
- internal static InboundFrame ReadFrom ( Stream reader )
215
+ internal static InboundFrame ReadFrom ( Stream reader , byte [ ] frameHeaderBuffer )
214
216
{
215
217
int type = default ;
216
-
217
218
try
218
219
{
219
220
type = reader . ReadByte ( ) ;
220
- if ( type == - 1 )
221
- {
222
- throw new EndOfStreamException ( "Reached the end of the stream. Possible authentication failure." ) ;
223
- }
224
221
}
225
222
catch ( IOException ioe )
226
223
{
@@ -237,51 +234,51 @@ internal static InboundFrame ReadFrom(Stream reader)
237
234
ExceptionDispatchInfo . Capture ( ioe . InnerException ) . Throw ( ) ;
238
235
}
239
236
240
- if ( type == 'A' )
237
+ switch ( type )
241
238
{
242
- // Probably an AMQP protocol header, otherwise meaningless
243
- ProcessProtocolHeader ( reader ) ;
239
+ case - 1 :
240
+ throw new EndOfStreamException ( "Reached the end of the stream. Possible authentication failure." ) ;
241
+ case 'A' :
242
+ // Probably an AMQP protocol header, otherwise meaningless
243
+ ProcessProtocolHeader ( reader ) ;
244
+ break ;
244
245
}
245
246
246
- Span < byte > headerBytes = stackalloc byte [ 6 ] ;
247
- reader . Read ( headerBytes ) ;
248
- int channel = NetworkOrderDeserializer . ReadUInt16 ( headerBytes ) ;
249
- int payloadSize = NetworkOrderDeserializer . ReadInt32 ( headerBytes . Slice ( 2 ) ) ; // FIXME - throw exn on unreasonable value
247
+ reader . Read ( frameHeaderBuffer , 0 , frameHeaderBuffer . Length ) ;
248
+ int channel = NetworkOrderDeserializer . ReadUInt16 ( new ReadOnlySpan < byte > ( frameHeaderBuffer ) ) ;
249
+ int payloadSize = NetworkOrderDeserializer . ReadInt32 ( new ReadOnlySpan < byte > ( frameHeaderBuffer , 2 , 4 ) ) ; // FIXME - throw exn on unreasonable value
250
250
251
+ const int EndMarkerLength = 1 ;
251
252
// Is returned by InboundFrame.Dispose in Connection.MainLoopIteration
252
- byte [ ] payloadBytes = ArrayPool < byte > . Shared . Rent ( payloadSize ) ;
253
- Memory < byte > payload = new Memory < byte > ( payloadBytes , 0 , payloadSize ) ;
253
+ var readSize = payloadSize + EndMarkerLength ;
254
+ byte [ ] payloadBytes = ArrayPool < byte > . Shared . Rent ( readSize ) ;
254
255
int bytesRead = 0 ;
255
256
try
256
257
{
257
- while ( bytesRead < payloadSize )
258
+ while ( bytesRead < readSize )
258
259
{
259
- bytesRead += reader . Read ( payload . Slice ( bytesRead , payloadSize - bytesRead ) ) ;
260
+ bytesRead += reader . Read ( payloadBytes , bytesRead , readSize - bytesRead ) ;
260
261
}
261
262
}
262
263
catch ( Exception )
263
264
{
264
265
// Early EOF.
265
266
ArrayPool < byte > . Shared . Return ( payloadBytes ) ;
266
- throw new MalformedFrameException ( $ "Short frame - expected to read { payloadSize } bytes, only got { bytesRead } bytes") ;
267
+ throw new MalformedFrameException ( $ "Short frame - expected to read { readSize } bytes, only got { bytesRead } bytes") ;
267
268
}
268
269
269
- int frameEndMarker = reader . ReadByte ( ) ;
270
- if ( frameEndMarker != Constants . FrameEnd )
270
+ if ( payloadBytes [ payloadSize ] != Constants . FrameEnd )
271
271
{
272
272
ArrayPool < byte > . Shared . Return ( payloadBytes ) ;
273
- throw new MalformedFrameException ( $ "Bad frame end marker: { frameEndMarker } ") ;
273
+ throw new MalformedFrameException ( $ "Bad frame end marker: { payloadBytes [ payloadSize ] } ") ;
274
274
}
275
275
276
- return new InboundFrame ( ( FrameType ) type , channel , payload ) ;
276
+ return new InboundFrame ( ( FrameType ) type , channel , new Memory < byte > ( payloadBytes , 0 , payloadSize ) , payloadBytes ) ;
277
277
}
278
278
279
279
public void Dispose ( )
280
280
{
281
- if ( MemoryMarshal . TryGetArray ( Payload , out ArraySegment < byte > segment ) )
282
- {
283
- ArrayPool < byte > . Shared . Return ( segment . Array ) ;
284
- }
281
+ ArrayPool < byte > . Shared . Return ( _rentedArray ) ;
285
282
}
286
283
287
284
public override string ToString ( )
0 commit comments