@@ -8,6 +8,7 @@ namespace System.Net
88{
99 using System . IO ;
1010 using System . Net . Sockets ;
11+ using System . Text ;
1112
1213 /// <summary>
1314 /// The OutputNetworkStreamWrapper is used to re-implement calls to NetworkStream.Write
@@ -29,6 +30,11 @@ internal class OutputNetworkStreamWrapper : Stream
2930 /// </summary>
3031 internal NetworkStream m_Stream ;
3132
33+ /// <summary>
34+ /// If true causes all written data to be encoded as chunks
35+ /// </summary>
36+ internal bool m_enableChunkedEncoding = false ;
37+
3238 /// <summary>
3339 /// Type definition of delegate for sending of HTTP headers.
3440 /// </summary>
@@ -40,6 +46,11 @@ internal class OutputNetworkStreamWrapper : Stream
4046 /// </summary>
4147 private SendHeadersDelegate m_headersSend ;
4248
49+ /// <summary>
50+ /// EOL marker in chunked encoding
51+ /// </summary>
52+ private readonly byte [ ] EOLMarker = { 0xd , 0xa } ;
53+
4354 /// <summary>
4455 /// Just passes parameters to the base.
4556 /// Socket is not owned by base NetworkStream
@@ -118,6 +129,35 @@ public override int WriteTimeout
118129 set { m_Stream . WriteTimeout = value ; }
119130 }
120131
132+ /// <summary>
133+ /// Writes to stream size of chunk and marks start of the chunk
134+ /// </summary>
135+ private void WriteChunkStart ( int size )
136+ {
137+ byte [ ] chunkLengthBytes = Encoding . UTF8 . GetBytes ( $ "{ size : X} ") ;
138+ m_Stream . Write ( chunkLengthBytes , 0 , chunkLengthBytes . Length ) ;
139+ m_Stream . Write ( EOLMarker , 0 , EOLMarker . Length ) ;
140+ }
141+
142+ /// <summary>
143+ /// Writes to stream marker - finish of the chunk
144+ /// </summary>
145+ private void WriteChunkEnd ( )
146+ {
147+ m_Stream . Write ( EOLMarker , 0 , EOLMarker . Length ) ;
148+ }
149+
150+ /// <summary>
151+ /// Writes to stream marker - finish of all chunks
152+ /// </summary>
153+ private void WriteChunkFinish ( )
154+ {
155+ byte [ ] zero = { 0x30 } ;
156+ m_Stream . Write ( zero , 0 , 1 ) ;
157+ m_Stream . Write ( EOLMarker , 0 , EOLMarker . Length ) ;
158+ m_Stream . Write ( EOLMarker , 0 , EOLMarker . Length ) ;
159+ }
160+
121161 /// <summary>
122162 /// Closes the stream. Verifies that HTTP response is sent before closing.
123163 /// </summary>
@@ -144,7 +184,12 @@ public override void Flush()
144184 // Calls HttpListenerResponse.SendHeaders. HttpListenerResponse.SendHeaders sets m_headersSend to null.
145185 m_headersSend ( ) ;
146186 }
147-
187+
188+ if ( m_enableChunkedEncoding )
189+ {
190+ WriteChunkFinish ( ) ;
191+ }
192+
148193 // Need to check for null before using here
149194 m_Stream ? . Flush ( ) ;
150195 }
@@ -194,9 +239,26 @@ public override void SetLength(long value)
194239 /// <param name="value">Byte value to write.</param>
195240 public override void WriteByte ( byte value )
196241 {
242+ if ( m_headersSend != null )
243+ {
244+ // Calls HttpListenerResponse.SendHeaders. HttpListenerResponse.SendHeaders sets m_headersSend to null.
245+ m_headersSend ( ) ;
246+ }
247+
248+ if ( m_enableChunkedEncoding )
249+ {
250+ WriteChunkStart ( 1 ) ;
251+ }
252+
197253 m_Stream . WriteByte ( value ) ;
254+
255+ if ( m_enableChunkedEncoding )
256+ {
257+ WriteChunkEnd ( ) ;
258+ }
198259 }
199260
261+
200262 /// <summary>
201263 /// Re-implements writing of data to network stream.
202264 /// The only functionality - on first write it sends HTTP headers.
@@ -213,7 +275,17 @@ public override void Write(byte[] buffer, int offset, int size)
213275 m_headersSend ( ) ;
214276 }
215277
216- m_Stream . Write ( buffer , offset , size ) ;
278+ if ( m_enableChunkedEncoding )
279+ {
280+ WriteChunkStart ( size ) ;
281+ }
282+
283+ m_Stream . Write ( buffer , 0 , size ) ;
284+
285+ if ( m_enableChunkedEncoding )
286+ {
287+ WriteChunkEnd ( ) ;
288+ }
217289 }
218290 }
219291}
0 commit comments