Skip to content

Commit

Permalink
Drop ICustomMarshaler for error string, use ErrorBuffer class instead.ss
Browse files Browse the repository at this point in the history
  • Loading branch information
kayoub5 committed Oct 1, 2024
1 parent a7db60e commit 0464f05
Show file tree
Hide file tree
Showing 9 changed files with 51 additions and 104 deletions.
7 changes: 3 additions & 4 deletions SharpPcap/LibPcap/CaptureFileReaderDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ public CaptureFileReaderDevice(string captureFilename)
/// </summary>
public override void Open(DeviceConfiguration configuration)
{
// holds errors
StringBuilder errbuf = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE); //will hold errors
ErrorBuffer errbuf; //will hold errors

PcapHandle adapterHandle;

Expand All @@ -82,7 +81,7 @@ public override void Open(DeviceConfiguration configuration)
var resolution = configuration.TimestampResolution ?? TimestampResolution.Microsecond;
if (has_offline_with_tstamp_precision_support)
{
adapterHandle = LibPcapSafeNativeMethods.pcap_open_offline_with_tstamp_precision(m_pcapFile, (uint)resolution, errbuf);
adapterHandle = LibPcapSafeNativeMethods.pcap_open_offline_with_tstamp_precision(m_pcapFile, (uint)resolution, out errbuf);
}
else
{
Expand All @@ -97,7 +96,7 @@ public override void Open(DeviceConfiguration configuration)
);
}

adapterHandle = LibPcapSafeNativeMethods.pcap_open_offline(m_pcapFile, errbuf);
adapterHandle = LibPcapSafeNativeMethods.pcap_open_offline(m_pcapFile, out errbuf);
}

// handle error
Expand Down
4 changes: 2 additions & 2 deletions SharpPcap/LibPcap/CaptureHandleReaderDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ public CaptureHandleReaderDevice(SafeHandle handle)
public override void Open(DeviceConfiguration configuration)
{
// holds errors
StringBuilder errbuf = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE);
ErrorBuffer errbuf;

var resolution = configuration.TimestampResolution ?? TimestampResolution.Microsecond;
PcapHandle adapterHandle;
try
{
adapterHandle = LibPcapSafeNativeMethods.pcap_open_handle_offline_with_tstamp_precision(
FileHandle, (uint)resolution, errbuf);
FileHandle, (uint)resolution, out errbuf);
}
catch (TypeLoadException ex)
{
Expand Down
18 changes: 7 additions & 11 deletions SharpPcap/LibPcap/LibPcapLiveDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public override void Open(DeviceConfiguration configuration)
// See https://www.tcpdump.org/manpages/pcap_set_immediate_mode.3pcap.html
var mintocopy_supported = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);

var errbuf = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE); //will hold errors
ErrorBuffer errbuf; //will hold errors

// set the StopCaptureTimeout value to twice the read timeout to ensure that
// we wait long enough before considering the capture thread to be stuck when stopping
Expand Down Expand Up @@ -131,7 +131,7 @@ public override void Open(DeviceConfiguration configuration)
{
Handle = LibPcapSafeNativeMethods.pcap_create(
Name, // name of the device
errbuf); // error buffer
out errbuf); // error buffer

