|
| 1 | +using System.Net; |
| 2 | +using System.Net.Sockets; |
| 3 | +using System.Threading.Tasks; |
| 4 | +using Onvif.Core.Discovery.Interfaces; |
| 5 | + |
| 6 | +namespace OpenIPC.Viewer.Devices.Onvif.Discovery; |
| 7 | + |
| 8 | +// Drop-in IUdpClient for Onvif.Core's WSDiscovery. The stock UdpClientWrapper |
| 9 | +// calls IPGlobalProperties.GetActiveTcpListeners() in its constructor (a |
| 10 | +// port-collision pre-check) — that API is unimplemented on Android/iOS and |
| 11 | +// throws PlatformNotSupportedException ("Arg_PlatformNotSupported"), so device |
| 12 | +// discovery died before sending a single probe on mobile. |
| 13 | +// |
| 14 | +// This implementation skips that check: it binds an ephemeral UDP socket and |
| 15 | +// sends the multicast probe to 239.255.255.250:3702. WS-Discovery ProbeMatch |
| 16 | +// replies come back as *unicast* to our source port, so we never join a |
| 17 | +// multicast group — which also means no Android WifiManager.MulticastLock is |
| 18 | +// required. Works identically on desktop, so no per-platform branching. |
| 19 | +internal sealed class PlatformSafeUdpClient : IUdpClient |
| 20 | +{ |
| 21 | + private readonly UdpClient _client; |
| 22 | + |
| 23 | + public PlatformSafeUdpClient() |
| 24 | + { |
| 25 | + // Port 0 = let the OS pick a free ephemeral port. The stock wrapper |
| 26 | + // hard-bound port 80, which is both privileged and collision-prone. |
| 27 | + _client = new UdpClient(new IPEndPoint(IPAddress.Any, 0)) { EnableBroadcast = true }; |
| 28 | + } |
| 29 | + |
| 30 | + public short Ttl |
| 31 | + { |
| 32 | + get => _client.Ttl; |
| 33 | + set => _client.Ttl = value; |
| 34 | + } |
| 35 | + |
| 36 | + public Task<int> SendAsync(byte[] datagram, int bytes, IPEndPoint endPoint) => |
| 37 | + _client.SendAsync(datagram, bytes, endPoint); |
| 38 | + |
| 39 | + public Task<UdpReceiveResult> ReceiveAsync() => _client.ReceiveAsync(); |
| 40 | + |
| 41 | + public void Close() => _client.Close(); |
| 42 | + |
| 43 | + public void Dispose() => _client.Dispose(); |
| 44 | +} |
0 commit comments