@@ -45,12 +45,9 @@ internal sealed class CommandAssembler
4545 private const int MaxArrayOfBytesSize = 2_147_483_591 ;
4646
4747 private ProtocolCommandId _commandId ;
48- private ReadOnlyMemory < byte > _methodMemory ;
49- private byte [ ] ? _rentedMethodArray ;
50- private ReadOnlyMemory < byte > _headerMemory ;
51- private byte [ ] ? _rentedHeaderArray ;
52- private ReadOnlyMemory < byte > _bodyMemory ;
53- private byte [ ] ? _rentedBodyArray ;
48+ private RentedMemory _methodMemory ;
49+ private RentedMemory _headerMemory ;
50+ private RentedMemory _bodyMemory ;
5451 private int _remainingBodyByteCount ;
5552 private int _offset ;
5653 private AssemblyState _state ;
@@ -66,61 +63,49 @@ public CommandAssembler(uint maxBodyLength)
6663 private void Reset ( )
6764 {
6865 _commandId = default ;
69- _methodMemory = ReadOnlyMemory < byte > . Empty ;
70- _rentedMethodArray = null ;
71- _headerMemory = ReadOnlyMemory < byte > . Empty ;
72- _rentedHeaderArray = null ;
73- _bodyMemory = ReadOnlyMemory < byte > . Empty ;
74- _rentedBodyArray = null ;
66+ _methodMemory = default ;
67+ _headerMemory = default ;
68+ _bodyMemory = default ;
7569 _remainingBodyByteCount = 0 ;
7670 _offset = 0 ;
7771 _state = AssemblyState . ExpectingMethod ;
7872 }
7973
80- public bool HandleFrame ( in InboundFrame frame , out IncomingCommand command )
74+ public void HandleFrame ( InboundFrame frame , out IncomingCommand command )
8175 {
82- bool shallReturn = true ;
8376 switch ( _state )
8477 {
8578 case AssemblyState . ExpectingMethod :
86- ParseMethodFrame ( in frame ) ;
87- shallReturn = false ;
79+ ParseMethodFrame ( frame ) ;
8880 break ;
8981 case AssemblyState . ExpectingContentHeader :
90- shallReturn = ParseHeaderFrame ( in frame ) ;
82+ ParseHeaderFrame ( frame ) ;
9183 break ;
9284 case AssemblyState . ExpectingContentBody :
93- shallReturn = ParseBodyFrame ( in frame ) ;
85+ ParseBodyFrame ( frame ) ;
9486 break ;
9587 }
9688
9789 if ( _state != AssemblyState . Complete )
9890 {
9991 command = IncomingCommand . Empty ;
100- return shallReturn ;
92+ return ;
10193 }
10294
10395 RabbitMqClientEventSource . Log . CommandReceived ( ) ;
104-
105- var method = new RentedMemory ( _methodMemory , _rentedMethodArray ) ;
106- var header = new RentedMemory ( _headerMemory , _rentedHeaderArray ) ;
107- var body = new RentedMemory ( _bodyMemory , _rentedBodyArray ) ;
108-
109- command = new IncomingCommand ( _commandId , method , header , body ) ;
96+ command = new IncomingCommand ( _commandId , _methodMemory , _headerMemory , _bodyMemory ) ;
11097 Reset ( ) ;
111- return shallReturn ;
11298 }
11399
114- private void ParseMethodFrame ( in InboundFrame frame )
100+ private void ParseMethodFrame ( InboundFrame frame )
115101 {
116102 if ( frame . Type != FrameType . FrameMethod )
117103 {
118104 throw new UnexpectedFrameException ( frame . Type ) ;
119105 }
120106
121- _rentedMethodArray = frame . TakeoverPayload ( ) ;
122107 _commandId = ( ProtocolCommandId ) NetworkOrderDeserializer . ReadUInt32 ( frame . Payload . Span ) ;
123- _methodMemory = frame . Payload . Slice ( 4 ) ;
108+ _methodMemory = frame . TakeoverPayload ( Framing . Method . ArgumentsOffset ) ;
124109
125110 switch ( _commandId )
126111 {
@@ -136,7 +121,7 @@ private void ParseMethodFrame(in InboundFrame frame)
136121 }
137122 }
138123
139- private bool ParseHeaderFrame ( in InboundFrame frame )
124+ private void ParseHeaderFrame ( InboundFrame frame )
140125 {
141126 if ( frame . Type != FrameType . FrameHeader )
142127 {
@@ -150,7 +135,7 @@ private bool ParseHeaderFrame(in InboundFrame frame)
150135 throw new UnknownClassOrMethodException ( classId , 0 ) ;
151136 }
152137
153- ulong totalBodyBytes = NetworkOrderDeserializer . ReadUInt64 ( span . Slice ( 4 ) ) ;
138+ ulong totalBodyBytes = NetworkOrderDeserializer . ReadUInt64 ( span . Slice ( Framing . Header . BodyLengthOffset ) ) ;
154139 if ( totalBodyBytes > MaxArrayOfBytesSize )
155140 {
156141 throw new UnexpectedFrameException ( frame . Type ) ;
@@ -162,16 +147,21 @@ private bool ParseHeaderFrame(in InboundFrame frame)
162147 throw new MalformedFrameException ( message : msg , canShutdownCleanly : false ) ;
163148 }
164149
165- _rentedHeaderArray = totalBodyBytes != 0 ? frame . TakeoverPayload ( ) : Array . Empty < byte > ( ) ;
166-
167- _headerMemory = frame . Payload . Slice ( 12 ) ;
150+ // There are always at least 2 bytes, even for empty ones
151+ if ( frame . Payload . Length <= Framing . Header . HeaderArgumentOffset + 2 )
152+ {
153+ frame . TryReturnPayload ( ) ;
154+ }
155+ else
156+ {
157+ _headerMemory = frame . TakeoverPayload ( Framing . Header . HeaderArgumentOffset ) ;
158+ }
168159
169160 _remainingBodyByteCount = ( int ) totalBodyBytes ;
170161 UpdateContentBodyState ( ) ;
171- return _rentedHeaderArray . Length == 0 ;
172162 }
173163
174- private bool ParseBodyFrame ( in InboundFrame frame )
164+ private void ParseBodyFrame ( InboundFrame frame )
175165 {
176166 if ( frame . Type != FrameType . FrameBody )
177167 {
@@ -184,27 +174,26 @@ private bool ParseBodyFrame(in InboundFrame frame)
184174 throw new MalformedFrameException ( $ "Overlong content body received - { _remainingBodyByteCount } bytes remaining, { payloadLength } bytes received") ;
185175 }
186176
187- if ( _rentedBodyArray is null )
177+ if ( _bodyMemory . RentedArray is null )
188178 {
189179 // check for single frame payload for an early exit
190180 if ( payloadLength == _remainingBodyByteCount )
191181 {
192- _rentedBodyArray = frame . TakeoverPayload ( ) ;
193- _bodyMemory = frame . Payload ;
182+ _bodyMemory = frame . TakeoverPayload ( 0 ) ;
194183 _state = AssemblyState . Complete ;
195- return false ;
184+ return ;
196185 }
197186
198187 // Is returned by IncomingCommand.ReturnPayload in Session.HandleFrame
199- _rentedBodyArray = ArrayPool < byte > . Shared . Rent ( _remainingBodyByteCount ) ;
200- _bodyMemory = new ReadOnlyMemory < byte > ( _rentedBodyArray , 0 , _remainingBodyByteCount ) ;
188+ var rentedBodyArray = ArrayPool < byte > . Shared . Rent ( _remainingBodyByteCount ) ;
189+ _bodyMemory = new RentedMemory ( new ReadOnlyMemory < byte > ( rentedBodyArray , 0 , _remainingBodyByteCount ) , rentedBodyArray ) ;
201190 }
202191
203- frame . Payload . Span . CopyTo ( _rentedBodyArray . AsSpan ( _offset ) ) ;
192+ frame . Payload . Span . CopyTo ( _bodyMemory . RentedArray . AsSpan ( _offset ) ) ;
193+ frame . TryReturnPayload ( ) ;
204194 _remainingBodyByteCount -= payloadLength ;
205195 _offset += payloadLength ;
206196 UpdateContentBodyState ( ) ;
207- return true ;
208197 }
209198
210199 private void UpdateContentBodyState ( )
0 commit comments