AsperaFaspService
class AsperaFaspService
using Aspera.Transfer;
using Relativity.Transfer.Aspera.Resources;
using Relativity.Transfer.Resources;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
namespace Relativity.Transfer.Aspera
{
internal class AsperaFaspService
{
private static readonly object SyncRoot = new object();
private readonly ITransferLog log;
private readonly AsperaClientConfiguration configuration;
private readonly IAsperaFaspProxy faspProxy;
private readonly IFileSystemService fileSystemService;
private int retryCount;
public int RetryCount {
get {
lock (SyncRoot) {
return retryCount;
}
}
set {
lock (SyncRoot) {
retryCount = value;
}
}
}
public AsperaFaspService(ITransferLog log, AsperaClientConfiguration configuration, IAsperaFaspProxy proxy, IFileSystemService fileSystemService)
{
if (log == null)
throw new ArgumentNullException("log");
if (configuration == null)
throw new ArgumentNullException("configuration");
if (proxy == null)
throw new ArgumentNullException("proxy");
if (fileSystemService == null)
throw new ArgumentNullException("fileSystemService");
this.log = log;
this.configuration = configuration;
faspProxy = proxy;
this.fileSystemService = fileSystemService;
}
public static string EncodeCookieString(string name, Guid cookie)
{
return (!string.IsNullOrWhiteSpace(name)) ? $"""{cookie}""{name}" : cookie.ToString();
}
public static string EncodeCookieString(string name, Guid jobId, Guid cookie)
{
return $"{EncodeCookieString(name, cookie)}""{jobId}";
}
public Guid CreateAsperaJob(ITransferRequest request, FileTransferListener listener)
{
if (request == null)
throw new ArgumentNullException("request");
if (listener == null)
throw new ArgumentNullException("listener");
faspProxy.SetupRuntime();
if (!request.ClientRequestId.HasValue)
request.ClientRequestId = Guid.NewGuid();
if (!request.JobId.HasValue)
request.JobId = Guid.NewGuid();
FileLocation source;
FileLocation destination;
if (request.Direction == TransferDirection.Upload) {
source = new LocalFileLocation();
destination = CreateRemoteFileLocation(new TransferPath[0]);
} else {
source = CreateRemoteFileLocation(new TransferPath[0]);
destination = new LocalFileLocation();
}
XferParams xferParams = CreateTransferParameters(request.Name, request.JobId.Value, request.ClientRequestId.Value);
JobOrder order = new JobOrder(source, destination, xferParams);
return faspProxy.StartTransfer(order, request.JobId.Value, RetryCount, listener);
}
public void LockSession(Guid sessionId)
{
if (sessionId == Guid.Empty)
throw new ArgumentException(AsperaStrings.SessionIdArgumentExceptionMessage, "sessionId");
faspProxy.LockPersistentSession(sessionId);
}
public void AddFile(Guid sessionId, TransferPath path)
{
if (sessionId == Guid.Empty)
throw new ArgumentException(AsperaStrings.SessionIdArgumentExceptionMessage, "sessionId");
if (path == (TransferPath)null)
throw new ArgumentNullException("path");
if (string.IsNullOrEmpty(path.SourcePath))
throw new ArgumentException(CoreStrings.SourcePathArgumentExceptionMessage, "path");
if (string.IsNullOrEmpty(path.TargetPath))
throw new ArgumentException(CoreStrings.TargetPathArgumentExceptionMessage, "path");
try {
faspProxy.AddPersistentPath(sessionId, path);
} catch (FaspManagerException innerException) {
throw new TransferException(AsperaStrings.AddSourceExcpetionMessage, innerException);
}
}
public bool JobExists(Guid sessionId)
{
if (sessionId == Guid.Empty)
throw new ArgumentException(AsperaStrings.SessionIdArgumentExceptionMessage, "sessionId");
IEnumerable<Guid> sessionIds = faspProxy.GetSessionIds();
return sessionIds.Any((Guid x) => x == sessionId);
}
public void CancelJob(Guid sessionId, bool persist, FileTransferListener listener)
{
if (sessionId == Guid.Empty)
throw new ArgumentException(AsperaStrings.SessionIdArgumentExceptionMessage, "sessionId");
IEnumerable<Guid> sessionIds = faspProxy.GetSessionIds();
if (!sessionIds.Any((Guid x) => x == sessionId))
log.LogInformation("The Aspera '{SessionId}' session cannot be cancelled because the job does not exist.", sessionId);
else {
log.LogInformation("Preparing to cancel the '{SessionId}' Aspera session.", sessionId);
faspProxy.RemoveJobListener(sessionId, listener);
faspProxy.CancelTransfer(sessionId, persist);
faspProxy.RemoveSession(sessionId);
log.LogInformation("Successfully cancelled the '{SessionId}' Aspera session.", sessionId);
}
}
public void RemoveJob(Guid sessionId, FileTransferListener listener)
{
if (sessionId == Guid.Empty)
throw new ArgumentException(AsperaStrings.SessionIdArgumentExceptionMessage, "sessionId");
IEnumerable<Guid> sessionIds = faspProxy.GetSessionIds();
if (!sessionIds.Any((Guid x) => x == sessionId))
log.LogInformation("The Aspera '{SessionId}' job cannot be removed because the job does not exist.", sessionId);
else
try {
faspProxy.RemoveJobListener(sessionId, listener);
} finally {
faspProxy.RemoveSession(sessionId);
}
}
private RemoteFileLocation CreateRemoteFileLocation(IEnumerable<TransferPath> paths)
{
RemoteFileLocation remoteFileLocation;
try {
AsperaCredential asperaCredential = new AsperaCredential(configuration.Credential);
if (!string.IsNullOrEmpty(configuration.SshPrivateKeyFile)) {
if (!fileSystemService.FileExists(configuration.SshPrivateKeyFile)) {
string message = string.Format(CultureInfo.CurrentCulture, AsperaStrings.AsperaSshPrivateKeyFileNotFoundArgumentExceptionMessage, configuration.SshPrivateKeyFile);
throw new TransferException(message, true);
}
if (string.IsNullOrEmpty(configuration.SecurityToken)) {
string message2 = string.Format(CultureInfo.CurrentCulture, AsperaStrings.AsperaSecurityTokenArgumentExceptionMessage, Array.Empty<object>());
throw new TransferException(message2, true);
}
remoteFileLocation = new RemoteFileLocation(asperaCredential.Host.ToString(), asperaCredential.AccountUserName.UnprotectData(), configuration.SshPrivateKeyFile, configuration.SshPassphrase);
} else
remoteFileLocation = new RemoteFileLocation(asperaCredential.Host.ToString(), asperaCredential.AccountUserName.UnprotectData(), asperaCredential.AccountPassword.UnprotectData());
} catch (Exception ex) {
throw new TransferException(ex.Message, true);
}
foreach (TransferPath path in paths) {
if (string.IsNullOrEmpty(path.SourcePath))
throw new ArgumentException(AsperaStrings.AsperaTargetPathArgumentExceptionMessage, "paths");
if (string.IsNullOrEmpty(path.TargetFileName))
remoteFileLocation.addPath(path.SourcePath);
else
remoteFileLocation.addPath(path.SourcePath, path.TargetFileName);
}
return remoteFileLocation;
}
private XferParams CreateTransferParameters(string name, Guid jobId, Guid cookie)
{
string localLogDir = TransferHelper.CreateTransferLogDirectory(log, fileSystemService, configuration.TransferLogDirectory, "Aspera-Transfers");
string token = string.Empty;
if (!string.IsNullOrEmpty(configuration.SecurityToken))
token = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(configuration.SecurityToken));
XferParams xferParams = new XferParams {
reportSkippedFiles = configuration.ReportNotOverriddenFiles,
cookie = EncodeCookieString(name, jobId, cookie),
createDirs = configuration.CreateDirectories,
cipher = new Cipher?(TypeHelper.ParseEnum(configuration.EncryptionCipher, Cipher.AES_256, log)),
httpFallback = null,
localLogDir = localLogDir,
minimumRateKbps = configuration.MinDataRateMbps * 1000,
overwritePolicy = TypeHelper.ParseEnum(configuration.OverwritePolicy, OverwritePolicy.ALWAYS, log),
partialFileSuffix = null,
persist = true,
policy = TypeHelper.ParseEnum(configuration.Policy, Policy.FAIR, log),
preserveDates = configuration.PreserveDates,
resumeCheck = new Resume?(TypeHelper.ParseEnum(configuration.ResumeCheck, Resume.OFF, log)),
retryTimeoutS = Convert.ToInt32(configuration.HttpTimeoutSeconds),
saveBeforeOverwriteEnabled = configuration.SaveBeforeOverwriteEnabled,
targetRateKbps = configuration.TargetDataRateMbps * 1000,
token = token,
tcpPort = configuration.TcpPort,
udpPort = configuration.UdpPortStartRange,
datagramSize = configuration.DatagramSize
};
log.LogInformation(xferParams.Dump(), Array.Empty<object>());
return xferParams;
}
}
}