FileTransferSession
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;
}
}
}