<PackageReference Include="Relativity.Server.Transfer.SDK" Version="24000.0.1" />

FileTransferSession

public class FileTransferSession : Session
using Newtonsoft.Json.Linq; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; using System.Text.RegularExpressions; namespace Aspera.Transfer { public class FileTransferSession : Session { private bool _newFileObserved; private FileStats tempActiveFileStats; private FileStats currentFileStats; private Hashtable _fileStatsList = new Hashtable(); private string currMsgType; private string Destination = ""; private string Source = ""; private DateTime startTime; private FaspManager _fm; public FileTransferSession(bool debugEnabled) : base(debugEnabled) { Operation = "Transfer"; startTime = DateTime.Now; } public FileTransferSession(JobOrder order, FileTransferListener listener, string jobId, bool debugEnabled) : base(order, jobId, debugEnabled) { if (listener != null) { Logger.Log(TraceEventType.Verbose, id + " - Adding a job listener"); addListener(listener); } Operation = "Transfer"; startTime = DateTime.Now; state = SessionState.SUBMITTED; } internal void setFM(FaspManager fm) { _fm = fm; } public static string EscapeArguments(params string[] args) { StringBuilder stringBuilder = new StringBuilder(); Regex regex = new Regex("[\n\r]"); Regex regex2 = new Regex("\\s|\""); Regex regex3 = new Regex("(\\\\*)(\"|$)"); int num = 0; while (args != null && num < args.Length) { if (args[num] == null) throw new ArgumentNullException("args[" + num + "]"); if (regex.IsMatch(args[num])) throw new ArgumentOutOfRangeException("args[" + num + "]"); if (args[num] == string.Empty) stringBuilder.Append("\"\""); else if (!regex2.IsMatch(args[num])) { stringBuilder.Append(args[num]); } else { stringBuilder.Append('"'); stringBuilder.Append(regex3.Replace(args[num], (Match m) => m.Groups[1].Value + m.Groups[1].Value + ((m.Groups[2].Value == "\"") ? "\\\"" : ""))); stringBuilder.Append('"'); } if (num + 1 < args.Length) stringBuilder.Append(' '); num++; } return stringBuilder.ToString(); } internal override void start(int mgmtPort) { try { List<string> list = new List<string>(); if (nbProcesses > 1) { list.Add("-C"); list.Add(processIndex + ":" + nbProcesses); } string environmentVariable = System.Environment.GetEnvironmentVariable("aspera.altManagementPort"); if (environmentVariable != null && environmentVariable != string.Empty) try { mgmtPort = int.Parse(environmentVariable); } catch (Exception ex) { Logger.Log(TraceEventType.Error, "Invalid: not setting the alternative management port: " + environmentVariable + " ex:" + ex); } if (_order.getXferParams().reportSkippedFiles) list.Add("-Ms" + mgmtPort); else list.Add("-M" + mgmtPort); if (debugEnabled) list.Add("-DD"); list.Add("-u"); list.Add(id); list.AddRange(_order.buildCommand(xferId, xferRetry)); ProcessStartInfo processStartInfo = new ProcessStartInfo(); processStartInfo.CreateNoWindow = true; processStartInfo.Arguments = EscapeArguments(list.ToArray()); processStartInfo.FileName = Environment.getFaspScpPath(); processStartInfo.UseShellExecute = false; processStartInfo.RedirectStandardError = true; string value = (!_order.isUpload()) ? ((RemoteFileLocation)_order.getSource()).getPassword() : ((RemoteFileLocation)_order.getDestination()).getPassword(); processStartInfo.EnvironmentVariables.Add("ASPERA_SCP_PASS", value); if (_order.getXferParams().cookie != null && _order.getXferParams().cookie.Length > 0) processStartInfo.EnvironmentVariables.Add("ASPERA_SCP_COOKIE", _order.getXferParams().cookie); if (_order.getXferParams().token != null && _order.getXferParams().token.Length > 0) processStartInfo.EnvironmentVariables.Add("ASPERA_SCP_TOKEN", _order.getXferParams().token); if (_order.getXferParams().contentProtectionPassphrase != null) processStartInfo.EnvironmentVariables.Add("ASPERA_SCP_FILEPASS", _order.getXferParams().contentProtectionPassphrase); Logger.Log(TraceEventType.Information, id + " - Launching " + processStartInfo.FileName + " " + processStartInfo.Arguments); try { new TempFileDeleter(Process.Start(processStartInfo), _order.getSource().TempFileName, this); } catch (Exception e) { throw new FaspManagerException("SessionID: " + id + "Failed to start the transfer. Check Environment::AsperaScpPath", e); } } catch (Exception ex2) { Logger.Log(TraceEventType.Error, "SessionID: " + id + " - Failed to launch transfer. Exception thrown: " + ex2); string text = null; try { text = _order.getSource().TempFileName; File.Delete(text); } catch (Exception ex3) { Logger.Log(TraceEventType.Error, "SessionID: " + id + " - Failed to delete temp file [" + text + "] on launch failure. Exception: " + ex3); } throw ex2; } } public string getCurrentFile() { if (currentFileStats == null) return null; return currentFileStats.name; } public override void handleAscpCrash() { if (state != SessionState.FINISHED) { if (currentFileStats != null && currentFileStats.state == FileState.TRANSFERRING) { currentFileStats.state = FileState.FAILED; currentFileStats.errCode = 11; currentFileStats.errDescription = "Internal error"; } invokeListener(TransferEvent.SESSION_ERROR); } } protected virtual void invokeListener(TransferEvent evnt) { ArrayList arrayList = new ArrayList(_listenersList); SessionStats sessionStats = getSessionStats(); Logger.Log(TraceEventType.Verbose, id + " - Invoking listeners. Event: " + evnt.ToString()); for (int i = 0; i < arrayList.Count; i++) { FileTransferListener fileTransferListener = (FileTransferListener)arrayList[i]; if (fileTransferListener != null) try { fileTransferListener.fileSessionEvent(evnt, sessionStats.Clone(), (currentFileStats == null) ? null : currentFileStats.Clone()); } catch (Exception ex) { Logger.Log(TraceEventType.Error, "Listener [" + fileTransferListener.ToString() + "] throws exception when invoked. Exception " + ex); } } if (evnt == TransferEvent.SESSION_STOP || evnt == TransferEvent.SESSION_ERROR) _fm.removeCompletedSession(getWriteSocket()); } private void cleanFinishedFileStats() { } public FileStats getCurrentFileStats() { return currentFileStats.Clone(); } protected internal override void processReadData(string rawMsgString) { string text = null; msgBuffer += rawMsgString; int num = 0; while (msgBuffer.IndexOf("\n\n") != -1) { num = msgBuffer.IndexOf("\n\n"); text = msgBuffer.Substring(0, num); msgBuffer = msgBuffer.Substring(num + 2); processMgmtMessage(text); } } private void processMgmtMessage(string message) { bool flag = false; string[] array = message.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); tempActiveFileStats = new FileStats(); string[] array2 = array; foreach (string text in array2) { int num = text.IndexOf(":"); if (num == -1) { if (text.Contains("FASPMGR")) version = text; else flag = true; } else { string text2 = text.Substring(0, num).Trim(); string value = text.Substring(num + 2).Trim(); if (text2 == "Type") currMsgType = value; updateFASPSessionData(text2, value); } } Logger.Log(TraceEventType.Verbose, id + " - Processing " + currMsgType + " message\n" + message); if (flag) Logger.Log(TraceEventType.Warning, id + " - Errors parsing the management message: " + message); else { commitTempActiveFileStats(); tempActiveFileStats = null; notifyListeners(currMsgType); _newFileObserved = false; cleanupFileStatsList(); } } private void cleanupFileStatsList() { string[] array = new string[_fileStatsList.Keys.Count]; _fileStatsList.Keys.CopyTo(array, 0); string[] array2 = array; foreach (string key in array2) { if (((FileStats)_fileStatsList[key]).state == FileState.FINISHED) _fileStatsList.Remove(key); } } private void notifyListeners(string currMsgType) { TransferEvent evnt; switch (currMsgType) { default: return; case "INIT": evnt = TransferEvent.CONNECTING; break; case "SESSION": evnt = TransferEvent.SESSION_START; break; case "NOTIFICATION": evnt = TransferEvent.RATE_MODIFICATION; break; case "STATS": evnt = (_newFileObserved ? TransferEvent.FILE_START : TransferEvent.PROGRESS); break; case "STOP": evnt = TransferEvent.FILE_STOP; filesComplete++; break; case "FILEERROR": evnt = TransferEvent.FILE_ERROR; filesFailed++; break; case "ERROR": evnt = TransferEvent.SESSION_ERROR; break; case "DONE": evnt = TransferEvent.SESSION_STOP; break; case "SKIP": evnt = TransferEvent.FILE_SKIP; filesComplete++; filesSkipped++; break; } invokeListener(evnt); } private void updateFASPSessionData(string key, string value) { switch (key) { case "ArgScansAttempted": case "ArgScansCompleted": case "FileScansCompleted": case "Policy": case "PreTransferDirs": case "PreTransferSpecial": break; case "Adaptive": Adaptive = PolicyHelper.policyFromMgmtValue(value); break; case "BWMeasurement": try { BWMeasurement = Convert.ToUInt32(value); } catch (Exception) { BWMeasurement = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "BlockInfo": BlockInfo = value; break; case "Bytescont": updateTempActiveFileStats(key, value); break; case "Code": if (!(currMsgType == "FILEERROR")) try { errNum = Convert.ToInt16(value); } catch (Exception) { errNum = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } else updateTempActiveFileStats(key, value); break; case "Cookie": Cookie = value; break; case "Delay": try { Delay = Convert.ToUInt32(value); } catch (Exception) { Delay = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "Description": if (currMsgType == "FILEERROR") updateTempActiveFileStats(key, value); else errDescription = value; break; case "Destination": Destination = value; break; case "Direction": Direction = value; if (Direction == "Receive") IsUpload = false; else IsUpload = true; break; case "DiskInfo": DiskInfo = value; break; case "Elapsedusec": try { ElapsedUsec = Convert.ToUInt64(value); } catch (Exception) { ElapsedUsec = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "Encryption": if (value == "Yes") Encryption = true; break; case "EndByte": updateTempActiveFileStats(key, value); break; case "FileBytes": try { FileBytes = Convert.ToUInt64(value); } catch (Exception) { FileBytes = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "File": updateTempActiveFileStats(key, value); break; case "Host": Host = value; break; case "Loss": try { totalLostBytes = Convert.ToUInt64(value); } catch (Exception) { totalLostBytes = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "ManifestFile": manifestFilePath = value; break; case "MinRate": try { minimumRateKbps = Convert.ToUInt64(value); } catch (Exception) { minimumRateKbps = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "Operation": Operation = value; break; case "Password": Password = value; break; case "PathScansAttempted": try { sourcePathsScanAttempted = int.Parse(value); } catch (Exception) { sourcePathsScanAttempted = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "PathScansExcluded": try { sourcePathsScanExcluded = int.Parse(value); } catch (Exception) { sourcePathsScanExcluded = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "PathScansFailed": try { sourcePathsScanFailed = int.Parse(value); } catch (Exception) { sourcePathsScanFailed = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "PathScansIrregular": try { sourcePathsScanIrregular = int.Parse(value); } catch (Exception) { sourcePathsScanIrregular = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "PMTU": try { pmtu = int.Parse(value); } catch (Exception) { pmtu = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "Port": try { udpPort = Convert.ToUInt32(value); } catch (Exception) { udpPort = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "PreTransferBytes": try { preTransferBytes = Convert.ToUInt64(value); } catch (Exception) { preTransferBytes = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "PreTransferFiles": try { preTransferFiles = Convert.ToUInt64(value); } catch (Exception) { preTransferFiles = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "Priority": try { priority = Convert.ToUInt32(value); } catch (Exception) { priority = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "Progress": Progress = value; break; case "Query": Query = value; break; case "QueryResponse": QueryResponse = value; break; case "Rate": try { targetRateKbps = Convert.ToUInt64(value); } catch (Exception) { targetRateKbps = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "Remote": if (value == "Yes") IsRemote = true; else IsRemote = false; break; case "ServiceLevel": try { bandwidthCapKbps = Convert.ToUInt64(value); } catch (Exception) { bandwidthCapKbps = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "SessionId": if (SessionId == "") SessionId = value; break; case "Size": updateTempActiveFileStats(key, value); break; case "Source": Source = value; break; case "StartByte": updateTempActiveFileStats(key, value); break; case "Token": Token = value; break; case "TransferBytes": try { TransferBytes = Convert.ToUInt64(value); } catch (Exception) { TransferBytes = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "TransfersAttempted": try { transfersAttempted = int.Parse(value); } catch (Exception) { transfersAttempted = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "TransfersPassed": try { transfersPassed = int.Parse(value); } catch (Exception) { transfersPassed = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "TransfersSkipped": try { transfersSkipped = int.Parse(value); } catch (Exception) { transfersSkipped = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "Type": currMsgType = value; if (value == "DONE") state = SessionState.FINISHED; else if (value == "ERROR") { state = SessionState.FAILED; } else if (value == "INIT") { state = SessionState.CONNECTING; } else if (value == "QUERY") { state = SessionState.AUTHENTICATING; } else if (value == "SESSION") { state = SessionState.STARTED; } else if (value == "STATS" || value == "STOP" || value == "START" || value == "FILEERROR" || value == "SKIP" || value == "ARGSTOP") { state = SessionState.TRANSFERRING; } updateTempActiveFileStats(key, value); break; case "User": User = value; break; case "UserStr": if (id == null || id.Length == 0) id = value; break; case "Written": updateTempActiveFileStats(key, value); break; case "XferId": { Guid guid = Guid.Parse(value); if (!IsOtherInitiated && !guid.Equals(xferId)) throw new FaspManagerException("Something is wrong: XferId received: " + guid + " is different from xferId of this session: " + xferId); break; } case "XferRetry": { int num = int.Parse(value); if (!IsOtherInitiated && num != xferRetry) throw new FaspManagerException("Something is wrong: XferRetry received: " + num + " is different from xferRetry of this session: " + xferRetry); break; } case "Tags": try { tags = JObject.Parse(value); } catch (Exception) { tags = JObject.Parse("{}"); Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a JSON."); } break; case "RetryTimeout": try { retryTimeout = int.Parse(value); } catch (Exception) { retryTimeout = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "TCPPort": try { tcpPort = Convert.ToUInt32(value); } catch (Exception) { tcpPort = 0; Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "ServerNodeId": serverNodeId = value; break; case "ServerClusterId": serverClusterId = value; break; case "ClientNodeId": clientNodeId = value; break; case "ClientClusterId": clientClusterId = value; break; case "FileChecksumType": updateTempActiveFileStats(key, value); break; case "FileChecksum": updateTempActiveFileStats(key, value); break; } } private void updateTempActiveFileStats(string key, string value) { switch (key) { case "Bytescont": try { tempActiveFileStats.contiguousBytes = Convert.ToInt64(value); } catch (Exception) { Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "Code": try { tempActiveFileStats.errCode = Convert.ToInt32(value); } catch (Exception) { Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "Description": tempActiveFileStats.errDescription = value; break; case "File": tempActiveFileStats.name = value; break; case "Size": try { tempActiveFileStats.sizeBytes = Convert.ToInt64(value); } catch (Exception) { Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "StartByte": try { tempActiveFileStats.startByte = Convert.ToInt64(value); } catch (Exception) { Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "EndByte": try { tempActiveFileStats.endByte = Convert.ToInt64(value); } catch (Exception) { Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "Type": if (value == "FILEERROR") tempActiveFileStats.state = FileState.FAILED; else if (value == "STOP") { tempActiveFileStats.state = FileState.FINISHED; } else if (value == "STATS") { tempActiveFileStats.state = FileState.TRANSFERRING; } else if (value == "SKIP") { tempActiveFileStats.state = FileState.SKIPPED; } else if (value == "ARGSTOP") { tempActiveFileStats.state = FileState.FINISHED; } break; case "Written": try { tempActiveFileStats.writtenBytes = Convert.ToInt64(value); } catch (Exception) { Logger.Log(TraceEventType.Error, "Cannot convert received value " + value + " for " + key + " to a number."); } break; case "FileChecksumType": tempActiveFileStats.fileChecksumType = value; break; case "FileChecksum": tempActiveFileStats.fileChecksum = value; break; } } private void commitTempActiveFileStats() { FileStats fileStats = tempActiveFileStats; if (fileStats.name.Length != 0 && fileStats.name != null) { if (_fileStatsList.ContainsKey(fileStats.name)) { FileStats fileStats2 = (FileStats)_fileStatsList[fileStats.name]; fileStats2.name = fileStats.name; fileStats2.errCode = fileStats.errCode; fileStats2.state = fileStats.state; fileStats2.fileChecksumType = fileStats.fileChecksumType; fileStats2.fileChecksum = fileStats.fileChecksum; if (fileStats.contiguousBytes != 0) fileStats2.contiguousBytes = fileStats.contiguousBytes; if (fileStats.sizeBytes != 0) fileStats2.sizeBytes = fileStats.sizeBytes; if (fileStats.startByte != 0) fileStats2.startByte = fileStats.startByte; if (fileStats.endByte != 0) fileStats2.endByte = fileStats.endByte; if (fileStats.writtenBytes != 0) fileStats2.writtenBytes = fileStats.writtenBytes; currentFileStats = fileStats2; } else { _fileStatsList.Add(fileStats.name, fileStats); _newFileObserved = true; currentFileStats = fileStats; } } } public string getSourcePath() { return Source; } public string getDestinationPath() { return Destination; } public SessionStats getSessionStats() { SessionStats sessionStats = new SessionStats(); sessionStats.BandwidthCapKbps = bandwidthCapKbps; sessionStats.Cookie = Cookie; sessionStats.DelayMs = Delay; sessionStats.DestPath = Destination; sessionStats.SourcePaths = Source; sessionStats.Direction = Direction; sessionStats.Encryption = Encryption; sessionStats.ErrorCode = errNum; sessionStats.ErrorDescription = errDescription; sessionStats.FilesComplete = filesComplete; sessionStats.FilesSkipped = filesSkipped; sessionStats.FilesFailed = filesFailed; sessionStats.Host = Host; sessionStats.Id = id; sessionStats.SessionId = SessionId; sessionStats.XferId = xferId; sessionStats.XferRetry = xferRetry; sessionStats.MeasuredLinkRateKbps = BWMeasurement; sessionStats.MinRateKbps = minimumRateKbps; sessionStats.Policy = Adaptive; if (priority == 1) sessionStats.Policy = Policy.HIGH; sessionStats.PreCalcTotalBytes = preTransferBytes; sessionStats.PreCalcTotalFiles = preTransferFiles; sessionStats.Remote = IsRemote; sessionStats.StartTime = startTime; sessionStats.State = state; sessionStats.TargetRateKbps = targetRateKbps; sessionStats.Token = Token; sessionStats.TotalWrittenBytes = FileBytes; sessionStats.TotalLostBytes = totalLostBytes; sessionStats.TotalTransferredBytes = TransferBytes; sessionStats.UdpPort = udpPort; sessionStats.User = User; sessionStats.ElapsedUSec = ElapsedUsec; sessionStats.ManifestFilePath = manifestFilePath; sessionStats.OtherInitiated = IsOtherInitiated; sessionStats.TransfersAttempted = transfersAttempted; sessionStats.TransfersFailed = transfersFailed; sessionStats.TransfersPassed = transfersPassed; sessionStats.TransfersSkipped = transfersSkipped; sessionStats.SourcePathsScanAttempted = sourcePathsScanAttempted; sessionStats.SourcePathsScanExcluded = sourcePathsScanExcluded; sessionStats.SourcePathsScanFailed = sourcePathsScanFailed; sessionStats.SourcePathsScanIrregular = sourcePathsScanIrregular; sessionStats.Tags = tags; sessionStats.Pmtu = pmtu; sessionStats.TcpPort = tcpPort; sessionStats.ServerNodeId = serverNodeId; sessionStats.ServerClusterId = serverClusterId; sessionStats.ClientNodeId = clientNodeId; sessionStats.ClientClusterId = clientClusterId; sessionStats.RetryTimeout = retryTimeout; return sessionStats; } } }