372 lines
13 KiB
C#
372 lines
13 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using Renci.SshNet;
|
|
|
|
namespace cdrtool
|
|
{
|
|
public class sftp
|
|
{
|
|
private static SftpClient CreateClient(
|
|
string host,
|
|
int port,
|
|
string username,
|
|
string password)
|
|
{
|
|
var client = new SftpClient(host, port, username, password);
|
|
|
|
client.ConnectionInfo.Timeout = System.TimeSpan.FromSeconds(15);
|
|
client.OperationTimeout = System.TimeSpan.FromSeconds(30);
|
|
client.KeepAliveInterval = System.TimeSpan.FromSeconds(10);
|
|
|
|
return client;
|
|
}
|
|
|
|
public static Renci.SshNet.ConnectionInfo BuildConnectionInfo(
|
|
string host,
|
|
int port,
|
|
string username,
|
|
string password,
|
|
Renci.SshNet.PrivateKeyFile privateKeyFile = null)
|
|
{
|
|
var auth = new System.Collections.Generic.List<Renci.SshNet.AuthenticationMethod>();
|
|
|
|
if (privateKeyFile != null)
|
|
auth.Add(new Renci.SshNet.PrivateKeyAuthenticationMethod(username, privateKeyFile));
|
|
|
|
if (!string.IsNullOrEmpty(password))
|
|
{
|
|
var kb = new Renci.SshNet.KeyboardInteractiveAuthenticationMethod(username);
|
|
kb.AuthenticationPrompt += (s, e) =>
|
|
{
|
|
foreach (var p in e.Prompts)
|
|
p.Response = password;
|
|
};
|
|
auth.Add(kb);
|
|
|
|
auth.Add(new Renci.SshNet.PasswordAuthenticationMethod(username, password));
|
|
}
|
|
|
|
return new Renci.SshNet.ConnectionInfo(host, port, username, auth.ToArray())
|
|
{
|
|
Timeout = System.TimeSpan.FromSeconds(30),
|
|
RetryAttempts = 1
|
|
};
|
|
}
|
|
|
|
/*
|
|
public static bool ConnectWithRetries(
|
|
Renci.SshNet.ConnectionInfo info,
|
|
int maxAttempts,
|
|
int timeoutSeconds)
|
|
{
|
|
for (int i = 0; i < maxAttempts; i++)
|
|
{
|
|
if (TrySftpConnectWithHardTimeout(info, timeoutSeconds))
|
|
return true;
|
|
|
|
System.Threading.Thread.Sleep(5000);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
*/
|
|
public static Renci.SshNet.SftpClient TrySftpConnectWithHardTimeout(
|
|
Renci.SshNet.ConnectionInfo connectionInfo,
|
|
int maxAttempts,
|
|
int timeoutSeconds)
|
|
{
|
|
for (int i = 0; i < maxAttempts; i++)
|
|
{
|
|
|
|
Renci.SshNet.SftpClient client = null;
|
|
|
|
try
|
|
{
|
|
var task = System.Threading.Tasks.Task.Run(() =>
|
|
{
|
|
client = new Renci.SshNet.SftpClient(connectionInfo);
|
|
|
|
// These are still useful, but not sufficient alone
|
|
client.ConnectionInfo.Timeout =
|
|
System.TimeSpan.FromSeconds(30);
|
|
|
|
client.KeepAliveInterval =
|
|
System.TimeSpan.FromSeconds(15);
|
|
|
|
client.Connect();
|
|
});
|
|
|
|
bool completed =
|
|
task.Wait(System.TimeSpan.FromSeconds(timeoutSeconds));
|
|
|
|
if (!completed)
|
|
{
|
|
// HARD TIMEOUT
|
|
try
|
|
{
|
|
client?.Dispose();
|
|
}
|
|
catch { }
|
|
|
|
//return null;
|
|
}
|
|
else
|
|
{
|
|
return client;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
try
|
|
{
|
|
client?.Dispose();
|
|
}
|
|
catch { }
|
|
|
|
//return null;
|
|
}
|
|
|
|
System.Threading.Thread.Sleep(5000);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
public static void Upload_stream(MemoryStream ms, string filename, string host, int port, string username, string password)
|
|
{
|
|
int maxAttempts = 5;
|
|
int timeout = 120; //seconds
|
|
|
|
try
|
|
{
|
|
//using (var sftpClient = CreateClient(host, port, username, password))
|
|
var sftpInfo = BuildConnectionInfo(host, port, username, password);
|
|
Renci.SshNet.SftpClient sftpClient = null;
|
|
try
|
|
{
|
|
sftpClient = TrySftpConnectWithHardTimeout(sftpInfo, maxAttempts, timeout);
|
|
}
|
|
catch (Renci.SshNet.Common.SshConnectionException e)
|
|
{
|
|
Logger.Log(1, " connection exception ({0}) : {1}", "", e.Message);
|
|
}
|
|
|
|
if ( sftpClient == null)
|
|
{
|
|
Logger.Log(1, " null connection exception. Transfer failed.");
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
sftpClient.UploadFile(
|
|
ms,
|
|
filename,
|
|
uploaded =>
|
|
{
|
|
Logger.Log(5, $"Uploaded {(double)uploaded / ms.Length * 100}% of the file.");
|
|
});
|
|
}
|
|
catch (Renci.SshNet.Common.SshException e)
|
|
{
|
|
Logger.Log(0, " SSH upload Exception {0}:{1}", e.Message, e.InnerException.Message);
|
|
}
|
|
Logger.Log(1, " -- uploaded: {0} ({3}KB) to {1}:{2}", filename, host, port, (ms.Length / 1024));
|
|
|
|
sftpClient.Disconnect();
|
|
Logger.Log(" SSH Disconnected");
|
|
try
|
|
{
|
|
sftpClient?.Dispose();
|
|
}
|
|
catch { }
|
|
|
|
return; // success
|
|
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Logger.Log(0, "SFTP exception {0}:{1}", e.Message, e.InnerException.Message);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public static void Upload_stream_linear(MemoryStream ms, string filename, string host, int port, string username, string password)
|
|
{
|
|
|
|
int attempts = 0;
|
|
int maxAttempts = 5;
|
|
|
|
while (true)
|
|
{
|
|
try
|
|
{
|
|
using (var sftpClient = CreateClient(host, port, username, password))
|
|
{
|
|
attempts++;
|
|
try
|
|
{
|
|
sftpClient.Connect();
|
|
}
|
|
catch (Renci.SshNet.Common.SshConnectionException e)
|
|
{
|
|
Logger.Log(1, " connection exception ({0}) : {1}", attempts, e.Message);
|
|
}
|
|
|
|
//------------
|
|
if (!sftpClient.IsConnected)
|
|
{
|
|
Logger.Log(1, " connection failure {0}", attempts);
|
|
if (attempts < 10) { Thread.Sleep(TimeSpan.FromSeconds(5)); continue; } else { break; };
|
|
}
|
|
|
|
try
|
|
{
|
|
sftpClient.UploadFile(
|
|
ms,
|
|
filename,
|
|
uploaded =>
|
|
{
|
|
Logger.Log(5, $"Uploaded {(double)uploaded / ms.Length * 100}% of the file.");
|
|
});
|
|
}
|
|
catch (Renci.SshNet.Common.SshException e)
|
|
{
|
|
Logger.Log(0, " SSH upload Exception {0}:{1}", e.Message, e.InnerException.Message);
|
|
}
|
|
Logger.Log(1, " -- uploaded: {0} ({3}KB) to {1}:{2}", filename, host, port, (ms.Length / 1024));
|
|
sftpClient.Disconnect();
|
|
Logger.Log(" SSH Disconnected");
|
|
return; // success
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Logger.Log(0, "SFTP exception {0}:{1}", e.Message, e.InnerException.Message);
|
|
}
|
|
|
|
attempts++;
|
|
if (attempts >= maxAttempts)
|
|
{
|
|
Logger.Log(0, ("Failed to Connect after 10 attempts."));
|
|
return;
|
|
}
|
|
Logger.Log(1, " ...retrying ({0})", attempts);
|
|
Thread.Sleep(TimeSpan.FromSeconds(5));
|
|
} // end of while true/do forever
|
|
}
|
|
|
|
public static void Upload_stream_old( MemoryStream ms, string filename, string host, int port, string username, string password)
|
|
{
|
|
try
|
|
{
|
|
using (var sftpClient = new SftpClient(host, port, username, password))
|
|
//using (var fs = new FileStream(fileToUpload, FileMode.Open))
|
|
{
|
|
sftpClient.OperationTimeout = TimeSpan.FromSeconds(30);
|
|
sftpClient.ConnectionInfo.Timeout = TimeSpan.FromSeconds(30);
|
|
|
|
int attempts = 0;
|
|
do
|
|
{
|
|
attempts++;
|
|
try
|
|
{
|
|
sftpClient.Connect();
|
|
}
|
|
catch (Renci.SshNet.Common.SshConnectionException e)
|
|
{
|
|
Logger.Log(1," retrying ({0}) : {1}",attempts, e.Message);
|
|
Thread.Sleep(TimeSpan.FromSeconds(5));
|
|
}
|
|
}
|
|
while (attempts < 10 && !sftpClient.IsConnected);
|
|
|
|
if (attempts >= 10)
|
|
{
|
|
throw new Exception("Failed to Connect after 10 attempts.");
|
|
}
|
|
else
|
|
{
|
|
|
|
Logger.Log(" SSH Connected");
|
|
|
|
try
|
|
{
|
|
sftpClient.UploadFile(
|
|
ms,
|
|
filename,
|
|
uploaded =>
|
|
{
|
|
Logger.Log(5, $"Uploaded {(double)uploaded / ms.Length * 100}% of the file.");
|
|
});
|
|
}
|
|
catch (Renci.SshNet.Common.SshException e)
|
|
{
|
|
Logger.Log(0, " SSH upload Exception {0}:{1}", e.Message, e.InnerException.Message);
|
|
}
|
|
Logger.Log(" SSH Disconnected");
|
|
sftpClient.Disconnect();
|
|
}
|
|
|
|
}
|
|
Logger.Log(1, " -- uploaded: {0} ({3}KB) to {1}:{2}", filename, host, port, ( ms.Length/1024) );
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Logger.Log(e.Message);
|
|
}
|
|
}
|
|
|
|
public static void Upload_file(string fileToUpload, string host, int port, string username, string password)
|
|
{
|
|
try
|
|
{
|
|
using (var sftpClient = new SftpClient(host, port, username, password))
|
|
using (var fs = new FileStream(fileToUpload, FileMode.Open))
|
|
{
|
|
sftpClient.OperationTimeout = TimeSpan.FromSeconds(30);
|
|
int attempts = 0;
|
|
do
|
|
{
|
|
try
|
|
{
|
|
attempts += 1;
|
|
sftpClient.Connect();
|
|
}
|
|
catch (Renci.SshNet.Common.SshConnectionException e)
|
|
{
|
|
Logger.Log(1, " retrying in 5s ({0}) : {1}", attempts, e.Message);
|
|
Thread.Sleep(TimeSpan.FromSeconds(5));
|
|
}
|
|
} while (attempts < 10 && !sftpClient.IsConnected);
|
|
Logger.Log(" SSH Connected");
|
|
|
|
try
|
|
{
|
|
sftpClient.UploadFile(
|
|
fs,
|
|
"/Doug/" + Path.GetFileName(fileToUpload),
|
|
uploaded =>
|
|
{
|
|
Logger.Log(5,$"Uploaded {(double)uploaded / fs.Length * 100}% of the file.");
|
|
});
|
|
}
|
|
catch (Renci.SshNet.Common.SshException e)
|
|
{
|
|
Logger.Log(0, " SSH Exception {0}:{1}", e.Message, e.InnerException.Message);
|
|
}
|
|
|
|
sftpClient.Disconnect();
|
|
}
|
|
Logger.Log(1," uploaded: {0}", fileToUpload);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine(e.Message);
|
|
}
|
|
}
|
|
}
|
|
} |