diff --git a/SharpPcap/LibPcap/SendQueue.cs b/SharpPcap/LibPcap/SendQueue.cs index 9d17bfab..6db1edc2 100644 --- a/SharpPcap/LibPcap/SendQueue.cs +++ b/SharpPcap/LibPcap/SendQueue.cs @@ -105,6 +105,27 @@ public int Transmit(PcapDevice device, bool synchronized) return Transmit(device, (synchronized == true) ? SendQueueTransmitModes.Synchronized : SendQueueTransmitModes.Normal); } + /// + /// Send a queue of raw packets to the network. + /// + /// + /// The device on which to send the queue + /// A + /// + /// + /// Should the timestamps be respected + /// + /// + /// transmission cancellation token + /// + /// + /// The number of bytes sent as an + /// + public int Transmit(PcapDevice device, bool synchronized, CancellationToken token) + { + return Transmit(device, (synchronized == true) ? SendQueueTransmitModes.Synchronized : SendQueueTransmitModes.Normal, token); + } + /// /// Send a queue of raw packets to the network. /// @@ -119,6 +140,27 @@ public int Transmit(PcapDevice device, bool synchronized) /// The number of bytes sent as an /// public int Transmit(PcapDevice device, SendQueueTransmitModes transmitMode) + { + return Transmit(device, transmitMode, CancellationToken.None); + } + + /// + /// Send a queue of raw packets to the network. + /// + /// + /// The device on which to send the queue + /// A + /// + /// + /// Should the timestamps be respected + /// + /// + /// transmission cancellation token + /// + /// + /// The number of bytes sent as an + /// + public int Transmit(PcapDevice device, SendQueueTransmitModes transmitMode, CancellationToken token) { if (buffer == null) { @@ -128,14 +170,14 @@ public int Transmit(PcapDevice device, SendQueueTransmitModes transmitMode) { throw new DeviceNotReadyException("Can't transmit queue, the pcap device is closed"); } - if (IsHardwareAccelerated) + if (IsHardwareAccelerated && token == CancellationToken.None) { return NativeTransmit(device, transmitMode); } - return ManagedTransmit(device, transmitMode); + return ManagedTransmit(device, transmitMode, token); } - protected unsafe int ManagedTransmit(PcapDevice device, SendQueueTransmitModes transmitMode) + protected unsafe int ManagedTransmit(PcapDevice device, SendQueueTransmitModes transmitMode, CancellationToken token) { if (CurrentLength == 0) { @@ -148,7 +190,7 @@ protected unsafe int ManagedTransmit(PcapDevice device, SendQueueTransmitModes t { var bufPtr = new IntPtr(buf); var firstTimestamp = TimeSpan.FromTicks(PcapHeader.FromPointer(bufPtr, TimeResolution).Timeval.Date.Ticks); - while (position < CurrentLength) + while ((position < CurrentLength) && (!token.IsCancellationRequested)) { // Extract packet from buffer var header = PcapHeader.FromPointer(bufPtr + position, TimeResolution); diff --git a/Test/SendQueueTest.cs b/Test/SendQueueTest.cs index 62fb297c..e5a33048 100644 --- a/Test/SendQueueTest.cs +++ b/Test/SendQueueTest.cs @@ -11,6 +11,8 @@ using System.Linq; using static Test.TestHelper; using static System.TimeSpan; +using System.Threading; +using System.Threading.Tasks; namespace Test { @@ -285,9 +287,9 @@ public SendQueueWrapper(int memSize) : base(memSize) return base.NativeTransmit(device, transmitMode); } - internal new int ManagedTransmit(PcapDevice device, SendQueueTransmitModes transmitMode) + internal int ManagedTransmit(PcapDevice device, SendQueueTransmitModes transmitMode) { - return base.ManagedTransmit(device, transmitMode); + return base.ManagedTransmit(device, transmitMode, CancellationToken.None); } } @@ -302,7 +304,31 @@ public void Cleanup() { TestHelper.ConfirmIdleState(); } - } - + [TestCase(true)] + [TestCase(false)] + [Author("Andreas Amereller ")] + [Retry(3)] + public void TestCancelSending(bool synchronized) + { + var queue = new SendQueue(1024*1024*64); + int packages = 0; + while (queue.Add(EthernetPacket.RandomPacket())) + { + packages++; + } + var canceller = new CancellationTokenSource(); + int packagesSent = 0; + using (var testInterface = TestHelper.GetPcapDevice()) + { + testInterface.Open(); + var snd = new Task(() => { packagesSent = queue.Transmit(testInterface, synchronized, canceller.Token); } ); + snd.Start(); + Thread.Sleep(100); + canceller.Cancel(); + snd.Wait(); + } + Assert.That(packagesSent < packages); + } + } }