UPnP Checking and updates

This commit is contained in:
2025-08-31 21:27:06 -04:00
parent 8853f56df7
commit 40283c2577
4 changed files with 404 additions and 6 deletions

View File

@@ -13,6 +13,7 @@ public interface IUPnPManager
Task<bool> AddPortMappingAsync(int externalPort, int internalPort, string description);
Task<bool> RemovePortMappingAsync(int externalPort);
Task<List<PortMapping>> GetPortMappingsAsync();
Task<string> GetUPnPDiagnosticsAsync();
}
public class UPnPManager : IUPnPManager
@@ -34,27 +35,49 @@ public class UPnPManager : IUPnPManager
try
{
_logger?.LogInformation("Initializing UPnP/NAT discovery...");
_logger?.LogInformation("Initializing UPnP/NAT discovery for macOS...");
// Create a new NAT discoverer
var discoverer = new NatDiscoverer();
// Discover UPnP devices with a 10-second timeout
_natDevice = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, new CancellationTokenSource(TimeSpan.FromSeconds(10)));
// Try UPnP first (most common on home routers)
_logger?.LogInformation("Trying UPnP discovery...");
_natDevice = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, new CancellationTokenSource(TimeSpan.FromSeconds(8)));
if (_natDevice != null)
{
_logger?.LogInformation("UPnP device discovered successfully");
_isInitialized = true;
return;
}
else
// Try NAT-PMP (Apple's protocol, common on Apple routers)
_logger?.LogInformation("UPnP not found, trying NAT-PMP...");
_natDevice = await discoverer.DiscoverDeviceAsync(PortMapper.Pmp, new CancellationTokenSource(TimeSpan.FromSeconds(5)));
if (_natDevice != null)
{
_logger?.LogWarning("No UPnP devices found");
_logger?.LogInformation("NAT-PMP device discovered successfully");
_isInitialized = true;
return;
}
// Note: PCP (Port Control Protocol) is not supported by Open.NAT library
// We'll stick with UPnP and NAT-PMP which are the most common
_logger?.LogWarning("No UPnP/NAT devices found. This could be due to:");
_logger?.LogWarning("- Router doesn't support UPnP");
_logger?.LogWarning("- macOS firewall blocking discovery");
_logger?.LogWarning("- Network policy blocking UPnP");
_logger?.LogWarning("- Router UPnP is disabled");
}
catch (Exception ex)
{
_logger?.LogWarning(ex, "UPnP initialization failed");
_logger?.LogWarning(ex, "UPnP/NAT initialization failed");
_logger?.LogInformation("Common solutions:");
_logger?.LogInformation("- Check router UPnP settings");
_logger?.LogInformation("- Temporarily disable macOS firewall");
_logger?.LogInformation("- Try from a different network");
_natDevice = null;
_isInitialized = false;
}
@@ -74,6 +97,84 @@ public class UPnPManager : IUPnPManager
}
}
public async Task<string> GetUPnPDiagnosticsAsync()
{
try
{
var diagnostics = new List<string>();
// Check if we can discover devices
diagnostics.Add("🔍 UPnP Discovery Test:");
var discoverer = new NatDiscoverer();
// Test UPnP
try
{
var upnpDevice = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, new CancellationTokenSource(TimeSpan.FromSeconds(5)));
if (upnpDevice != null)
{
diagnostics.Add("✅ UPnP: Available");
var externalIp = await upnpDevice.GetExternalIPAsync();
diagnostics.Add($" External IP: {externalIp}");
}
else
{
diagnostics.Add("❌ UPnP: Not available");
}
}
catch (Exception ex)
{
diagnostics.Add($"❌ UPnP: Error - {ex.Message}");
}
// Test NAT-PMP
try
{
var pmpDevice = await discoverer.DiscoverDeviceAsync(PortMapper.Pmp, new CancellationTokenSource(TimeSpan.FromSeconds(5)));
if (pmpDevice != null)
{
diagnostics.Add("✅ NAT-PMP: Available");
var externalIp = await pmpDevice.GetExternalIPAsync();
diagnostics.Add($" External IP: {externalIp}");
}
else
{
diagnostics.Add("❌ NAT-PMP: Not available");
}
}
catch (Exception ex)
{
diagnostics.Add($"❌ NAT-PMP: Error - {ex.Message}");
}
// Note: PCP is not supported by Open.NAT library
diagnostics.Add("❌ PCP: Not supported by Open.NAT library");
// Network information
diagnostics.Add("\n🌐 Network Information:");
var localIp = GetLocalIpAddress();
diagnostics.Add($"Local IP: {localIp?.ToString() ?? "Unknown"}");
// Try external IP service as fallback
try
{
var externalIp = await GetExternalIpFromServiceAsync();
diagnostics.Add($"External IP (Service): {externalIp?.ToString() ?? "Unknown"}");
}
catch
{
diagnostics.Add("External IP (Service): Failed");
}
return string.Join("\n", diagnostics);
}
catch (Exception ex)
{
return $"Diagnostics failed: {ex.Message}";
}
}
public async Task<IPAddress?> GetExternalIpAddressAsync()
{
try