Compare commits

..

No commits in common. "main" and "v2.42.0-feature-mobile-control-https-wss-support.1" have entirely different histories.

4 changed files with 32 additions and 39 deletions

View file

@ -1,6 +1,6 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<Version>2.42.1-local</Version> <Version>2.36.6-local</Version>
<InformationalVersion>$(Version)</InformationalVersion> <InformationalVersion>$(Version)</InformationalVersion>
<Authors>PepperDash Technology</Authors> <Authors>PepperDash Technology</Authors>
<Company>PepperDash Technology</Company> <Company>PepperDash Technology</Company>

View file

@ -151,8 +151,6 @@ namespace PepperDash.Core
// Thread-safety lock for state changes // Thread-safety lock for state changes
private readonly object _stateLock = new object(); private readonly object _stateLock = new object();
private volatile bool _isProgramStopping;
private bool disconnectLogged = false; private bool disconnectLogged = false;
/// <summary> /// <summary>
@ -209,11 +207,13 @@ namespace PepperDash.Core
{ {
if (programEventType == eProgramStatusEventType.Stopping) if (programEventType == eProgramStatusEventType.Stopping)
{ {
_isProgramStopping = true; if (client != null)
{
this.LogDebug("Program stopping. Closing connection"); this.LogDebug("Program stopping. Closing connection");
Disconnect(); Disconnect();
} }
} }
}
/// <summary> /// <summary>
/// Connect method /// Connect method
@ -228,12 +228,6 @@ namespace PepperDash.Core
return; return;
} }
if (_isProgramStopping)
{
this.LogDebug("Skipping connect because program is stopping");
return;
}
ConnectEnabled = true; ConnectEnabled = true;
try try
@ -293,7 +287,13 @@ namespace PepperDash.Core
} }
catch (SshConnectionException e) catch (SshConnectionException e)
{ {
var ie = e.InnerException; // The details are inside, when present - remote can close the connection with no inner exception at all var ie = e.InnerException; // The details are inside!!
if (ie is SocketException)
{
this.LogError("CONNECTION failure: Cannot reach host");
this.LogVerbose(ie, "Exception details: ");
}
if (ie is System.Net.Sockets.SocketException socketException) if (ie is System.Net.Sockets.SocketException socketException)
{ {
@ -301,20 +301,20 @@ namespace PepperDash.Core
Hostname, Port); Hostname, Port);
this.LogVerbose(socketException, "SocketException details: "); this.LogVerbose(socketException, "SocketException details: ");
} }
else if (ie is SshAuthenticationException) if (ie is SshAuthenticationException)
{ {
this.LogError("Authentication failure for username {userName}", Username); this.LogError("Authentication failure for username {userName}", Username);
this.LogVerbose(ie, "AuthenticationException details: "); this.LogVerbose(ie, "AuthenticationException details: ");
} }
else else
{ {
this.LogError("Error on connect: {error}", ie?.Message ?? e.Message); this.LogError("Error on connect: {error}", ie.Message);
this.LogVerbose(ie ?? e, "Exception details: "); this.LogVerbose(ie, "Exception details: ");
} }
disconnectLogged = true; disconnectLogged = true;
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
if (AutoReconnect && ConnectEnabled && !_isProgramStopping) if (AutoReconnect)
{ {
this.LogDebug("Checking autoreconnect: {autoReconnect}, {autoReconnectInterval}ms", AutoReconnect, AutoReconnectIntervalMs); this.LogDebug("Checking autoreconnect: {autoReconnect}, {autoReconnectInterval}ms", AutoReconnect, AutoReconnectIntervalMs);
StartReconnectTimer(); StartReconnectTimer();
@ -326,7 +326,7 @@ namespace PepperDash.Core
disconnectLogged = true; disconnectLogged = true;
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
if (AutoReconnect && ConnectEnabled && !_isProgramStopping) if (AutoReconnect)
{ {
this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs); this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs);
StartReconnectTimer(); StartReconnectTimer();
@ -338,7 +338,7 @@ namespace PepperDash.Core
this.LogVerbose(e, "Exception details: "); this.LogVerbose(e, "Exception details: ");
disconnectLogged = true; disconnectLogged = true;
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
if (AutoReconnect && ConnectEnabled && !_isProgramStopping) if (AutoReconnect)
{ {
this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs); this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs);
StartReconnectTimer(); StartReconnectTimer();
@ -473,7 +473,7 @@ namespace PepperDash.Core
{ {
connectLock.Release(); connectLock.Release();
} }
if (AutoReconnect && ConnectEnabled && !_isProgramStopping) if (AutoReconnect && ConnectEnabled)
{ {
this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs); this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs);
StartReconnectTimer(); StartReconnectTimer();
@ -516,11 +516,8 @@ namespace PepperDash.Core
this.LogError("ObjectDisposedException sending '{message}'. Restarting connection...", text.Trim()); this.LogError("ObjectDisposedException sending '{message}'. Restarting connection...", text.Trim());
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
if (AutoReconnect && ConnectEnabled && !_isProgramStopping)
{
StartReconnectTimer(); StartReconnectTimer();
} }
}
catch (Exception ex) catch (Exception ex)
{ {
this.LogException(ex, "Exception sending text: '{message}'", text); this.LogException(ex, "Exception sending text: '{message}'", text);
@ -552,11 +549,8 @@ namespace PepperDash.Core
this.LogException(ex, "ObjectDisposedException sending {message}", ComTextHelper.GetEscapedText(bytes)); this.LogException(ex, "ObjectDisposedException sending {message}", ComTextHelper.GetEscapedText(bytes));
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
if (AutoReconnect && ConnectEnabled && !_isProgramStopping)
{
StartReconnectTimer(); StartReconnectTimer();
} }
}
catch (Exception ex) catch (Exception ex)
{ {
this.LogException(ex, "Exception sending {message}", ComTextHelper.GetEscapedText(bytes)); this.LogException(ex, "Exception sending {message}", ComTextHelper.GetEscapedText(bytes));

View file

@ -554,6 +554,13 @@ namespace PepperDash.Essentials.Touchpanel
return false; return false;
}) ? csIpAddress.ToString() : processorIp; }) ? csIpAddress.ToString() : processorIp;
var match = Regex.Match(url, @"^(https?)://([^:/]+):\d+/mc/app\?token=.+$");
if (match.Success)
{
string ipa = match.Groups[2].Value;
// ip will be "192.168.1.100"
}
// replace the host but preserve whatever scheme (http/https) is already present in the URL // replace the host but preserve whatever scheme (http/https) is already present in the URL
var updatedUrl = Regex.Replace(url, @"^(https?)://[^:/]+", $"$1://{ip}"); var updatedUrl = Regex.Replace(url, @"^(https?)://[^:/]+", $"$1://{ip}");

