Skip to content

Commit

Permalink
Fixed multicast based discoverer.
Browse files Browse the repository at this point in the history
  • Loading branch information
lextm committed Oct 19, 2024
1 parent c4dfca9 commit e8eb257
Showing 1 changed file with 24 additions and 34 deletions.
58 changes: 24 additions & 34 deletions SharpSnmpLib/Messaging/Discoverer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public void Discover(VersionCode version, IPEndPoint broadcastAddress, OctetStri
using var udp = new UdpClient(addressFamily);
if (addressFamily == AddressFamily.InterNetworkV6)
{
udp.JoinMulticastGroup(broadcastAddress.Address);
udp.MulticastLoopback = false;
}
else if (addressFamily == AddressFamily.InterNetwork)
{
Expand All @@ -111,9 +111,9 @@ public void Discover(VersionCode version, IPEndPoint broadcastAddress, OctetStri
_bufferSize = udp.Client.ReceiveBufferSize = Messenger.MaxMessageSize;

#if ASYNC
Task.Factory.StartNew(() => AsyncBeginReceive(udp.Client));
Task.Factory.StartNew(() => AsyncBeginReceive(udp));
#else
Task.Factory.StartNew(() => AsyncReceive(udp.Client));
Task.Factory.StartNew(() => AsyncReceive(udp));
#endif

Thread.Sleep(interval);
Expand Down Expand Up @@ -198,7 +198,7 @@ private void AsyncEndReceive(IAsyncResult iar)
}
#else

private void AsyncReceive(Socket socket)
private void AsyncReceive(UdpClient client)
{
while (true)
{
Expand All @@ -210,10 +210,9 @@ private void AsyncReceive(Socket socket)

try
{
var buffer = new byte[_bufferSize];
EndPoint remote = new IPEndPoint(IPAddress.Any, 0);
var count = socket.ReceiveFrom(buffer, ref remote);
Task.Factory.StartNew(() => HandleMessage(buffer, count, (IPEndPoint)remote));
var remote = new IPEndPoint(IPAddress.Any, 0);
var buffer = client.Receive(ref remote);
Task.Factory.StartNew(() => HandleMessage(buffer, buffer.Length, remote));
}
catch (SocketException ex)
{
Expand Down Expand Up @@ -298,11 +297,6 @@ public async Task DiscoverAsync(VersionCode version, IPEndPoint broadcastAddress
}

var addressFamily = broadcastAddress.AddressFamily;
if (addressFamily == AddressFamily.InterNetworkV6)
{
throw new ArgumentException("IP v6 is not yet supported.", nameof(broadcastAddress));
}

byte[] bytes;
_requestId = Messenger.NextRequestId;
if (version == VersionCode.V3)
Expand All @@ -316,25 +310,32 @@ public async Task DiscoverAsync(VersionCode version, IPEndPoint broadcastAddress
bytes = message.ToBytes();
}

using var udp = new Socket(addressFamily, SocketType.Dgram, ProtocolType.Udp);
udp.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
var buffer = new ArraySegment<byte>(bytes);
await udp.SendToAsync(buffer, SocketFlags.None, broadcastAddress);
using var udp = new UdpClient(addressFamily);
if (addressFamily == AddressFamily.InterNetworkV6)
{
udp.MulticastLoopback = false;
}
else if (addressFamily == AddressFamily.InterNetwork)
{
#if (!CF)
udp.EnableBroadcast = true;
#endif
}

await udp.SendAsync(bytes, bytes.Length, broadcastAddress);
var activeBefore = Interlocked.CompareExchange(ref _active, Active, Inactive);
if (activeBefore == Active)
{
// If already started, we've nothing to do.
return;
}

_bufferSize = udp.ReceiveBufferSize;
#if NET6_0_OR_GREATER
var source = new CancellationTokenSource();
source.CancelAfter(interval);
try
{
await ReceiveAsync(udp, source.Token);
await ReceiveAsync(udp.Client, source.Token);
}
catch (OperationCanceledException)
{
Expand All @@ -346,18 +347,10 @@ await Task.WhenAny(
Task.Delay(interval));
#endif
Interlocked.CompareExchange(ref _active, Inactive, Active);
try
{
udp.Shutdown(SocketShutdown.Both);
}
catch (SocketException)
{
// This exception is thrown in .NET Core <=2.1.4 on non-Windows systems.
// However, the shutdown call is necessary to release the socket binding.
}
udp.Close();
}
#if !NET6_0_OR_GREATER
private async Task ReceiveAsync(Socket socket)
private async Task ReceiveAsync(UdpClient client)
{
while (true)
{
Expand All @@ -369,11 +362,8 @@ private async Task ReceiveAsync(Socket socket)

try
{
EndPoint remote = new IPEndPoint(IPAddress.Any, 0);

var buffer = new byte[_bufferSize];
var result = await socket.ReceiveMessageFromAsync(new ArraySegment<byte>(buffer), SocketFlags.None, remote);
await Task.Factory.StartNew(() => HandleMessage(buffer, result.ReceivedBytes, (IPEndPoint) result.RemoteEndPoint))
var result = await client.ReceiveAsync();
await Task.Factory.StartNew(() => HandleMessage(result.Buffer, result.Buffer.Length, result.RemoteEndPoint))
.ConfigureAwait(false);
}
catch (SocketException ex)
Expand Down

0 comments on commit e8eb257

Please sign in to comment.