diff --git a/WindivertDotnet/WinDivertPacket.cs b/WindivertDotnet/WinDivertPacket.cs index 0acc00c..cd9eee9 100644 --- a/WindivertDotnet/WinDivertPacket.cs +++ b/WindivertDotnet/WinDivertPacket.cs @@ -1,5 +1,6 @@ using Microsoft.Win32.SafeHandles; using System; +using System.Buffers; using System.ComponentModel; using System.Diagnostics; using System.Net.Sockets; @@ -13,6 +14,9 @@ namespace WindivertDotnet [DebuggerDisplay("Length = {Length}, Capacity = {Capacity}")] public class WinDivertPacket : SafeHandleZeroOrMinusOneIsInvalid { + /// + /// 有效数据的长度 + /// [DebuggerBrowsable(DebuggerBrowsableState.Never)] private int length; @@ -24,7 +28,7 @@ public class WinDivertPacket : SafeHandleZeroOrMinusOneIsInvalid /// /// 获取有效数据视图 /// - public Span Span => this.GetSpan(this.length); + public Span Span => this.GetSpan(0, this.length); /// /// 获取或设置有效数据的长度 @@ -60,18 +64,18 @@ public WinDivertPacket(int capacity = 0xFFFF + 40) /// public void Clear() { - this.GetSpan(this.Capacity).Clear(); + this.GetSpan(0, this.Capacity).Clear(); } /// - /// 将指定的数据复制到packet缓冲区 + /// 创建缓冲区写入对象 /// - /// 数据 + /// 缓冲区偏移量 /// - public void SetBuffer(Span span) + /// + public IBufferWriter CreateBufferWriter(int offset = 0) { - this.Length = span.Length; - span.CopyTo(this.Span); + return new BufferWriter(this, offset); } /// @@ -87,11 +91,23 @@ protected override bool ReleaseHandle() /// /// 获取span /// - /// + /// + /// /// - private unsafe Span GetSpan(int length) + private unsafe Span GetSpan(int offset, int sizeHint) { - return new Span(this.handle.ToPointer(), length); + if (offset > this.Capacity) + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } + + if (this.Capacity - offset < sizeHint) + { + throw new ArgumentOutOfRangeException(nameof(sizeHint)); + } + + var pointer = (byte*)this.handle.ToPointer() + offset; + return new Span(pointer, sizeHint); } /// @@ -187,5 +203,43 @@ public unsafe WinDivertParseResult GetParseResult() NextLength = nextLength }; } + + + private class BufferWriter : IBufferWriter + { + private int index; + private readonly WinDivertPacket packet; + + public BufferWriter(WinDivertPacket packet, int offset) + { + if (offset >= packet.Capacity) + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } + + this.index = offset; + this.packet = packet; + } + + public void Advance(int count) + { + this.index += count; + this.packet.Length = this.index; + } + + public Span GetSpan(int sizeHint = 0) + { + if (sizeHint == 0) + { + sizeHint = this.packet.Capacity - this.index; + } + return this.packet.GetSpan(this.index, sizeHint); + } + + public Memory GetMemory(int sizeHint = 0) + { + throw new NotSupportedException(); + } + } } }