Skip to content

Commit 8f43544

Browse files
shanselmanCopilot
andcommitted
fix: signature fallback retries connect, SSH tunnel auto-restart (closes #131, #132)
#131: Store challenge nonce and re-send connect message after advancing signature mode on 'device signature invalid' rejection. Previously the client got stuck in Connecting state after mode fallback. #132: Clean up process/spec on unexpected SSH tunnel exit, raise TunnelExited event. App.xaml.cs subscribes and auto-restarts after 3s delay. Previously the tunnel stayed dead until manual intervention. Co-authored-by: Copilot <[email protected]>
1 parent 4ffd028 commit 8f43544

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

src/OpenClaw.Shared/OpenClawGatewayClient.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ private enum SignatureTokenMode
5353
private string _connectAuthToken;
5454
private SignatureTokenMode _signatureTokenMode = SignatureTokenMode.V3AuthToken;
5555
private long? _challengeTimestampMs;
56+
private string? _currentChallengeNonce;
5657
private bool _usageStatusUnsupported;
5758
private bool _usageCostUnsupported;
5859
private bool _sessionPreviewUnsupported;
@@ -788,6 +789,7 @@ private void HandleRequestError(string? method, JsonElement root)
788789
if (_signatureTokenMode != previousMode)
789790
{
790791
_logger.Warn($"Gateway rejected device signature with mode {previousMode}; retrying with mode {_signatureTokenMode}");
792+
_ = SendConnectMessageAsync(_currentChallengeNonce);
791793
return;
792794
}
793795

@@ -1125,6 +1127,7 @@ private void HandleConnectChallenge(JsonElement root)
11251127
}
11261128

11271129
_challengeTimestampMs = ts;
1130+
_currentChallengeNonce = nonce;
11281131

11291132
_logger.Info($"Received challenge, nonce: {nonce}");
11301133
_ = SendConnectMessageAsync(nonce);

src/OpenClaw.Tray.WinUI/App.xaml.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ protected override async void OnLaunched(LaunchActivatedEventArgs args)
270270
ToastNotificationManagerCompat.OnActivated += OnToastActivated;
271271

272272
_sshTunnelService = new SshTunnelService(new AppLogger());
273+
_sshTunnelService.TunnelExited += OnSshTunnelExited;
273274

274275
// First-run check
275276
if (string.IsNullOrWhiteSpace(_settings.Token))
@@ -2264,7 +2265,25 @@ _settings.SshTunnelRemotePort is < 1 or > 65535 ||
22642265

22652266
#endregion
22662267

2267-
private Microsoft.UI.Dispatching.DispatcherQueue? AppDispatcherQueue =>
2268+
private async void OnSshTunnelExited(object? sender, int exitCode)
2269+
{
2270+
Logger.Warn($"SSH tunnel exited unexpectedly (code {exitCode}); restarting in 3s...");
2271+
await Task.Delay(3000);
2272+
if (_sshTunnelService != null && _settings?.UseSshTunnel == true)
2273+
{
2274+
try
2275+
{
2276+
_sshTunnelService.EnsureStarted(_settings);
2277+
Logger.Info("SSH tunnel restarted successfully");
2278+
}
2279+
catch (Exception ex)
2280+
{
2281+
Logger.Error($"SSH tunnel restart failed: {ex.Message}");
2282+
}
2283+
}
2284+
}
2285+
2286+
private Microsoft.UI.Dispatching.DispatcherQueue? AppDispatcherQueue =>
22682287
Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
22692288
}
22702289

src/OpenClaw.Tray.WinUI/Services/SshTunnelService.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ public sealed class SshTunnelService : IDisposable
1616
private string? _lastSpec;
1717
private bool _stopping;
1818

19+
/// <summary>Raised when the SSH tunnel exits unexpectedly (not during shutdown).</summary>
20+
public event EventHandler<int>? TunnelExited;
21+
1922
public SshTunnelService(IOpenClawLogger logger)
2023
{
2124
_logger = logger;
@@ -130,6 +133,10 @@ private void StartProcess(string user, string host, int remotePort, int localPor
130133
else
131134
{
132135
_logger.Warn($"SSH tunnel exited unexpectedly (code {exitCode})");
136+
try { process.Dispose(); } catch { }
137+
_process = null;
138+
_lastSpec = null;
139+
TunnelExited?.Invoke(this, exitCode);
133140
}
134141
};
135142

0 commit comments

Comments
 (0)