diff --git a/NAPS2.Escl.Server/EsclServer.cs b/NAPS2.Escl.Server/EsclServer.cs index 502bd5d8d..34f6e1c7b 100644 --- a/NAPS2.Escl.Server/EsclServer.cs +++ b/NAPS2.Escl.Server/EsclServer.cs @@ -3,17 +3,12 @@ using EmbedIO.WebApi; namespace NAPS2.Escl.Server; -public class EsclServer : IDisposable +public class EsclServer : IEsclServer { - private readonly CancellationTokenSource _cts = new(); - private readonly MdnsAdvertiser _advertiser; private readonly Dictionary _devices = new(); private bool _started; - - public EsclServer() - { - _advertiser = new MdnsAdvertiser(); - } + private CancellationTokenSource? _cts; + private MdnsAdvertiser? _advertiser; public void AddDevice(EsclDeviceConfig deviceConfig) { @@ -21,18 +16,23 @@ public class EsclServer : IDisposable { deviceConfig.Port = Port++; } - Task.Run(() => _advertiser.AdvertiseDevice(deviceConfig)); _devices[deviceConfig] = new CancellationTokenSource(); if (_started) { StartServer(deviceConfig); + var advertiser = _advertiser!; + Task.Run(() => advertiser.AdvertiseDevice(deviceConfig)); } } public void RemoveDevice(EsclDeviceConfig deviceConfig) { - // TODO: Maybe enforce ordering to ensure we don't unadvertise before advertising? - Task.Run(() => _advertiser.UnadvertiseDevice(deviceConfig)); + if (_started) + { + // TODO: Maybe enforce ordering to ensure we don't unadvertise before advertising? + var advertiser = _advertiser!; + Task.Run(() => advertiser.UnadvertiseDevice(deviceConfig)); + } _devices[deviceConfig].Cancel(); _devices.Remove(deviceConfig); } @@ -47,10 +47,13 @@ public class EsclServer : IDisposable throw new InvalidOperationException(); } _started = true; + _cts = new CancellationTokenSource(); + _advertiser = new MdnsAdvertiser(); foreach (var device in _devices.Keys) { StartServer(device); + Task.Run(() => _advertiser!.AdvertiseDevice(device)); } } @@ -64,7 +67,21 @@ public class EsclServer : IDisposable .WithUrlPrefix(url)) .WithWebApi("/eSCL", m => m.WithController(() => new EsclApiController(deviceConfig, serverState))); server.StateChanged += ServerOnStateChanged; - server.RunAsync(CancellationTokenSource.CreateLinkedTokenSource(_cts.Token, _devices[deviceConfig].Token).Token); + server.RunAsync(CancellationTokenSource.CreateLinkedTokenSource(_cts!.Token, _devices[deviceConfig].Token).Token); + } + + public void Stop() + { + if (!_started) + { + throw new InvalidOperationException(); + } + _started = false; + + _cts!.Cancel(); + _advertiser!.Dispose(); + _cts = null; + _advertiser = null; } private void ServerOnStateChanged(object sender, WebServerStateChangedEventArgs e) @@ -73,7 +90,9 @@ public class EsclServer : IDisposable public void Dispose() { - _cts.Cancel(); - _advertiser.Dispose(); + if (_started) + { + Stop(); + } } } \ No newline at end of file diff --git a/NAPS2.Escl/Client/CapabilitiesParser.cs b/NAPS2.Escl/Client/CapabilitiesParser.cs index 0b4539ed2..dc4fef57b 100644 --- a/NAPS2.Escl/Client/CapabilitiesParser.cs +++ b/NAPS2.Escl/Client/CapabilitiesParser.cs @@ -28,7 +28,7 @@ internal static class CapabilitiesParser var adfDuplexCapsEl = root.Element(ScanNs + "Adf")?.Element(ScanNs + "AdfDuplexInputCaps"); return new EsclCapabilities { - Version = root.Element(PwgNs + "Version")?.Value, + Version = root.Element(PwgNs + "Version")?.Value ?? EsclCapabilities.DEFAULT_VERSION, MakeAndModel = root.Element(PwgNs + "MakeAndModel")?.Value, SerialNumber = root.Element(PwgNs + "SerialNumber")?.Value, Uuid = root.Element(ScanNs + "UUID")?.Value, diff --git a/NAPS2.Escl/EsclCapabilities.cs b/NAPS2.Escl/EsclCapabilities.cs index 7b11b19c1..61b94a380 100644 --- a/NAPS2.Escl/EsclCapabilities.cs +++ b/NAPS2.Escl/EsclCapabilities.cs @@ -2,7 +2,9 @@ namespace NAPS2.Escl; public class EsclCapabilities { - public string Version { get; init; } = "2.6"; + public const string DEFAULT_VERSION = "2.6"; + + public string Version { get; init; } = DEFAULT_VERSION; public string? MakeAndModel { get; init; } public string? SerialNumber { get; init; } public string? Uuid { get; init; } diff --git a/NAPS2.Escl.Server/EsclDeviceConfig.cs b/NAPS2.Escl/Server/EsclDeviceConfig.cs similarity index 100% rename from NAPS2.Escl.Server/EsclDeviceConfig.cs rename to NAPS2.Escl/Server/EsclDeviceConfig.cs diff --git a/NAPS2.Escl.Server/IEsclScanJob.cs b/NAPS2.Escl/Server/IEsclScanJob.cs similarity index 100% rename from NAPS2.Escl.Server/IEsclScanJob.cs rename to NAPS2.Escl/Server/IEsclScanJob.cs diff --git a/NAPS2.Escl/Server/IEsclServer.cs b/NAPS2.Escl/Server/IEsclServer.cs new file mode 100644 index 000000000..af6518db3 --- /dev/null +++ b/NAPS2.Escl/Server/IEsclServer.cs @@ -0,0 +1,10 @@ +namespace NAPS2.Escl.Server; + +public interface IEsclServer : IDisposable +{ + void AddDevice(EsclDeviceConfig deviceConfig); + void RemoveDevice(EsclDeviceConfig deviceConfig); + int Port { get; set; } + void Start(); + void Stop(); +} \ No newline at end of file diff --git a/NAPS2.Escl.Server/JobStatus.cs b/NAPS2.Escl/Server/JobStatus.cs similarity index 100% rename from NAPS2.Escl.Server/JobStatus.cs rename to NAPS2.Escl/Server/JobStatus.cs diff --git a/NAPS2.Lib/NAPS2.Lib.csproj b/NAPS2.Lib/NAPS2.Lib.csproj index 02d546845..2062021f9 100644 --- a/NAPS2.Lib/NAPS2.Lib.csproj +++ b/NAPS2.Lib/NAPS2.Lib.csproj @@ -30,6 +30,7 @@ + diff --git a/NAPS2.Lib/Remoting/Server/SharedDeviceManager.cs b/NAPS2.Lib/Remoting/Server/SharedDeviceManager.cs index 0d694eb4b..ef75042f9 100644 --- a/NAPS2.Lib/Remoting/Server/SharedDeviceManager.cs +++ b/NAPS2.Lib/Remoting/Server/SharedDeviceManager.cs @@ -1,3 +1,4 @@ +using NAPS2.Escl.Server; using NAPS2.Scan; namespace NAPS2.Remoting.Server; @@ -10,7 +11,7 @@ public class SharedDeviceManager : ISharedDeviceManager public SharedDeviceManager(ScanningContext scanningContext, Naps2Config config) { _config = config; - _server = new ScanServer(scanningContext); + _server = new ScanServer(scanningContext, new EsclServer()); _server.SetDefaultIcon(Icons.scanner_128); RegisterDevicesFromConfig(); } diff --git a/NAPS2.Sdk/NAPS2.Sdk.csproj b/NAPS2.Sdk/NAPS2.Sdk.csproj index 6f85f8d7e..050083d71 100644 --- a/NAPS2.Sdk/NAPS2.Sdk.csproj +++ b/NAPS2.Sdk/NAPS2.Sdk.csproj @@ -86,7 +86,6 @@ - diff --git a/NAPS2.Sdk/Remoting/Server/ScanServer.cs b/NAPS2.Sdk/Remoting/Server/ScanServer.cs index 1fa1472ab..1c40ba55d 100644 --- a/NAPS2.Sdk/Remoting/Server/ScanServer.cs +++ b/NAPS2.Sdk/Remoting/Server/ScanServer.cs @@ -8,12 +8,13 @@ public class ScanServer : IDisposable { private readonly ScanningContext _scanningContext; private readonly Dictionary<(Driver, string), EsclDeviceConfig> _currentDevices = new(); - private EsclServer? _esclServer; + private readonly IEsclServer _esclServer; private byte[]? _defaultIconPng; - public ScanServer(ScanningContext scanningContext) + public ScanServer(ScanningContext scanningContext, IEsclServer esclServer) { _scanningContext = scanningContext; + _esclServer = esclServer; ScanController = new ScanController(scanningContext); } @@ -29,7 +30,7 @@ public class ScanServer : IDisposable var key = (device.Driver, device.Device.ID); var esclDeviceConfig = MakeEsclDeviceConfig(device); _currentDevices.Add(key, esclDeviceConfig); - _esclServer?.AddDevice(esclDeviceConfig); + _esclServer.AddDevice(esclDeviceConfig); } public void UnregisterDevice(SharedDevice device) @@ -37,7 +38,7 @@ public class ScanServer : IDisposable var key = (device.Driver, device.Device.ID); var esclDeviceConfig = _currentDevices[key]; _currentDevices.Remove(key); - _esclServer?.RemoveDevice(esclDeviceConfig); + _esclServer.RemoveDevice(esclDeviceConfig); } private EsclDeviceConfig MakeEsclDeviceConfig(SharedDevice device) @@ -69,27 +70,9 @@ public class ScanServer : IDisposable }; } - public void Start() - { - if (_esclServer != null) throw new InvalidOperationException("Already started"); - _esclServer = new EsclServer(); - foreach (var device in _currentDevices.Values) - { - _esclServer.AddDevice(device); - } - _esclServer.Start(); - } + public void Start() => _esclServer.Start(); - public void Stop() - { - if (_esclServer == null) throw new InvalidOperationException("Not started"); - _esclServer.Dispose(); - _esclServer = null; - } + public void Stop() => _esclServer.Stop(); - public void Dispose() - { - _esclServer?.Dispose(); - _esclServer = null; - } + public void Dispose() => _esclServer.Dispose(); } \ No newline at end of file