Skip to content

Commit

Permalink
Much better disconnect support for new SSH library behavior.
Browse files Browse the repository at this point in the history
Show taskbar as red on error.
Updated ssh library.
  • Loading branch information
mitchcapper committed Apr 8, 2017
1 parent e3651bc commit 8175393
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 60 deletions.
7 changes: 6 additions & 1 deletion MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ public MainWindow() {

private static MainWindow instance;
public static void ShowMessage(string message, string caption) {
instance.Dispatcher.BeginInvoke((Action) (() => MessageBox.Show(message, caption)));
instance.Dispatcher.Invoke(() => {
instance.TaskbarItemInfo.ProgressState = TaskbarItemProgressState.Error;
instance.TaskbarItemInfo.ProgressValue = 100;
MessageBox.Show(instance, message, caption);
instance.TaskbarItemInfo.ProgressState = TaskbarItemProgressState.None;
});
}

void MainWindow_Loaded(object sender, RoutedEventArgs e) {
Expand Down
112 changes: 62 additions & 50 deletions Model/SFTPFileUploader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public SFTPFileUploader() {
private SftpClient client;
private string base_path;
private int base_path_len;
public void connect(String host, int port, String user, String local_path, String remote_path, String password) {
public async Task connect(String host, int port, String user, String local_path, String remote_path, String password) {
base_path = local_path;
base_path_len = (base_path.EndsWith("/") || base_path.EndsWith("\\")) ? base_path.Length : base_path.Length + 1; //if it doesnt end in a slash we need to skip it
if (String.IsNullOrWhiteSpace(user)) {
Expand All @@ -47,13 +47,13 @@ public void connect(String host, int port, String user, String local_path, Strin
client.ChangeDirectory(remote_path);
ConnChanged();
} catch (SocketException e) {
disconnect();
await disconnect();
MainWindow.ShowMessage("Unable to connect due to socket exception of: " + e.Message, "Connection Error");
} catch (SshAuthenticationException e) {
disconnect();
await disconnect();
MainWindow.ShowMessage("Unable to connect due to auth exception of: " + e.Message, "Connection Error");
} catch (SftpPathNotFoundException) {
disconnect();
await disconnect();
MainWindow.ShowMessage("Unable to switch to remote folder of: " + remote_path + " as it doesn't exist", "Connection Error");
}
}
Expand All @@ -65,17 +65,17 @@ private void ConnChanged() {
public bool is_connected {
get { return client != null && client.IsConnected; }
}
void client_ErrorOccurred(object sender, Renci.SshNet.Common.ExceptionEventArgs e) {
async void client_ErrorOccurred(object sender, Renci.SshNet.Common.ExceptionEventArgs e) {
try {
throw e.Exception;
} catch (SocketException exp) {
disconnect();
await disconnect();
MainWindow.ShowMessage("Connection lost due to " + exp.SocketErrorCode + ": " + exp.Message, "Connection Error");
} catch (SshConnectionException ss_exp) {
disconnect();
await disconnect();
MainWindow.ShowMessage("Connection issue due to " + ss_exp.DisconnectReason + ": " + ss_exp.Message, "Connection Error");
} catch (Exception ee) {
disconnect();
await disconnect();
if (Debugger.IsAttached)
throw ee;
MainWindow.ShowMessage("unknown error let us know: " + ee.Message, "Unknown Error");
Expand All @@ -88,43 +88,48 @@ private void UploadCallback(ulong progress, ulong total_size) {
UploadEvtProgress(this, evt);
}
ConcurrentQueue<string> CurQueue = new ConcurrentQueue<string>();
private async void UploadLoop() {
private void UploadLoop() {//don't make async as then lose thread name
string file;
string last_file = null;
int was_connected_cnt = 0;
while (true) {
while (CurQueue.TryDequeue(out file)) {
if (!is_connected) {
was_connected_cnt = 0;
CurQueue = new ConcurrentQueue<string>();
disconnect();
MainWindow.ShowMessage("Connection to server lost.", "Lost Connection");//maybe not supposed to ever happen? should have been caught sooner
break;
}
was_connected_cnt = 1;
if (file == last_file)
await Task.Delay(50);
last_file = file;
if ((DateTime.Now - last_changed[file]).TotalMilliseconds < 50) {
CurQueue.Enqueue(file);
continue;
}
var remote_name = file.Substring(base_path_len);
remote_name = remote_name.Replace('\\', '/');
if (CurQueue.Contains(file))//continue if it was added to the queue again since we started
continue;
await UploadFile(file, remote_name);
if (!CurQueue.Contains(file))
last_changed.Remove(file);
try {
while (CurQueue.TryDequeue(out file)) {
if (!is_connected) {
was_connected_cnt = 0;
CurQueue = new ConcurrentQueue<string>();
disconnect().Wait();
MainWindow.ShowMessage("Connection to server lost.", "Lost Connection"); //maybe not supposed to ever happen? should have been caught sooner
break;
}
was_connected_cnt = 1;
if (file == last_file)
Task.Delay(50).Wait();
last_file = file;
if ((DateTime.Now - last_changed[file]).TotalMilliseconds < 50) {
CurQueue.Enqueue(file);
continue;
}
var remote_name = file.Substring(base_path_len);
remote_name = remote_name.Replace('\\', '/');
if (CurQueue.Contains(file)) //continue if it was added to the queue again since we started
continue;
UploadFile(file, remote_name).Wait();
if (!CurQueue.Contains(file))
last_changed.Remove(file);

}
bool is_conn = false;
if (was_connected_cnt > 0 && was_connected_cnt++ < 60 * 100 || (is_conn = is_connected)) {
//so isconnected is a bit of a possible costly call so lets not call it every 50ms. Lets cache for up to 5 minutes
if (is_conn)
was_connected_cnt = 1;
Task.Delay(50).Wait();
} else
Task.Delay(1000).Wait();
}catch(Exception e) {
MessageBox.Show("Exception in upload loop should attach debugger and figure out why this is not caught currently: " + e.Message + "\n" + e.StackTrace);
}
bool is_conn = false;
if (was_connected_cnt > 0 && was_connected_cnt++ < 60 * 100 || (is_conn = is_connected)) { //so isconnected is a bit of a possible costly call so lets not call it every 50ms. Lets cache for up to 5 minutes
if (is_conn)
was_connected_cnt = 1;
await Task.Delay(50);
} else
await Task.Delay(1000);
}
}
private async Task UploadFile(String filename, String remote_name) {
Expand All @@ -143,31 +148,38 @@ private async Task UploadFile(String filename, String remote_name) {
}
throw e;
} catch (SshConnectionException e) {
disconnect();
await disconnect();
MainWindow.ShowMessage("Connection to server lost details: " + e.Message, "Lost Connection");
} catch (SftpPermissionDeniedException e) {
disconnect();
await disconnect();
MainWindow.ShowMessage("Permission denied trying to upload due to: " + e.Message, "Permission Error");
} catch (SftpPathNotFoundException) {
disconnect();
MainWindow.ShowMessage("Remote file not found, most likely invalid remote path(make sure folder exists)", "Path Not Found Error");
} catch (SftpPathNotFoundException e) {
await disconnect();
MainWindow.ShowMessage($"Remote file not accessible, most likely invalid remote path(make sure folder exists): {remote_name}", "Path Not Found Error");
} catch (SshException e) {
if (e.Message == "Channel was closed.") {
disconnect();
await disconnect();
MainWindow.ShowMessage("Connection to server lost details: " + e.Message, "Lost Connection");
} else if (e.Message == "Failure.") {
disconnect();
await disconnect();
MainWindow.ShowMessage("General failure from SSH Libary", "General Failure");
} else
throw e;
}
}
public void disconnect() {
public async Task disconnect() {
if (client != null) {
try {
client.Disconnect();
if (client.IsConnected)
client.Disconnect();
var tsk = Task.Run(() => {
if (client.IsConnected) //otherwise it can hang forever
client.Disconnect();
if (client.IsConnected)
client.Disconnect();
});
await Task.WhenAny(tsk, Task.Delay(60 * 1000));
if (!tsk.IsCompleted) {
MessageBox.Show("Prevented a hang on disconnect");
}
} catch (Exception e) {
Debug.WriteLine("Unable to disconnect due to: " + e.Message);
}
Expand Down
2 changes: 1 addition & 1 deletion NovaSFTP2.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>6</ApplicationRevision>
<ApplicationRevision>7</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
Expand Down
16 changes: 8 additions & 8 deletions ViewModel/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,23 +97,23 @@ private void UpdateButton() {
title = t_str;

}
private void connect() {
uploader.connect(hostname, port, username, local_folder, remote_folder, password);
private async Task connect() {
await uploader.connect(hostname, port, username, local_folder, remote_folder, password);

if (String.IsNullOrWhiteSpace(selected_host?.name) == false)
UpdateRecent(selected_host.name);
}
private void disconnect() {
private async Task disconnect() {
StopWatcher();
uploader.disconnect();
await uploader.disconnect();
}
private bool connected { get { return uploader.is_connected; } }
public ICommand ToggleConnectedCmd => new OurCommand(ToggleConnected,true,true);
private void ToggleConnected() {
public ICommand ToggleConnectedCmd => new OurCommand(ToggleConnected,true);
private async Task ToggleConnected() {
if (connected)
disconnect();
await disconnect();
else
connect();
await Task.Run(async ()=> await connect());
}
private void FileChanged(object sender, FileSystemEventArgs args) {
if (args.ChangeType == WatcherChangeTypes.Deleted)
Expand Down
Binary file modified lib_bins/Renci.SshNet.dll
Binary file not shown.

0 comments on commit 8175393

Please sign in to comment.