Make the Console<->Launcher system source-built and modern now that the console is under our control and the WinXP-era pods are gone. Contract extraction (Contract/Tesla.Contract.csproj): - One multi-targeted (net48;net8.0-windows) source project for the RPC contract, replacing the vendored TeslaConsoleLaunchLib.dll and the hand-synced Tesla.Net replica in Launcher/LaunchModels_Shared.cs. Emits assembly TeslaConsoleLaunchLib. SecureConfig extraction (SecureConfig/Tesla.SecureConfig.csproj): - net48 source of the first-boot provisioning protocol (UDP beacons, OFB crypto, RSA key exchange), replacing the vendored TeslaSecureConfiguration.dll. Remove BinaryFormatter from the wire (RCE sink + the reason net6 was pinned): - Console<->Launcher RPC is now length-prefixed System.Text.Json frames (Contract/PodRpcProtocol.cs) over the unchanged OFB transport; dispatch by method name. Deleted the SerializationBinder / MethodInfoProxy machinery. - Console-local BinaryFormatter (Site config, mission replays) intentionally retained: local net48 file I/O, not the network surface. Runtime modernization: - Launcher Service + Agent: net6 -> net8, win-x86 -> win-x64 (all pods are 64-bit Win10). Kept the SHA1-default PBKDF2 (Console key-derivation compat) with SYSLIB0041 suppressed and documented. Tests: differential suite now 73 green. Added SecureConfigCompatTests (OFB ciphertext byte-identical to the vendored DLL) and PodRpcProtocolTests (JSON round-trip of every request/response shape); removed the now-obsolete BinaryFormatter byte-identity guard. Build hygiene: per-project obj dirs (Launcher/Directory.Build.props) fix a NuGet restore collision between the two Launcher projects sharing one folder. NOT runtime-verified against a live pod. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
177 lines
4.8 KiB
C#
177 lines
4.8 KiB
C#
// =============================================================================
|
|
// Tesla.Contract — Shared RPC Wire Contract (assembly: TeslaConsoleLaunchLib)
|
|
// =============================================================================
|
|
// Single source of truth for the Console <-> Launcher protocol. Previously this
|
|
// lived in two hand-synced places: the vendored binary
|
|
// Console/lib/TeslaConsoleLaunchLib.dll (consumed by the Console) and a manual
|
|
// replica in Launcher/LaunchModels_Shared.cs (consumed by the Launcher Service).
|
|
//
|
|
// The wire types below are reconstructed verbatim from the original
|
|
// TeslaConsoleLaunchLib.dll. Field NAMES, TYPES and ORDER are load-bearing:
|
|
// they are serialized with BinaryFormatter and must match byte-for-byte or the
|
|
// protocol breaks silently at runtime. The byte-identical guarantee is asserted
|
|
// by WireContractCompatTests in the differential suite.
|
|
//
|
|
// This file is compiled for BOTH net48 (Console) and net6.0-windows (Launcher).
|
|
// The TCP/OFB/BinaryFormatter client (PodManagerConnection) is net48-only and
|
|
// lives under Client/ — it depends on TeslaSecureConfiguration.dll.
|
|
// =============================================================================
|
|
|
|
using System;
|
|
using System.Net;
|
|
using System.Reflection;
|
|
|
|
namespace Tesla.Net
|
|
{
|
|
/// <summary>App identifier + display name pair.</summary>
|
|
[Serializable]
|
|
public struct LaunchPair
|
|
{
|
|
public Guid LaunchKey;
|
|
|
|
public string DisplayName;
|
|
}
|
|
|
|
/// <summary>Describes one launchable simulation application.</summary>
|
|
[Serializable]
|
|
public struct LaunchData
|
|
{
|
|
public LaunchPair LaunchPair;
|
|
|
|
public string WorkingDirectory;
|
|
|
|
public string ExeFile;
|
|
|
|
public string Arguments;
|
|
|
|
public bool AutoRestart;
|
|
}
|
|
|
|
/// <summary>Tracks a currently running simulation process.</summary>
|
|
[Serializable]
|
|
public struct LaunchedAppData
|
|
{
|
|
public int ProcessId;
|
|
|
|
public Guid LaunchKey;
|
|
}
|
|
|
|
/// <summary>Progress of an out-of-band product installation.</summary>
|
|
[Serializable]
|
|
public struct OutOfBandProgress
|
|
{
|
|
public int PercentComplete;
|
|
|
|
public string Status;
|
|
|
|
public bool IsCompleted;
|
|
}
|
|
|
|
/// <summary>Complete pod state snapshot for the FullUpdate RPC.</summary>
|
|
[Serializable]
|
|
public struct FullUpdateData
|
|
{
|
|
public LaunchData[] InstalledApps;
|
|
|
|
public LaunchedAppData[] LaunchedApps;
|
|
|
|
public float VolumeLevel;
|
|
}
|
|
|
|
/// <summary>RPC command from the Console. Function is a MethodBase of ILauncherService.</summary>
|
|
[Serializable]
|
|
public struct InvokeCommand
|
|
{
|
|
public MethodBase Function;
|
|
|
|
public object[] Parameters;
|
|
}
|
|
|
|
/// <summary>RPC result returned to the Console.</summary>
|
|
[Serializable]
|
|
public struct InvokeResult
|
|
{
|
|
public object Result;
|
|
|
|
public Exception Exception;
|
|
|
|
public TimeSpan CallDuration;
|
|
}
|
|
|
|
public delegate void OutOfBandProgressChanged(Guid outOfBandCallId, OutOfBandProgress progress);
|
|
|
|
/// <summary>Server-side RPC surface. Method signatures are resolved by name from a
|
|
/// serialized MethodBase, so they must match the original exactly.</summary>
|
|
public interface ILauncherService
|
|
{
|
|
float VolumeLevel { get; set; }
|
|
|
|
void ClearStore();
|
|
|
|
DateTime Ping(DateTime now);
|
|
|
|
Guid InitiateInstallProduct();
|
|
|
|
OutOfBandProgress GetOutOfBandProgress(Guid invokeCallId);
|
|
|
|
int LaunchApp(Guid launchKey);
|
|
|
|
LaunchPair[] GetLaunchableApps();
|
|
|
|
void KillApp(Guid launchKey, int processId);
|
|
|
|
void KillAllOfType(Guid launchKey);
|
|
|
|
void KillAllApps();
|
|
|
|
void Shutdown(bool restart);
|
|
|
|
LaunchedAppData[] GetLaunchedApps();
|
|
|
|
LaunchData[] GetInstalledApps();
|
|
|
|
void RemoveApp(Guid index);
|
|
|
|
void InstallApp(LaunchData data);
|
|
|
|
void UninstallApp(Guid launchKey);
|
|
|
|
FullUpdateData FullUpdate();
|
|
}
|
|
|
|
/// <summary>Console-side connection: ILauncherService plus connection management
|
|
/// and the out-of-band InstallProduct file transfer.</summary>
|
|
public interface IPodManagerConnection : ILauncherService
|
|
{
|
|
bool IsOpen { get; }
|
|
|
|
void Open(IPEndPoint remoteEndPoint, byte[] secureKey);
|
|
|
|
void Close();
|
|
|
|
Guid InstallProduct(string filename);
|
|
}
|
|
}
|
|
|
|
namespace TeslaConsole
|
|
{
|
|
/// <summary>Thrown by the Console-side connection when the pod link drops.</summary>
|
|
[Serializable]
|
|
public class ConnectionLostException : Exception
|
|
{
|
|
public ConnectionLostException()
|
|
{
|
|
}
|
|
|
|
public ConnectionLostException(string message)
|
|
: base(message)
|
|
{
|
|
}
|
|
|
|
public ConnectionLostException(string message, Exception innerException)
|
|
: base(message, innerException)
|
|
{
|
|
}
|
|
}
|
|
}
|