Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CancellationToken support. #512

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
50 changes: 46 additions & 4 deletions SharpPcap/LibPcap/SendQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,27 @@ public int Transmit(PcapDevice device, bool synchronized)
return Transmit(device, (synchronized == true) ? SendQueueTransmitModes.Synchronized : SendQueueTransmitModes.Normal);
}

/// <summary>
/// Send a queue of raw packets to the network.
/// </summary>
/// <param name="device">
/// The device on which to send the queue
/// A <see cref="PcapDevice"/>
/// </param>
/// <param name="synchronized">
/// Should the timestamps be respected
/// </param>
/// <param name="token">
/// transmission cancellation token
/// </param>
/// <returns>
/// The number of bytes sent as an <see cref="int"/>
/// </returns>
public int Transmit(PcapDevice device, bool synchronized, CancellationToken token)
{
return Transmit(device, (synchronized == true) ? SendQueueTransmitModes.Synchronized : SendQueueTransmitModes.Normal, token);
}

/// <summary>
/// Send a queue of raw packets to the network.
/// </summary>
Expand All @@ -119,6 +140,27 @@ public int Transmit(PcapDevice device, bool synchronized)
/// The number of bytes sent as an <see cref="int"/>
/// </returns>
public int Transmit(PcapDevice device, SendQueueTransmitModes transmitMode)
{
return Transmit(device, transmitMode, CancellationToken.None);
}

/// <summary>
/// Send a queue of raw packets to the network.
/// </summary>
/// <param name="device">
/// The device on which to send the queue
/// A <see cref="PcapDevice"/>
/// </param>
/// <param name="transmitMode">
/// Should the timestamps be respected
/// </param>
/// <param name="token">
/// transmission cancellation token
/// </param>
/// <returns>
/// The number of bytes sent as an <see cref="int"/>
/// </returns>
public int Transmit(PcapDevice device, SendQueueTransmitModes transmitMode, CancellationToken token)
{
if (buffer == null)
{
Expand All @@ -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)
{
Expand All @@ -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);
Expand Down
34 changes: 30 additions & 4 deletions Test/SendQueueTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
using System.Linq;
using static Test.TestHelper;
using static System.TimeSpan;
using System.Threading;
using System.Threading.Tasks;

namespace Test
{
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -302,7 +304,31 @@ public void Cleanup()
{
TestHelper.ConfirmIdleState();
}
}


[TestCase(true)]
[TestCase(false)]
[Author("Andreas Amereller <[email protected]>")]
[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);
}
}
}
Loading