if (Handle.IsInvalid)
{
Expand Down Expand Up @@ -171,7 +171,7 @@ public override void Open(DeviceConfiguration configuration)
(short)mode, // flags
(short)configuration.ReadTimeout, // read timeout
ref auth, // authentication
errbuf); // error buffer
out errbuf); // error buffer
}
catch (TypeLoadException)
{
Expand Down Expand Up @@ -275,14 +275,12 @@ public bool NonBlockingMode
get
{
ThrowIfNotOpen("Can't get blocking mode, the device is closed");

var errbuf = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE); //will hold errors
int ret = LibPcapSafeNativeMethods.pcap_getnonblock(Handle, errbuf);
int ret = LibPcapSafeNativeMethods.pcap_getnonblock(Handle, out var errbuf);

// Errorbuf is only filled when ret = -1
if (ret == -1)
{
string err = "Unable to set get blocking" + errbuf.ToString();
string err = "Unable to get blocking mode. " + errbuf.ToString();
throw new PcapException(err);
}

Expand All @@ -294,18 +292,16 @@ public bool NonBlockingMode
{
ThrowIfNotOpen("Can't set blocking mode, the device is closed");

var errbuf = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE); //will hold errors

int block = disableBlocking;
if (value)
block = enableBlocking;

int ret = LibPcapSafeNativeMethods.pcap_setnonblock(Handle, block, errbuf);
int ret = LibPcapSafeNativeMethods.pcap_setnonblock(Handle, block, out var errbuf);

// Errorbuf is only filled when ret = -1
if (ret == -1)
{
string err = "Unable to set non blocking" + errbuf.ToString();
string err = "Unable to set blocking mode. " + errbuf.ToString();
throw new PcapException(err);
}
}
Expand Down
82 changes: 19 additions & 63 deletions SharpPcap/LibPcap/LibPcapSafeNativeMethods.Encoding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ internal static partial class LibPcapSafeNativeMethods
/// <summary>
/// This defaul is good enough for .NET Framework and .NET Core on non Windows with Libpcap default config
/// </summary>
private static readonly Encoding StringEncoding = Encoding.Default;
internal static readonly Encoding StringEncoding = Encoding.Default;

private static Encoding ConfigureStringEncoding()
{
Expand All @@ -29,9 +29,8 @@ private static Encoding ConfigureStringEncoding()
try
{
// Try to change Libpcap to UTF-8 mode
var errorBuffer = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE);
const uint PCAP_CHAR_ENC_UTF_8 = 1;
var res = pcap_init(PCAP_CHAR_ENC_UTF_8, errorBuffer);
var res = pcap_init(PCAP_CHAR_ENC_UTF_8, out var _);
if (res == 0)
{
// We made it
Expand All @@ -48,66 +47,6 @@ private static Encoding ConfigureStringEncoding()
return Encoding.GetEncoding(0);
}

/// <summary>
/// Helper class to marshall StringBuilder depending on encoding used by Libpcap
/// </summary>
private class PcapStringBuilderMarshaler : ICustomMarshaler
{

public static ICustomMarshaler GetInstance(string cookie)
{
return new PcapStringBuilderMarshaler();
}

public void CleanUpManagedData(object managedObj)
{
// Nothing to clean
}

public void CleanUpNativeData(IntPtr nativeData)
{
// Nothing to clean
}

public int GetNativeDataSize()
{
return -1;
}

public IntPtr MarshalManagedToNative(object managedObj)
{
var builder = (StringBuilder)managedObj;
var byteCount = builder.Capacity + 1;
var gcHandle = GCHandle.ToIntPtr(GCHandle.Alloc(managedObj));

// The problem is that we need a reference to the StringBuilder in MarshalNativeToManaged
// So we get a pointer to it with GCHandle, and put it as prefix of the pointer we return
var ptr = Marshal.AllocHGlobal(byteCount + IntPtr.Size);
Marshal.WriteIntPtr(ptr, gcHandle);
ptr += IntPtr.Size;
return ptr;
}

public unsafe object MarshalNativeToManaged(IntPtr nativeData)
{
var gcHandlePtr = Marshal.ReadIntPtr(nativeData - IntPtr.Size);
var bytes = (byte*)nativeData;
var nbBytes = 0;
while (*(bytes + nbBytes) != 0)
{
nbBytes++;
}
var stringData = StringEncoding.GetString(bytes, nbBytes);

var gcHandle = GCHandle.FromIntPtr(gcHandlePtr);
var stringBuilder = (StringBuilder)gcHandle.Target;
gcHandle.Free();
stringBuilder.Append(stringData);

return null;
}
}

/// <summary>
/// Helper class to marshall string depending on encoding used by Libpcap
/// </summary>
Expand Down Expand Up @@ -178,4 +117,21 @@ public unsafe object MarshalNativeToManaged(IntPtr nativeData)
}
}
}