View file

@ -414,7 +414,7 @@ namespace PepperDash.Essentials.WebSocketServer
ip = csIpAddress.ToString(); ip = csIpAddress.ToString();
} }
var appUrl = $"{HttpScheme}://{ip}:{Port}/mc/app?token={touchpanel.Key}"; var appUrl = $"{HttpScheme}://{ip}:{_parent.Config.DirectServer.Port}/mc/app?token={touchpanel.Key}";
this.LogVerbose("Sending URL {appUrl} to touchpanel {touchpanelKey}", appUrl, touchpanel.Touchpanel.Key); this.LogVerbose("Sending URL {appUrl} to touchpanel {touchpanelKey}", appUrl, touchpanel.Touchpanel.Key);
@ -498,7 +498,7 @@ namespace PepperDash.Essentials.WebSocketServer
{ {
var config = new MobileControlApplicationConfig var config = new MobileControlApplicationConfig
{ {
ApiPath = string.Format("{0}://{1}:{2}/mc/api", HttpScheme, processorIp, Port), ApiPath = string.Format("{0}://{1}:{2}/mc/api", HttpScheme, processorIp, _parent.Config.DirectServer.Port),
GatewayAppPath = "", GatewayAppPath = "",
LogoPath = _parent.Config.ApplicationConfig?.LogoPath ?? "logo/logo.png", LogoPath = _parent.Config.ApplicationConfig?.LogoPath ?? "logo/logo.png",
EnableDev = _parent.Config.ApplicationConfig?.EnableDev ?? false, EnableDev = _parent.Config.ApplicationConfig?.EnableDev ?? false,
@ -1109,8 +1109,7 @@ namespace PepperDash.Essentials.WebSocketServer
res.StatusCode = 200; res.StatusCode = 200;
res.Close(); res.Close();
// remote log collector has no dedicated secure flag; keep it on http regardless of DirectServer.Secure var logRequest = new HttpRequestMessage(HttpMethod.Post, $"{HttpScheme}://{_parent.Config.DirectServer.Logging.Host}:{_parent.Config.DirectServer.Logging.Port}/logs")
var logRequest = new HttpRequestMessage(HttpMethod.Post, $"http://{_parent.Config.DirectServer.Logging.Host}:{_parent.Config.DirectServer.Logging.Port}/logs")
{ {
Content = new StringContent(body, Encoding.UTF8, "application/json"), Content = new StringContent(body, Encoding.UTF8, "application/json"),
}; };
@ -1162,11 +1161,6 @@ namespace PepperDash.Essentials.WebSocketServer
var qp = req.QueryString; var qp = req.QueryString;
var token = qp["token"]; var token = qp["token"];
// Each join mints a single-use clientId; the panel webview must never replay a cached
// response, or it reconnects forever with an already-consumed id (1008 loop).
res.Headers.Add("Cache-Control", "no-store");
res.Headers.Add("Pragma", "no-cache");
this.LogVerbose("Join Room Request with token: {token}", token); this.LogVerbose("Join Room Request with token: {token}", token);
byte[] body; byte[] body;
@ -1268,8 +1262,6 @@ namespace PepperDash.Essentials.WebSocketServer
{ {
res.StatusCode = 200; res.StatusCode = 200;
res.ContentType = "application/json"; res.ContentType = "application/json";
res.Headers.Add("Cache-Control", "no-store");
res.Headers.Add("Pragma", "no-cache");
var version = new Version() { ServerVersion = _parent.GetConfigWithPluginVersion().RuntimeInfo.PluginVersion }; var version = new Version() { ServerVersion = _parent.GetConfigWithPluginVersion().RuntimeInfo.PluginVersion };
var message = JsonConvert.SerializeObject(version); var message = JsonConvert.SerializeObject(version);
this.LogVerbose("{message}", message); this.LogVerbose("{message}", message);