aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/SPConnectionHandler.m10
-rw-r--r--Source/SPSSHTunnel.h4
-rw-r--r--Source/SPSSHTunnel.m39
3 files changed, 42 insertions, 11 deletions
diff --git a/Source/SPConnectionHandler.m b/Source/SPConnectionHandler.m
index 0634df68..d930a299 100644
--- a/Source/SPConnectionHandler.m
+++ b/Source/SPConnectionHandler.m
@@ -357,7 +357,7 @@ static NSString *SPLocalhostAddress = @"127.0.0.1";
NSInteger newState = [theTunnel state];
- // If the user cancelled the password prompt dialog
+ // If the user cancelled the password prompt dialog, continue with no further action.
if ([theTunnel passwordPromptCancelled]) {
[self _restoreConnectionInterface];
@@ -365,6 +365,14 @@ static NSString *SPLocalhostAddress = @"127.0.0.1";
}
if (newState == SPMySQLProxyIdle) {
+
+ // If the connection closed unexpectedly, and muxing was enabled, disable muxing an re-try.
+ if ([theTunnel taskExitedUnexpectedly] && [theTunnel connectionMuxingEnabled]) {
+ [theTunnel setConnectionMuxingEnabled:NO];
+ [theTunnel connect];
+ return;
+ }
+
#ifndef SP_REFACTOR
[dbDocument setTitlebarStatus:NSLocalizedString(@"SSH Disconnected", @"SSH disconnected titlebar marker")];
#endif
diff --git a/Source/SPSSHTunnel.h b/Source/SPSSHTunnel.h
index b59acfe2..25a98cc4 100644
--- a/Source/SPSSHTunnel.h
+++ b/Source/SPSSHTunnel.h
@@ -67,9 +67,11 @@
SEL stateChangeSelector;
BOOL useHostFallback;
+ BOOL connectionMuxingEnabled;
BOOL requestedResponse;
BOOL passwordInKeychain;
BOOL passwordPromptCancelled;
+ BOOL taskExitedUnexpectedly;
IBOutlet NSWindow *sshQuestionDialog;
IBOutlet NSTextField *sshQuestionText;
@@ -80,6 +82,8 @@
}
@property (readonly) BOOL passwordPromptCancelled;
+@property (readwrite) BOOL connectionMuxingEnabled;
+@property (readonly) BOOL taskExitedUnexpectedly;
- (id)initToHost:(NSString *)theHost port:(NSInteger)thePort login:(NSString *)theLogin tunnellingToPort:(NSInteger)targetPort onHost:(NSString *)targetHost;
- (BOOL)setConnectionStateChangeSelector:(SEL)theStateChangeSelector delegate:(id)theDelegate;
diff --git a/Source/SPSSHTunnel.m b/Source/SPSSHTunnel.m
index 467c43fc..60a8cf84 100644
--- a/Source/SPSSHTunnel.m
+++ b/Source/SPSSHTunnel.m
@@ -44,6 +44,8 @@
@implementation SPSSHTunnel
@synthesize passwordPromptCancelled;
+@synthesize connectionMuxingEnabled;
+@synthesize taskExitedUnexpectedly;
/*
* Initialise with the supplied connection details. Host, login and port should all be provided.
@@ -67,6 +69,7 @@
delegate = nil;
stateChangeSelector = nil;
lastError = nil;
+ connectionMuxingEnabled = YES;
debugMessages = [[NSMutableArray alloc] init];
debugMessagesLock = [[NSLock alloc] init];
answerAvailableLock = [[NSLock alloc] init];
@@ -216,9 +219,12 @@
localPort = 0;
if (connectionState != SPMySQLProxyIdle) return;
+
[debugMessagesLock lock];
[debugMessages removeAllObjects];
[debugMessagesLock unlock];
+ taskExitedUnexpectedly = NO;
+
[NSThread detachNewThreadWithName:@"SPSSHTunnel SSH binary communication task" target:self selector:@selector(launchTask:) object:nil];
}
@@ -309,19 +315,26 @@
// Enable verbose mode for message parsing
[taskArguments addObject:@"-v"];
- // Ensure that the muxed connection can be used for only tunnels, not interactive
+ // Ensure that the connection can be used for only tunnels, not interactive
[taskArguments addObject:@"-N"];
- // Enable automatic connection muxing/sharing, for faster connections
- [taskArguments addObject:@"-o ControlMaster=auto"];
+ if (connectionMuxingEnabled) {
- // Set a custom control path to isolate connection sharing to Sequel Pro, to prevent picking up
- // existing masters without forwarding enabled and to isolate from interactive sessions. Use a short
- // hashed path to aid length limit issues.
- unsigned char hashedPathResult[16];
- NSString *pathString = [NSString stringWithFormat:@"%@@%@:%ld", sshLogin?sshLogin:@"", sshHost, sshPort?sshPort:0];
- CC_MD5([pathString UTF8String], (unsigned int)strlen([pathString UTF8String]), hashedPathResult);
- [taskArguments addObject:[NSString stringWithFormat:@"-o ControlPath=%@/SPSSH-%@", [NSFileManager temporaryDirectory], [[[NSData dataWithBytes:hashedPathResult length:16] dataToHexString] substringToIndex:8]]];
+ // Enable automatic connection muxing/sharing, for faster connections
+ [taskArguments addObject:@"-o ControlMaster=auto"];
+
+ // Set a custom control path to isolate connection sharing to Sequel Pro, to prevent picking up
+ // existing masters without forwarding enabled and to isolate from interactive sessions. Use a short
+ // hashed path to aid length limit issues.
+ unsigned char hashedPathResult[16];
+ NSString *pathString = [NSString stringWithFormat:@"%@@%@:%ld", sshLogin?sshLogin:@"", sshHost, sshPort?sshPort:0];
+ CC_MD5([pathString UTF8String], (unsigned int)strlen([pathString UTF8String]), hashedPathResult);
+ [taskArguments addObject:[NSString stringWithFormat:@"-o ControlPath=%@/SPSSH-%@", [NSFileManager temporaryDirectory], [[[NSData dataWithBytes:hashedPathResult length:16] dataToHexString] substringToIndex:8]]];
+ } else {
+
+ // Disable muxing if requested
+ [taskArguments addObject:@"-o ControlMaster=no"];
+ }
// If the port forwarding fails, exit - as this is the primary use case for the instance
[taskArguments addObject:@"-o ExitOnForwardFailure=yes"];
@@ -381,6 +394,11 @@
}
[task setEnvironment:taskEnvironment];
+ // Add the connection details to the debug messages
+ [debugMessagesLock lock];
+ [debugMessages addObject:[NSString stringWithFormat:@"Used command: %@ %@\n", [task launchPath], [[task arguments] componentsJoinedByString:@" "]]];
+ [debugMessagesLock unlock];
+
// Set up the standard error pipe
standardError = [[NSPipe alloc] init];
[task setStandardError:standardError];
@@ -406,6 +424,7 @@
// If the task closed unexpectedly, alert appropriately
if (connectionState != SPMySQLProxyIdle) {
connectionState = SPMySQLProxyIdle;
+ taskExitedUnexpectedly = YES;
if (lastError) [lastError release];
lastError = [[NSString alloc] initWithString:NSLocalizedString(@"The SSH Tunnel has unexpectedly closed.", @"SSH tunnel unexpectedly closed")];
if (delegate) [delegate performSelectorOnMainThread:stateChangeSelector withObject:self waitUntilDone:NO];