Add ClientContext and ProxiedScanDriver implementation

This commit is contained in:
Ben Olden-Cooligan 2018-09-22 13:54:10 -04:00
parent 909aadccf4
commit f65d7a6270
6 changed files with 167 additions and 1 deletions

View File

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using NAPS2.Util;
namespace NAPS2.ClientServer
{
public class ClientContext : IDisposable
{
public IServerService Service { get; set; }
public IServerCallback Callback { get; set; }
public void Dispose()
{
try
{
((IDisposable)Service)?.Dispose();
}
catch (CommunicationObjectFaultedException)
{
}
catch (Exception e)
{
Log.ErrorException("Error cleaning up client", e);
}
}
}
}

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using NAPS2.Scan;
namespace NAPS2.ClientServer
{
public class ClientContextFactory
{
public ClientContext Create(ScanProxyConfig proxyConfig)
{
// TODO: Validate IP
var uri = new Uri($"net.tcp://{proxyConfig.Ip}:{proxyConfig.Port}/NAPS2.Server");
var callback = new ServerCallback();
var instanceContext = new InstanceContext(callback);
var channelFactory = new DuplexChannelFactory<IServerService>(instanceContext,
new NetTcpBinding
{
MaxReceivedMessageSize = 1024 * 1024 * 1024
},
new EndpointAddress(uri));
var channel = channelFactory.CreateChannel();
return new ClientContext { Service = channel, Callback = callback };
}
}
}

View File

@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using NAPS2.Recovery;
using NAPS2.Scan;
using NAPS2.Scan.Exceptions;
using NAPS2.Scan.Images;
using NAPS2.WinForms;
namespace NAPS2.ClientServer
{
public class ProxiedScanDriver : ScanDriverBase
{
public const string DRIVER_NAME = "proxy";
private readonly ClientContextFactory clientContextFactory;
private readonly IFormFactory formFactory;
public ProxiedScanDriver(ClientContextFactory clientContextFactory, IFormFactory formFactory)
{
this.clientContextFactory = clientContextFactory;
this.formFactory = formFactory;
}
public override string DriverName => DRIVER_NAME;
public override bool IsSupported => true;
protected override ScanDevice PromptForDeviceInternal()
{
var deviceList = GetDeviceList();
if (!deviceList.Any())
{
throw new NoDevicesFoundException();
}
var form = formFactory.Create<FSelectDevice>();
form.DeviceList = deviceList;
form.ShowDialog();
return form.SelectedDevice;
}
protected override List<ScanDevice> GetDeviceListInternal()
{
if (ScanProfile == null)
{
throw new InvalidOperationException("ScanProfile must be set before calling methods on ProxiedScanDriver.");
}
if (ScanProfile.ProxyConfig == null)
{
throw new InvalidOperationException("ScanProfile.ProxyConfig must be specified to use ProxiedScanDriver.");
}
using (var client = clientContextFactory.Create(ScanProfile.ProxyConfig))
{
return client.Service.GetDeviceList(ScanProfile.ProxyConfig.RemoteDriverName);
}
}
protected override Task ScanInternal(ScannedImageSource.Concrete source)
{
if (ScanProfile == null)
{
throw new InvalidOperationException("ScanProfile must be set before calling methods on ProxiedScanDriver.");
}
if (ScanProfile.ProxyConfig == null)
{
throw new InvalidOperationException("ScanProfile.ProxyConfig must be specified to use ProxiedScanDriver.");
}
return Task.Factory.StartNew(() =>
{
using (var client = clientContextFactory.Create(ScanProfile.ProxyConfig))
{
client.Callback.ImageCallback += (imageBytes, indexImage) =>
{
indexImage.FileName = RecoveryImage.GetNextFileName() + Path.GetExtension(indexImage.FileName);
var recoveryFilePath = Path.Combine(RecoveryImage.RecoveryFolder.FullName, indexImage.FileName);
File.WriteAllBytes(recoveryFilePath, imageBytes);
var image = new ScannedImage(indexImage);
// TODO: Post-processing etc.
// TODO: Also add a ScanParams flag to disable post-processing on the server
source.Put(image);
};
client.Service.Scan(ScanProfile, ScanParams);
}
}, TaskCreationOptions.LongRunning);
}
}
}

View File

@ -149,8 +149,11 @@
<Compile Include="Automation\ConsoleOverwritePrompt.cs" />
<Compile Include="Automation\ConsolePdfPasswordProvider.cs" />
<Compile Include="Automation\ConsoleComponentInstallPrompt.cs" />
<Compile Include="ClientServer\ClientContext.cs" />
<Compile Include="ClientServer\ClientContextFactory.cs" />
<Compile Include="ClientServer\IServerCallback.cs" />
<Compile Include="ClientServer\IServerService.cs" />
<Compile Include="ClientServer\ProxiedScanDriver.cs" />
<Compile Include="ClientServer\ServerCallback.cs" />
<Compile Include="ClientServer\ServerService.cs" />
<Compile Include="Dependencies\ComponentManager.cs" />

View File

@ -96,7 +96,7 @@ namespace NAPS2.Recovery
}
}
private static string GetNextFileName()
public static string GetNextFileName()
{
lock (RecoveryFileNumberLock)
{

View File

@ -47,6 +47,8 @@ namespace NAPS2.Scan
[XmlIgnore]
public bool IsDeviceLocked { get; set; }
public ScanProxyConfig ProxyConfig { get; set; }
public ScanDevice Device { get; set; }
public string DriverName { get; set; }
@ -118,6 +120,17 @@ namespace NAPS2.Scan
public KeyValueScanOptions KeyValueOptions { get; set; }
}
public class ScanProxyConfig
{
public string Name { get; set; }
public string RemoteDriverName { get; set; }
public string Ip { get; set; }
public int Port { get; set; }
}
/// <summary>
/// User configuration for the Auto Save feature, which saves to a file immediately after scanning.
/// </summary>