40
40
41
41
using System ;
42
42
using System . Buffers ;
43
- using System . Collections . Generic ;
44
43
using System . Runtime . InteropServices ;
45
- using RabbitMQ . Client . Exceptions ;
46
44
using RabbitMQ . Client . Framing . Impl ;
47
45
48
46
namespace RabbitMQ . Client . Impl
@@ -57,11 +55,6 @@ class Command : IDisposable
57
55
private const int EmptyFrameSize = 8 ;
58
56
private readonly bool _returnBufferOnDispose ;
59
57
60
- static Command ( )
61
- {
62
- CheckEmptyFrameSize ( ) ;
63
- }
64
-
65
58
internal Command ( MethodBase method ) : this ( method , null , null , false )
66
59
{
67
60
}
@@ -80,38 +73,57 @@ public Command(MethodBase method, ContentHeaderBase header, ReadOnlyMemory<byte>
80
73
81
74
internal MethodBase Method { get ; private set ; }
82
75
83
- public static void CheckEmptyFrameSize ( )
76
+ internal void Transmit ( ushort channelNumber , Connection connection )
84
77
{
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 ) ;
89
80
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 )
91
87
{
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
+ }
97
97
}
98
+
99
+ if ( offset != size )
100
+ {
101
+ throw new InvalidOperationException ( $ "Serialized to wrong size, expect { size } , offset { offset } ") ;
102
+ }
103
+
104
+ connection . Write ( memory ) ;
98
105
}
99
106
100
- internal void Transmit ( int channelNumber , Connection connection )
107
+ private int GetMaxSize ( int maxPayloadBytes )
101
108
{
102
- connection . WriteFrame ( new MethodOutboundFrame ( channelNumber , Method ) ) ;
103
- if ( Method . HasContent )
109
+ if ( ! Method . HasContent )
104
110
{
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 ;
114
124
}
125
+
126
+ return ( Body . Length + maxPayloadBytes - 1 ) / maxPayloadBytes ;
115
127
}
116
128
117
129
public void Dispose ( )
0 commit comments