[StructLayout(LayoutKind.Sequential)]
internal struct ErrorBuffer
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
internal byte[] Data;

public override string ToString()
{
var nbBytes = 0;
while (Data[nbBytes] != 0)
{
nbBytes++;
}
return LibPcapSafeNativeMethods.StringEncoding.GetString(new Span<byte>(Data, 0, nbBytes));
}
}
}
22 changes: 11 additions & 11 deletions SharpPcap/LibPcap/LibPcapSafeNativeMethods.Interop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,21 @@ internal static partial class LibPcapSafeNativeMethods
[DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)]
internal extern static int pcap_init(
uint opts,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringBuilderMarshaler))] StringBuilder /* char* */ errbuf
out ErrorBuffer /* char* */ errbuf
);

[DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)]
internal extern static int pcap_findalldevs(
ref IntPtr /* pcap_if_t** */ alldevs,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringBuilderMarshaler))] StringBuilder /* char* */ errbuf
out ErrorBuffer /* char* */ errbuf
);

[DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)]
internal extern static int pcap_findalldevs_ex(
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] string /*char **/source,
ref pcap_rmtauth /*pcap_rmtauth **/auth,
ref IntPtr /*pcap_if_t ** */alldevs,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringBuilderMarshaler))] StringBuilder /*char * */errbuf
out ErrorBuffer /* char* */ errbuf
);

[DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)]
Expand All @@ -57,19 +57,19 @@ internal extern static int pcap_findalldevs_ex(
int flags,
int read_timeout,
ref pcap_rmtauth rmtauth,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringBuilderMarshaler))] StringBuilder errbuf
out ErrorBuffer /* char* */ errbuf
);

[DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)]
internal extern static PcapHandle /* pcap_t* */ pcap_create(
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] string dev,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringBuilderMarshaler))] StringBuilder errbuf
out ErrorBuffer /* char* */ errbuf
);

[DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)]
internal extern static PcapHandle /* pcap_t* */ pcap_open_offline(
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] string/*const char* */ fname,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringBuilderMarshaler))] StringBuilder/* char* */ errbuf
out ErrorBuffer /* char* */ errbuf
);

[DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)]
Expand Down Expand Up @@ -187,7 +187,7 @@ internal extern static int pcap_compile(
internal extern static int pcap_setnonblock(
PcapHandle /* pcap_if_t** */ adaptHandle,
int nonblock,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringBuilderMarshaler))] StringBuilder /* char* */ errbuf
out ErrorBuffer /* char* */ errbuf
);

/// <summary>
Expand All @@ -196,7 +196,7 @@ internal extern static int pcap_setnonblock(
[DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)]
internal extern static int pcap_getnonblock(
PcapHandle /* pcap_if_t** */ adaptHandle,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringBuilderMarshaler))] StringBuilder /* char* */ errbuf
out ErrorBuffer /* char* */ errbuf
);

/// <summary>
Expand Down Expand Up @@ -422,7 +422,7 @@ internal extern static int pcap_tstamp_type_name_to_val(
internal extern static PcapHandle /* pcap_t* */ pcap_open_offline_with_tstamp_precision(
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] string /* const char* */ fname,
uint precision,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringBuilderMarshaler))] StringBuilder /* char* */ errbuf
out ErrorBuffer /* char* */ errbuf
);

/// <summary>
Expand Down Expand Up @@ -488,7 +488,7 @@ internal extern static int pcap_tstamp_type_name_to_val(
internal extern static IntPtr /* pcap_t* */ _pcap_hopen_offline_with_tstamp_precision(
SafeHandle handle,
uint precision,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringBuilderMarshaler))] StringBuilder /* char* */ errbuf
out ErrorBuffer /* char* */ errbuf
);

