@@ -45,12 +45,9 @@ internal sealed class CommandAssembler
45
45
private const int MaxArrayOfBytesSize = 2_147_483_591 ;
46
46
47
47
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 ;
54
51
private int _remainingBodyByteCount ;
55
52
private int _offset ;
56
53
private AssemblyState _state ;
@@ -66,61 +63,49 @@ public CommandAssembler(uint maxBodyLength)
66
63
private void Reset ( )
67
64
{
68
65
_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 ;
75
69
_remainingBodyByteCount = 0 ;
76
70
_offset = 0 ;
77
71
_state = AssemblyState . ExpectingMethod ;
78
72
}
79
73
80
- public bool HandleFrame ( in InboundFrame frame , out IncomingCommand command )
74
+ public void HandleFrame ( InboundFrame frame , out IncomingCommand command )
81
75
{
82
- bool shallReturn = true ;
83
76
switch ( _state )
84
77
{
85
78
case AssemblyState . ExpectingMethod :
86
- ParseMethodFrame ( in frame ) ;
87
- shallReturn = false ;
79
+ ParseMethodFrame ( frame ) ;
88
80
break ;
89
81
case AssemblyState . ExpectingContentHeader :
90
- shallReturn = ParseHeaderFrame ( in frame ) ;
82
+ ParseHeaderFrame ( frame ) ;
91
83
break ;
92
84
case AssemblyState . ExpectingContentBody :
93
- shallReturn = ParseBodyFrame ( in frame ) ;
85
+ ParseBodyFrame ( frame ) ;
94
86
break ;
95
87
}
96
88
97
89
if ( _state != AssemblyState . Complete )
98
90
{
99
91
command = IncomingCommand . Empty ;
100
- return shallReturn ;
92
+ return ;
101
93
}
102
94
103
95
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 ) ;
110
97
Reset ( ) ;
111
- return shallReturn ;
112
98
}
113
99
114
- private void ParseMethodFrame ( in InboundFrame frame )
100
+ private void ParseMethodFrame ( InboundFrame frame )
115
101
{
116
102
if ( frame . Type != FrameType . FrameMethod )
117
103
{
118
104
throw new UnexpectedFrameException ( frame . Type ) ;
119
105
}
120
106
121
- _rentedMethodArray = frame . TakeoverPayload ( ) ;
122
107
_commandId = ( ProtocolCommandId ) NetworkOrderDeserializer . ReadUInt32 ( frame . Payload . Span ) ;
123
- _methodMemory = frame . Payload . Slice ( 4 ) ;
108
+ _methodMemory = frame . TakeoverPayload ( Framing . Method . ArgumentsOffset ) ;
124
109
125
110
switch ( _commandId )
126
111
{
@@ -136,7 +121,7 @@ private void ParseMethodFrame(in InboundFrame frame)
136
121
}
137
122
}
138
123
139
- private bool ParseHeaderFrame ( in InboundFrame frame )
124
+ private void ParseHeaderFrame ( InboundFrame frame )
140
125
{
141
126
if ( frame . Type != FrameType . FrameHeader )
142
127
{
@@ -150,7 +135,7 @@ private bool ParseHeaderFrame(in InboundFrame frame)
150
135
throw new UnknownClassOrMethodException ( classId , 0 ) ;
151
136
}
152
137
153
- ulong totalBodyBytes = NetworkOrderDeserializer . ReadUInt64 ( span . Slice ( 4 ) ) ;
138
+ ulong totalBodyBytes = NetworkOrderDeserializer . ReadUInt64 ( span . Slice ( Framing . Header . BodyLengthOffset ) ) ;
154
139
if ( totalBodyBytes > MaxArrayOfBytesSize )
155
140
{
156
141
throw new UnexpectedFrameException ( frame . Type ) ;
@@ -162,16 +147,21 @@ private bool ParseHeaderFrame(in InboundFrame frame)
162
147
throw new MalformedFrameException ( message : msg , canShutdownCleanly : false ) ;
163
148
}
164
149
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
+ }
168
159
169
160
_remainingBodyByteCount = ( int ) totalBodyBytes ;
170
161
UpdateContentBodyState ( ) ;
171
- return _rentedHeaderArray . Length == 0 ;
172
162
}
173
163
174
- private bool ParseBodyFrame ( in InboundFrame frame )
164
+ private void ParseBodyFrame ( InboundFrame frame )
175
165
{
176
166
if ( frame . Type != FrameType . FrameBody )
177
167
{
@@ -184,27 +174,26 @@ private bool ParseBodyFrame(in InboundFrame frame)
184
174
throw new MalformedFrameException ( $ "Overlong content body received - { _remainingBodyByteCount } bytes remaining, { payloadLength } bytes received") ;
185
175
}
186
176
187
- if ( _rentedBodyArray is null )
177
+ if ( _bodyMemory . RentedArray is null )
188
178
{
189
179
// check for single frame payload for an early exit
190
180
if ( payloadLength == _remainingBodyByteCount )
191
181
{
192
- _rentedBodyArray = frame . TakeoverPayload ( ) ;
193
- _bodyMemory = frame . Payload ;
182
+ _bodyMemory = frame . TakeoverPayload ( 0 ) ;
194
183
_state = AssemblyState . Complete ;
195
- return false ;
184
+ return ;
196
185
}
197
186
198
187
// 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 ) ;
201
190
}
202
191
203
- frame . Payload . Span . CopyTo ( _rentedBodyArray . AsSpan ( _offset ) ) ;
192
+ frame . Payload . Span . CopyTo ( _bodyMemory . RentedArray . AsSpan ( _offset ) ) ;
193
+ frame . TryReturnPayload ( ) ;
204
194
_remainingBodyByteCount -= payloadLength ;
205
195
_offset += payloadLength ;
206
196
UpdateContentBodyState ( ) ;
207
- return true ;
208
197
}
209
198
210
199
private void UpdateContentBodyState ( )
0 commit comments