From e8eb25733fcdfe0d8eb0121599a9ead5b01ac980 Mon Sep 17 00:00:00 2001 From: Lex Li Date: Sat, 19 Oct 2024 00:52:14 -0700 Subject: [PATCH] Fixed multicast based discoverer. --- SharpSnmpLib/Messaging/Discoverer.cs | 58 ++++++++++++---------------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/SharpSnmpLib/Messaging/Discoverer.cs b/SharpSnmpLib/Messaging/Discoverer.cs index fbeea5b8..06abc42a 100644 --- a/SharpSnmpLib/Messaging/Discoverer.cs +++ b/SharpSnmpLib/Messaging/Discoverer.cs @@ -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) { @@ -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); @@ -198,7 +198,7 @@ private void AsyncEndReceive(IAsyncResult iar) } #else - private void AsyncReceive(Socket socket) + private void AsyncReceive(UdpClient client) { while (true) { @@ -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) { @@ -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) @@ -316,11 +310,19 @@ 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(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) { @@ -328,13 +330,12 @@ public async Task DiscoverAsync(VersionCode version, IPEndPoint broadcastAddress 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) { @@ -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) { @@ -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(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)