/// <summary>
Expand All @@ -503,7 +503,7 @@ internal extern static int pcap_tstamp_type_name_to_val(
internal extern static IntPtr /* pcap_t* */ _pcap_fopen_offline_with_tstamp_precision(
SafeHandle fileObject,
uint precision,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringBuilderMarshaler))] StringBuilder /* char* */ errbuf
out ErrorBuffer /* char* */ errbuf
);
}
}
6 changes: 3 additions & 3 deletions SharpPcap/LibPcap/LibPcapSafeNativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ internal static int pcap_get_tstamp_precision(PcapHandle /* pcap_t* p */ adapter
/// <param name="errbuf">Buffer that will receive an error description if an error occurs.</param>
/// <returns></returns>
internal static PcapHandle pcap_open_handle_offline_with_tstamp_precision(
SafeHandle handle, uint precision, StringBuilder errbuf)
SafeHandle handle, uint precision, out ErrorBuffer errbuf)
{
var pointer = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? _pcap_hopen_offline_with_tstamp_precision(handle, precision, errbuf)
: _pcap_fopen_offline_with_tstamp_precision(handle, precision, errbuf);
? _pcap_hopen_offline_with_tstamp_precision(handle, precision, out errbuf)
: _pcap_fopen_offline_with_tstamp_precision(handle, precision, out errbuf);
if (pointer == IntPtr.Zero)
{
return PcapHandle.Invalid;
Expand Down
13 changes: 5 additions & 8 deletions SharpPcap/LibPcap/PcapInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,14 @@ static public IReadOnlyList<PcapInterface> GetAllPcapInterfaces(IPEndPoint sourc
static public IReadOnlyList<PcapInterface> GetAllPcapInterfaces(string source, RemoteAuthentication credentials)
{
var devicePtr = IntPtr.Zero;
var errorBuffer = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE);
var auth = RemoteAuthentication.CreateAuth(credentials);

try
{
var result = LibPcapSafeNativeMethods.pcap_findalldevs_ex(source, ref auth, ref devicePtr, errorBuffer);
var result = LibPcapSafeNativeMethods.pcap_findalldevs_ex(source, ref auth, ref devicePtr, out var errbuf);
if (result < 0)
{
throw new PcapException(errorBuffer.ToString());
throw new PcapException(errbuf.ToString());
}
}
catch (TypeLoadException ex)
Expand All @@ -206,12 +205,11 @@ static public IReadOnlyList<PcapInterface> GetAllPcapInterfaces(string source, R
static public IReadOnlyList<PcapInterface> GetAllPcapInterfaces()
{
var devicePtr = IntPtr.Zero;
var errorBuffer = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE);

int result = LibPcapSafeNativeMethods.pcap_findalldevs(ref devicePtr, errorBuffer);
int result = LibPcapSafeNativeMethods.pcap_findalldevs(ref devicePtr, out var errbuf);
if (result < 0)
{
throw new PcapException(errorBuffer.ToString());
throw new PcapException(errbuf.ToString());
}
var pcapInterfaces = GetAllPcapInterfaces(devicePtr, null);

Expand Down Expand Up @@ -260,8 +258,7 @@ public System.Collections.Generic.List<PcapClock> TimestampsSupported
{
get
{
StringBuilder errbuf = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE); //will hold errors
using (var handle = LibPcapSafeNativeMethods.pcap_create(Name, errbuf))
using (var handle = LibPcapSafeNativeMethods.pcap_create(Name, out var errbuf))
{

IntPtr typePtr = IntPtr.Zero;
Expand Down
1 change: 0 additions & 1 deletion SharpPcap/Pcap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ public class Pcap
/* interface is loopback */
internal const uint PCAP_IF_LOOPBACK = 0x00000001;
internal const int MAX_PACKET_SIZE = 65536;
internal const int PCAP_ERRBUF_SIZE = 256;

// Constants for address families
// These are set in a Pcap static initializer because the values
Expand Down
2 changes: 1 addition & 1 deletion SharpPcap/SharpPcap.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ SPDX-License-Identifier: MIT
-->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
<TargetFramework>net8.0</TargetFramework>
<Version>6.3.0</Version>
<Description>A packet capture framework for .NET</Description>
<Authors>Tamir Gal, Chris Morgan and others</Authors>
Expand Down

0 comments on commit 0464f05

Please sign in to comment.