diff --git a/Shoko.Plugin.Abstractions/Services/IConnectivityService.cs b/Shoko.Plugin.Abstractions/Services/IConnectivityService.cs
index 13847a111..c1acc11b0 100644
--- a/Shoko.Plugin.Abstractions/Services/IConnectivityService.cs
+++ b/Shoko.Plugin.Abstractions/Services/IConnectivityService.cs
@@ -1,5 +1,6 @@
using System;
+using System.Threading.Tasks;
using Shoko.Plugin.Abstractions.Enums;
namespace Shoko.Plugin.Abstractions.Services
@@ -33,5 +34,11 @@ public interface IConnectivityService
/// Are we currently banned from using the AniDB UDP API?
///
public bool IsAniDBUdpBanned { get; }
+
+ ///
+ /// Check for network availability now.
+ ///
+ /// The updated network availability status.
+ public Task CheckAvailability();
}
}
diff --git a/Shoko.Plugin.Abstractions/Shoko.Plugin.Abstractions.csproj b/Shoko.Plugin.Abstractions/Shoko.Plugin.Abstractions.csproj
index cdebf3b9b..636bff6e5 100644
--- a/Shoko.Plugin.Abstractions/Shoko.Plugin.Abstractions.csproj
+++ b/Shoko.Plugin.Abstractions/Shoko.Plugin.Abstractions.csproj
@@ -12,7 +12,7 @@
https://github.com/ShokoAnime/ShokoServer
plugins, shoko, anime, metadata, tagging
File Events
- 2.5.0-alpha1
+ 2.5.0-alpha2
Debug;Release
AnyCPU;x64
diff --git a/Shoko.Server/Scheduling/Jobs/ConnectivityMonitorJob.cs b/Shoko.Server/Scheduling/Jobs/ConnectivityMonitorJob.cs
index 438f8350a..d401b2fcc 100644
--- a/Shoko.Server/Scheduling/Jobs/ConnectivityMonitorJob.cs
+++ b/Shoko.Server/Scheduling/Jobs/ConnectivityMonitorJob.cs
@@ -3,17 +3,11 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net.NetworkInformation;
using System.Threading.Tasks;
-using Microsoft.Extensions.Logging;
using Quartz;
using QuartzJobFactory.Attributes;
-using Shoko.Plugin.Abstractions.Enums;
using Shoko.Plugin.Abstractions.Services;
using Shoko.Server.Services.Connectivity;
-using Shoko.Server.Settings;
namespace Shoko.Server.Scheduling.Jobs;
@@ -22,101 +16,25 @@ namespace Shoko.Server.Scheduling.Jobs;
[DisallowConcurrentExecution]
public class ConnectivityMonitorJob : IJob
{
- private readonly ISettingsProvider _settingsProvider;
- private readonly IConnectivityMonitor[] _connectivityMonitors;
- private readonly ILogger _logger;
-
private readonly ConnectivityService _connectivityService;
- public ConnectivityMonitorJob(ISettingsProvider settingsProvider, IEnumerable connectivityMonitors, IConnectivityService connectivityService, ILogger logger)
+ public ConnectivityMonitorJob(IConnectivityService connectivityService)
{
- _settingsProvider = settingsProvider;
- _connectivityMonitors = connectivityMonitors.ToArray();
_connectivityService = connectivityService as ConnectivityService;
- _logger = logger;
}
protected ConnectivityMonitorJob() { }
public async Task Execute(IJobExecutionContext context)
{
- try
+ try
{
- var localNetwork = GetLANConnectivity();
- if (localNetwork != NetworkAvailability.LocalOnly)
- {
- _connectivityService.NetworkAvailability = localNetwork;
- return;
- }
-
- var wideNetwork = await GetWANConnectivity();
- _connectivityService.NetworkAvailability = wideNetwork;
- } catch (Exception ex) {
- // do you want the job to refire?
- throw new JobExecutionException(msg: "", refireImmediately: false, cause: ex);
- }
- }
-
- private NetworkAvailability GetLANConnectivity()
- {
- _logger.LogInformation("Checking LAN Connectivity…");
- // Get all active network interfaces
- var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces()
- .Where(n => n.OperationalStatus == OperationalStatus.Up)
- .ToList();
-
- if (!networkInterfaces.Any())
- return NetworkAvailability.NoInterfaces;
-
- foreach (var netInterface in networkInterfaces)
- {
- var properties = netInterface.GetIPProperties();
- if (properties == null)
- continue;
-
- var defaultGateway = properties.GatewayAddresses
- .Select(g => g.Address)
- .FirstOrDefault();
- if (defaultGateway == null)
- continue;
-
- _logger.LogInformation("Found a local gateway to use.");
- return NetworkAvailability.LocalOnly;
+ await _connectivityService.CheckAvailability();
}
-
- _logger.LogInformation("No local gateway was found.");
- return NetworkAvailability.NoGateways;
- }
-
- private async Task GetWANConnectivity()
- {
- var currentlyDisabledMonitors = _settingsProvider.GetSettings().Connectivity.DisabledMonitorServices
- .ToHashSet();
- var monitors = _connectivityMonitors
- .Where(monitor => !currentlyDisabledMonitors.Contains(monitor.Service, StringComparer.InvariantCultureIgnoreCase))
- .ToList();
- if (monitors.Count == 0)
+ catch (Exception ex)
{
- _logger.LogInformation("Skipped checking WAN Connectivity.");
- return NetworkAvailability.Internet;
+ // do you want the job to refire?
+ throw new JobExecutionException(msg: "", refireImmediately: false, cause: ex);
}
-
- _logger.LogInformation("Checking WAN Connectivity…");
- await Parallel.ForEachAsync(monitors, async (monitor, token) =>
- {
- await monitor.ExecuteCheckAsync(token);
- });
-
- var connectedCount = monitors.Count(a => a.HasConnected);
- _logger.LogInformation("Successfully connected to {Count}/{Total} internet service endpoints.", connectedCount,
- monitors.Count);
-
- return connectedCount > 0 ? (
- // We managed to connect to WAN, either partially or fully.
- connectedCount == monitors.Count ? NetworkAvailability.Internet : NetworkAvailability.PartialInternet
- ) : (
- // We didn't manage to connect to WAN, but we reached the gateway
- NetworkAvailability.LocalOnly
- );
}
}
diff --git a/Shoko.Server/Services/Connectivity/ConnectivityService.cs b/Shoko.Server/Services/Connectivity/ConnectivityService.cs
index 8f69284e5..b0a59abdf 100644
--- a/Shoko.Server/Services/Connectivity/ConnectivityService.cs
+++ b/Shoko.Server/Services/Connectivity/ConnectivityService.cs
@@ -1,5 +1,9 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.NetworkInformation;
using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
using Shoko.Plugin.Abstractions;
using Shoko.Plugin.Abstractions.Enums;
using Shoko.Plugin.Abstractions.Extensions;
@@ -8,17 +12,25 @@
using Shoko.Server.Commands.Generic;
using Shoko.Server.Providers.AniDB.Interfaces;
+using ISettingsProvider = Shoko.Server.Settings.ISettingsProvider;
+
namespace Shoko.Server.Services.Connectivity;
public class ConnectivityService : IConnectivityService
{
- private readonly IUDPConnectionHandler AnidbUdpHandler;
+ private readonly ILogger _logger;
+
+ private readonly ISettingsProvider _settingsProvider;
+
+ private readonly IConnectivityMonitor[] _connectivityMonitors;
+
+ private readonly IUDPConnectionHandler _anidbUdpHandler;
- private readonly IHttpConnectionHandler AnidbHttpHandler;
+ private readonly IHttpConnectionHandler _anidbHttpHandler;
- private readonly CommandProcessor GeneralQueue;
+ private readonly CommandProcessor _generalQueue;
- private readonly CommandProcessor ImagesQueue;
+ private readonly CommandProcessor _imagesQueue;
private NetworkAvailability _networkAvailability { get; set; } = NetworkAvailability.NoInterfaces;
@@ -29,7 +41,7 @@ public class ConnectivityService : IConnectivityService
public NetworkAvailability NetworkAvailability
{
get => _networkAvailability;
- set
+ private set
{
var hasChanged = _networkAvailability != value;
_networkAvailability = value;
@@ -40,22 +52,25 @@ public NetworkAvailability NetworkAvailability
///
public bool IsAniDBUdpReachable =>
- AnidbUdpHandler.IsNetworkAvailable;
+ _anidbUdpHandler.IsNetworkAvailable;
///
public bool IsAniDBHttpBanned =>
- AnidbHttpHandler.IsBanned;
+ _anidbHttpHandler.IsBanned;
///
public bool IsAniDBUdpBanned =>
- AnidbUdpHandler.IsBanned;
+ _anidbUdpHandler.IsBanned;
- public ConnectivityService(IUDPConnectionHandler udpHandler, IHttpConnectionHandler httpHandler, CommandProcessorGeneral generalQueue, CommandProcessorImages imagesQueue)
+ public ConnectivityService(ILogger logger, ISettingsProvider settingsProvider, IEnumerable connectivityMonitors, IUDPConnectionHandler udpHandler, IHttpConnectionHandler httpHandler, CommandProcessorGeneral generalQueue, CommandProcessorImages imagesQueue)
{
- AnidbUdpHandler = udpHandler;
- AnidbHttpHandler = httpHandler;
- GeneralQueue = generalQueue;
- ImagesQueue = imagesQueue;
+ _logger = logger;
+ _settingsProvider = settingsProvider;
+ _connectivityMonitors = connectivityMonitors.ToArray();
+ _anidbUdpHandler = udpHandler;
+ _anidbHttpHandler = httpHandler;
+ _generalQueue = generalQueue;
+ _imagesQueue = imagesQueue;
NetworkAvailabilityChanged += OnNetworkAvailabilityChanged;
}
@@ -64,16 +79,99 @@ public ConnectivityService(IUDPConnectionHandler udpHandler, IHttpConnectionHand
NetworkAvailabilityChanged -= OnNetworkAvailabilityChanged;
}
+ public async Task CheckAvailability()
+ {
+ try
+ {
+ var localNetwork = GetLANConnectivity();
+ if (localNetwork != NetworkAvailability.LocalOnly)
+ {
+ return NetworkAvailability = localNetwork;
+ }
+
+ var wideNetwork = await GetWANConnectivity();
+ return NetworkAvailability = wideNetwork;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to check network availability.");
+ return NetworkAvailability;
+ }
+ }
+
+ private NetworkAvailability GetLANConnectivity()
+ {
+ _logger.LogInformation("Checking LAN Connectivity…");
+ // Get all active network interfaces
+ var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces()
+ .Where(n => n.OperationalStatus == OperationalStatus.Up)
+ .ToList();
+
+ if (!networkInterfaces.Any())
+ return NetworkAvailability.NoInterfaces;
+
+ foreach (var netInterface in networkInterfaces)
+ {
+ var properties = netInterface.GetIPProperties();
+ if (properties == null)
+ continue;
+
+ var defaultGateway = properties.GatewayAddresses
+ .Select(g => g.Address)
+ .FirstOrDefault();
+ if (defaultGateway == null)
+ continue;
+
+ _logger.LogInformation("Found a local gateway to use.");
+ return NetworkAvailability.LocalOnly;
+ }
+
+ _logger.LogInformation("No local gateway was found.");
+ return NetworkAvailability.NoGateways;
+ }
+
+ private async Task GetWANConnectivity()
+ {
+ var currentlyDisabledMonitors = _settingsProvider.GetSettings().Connectivity.DisabledMonitorServices
+ .ToHashSet();
+ var monitors = _connectivityMonitors
+ .Where(monitor => !currentlyDisabledMonitors.Contains(monitor.Service, StringComparer.InvariantCultureIgnoreCase))
+ .ToList();
+ if (monitors.Count == 0)
+ {
+ _logger.LogInformation("Skipped checking WAN Connectivity.");
+ return NetworkAvailability.Internet;
+ }
+
+ _logger.LogInformation("Checking WAN Connectivity…");
+ await Parallel.ForEachAsync(monitors, async (monitor, token) =>
+ {
+ await monitor.ExecuteCheckAsync(token);
+ });
+
+ var connectedCount = monitors.Count(a => a.HasConnected);
+ _logger.LogInformation("Successfully connected to {Count}/{Total} internet service endpoints.", connectedCount,
+ monitors.Count);
+
+ return connectedCount > 0 ? (
+ // We managed to connect to WAN, either partially or fully.
+ connectedCount == monitors.Count ? NetworkAvailability.Internet : NetworkAvailability.PartialInternet
+ ) : (
+ // We didn't manage to connect to WAN, but we reached the gateway
+ NetworkAvailability.LocalOnly
+ );
+ }
+
// Notify the queues that they can start again.
private void OnNetworkAvailabilityChanged(object sender, NetworkAvailabilityChangedEventArgs eventArgs)
{
if (!eventArgs.NetworkAvailability.HasInternet())
return;
- if (!GeneralQueue.Paused && GeneralQueue.QueueCount > 0)
- GeneralQueue.NotifyOfNewCommand();
+ if (!_generalQueue.Paused && _generalQueue.QueueCount > 0)
+ _generalQueue.NotifyOfNewCommand();
- if (!ImagesQueue.Paused && ImagesQueue.QueueCount > 0)
- ImagesQueue.NotifyOfNewCommand();
+ if (!_imagesQueue.Paused && _imagesQueue.QueueCount > 0)
+ _imagesQueue.NotifyOfNewCommand();
}
}