Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
HttpResponseStream.cs
Go to the documentation of this file.
2using System.IO;
8
9namespace System.Net;
10
11internal sealed class HttpResponseStream : Stream
12{
13 private bool _closed;
14
16
17 private long _leftToWrite = long.MinValue;
18
19 private bool _inOpaqueMode;
20
22
23 private static readonly byte[] s_chunkTerminator = new byte[5] { 48, 13, 10, 13, 10 };
24
25 internal bool Closed => _closed;
26
27 public override bool CanRead => false;
28
29 public override bool CanSeek => false;
30
31 public override bool CanWrite => true;
32
33 public override long Length
34 {
35 get
36 {
38 }
39 }
40
41 public override long Position
42 {
43 get
44 {
46 }
47 set
48 {
50 }
51 }
52
54
55 public override void Flush()
56 {
57 }
58
63
64 public override long Seek(long offset, SeekOrigin origin)
65 {
67 }
68
69 public override void SetLength(long value)
70 {
72 }
73
74 public override int Read(byte[] buffer, int offset, int size)
75 {
77 }
78
79 public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
80 {
82 }
83
88
89 public override void Write(byte[] buffer, int offset, int count)
90 {
92 if (System.Net.NetEventSource.Log.IsEnabled())
93 {
94 System.Net.NetEventSource.Info(this, "buffer.Length:" + buffer.Length + " count:" + count + " offset:" + offset, "Write");
95 }
96 if (!_closed)
97 {
99 }
100 }
101
102 public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
103 {
105 if (System.Net.NetEventSource.Log.IsEnabled())
106 {
107 System.Net.NetEventSource.Info(this, "buffer.Length:" + buffer.Length + " count:" + count + " offset:" + offset, "BeginWrite");
108 }
109 return BeginWriteCore(buffer, offset, count, callback, state);
110 }
111
112 public override void EndWrite(IAsyncResult asyncResult)
113 {
114 if (System.Net.NetEventSource.Log.IsEnabled())
115 {
116 System.Net.NetEventSource.Info(this, $"asyncResult:{asyncResult}", "EndWrite");
117 }
118 if (asyncResult == null)
119 {
120 throw new ArgumentNullException("asyncResult");
121 }
123 }
124
125 protected override void Dispose(bool disposing)
126 {
127 try
128 {
129 if (disposing)
130 {
131 if (System.Net.NetEventSource.Log.IsEnabled())
132 {
133 System.Net.NetEventSource.Info(this, "_closed:" + _closed, "Dispose");
134 }
135 if (!_closed)
136 {
137 _closed = true;
138 DisposeCore();
139 }
140 }
141 }
142 finally
143 {
144 base.Dispose(disposing);
145 }
146 }
147
149 {
150 if (System.Net.NetEventSource.Log.IsEnabled())
151 {
152 System.Net.NetEventSource.Info(this, $"httpContect: {httpContext}", ".ctor");
153 }
154 _httpContext = httpContext;
155 }
156
157 internal global::Interop.HttpApi.HTTP_FLAGS ComputeLeftToWrite()
158 {
159 if (System.Net.NetEventSource.Log.IsEnabled())
160 {
161 System.Net.NetEventSource.Info(this, "_LeftToWrite:" + _leftToWrite, "ComputeLeftToWrite");
162 }
163 global::Interop.HttpApi.HTTP_FLAGS result = global::Interop.HttpApi.HTTP_FLAGS.NONE;
165 {
167 }
168 if (_leftToWrite == long.MinValue)
169 {
170 global::Interop.HttpApi.HTTP_VERB knownMethod = _httpContext.GetKnownMethod();
171 _leftToWrite = ((knownMethod != global::Interop.HttpApi.HTTP_VERB.HttpVerbHEAD) ? _httpContext.Response.ContentLength64 : 0);
172 if (System.Net.NetEventSource.Log.IsEnabled())
173 {
174 System.Net.NetEventSource.Info(this, "_LeftToWrite:" + _leftToWrite, "ComputeLeftToWrite");
175 }
176 }
177 return result;
178 }
179
180 internal void SetClosedFlag()
181 {
182 _closed = true;
183 }
184
185 private unsafe void WriteCore(byte[] buffer, int offset, int size)
186 {
187 global::Interop.HttpApi.HTTP_FLAGS hTTP_FLAGS = ComputeLeftToWrite();
188 if (size == 0 && _leftToWrite != 0L)
189 {
190 return;
191 }
192 if (_leftToWrite >= 0 && size > _leftToWrite)
193 {
195 }
196 uint num = (uint)size;
197 Microsoft.Win32.SafeHandles.SafeLocalAllocHandle safeLocalAllocHandle = null;
198 IntPtr zero = IntPtr.Zero;
199 bool sentHeaders = _httpContext.Response.SentHeaders;
200 uint num2;
201 try
202 {
203 if (size == 0)
204 {
205 num2 = _httpContext.Response.SendHeaders(null, null, hTTP_FLAGS, isWebSocketHandshake: false);
206 }
207 else
208 {
209 fixed (byte* ptr = buffer)
210 {
211 byte* ptr2 = ptr;
213 {
214 string text = size.ToString("x", CultureInfo.InvariantCulture);
215 num += (uint)(text.Length + 4);
216 safeLocalAllocHandle = Microsoft.Win32.SafeHandles.SafeLocalAllocHandle.LocalAlloc((int)num);
217 zero = safeLocalAllocHandle.DangerousGetHandle();
218 for (int i = 0; i < text.Length; i++)
219 {
220 Marshal.WriteByte(zero, i, (byte)text[i]);
221 }
222 Marshal.WriteInt16(zero, text.Length, 2573);
223 Marshal.Copy(buffer, offset, zero + text.Length + 2, size);
224 Marshal.WriteInt16(zero, (int)(num - 2), 2573);
225 ptr2 = (byte*)(void*)zero;
226 offset = 0;
227 }
228 global::Interop.HttpApi.HTTP_DATA_CHUNK hTTP_DATA_CHUNK = default(global::Interop.HttpApi.HTTP_DATA_CHUNK);
229 hTTP_DATA_CHUNK.DataChunkType = global::Interop.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
230 hTTP_DATA_CHUNK.pBuffer = ptr2 + offset;
231 hTTP_DATA_CHUNK.BufferLength = num;
232 hTTP_FLAGS |= ((_leftToWrite != size) ? global::Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA : global::Interop.HttpApi.HTTP_FLAGS.NONE);
233 if (!sentHeaders)
234 {
235 num2 = _httpContext.Response.SendHeaders(&hTTP_DATA_CHUNK, null, hTTP_FLAGS, isWebSocketHandshake: false);
236 }
237 else
238 {
239 if (System.Net.NetEventSource.Log.IsEnabled())
240 {
241 System.Net.NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody", "WriteCore");
242 }
243 num2 = global::Interop.HttpApi.HttpSendResponseEntityBody(_httpContext.RequestQueueHandle, _httpContext.RequestId, (uint)hTTP_FLAGS, 1, &hTTP_DATA_CHUNK, null, Microsoft.Win32.SafeHandles.SafeLocalAllocHandle.Zero, 0u, null, null);
244 if (System.Net.NetEventSource.Log.IsEnabled())
245 {
246 System.Net.NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + num2, "WriteCore");
247 }
249 {
250 if (System.Net.NetEventSource.Log.IsEnabled())
251 {
252 System.Net.NetEventSource.Info(this, "Write() suppressing error", "WriteCore");
253 }
254 num2 = 0u;
255 }
256 }
257 }
258 }
259 }
260 finally
261 {
262 safeLocalAllocHandle?.Close();
263 }
264 if (num2 != 0 && num2 != 38)
265 {
266 Exception ex = new HttpListenerException((int)num2);
267 if (System.Net.NetEventSource.Log.IsEnabled())
268 {
269 System.Net.NetEventSource.Error(this, ex.ToString(), "WriteCore");
270 }
271 _closed = true;
273 throw ex;
274 }
275 UpdateAfterWrite(num);
276 if (System.Net.NetEventSource.Log.IsEnabled())
277 {
278 System.Net.NetEventSource.DumpBuffer(this, buffer, offset, (int)num, "WriteCore");
279 }
280 }
281
282 private unsafe IAsyncResult BeginWriteCore(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
283 {
284 global::Interop.HttpApi.HTTP_FLAGS hTTP_FLAGS = ComputeLeftToWrite();
285 if (_closed || (size == 0 && _leftToWrite != 0L))
286 {
287 HttpResponseStreamAsyncResult httpResponseStreamAsyncResult = new HttpResponseStreamAsyncResult(this, state, callback);
288 httpResponseStreamAsyncResult.InvokeCallback(0u);
289 return httpResponseStreamAsyncResult;
290 }
291 if (_leftToWrite >= 0 && size > _leftToWrite)
292 {
294 }
295 uint numBytes = 0u;
296 hTTP_FLAGS |= ((_leftToWrite != size) ? global::Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA : global::Interop.HttpApi.HTTP_FLAGS.NONE);
297 bool sentHeaders = _httpContext.Response.SentHeaders;
298 HttpResponseStreamAsyncResult httpResponseStreamAsyncResult2 = new HttpResponseStreamAsyncResult(this, state, callback, buffer, offset, size, _httpContext.Response.BoundaryType == BoundaryType.Chunked, sentHeaders, _httpContext.RequestQueueBoundHandle);
299 UpdateAfterWrite((_httpContext.Response.BoundaryType != BoundaryType.Chunked) ? ((uint)size) : 0u);
300 uint num;
301 try
302 {
303 if (!sentHeaders)
304 {
305 num = _httpContext.Response.SendHeaders(null, httpResponseStreamAsyncResult2, hTTP_FLAGS, isWebSocketHandshake: false);
306 }
307 else
308 {
309 if (System.Net.NetEventSource.Log.IsEnabled())
310 {
311 System.Net.NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody", "BeginWriteCore");
312 }
313 num = global::Interop.HttpApi.HttpSendResponseEntityBody(_httpContext.RequestQueueHandle, _httpContext.RequestId, (uint)hTTP_FLAGS, httpResponseStreamAsyncResult2.dataChunkCount, httpResponseStreamAsyncResult2.pDataChunks, &numBytes, Microsoft.Win32.SafeHandles.SafeLocalAllocHandle.Zero, 0u, httpResponseStreamAsyncResult2._pOverlapped, null);
314 if (System.Net.NetEventSource.Log.IsEnabled())
315 {
316 System.Net.NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + num, "BeginWriteCore");
317 }
318 }
319 }
320 catch (Exception ex)
321 {
322 if (System.Net.NetEventSource.Log.IsEnabled())
323 {
324 System.Net.NetEventSource.Error(this, ex.ToString(), "BeginWriteCore");
325 }
326 httpResponseStreamAsyncResult2.InternalCleanup();
327 _closed = true;
329 throw;
330 }
331 if (num != 0 && num != 997)
332 {
333 httpResponseStreamAsyncResult2.InternalCleanup();
334 if (!(_httpContext.Listener.IgnoreWriteExceptions && sentHeaders))
335 {
336 Exception ex2 = new HttpListenerException((int)num);
337 if (System.Net.NetEventSource.Log.IsEnabled())
338 {
339 System.Net.NetEventSource.Error(this, ex2.ToString(), "BeginWriteCore");
340 }
341 _closed = true;
343 throw ex2;
344 }
345 if (System.Net.NetEventSource.Log.IsEnabled())
346 {
347 System.Net.NetEventSource.Info(this, "BeginWrite() Suppressing error", "BeginWriteCore");
348 }
349 }
351 {
352 httpResponseStreamAsyncResult2.IOCompleted(num, numBytes);
353 }
354 if ((hTTP_FLAGS & global::Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0)
355 {
356 _lastWrite = httpResponseStreamAsyncResult2;
357 }
358 return httpResponseStreamAsyncResult2;
359 }
360
362 {
363 if (!(asyncResult is HttpResponseStreamAsyncResult httpResponseStreamAsyncResult) || httpResponseStreamAsyncResult.AsyncObject != this)
364 {
365 throw new ArgumentException(System.SR.net_io_invalidasyncresult, "asyncResult");
366 }
367 if (httpResponseStreamAsyncResult.EndCalled)
368 {
370 }
371 httpResponseStreamAsyncResult.EndCalled = true;
372 object obj = httpResponseStreamAsyncResult.InternalWaitForCompletion();
373 if (obj is Exception ex)
374 {
375 if (System.Net.NetEventSource.Log.IsEnabled())
376 {
377 System.Net.NetEventSource.Error(this, "Rethrowing exception:" + ex, "EndWriteCore");
378 }
379 _closed = true;
382 }
383 }
384
385 private void UpdateAfterWrite(uint dataWritten)
386 {
387 if (System.Net.NetEventSource.Log.IsEnabled())
388 {
389 System.Net.NetEventSource.Info(this, "dataWritten:" + dataWritten + " _leftToWrite:" + _leftToWrite + " _closed:" + _closed, "UpdateAfterWrite");
390 }
391 if (!_inOpaqueMode)
392 {
393 if (_leftToWrite > 0)
394 {
395 _leftToWrite -= dataWritten;
396 }
397 if (_leftToWrite == 0L)
398 {
399 _closed = true;
400 }
401 }
402 if (System.Net.NetEventSource.Log.IsEnabled())
403 {
404 System.Net.NetEventSource.Info(this, "dataWritten:" + dataWritten + " _leftToWrite:" + _leftToWrite + " _closed:" + _closed, "UpdateAfterWrite");
405 }
406 }
407
408 private unsafe void DisposeCore()
409 {
410 global::Interop.HttpApi.HTTP_FLAGS hTTP_FLAGS = ComputeLeftToWrite();
411 if (_leftToWrite > 0 && !_inOpaqueMode)
412 {
414 }
415 bool sentHeaders = _httpContext.Response.SentHeaders;
416 if (sentHeaders && _leftToWrite == 0L)
417 {
418 return;
419 }
420 uint num = 0u;
421 if ((_httpContext.Response.BoundaryType == BoundaryType.Chunked || _httpContext.Response.BoundaryType == BoundaryType.None) && !string.Equals(_httpContext.Request.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase))
422 {
424 {
425 hTTP_FLAGS |= global::Interop.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY;
426 }
427 fixed (byte* ptr = &s_chunkTerminator[0])
428 {
429 void* pBuffer = ptr;
430 global::Interop.HttpApi.HTTP_DATA_CHUNK* ptr2 = null;
432 {
433 global::Interop.HttpApi.HTTP_DATA_CHUNK hTTP_DATA_CHUNK = default(global::Interop.HttpApi.HTTP_DATA_CHUNK);
434 hTTP_DATA_CHUNK.DataChunkType = global::Interop.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
435 hTTP_DATA_CHUNK.pBuffer = (byte*)pBuffer;
436 hTTP_DATA_CHUNK.BufferLength = (uint)s_chunkTerminator.Length;
437 ptr2 = &hTTP_DATA_CHUNK;
438 }
439 if (!sentHeaders)
440 {
441 num = _httpContext.Response.SendHeaders(ptr2, null, hTTP_FLAGS, isWebSocketHandshake: false);
442 }
443 else
444 {
445 if (System.Net.NetEventSource.Log.IsEnabled())
446 {
447 System.Net.NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody", "DisposeCore");
448 }
449 num = global::Interop.HttpApi.HttpSendResponseEntityBody(_httpContext.RequestQueueHandle, _httpContext.RequestId, (uint)hTTP_FLAGS, (ushort)((ptr2 != null) ? 1 : 0), ptr2, null, Microsoft.Win32.SafeHandles.SafeLocalAllocHandle.Zero, 0u, null, null);
450 if (System.Net.NetEventSource.Log.IsEnabled())
451 {
452 System.Net.NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + num, "DisposeCore");
453 }
455 {
456 if (System.Net.NetEventSource.Log.IsEnabled())
457 {
458 System.Net.NetEventSource.Info(this, "Suppressing error", "DisposeCore");
459 }
460 num = 0u;
461 }
462 }
463 }
464 }
465 else if (!sentHeaders)
466 {
467 num = _httpContext.Response.SendHeaders(null, null, hTTP_FLAGS, isWebSocketHandshake: false);
468 }
469 if (num != 0 && num != 38)
470 {
471 Exception ex = new HttpListenerException((int)num);
472 if (System.Net.NetEventSource.Log.IsEnabled())
473 {
474 System.Net.NetEventSource.Error(this, ex.ToString(), "DisposeCore");
475 }
477 throw ex;
478 }
479 _leftToWrite = 0L;
480 }
481
482 internal void SwitchToOpaqueMode()
483 {
484 if (System.Net.NetEventSource.Log.IsEnabled())
485 {
486 System.Net.NetEventSource.Info(this, null, "SwitchToOpaqueMode");
487 }
488 _inOpaqueMode = true;
489 _leftToWrite = long.MaxValue;
490 }
491
492 internal unsafe void CancelLastWrite(SafeHandle requestQueueHandle)
493 {
495 if (lastWrite != null && !lastWrite.IsCompleted)
496 {
497 global::Interop.Kernel32.CancelIoEx(requestQueueHandle, lastWrite._pOverlapped);
498 }
499 }
500}
static readonly Microsoft.Win32.SafeHandles.SafeLocalAllocHandle Zero
static Microsoft.Win32.SafeHandles.SafeLocalAllocHandle LocalAlloc(int cb)
override string ToString()
Definition Exception.cs:384
static CultureInfo InvariantCulture
static void ValidateBufferArguments(byte[] buffer, int offset, int count)
Definition Stream.cs:1044
ThreadPoolBoundHandle RequestQueueBoundHandle
global::Interop.HttpApi.HTTP_VERB GetKnownMethod()
global::Interop.HttpApi.HTTP_FLAGS ComputeHeaders()
unsafe uint SendHeaders(global::Interop.HttpApi.HTTP_DATA_CHUNK *pDataChunk, HttpResponseStreamAsyncResult asyncResult, global::Interop.HttpApi.HTTP_FLAGS flags, bool isWebSocketHandshake)
static readonly bool SkipIOCPCallbackOnSuccess
unsafe global::Interop.HttpApi.HTTP_DATA_CHUNK * pDataChunks
override int Read(byte[] buffer, int offset, int size)
override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
void UpdateAfterWrite(uint dataWritten)
override void Write(byte[] buffer, int offset, int count)
unsafe void CancelLastWrite(SafeHandle requestQueueHandle)
global::Interop.HttpApi.HTTP_FLAGS ComputeLeftToWrite()
static readonly byte[] s_chunkTerminator
HttpListenerContext InternalHttpContext
HttpResponseStream(HttpListenerContext httpContext)
unsafe void WriteCore(byte[] buffer, int offset, int size)
override long Seek(long offset, SeekOrigin origin)
override int EndRead(IAsyncResult asyncResult)
unsafe IAsyncResult BeginWriteCore(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
override Task FlushAsync(CancellationToken cancellationToken)
readonly HttpListenerContext _httpContext
override void SetLength(long value)
override void Dispose(bool disposing)
void EndWriteCore(IAsyncResult asyncResult)
override void EndWrite(IAsyncResult asyncResult)
HttpResponseStreamAsyncResult _lastWrite
void InvokeCallback(object result)
static readonly System.Net.NetEventSource Log
static void Info(object thisOrContextObject, FormattableString formattableString=null, [CallerMemberName] string memberName=null)
static void Error(object thisOrContextObject, FormattableString formattableString, [CallerMemberName] string memberName=null)
static void DumpBuffer(object thisOrContextObject, byte[] buffer, int offset, int count, [CallerMemberName] string memberName=null)
static void WriteInt16(object ptr, int ofs, short val)
Definition Marshal.cs:97
static void WriteByte(object ptr, int ofs, byte val)
Definition Marshal.cs:89
static void Copy(int[] source, int startIndex, IntPtr destination, int length)
Definition Marshal.cs:800
static string net_io_invalidendcall
Definition SR.cs:22
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string net_io_notenoughbyteswritten
Definition SR.cs:120
static string net_writeonlystream
Definition SR.cs:116
static string net_io_invalidasyncresult
Definition SR.cs:20
static string net_entitytoobig
Definition SR.cs:118
static string net_noseek
Definition SR.cs:114
Definition SR.cs:7
static Task CompletedTask
Definition Task.cs:1120
static readonly IntPtr Zero
Definition IntPtr.cs:18