You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
6.7 KiB

3 years ago
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Text;
  5. namespace Apewer.Web
  6. {
  7. internal sealed class MiniReader : Stream
  8. {
  9. bool _disposed = false;
  10. MiniConnection _connection;
  11. Stream _stream;
  12. long _remaining;
  13. internal byte[] RemainsBytes = null;
  14. int _offset = 0;
  15. long _total = 0L;
  16. internal MiniReader(MiniConnection connection, long remaining = -1)
  17. {
  18. _connection = connection;
  19. _stream = connection.Stream;
  20. _remaining = remaining;
  21. }
  22. public bool Disposed { get => _disposed; }
  23. public override bool CanRead { get => true; }
  24. public override bool CanWrite { get => false; }
  25. public override bool CanSeek { get => false; }
  26. public override long Length { get => throw new NotSupportedException(); }
  27. public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
  28. public override void Close() => _disposed = true;
  29. public override void Flush() { }
  30. public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
  31. public override void SetLength(long value) => throw new NotSupportedException();
  32. #region read
  33. int ReadRemins(byte[] buffer, int offset, int count)
  34. {
  35. // 返回 0,读取 Remains 已经完成,由外层继续读取。
  36. if (RemainsBytes == null) return 0;
  37. var length = RemainsBytes.Length;
  38. if (length < 1) return 0;
  39. // Remains 中剩余的长度,并根据 count 参数限制读取数量。
  40. var result = length - offset;
  41. if (result < 1) return 0;
  42. if (result > count) result = count;
  43. // Content-Length 指定的剩余长度。
  44. if (_remaining > 0 && result > _remaining) result = (int)_remaining;
  45. // RemainsBytes 长度溢出限制。
  46. if (result + _offset > length) result = length - _offset;
  47. // 从 Remains 中读取,返回具体的字节数。
  48. Buffer.BlockCopy(RemainsBytes, _offset, buffer, offset, result);
  49. _offset += result;
  50. _remaining -= result;
  51. _total += result;
  52. // 已完成 Remains 的读取。
  53. if (_offset >= length) RemainsBytes = null;
  54. return result;
  55. }
  56. public override int Read(byte[] buffer, int offset, int count)
  57. {
  58. if (_connection.Server.SynchronousIO)
  59. {
  60. if (_disposed) throw new ObjectDisposedException(typeof(Stream).FullName);
  61. // 检查参数。
  62. if (buffer == null) throw new ArgumentNullException("参数 buffer 无效。");
  63. if (offset < 0) throw new ArgumentOutOfRangeException("offset", "参数 offset 小于 0。");
  64. if (count < 0) throw new ArgumentOutOfRangeException("count", "参数 count 小于 0。");
  65. int bufferLength = buffer.Length;
  66. if (offset > bufferLength) throw new ArgumentOutOfRangeException("offset", "指定的 offset 的值超出了 buffer 数组的容量。");
  67. if (offset + count > bufferLength) throw new ArgumentException("指定的 offset 和 count 超出了 buffer 数组的容量。");
  68. if (count == 0) return 0;
  69. // 检查剩余读取量。
  70. if (_remaining == 0) return 0;
  71. // 从 Remains 中读取。
  72. var nread = ReadRemins(buffer, offset, count);
  73. if (nread > 0) return nread;
  74. // 根据 Content-Length 限定长度。
  75. if (_remaining > 0 && _remaining < count) count = (int)_remaining;
  76. var read = _stream.Read(buffer, offset, count);
  77. if (read > 0 && _remaining > 0) _remaining -= read;
  78. return read;
  79. }
  80. else
  81. {
  82. var async = BeginRead(buffer, offset, count, null, null);
  83. var result = EndRead(async);
  84. return result;
  85. }
  86. }
  87. public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback cback, object state)
  88. {
  89. #if DEBUG
  90. if (_disposed) throw new ObjectDisposedException(typeof(Stream).FullName);
  91. // 检查参数。
  92. if (buffer == null) throw new ArgumentNullException("参数 buffer 无效。");
  93. if (offset < 0) throw new ArgumentOutOfRangeException("offset", "参数 offset 小于 0。");
  94. if (count < 0) throw new ArgumentOutOfRangeException("count", "参数 count 小于 0。");
  95. int bufferLength = buffer.Length;
  96. if (offset > bufferLength) throw new ArgumentOutOfRangeException("offset", "指定的 offset 的值超出了 buffer 数组的容量。");
  97. if (offset + count > bufferLength) throw new ArgumentException("指定的 offset 和 count 超出了 buffer 数组的容量。");
  98. // Content-Length
  99. if (_remaining == 0)
  100. {
  101. var ares = new MiniStreamAsyncResult();
  102. ares.Buffer = buffer;
  103. ares.Offset = offset;
  104. ares.Count = count;
  105. ares.Callback = cback;
  106. ares.State = state;
  107. ares.SynchRead = 0;
  108. ares.Complete();
  109. return ares;
  110. }
  111. if (_remaining > 0 && _remaining < count) count = (int)_remaining;
  112. return _stream.BeginRead(buffer, offset, count, cback, state);
  113. #else
  114. throw new NotSupportedException();
  115. #endif
  116. }
  117. public override int EndRead(IAsyncResult ar)
  118. {
  119. #if DEBUG
  120. if (_disposed) throw new ObjectDisposedException(typeof(Stream).FullName);
  121. if (ar == null) throw new ArgumentNullException(nameof(ar));
  122. if (ar is MiniStreamAsyncResult)
  123. {
  124. var r = (MiniStreamAsyncResult)ar;
  125. if (!ar.IsCompleted) ar.AsyncWaitHandle.WaitOne();
  126. return r.SynchRead;
  127. }
  128. int nread = _stream.EndRead(ar);
  129. if (_remaining > 0 && nread > 0) _remaining -= nread;
  130. return nread;
  131. #else
  132. throw new NotSupportedException();
  133. #endif
  134. }
  135. #endregion
  136. #region write
  137. public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
  138. public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) => throw new NotSupportedException();
  139. public override void EndWrite(IAsyncResult ar) => throw new NotSupportedException();
  140. #endregion
  141. }
  142. }