4040
4141using System ;
4242using System . Buffers ;
43- using System . Collections . Generic ;
4443using System . Runtime . InteropServices ;
45- using RabbitMQ . Client . Exceptions ;
4644using RabbitMQ . Client . Framing . Impl ;
4745
4846namespace RabbitMQ . Client . Impl
@@ -57,11 +55,6 @@ class Command : IDisposable
5755 private const int EmptyFrameSize = 8 ;
5856 private readonly bool _returnBufferOnDispose ;
5957
60- static Command ( )
61- {
62- CheckEmptyFrameSize ( ) ;
63- }
64-
6558 internal Command ( MethodBase method ) : this ( method , null , null , false )
6659 {
6760 }
@@ -80,38 +73,57 @@ public Command(MethodBase method, ContentHeaderBase header, ReadOnlyMemory<byte>
8073
8174 internal MethodBase Method { get ; private set ; }
8275
83- public static void CheckEmptyFrameSize ( )
76+ internal void Transmit ( ushort channelNumber , Connection connection )
8477 {
85- var f = new EmptyOutboundFrame ( ) ;
86- byte [ ] b = new byte [ f . GetMinimumBufferSize ( ) ] ;
87- f . WriteTo ( b ) ;
88- long actualLength = f . ByteCount ;
78+ int maxBodyPayloadBytes = ( int ) ( connection . FrameMax == 0 ? int . MaxValue : connection . FrameMax - EmptyFrameSize ) ;
79+ var size = GetMaxSize ( maxBodyPayloadBytes ) ;
8980
90- if ( EmptyFrameSize != actualLength )
81+ // Will be returned by SocketFrameWriter.WriteLoop
82+ var memory = new Memory < byte > ( ArrayPool < byte > . Shared . Rent ( size ) , 0 , size ) ;
83+ var span = memory . Span ;
84+
85+ var offset = Framing . Method . WriteTo ( span , channelNumber , Method ) ;
86+ if ( Method . HasContent )
9187 {
92- string message =
93- string . Format ( "EmptyFrameSize is incorrect - defined as {0} where the computed value is in fact {1}." ,
94- EmptyFrameSize ,
95- actualLength ) ;
96- throw new ProtocolViolationException ( message ) ;
88+ int remainingBodyBytes = Body . Length ;
89+ offset += Framing . Header . WriteTo ( span . Slice ( offset ) , channelNumber , Header , remainingBodyBytes ) ;
90+ var bodySpan = Body . Span ;
91+ while ( remainingBodyBytes > 0 )
92+ {
93+ int frameSize = remainingBodyBytes > maxBodyPayloadBytes ? maxBodyPayloadBytes : remainingBodyBytes ;
94+ offset += Framing . BodySegment . WriteTo ( span . Slice ( offset ) , channelNumber , bodySpan . Slice ( bodySpan . Length - remainingBodyBytes , frameSize ) ) ;
95+ remainingBodyBytes -= frameSize ;
96+ }
9797 }
98+
99+ if ( offset != size )
100+ {
101+ throw new InvalidOperationException ( $ "Serialized to wrong size, expect { size } , offset { offset } ") ;
102+ }
103+
104+ connection . Write ( memory ) ;
98105 }
99106
100- internal void Transmit ( int channelNumber , Connection connection )
107+ private int GetMaxSize ( int maxPayloadBytes )
101108 {
102- connection . WriteFrame ( new MethodOutboundFrame ( channelNumber , Method ) ) ;
103- if ( Method . HasContent )
109+ if ( ! Method . HasContent )
104110 {
105- connection . WriteFrame ( new HeaderOutboundFrame ( channelNumber , Header , Body . Length ) ) ;
106- int frameMax = ( int ) Math . Min ( int . MaxValue , connection . FrameMax ) ;
107- int bodyPayloadMax = ( frameMax == 0 ) ? Body . Length : frameMax - EmptyFrameSize ;
108- for ( int offset = 0 ; offset < Body . Length ; offset += bodyPayloadMax )
109- {
110- int remaining = Body . Length - offset ;
111- int count = ( remaining < bodyPayloadMax ) ? remaining : bodyPayloadMax ;
112- connection . WriteFrame ( new BodySegmentOutboundFrame ( channelNumber , Body . Slice ( offset , count ) ) ) ;
113- }
111+ return Framing . Method . FrameSize + Method . GetRequiredBufferSize ( ) ;
112+ }
113+
114+ return Framing . Method . FrameSize + Method . GetRequiredBufferSize ( ) +
115+ Framing . Header . FrameSize + Header . GetRequiredPayloadBufferSize ( ) +
116+ Framing . BodySegment . FrameSize * GetBodyFrameCount ( maxPayloadBytes ) + Body . Length ;
117+ }
118+
119+ private int GetBodyFrameCount ( int maxPayloadBytes )
120+ {
121+ if ( maxPayloadBytes == int . MaxValue )
122+ {
123+ return 1 ;
114124 }
125+
126+ return ( Body . Length + maxPayloadBytes - 1 ) / maxPayloadBytes ;
115127 }
116128
117129 public void Dispose ( )
0 commit comments