Merge: net48-only launcher (pod-validated)
Launcher Service + Agent moved from net8/x64 self-contained to net48 framework-dependent; Tesla.Contract is now net48-only (single TFM across the suite). Package drops from ~91 MB zipped to ~1.6 MB. Tested OK end-to-end on a pod computer.
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Multi-targeted: net48 for the Console, net8.0-windows for the Launcher Service. -->
|
||||
<TargetFrameworks>net48;net8.0-windows</TargetFrameworks>
|
||||
<!-- net48 only: both consumers (Console and Launcher) target .NET Framework 4.8.
|
||||
(Was multi-targeted net48;net8.0-windows while the Launcher was on net8.) -->
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
|
||||
<!-- CRITICAL: the output assembly MUST be named TeslaConsoleLaunchLib at
|
||||
version 1.0.0.0. BinaryFormatter embeds the assembly name in the wire
|
||||
|
||||
@@ -21,6 +21,7 @@ using System.Net.Sockets;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Win32;
|
||||
@@ -813,7 +814,7 @@ namespace TeslaSecureConfig
|
||||
TcpReadExact(netStream, consoleIv);
|
||||
|
||||
var podIv = new byte[16];
|
||||
RandomNumberGenerator.Fill(podIv);
|
||||
using (var rng = RandomNumberGenerator.Create()) rng.GetBytes(podIv);
|
||||
netStream.Write(podIv, 0, 16);
|
||||
netStream.Flush();
|
||||
|
||||
@@ -836,7 +837,7 @@ namespace TeslaSecureConfig
|
||||
|
||||
var confReply = new byte[4];
|
||||
TcpReadExact(ofb, confReply);
|
||||
if (!confReply.AsSpan().SequenceEqual(confMsg))
|
||||
if (!confReply.SequenceEqual(confMsg))
|
||||
{
|
||||
Log($"CONF mismatch: got [{BitConverter.ToString(confReply)}], expected CONF — key/IV mismatch.");
|
||||
return;
|
||||
@@ -1188,7 +1189,7 @@ namespace TeslaSecureConfig
|
||||
private static string GenerateRandomString(int length)
|
||||
{
|
||||
var buf = new byte[length];
|
||||
RandomNumberGenerator.Fill(buf);
|
||||
using (var rng = RandomNumberGenerator.Create()) rng.GetBytes(buf);
|
||||
var sb = new System.Text.StringBuilder(length);
|
||||
for (int i = 0; i < length; i++)
|
||||
sb.Append(Proto.Alphabet[buf[i] % Proto.Alphabet.Length]);
|
||||
|
||||
@@ -422,8 +422,8 @@ namespace Tesla.Launcher.Agent
|
||||
}
|
||||
|
||||
var resBytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(response));
|
||||
pipe.Write(BitConverter.GetBytes(resBytes.Length));
|
||||
pipe.Write(resBytes);
|
||||
pipe.Write(BitConverter.GetBytes(resBytes.Length), 0, 4);
|
||||
pipe.Write(resBytes, 0, resBytes.Length);
|
||||
pipe.Flush();
|
||||
}
|
||||
|
||||
@@ -672,7 +672,7 @@ namespace Tesla.Launcher.Agent
|
||||
var scalar = parms[0].ValueKind == JsonValueKind.Number
|
||||
? (float)parms[0].GetDouble()
|
||||
: throw new Exception("Invalid volume value");
|
||||
SetMasterVolume(Math.Clamp(scalar, 0f, 1f));
|
||||
SetMasterVolume(Math.Max(0f, Math.Min(1f, scalar)));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<Nullable>disable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<WarningsAsErrors></WarningsAsErrors>
|
||||
<Version>4.11.4.1</Version>
|
||||
<ApplicationIcon>app.ico</ApplicationIcon>
|
||||
<AssemblyName>TeslaLauncherAgent</AssemblyName>
|
||||
<RootNamespace>Tesla.Launcher.Agent</RootNamespace>
|
||||
<Platforms>x64</Platforms>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<StartupObject>Tesla.Launcher.Agent.AgentApplication</StartupObject>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -25,8 +22,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Required by SecureConfig.cs for COM2/PlasmaIO serial output -->
|
||||
<PackageReference Include="System.IO.Ports" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
||||
<!-- Agent parses configuring.json + the IPC JSON; built-in on net6, a package on net48. -->
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.IO.Pipes;
|
||||
@@ -151,31 +152,39 @@ namespace Tesla.Launcher.Service
|
||||
_listener.Start();
|
||||
_logger.LogInformation("Listening. Waiting for Console connections...");
|
||||
|
||||
// net48's TcpListener has no CancellationToken overload for accept;
|
||||
// stop the listener on cancellation so the pending accept unblocks.
|
||||
using var stopReg = stoppingToken.Register(() => { try { _listener.Stop(); } catch { } });
|
||||
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
TcpClient client;
|
||||
try
|
||||
{
|
||||
var client = await _listener.AcceptTcpClientAsync(stoppingToken);
|
||||
_logger.LogInformation(
|
||||
"Console connected from {EP}", client.Client.RemoteEndPoint);
|
||||
|
||||
// Handle each Console connection on its own thread.
|
||||
// Frame reads are synchronous, so we offload to a
|
||||
// thread-pool thread via Task.Run.
|
||||
var task = Task.Run(
|
||||
() => HandleConsoleClient(client, stoppingToken),
|
||||
stoppingToken);
|
||||
|
||||
lock (_taskLock)
|
||||
{
|
||||
_clientTasks.Add(task);
|
||||
_clientTasks.RemoveAll(t => t.IsCompleted);
|
||||
}
|
||||
client = await _listener.AcceptTcpClientAsync();
|
||||
}
|
||||
catch (OperationCanceledException) { break; }
|
||||
catch (Exception) when (stoppingToken.IsCancellationRequested) { break; }
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error accepting Console connection");
|
||||
continue;
|
||||
}
|
||||
|
||||
_logger.LogInformation(
|
||||
"Console connected from {EP}", client.Client.RemoteEndPoint);
|
||||
|
||||
// Handle each Console connection on its own thread.
|
||||
// Frame reads are synchronous, so we offload to a
|
||||
// thread-pool thread via Task.Run.
|
||||
var task = Task.Run(
|
||||
() => HandleConsoleClient(client, stoppingToken),
|
||||
stoppingToken);
|
||||
|
||||
lock (_taskLock)
|
||||
{
|
||||
_clientTasks.Add(task);
|
||||
_clientTasks.RemoveAll(t => t.IsCompleted);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,7 +218,7 @@ namespace Tesla.Launcher.Service
|
||||
|
||||
// Generate and send our IV
|
||||
var podIv = new byte[16];
|
||||
RandomNumberGenerator.Fill(podIv);
|
||||
using (var rng = RandomNumberGenerator.Create()) rng.GetBytes(podIv);
|
||||
netStream.Write(podIv, 0, 16);
|
||||
netStream.Flush();
|
||||
|
||||
@@ -230,7 +239,7 @@ namespace Tesla.Launcher.Service
|
||||
_logger.LogWarning("CONF read failed: {Msg}", ex.Message);
|
||||
return;
|
||||
}
|
||||
if (!confReply.AsSpan().SequenceEqual(confMsg))
|
||||
if (!confReply.SequenceEqual(confMsg))
|
||||
{
|
||||
_logger.LogWarning("CONF mismatch — session key mismatch, dropping connection.");
|
||||
return;
|
||||
@@ -879,8 +888,8 @@ namespace Tesla.Launcher.Service
|
||||
|
||||
// Send IpcMessage
|
||||
var reqBytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(msg));
|
||||
await pipe.WriteAsync(BitConverter.GetBytes(reqBytes.Length), ct);
|
||||
await pipe.WriteAsync(reqBytes, ct);
|
||||
await pipe.WriteAsync(BitConverter.GetBytes(reqBytes.Length), 0, 4, ct);
|
||||
await pipe.WriteAsync(reqBytes, 0, reqBytes.Length, ct);
|
||||
await pipe.FlushAsync(ct);
|
||||
|
||||
// Read IpcResponse
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Worker">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Nullable>disable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<WarningsAsErrors></WarningsAsErrors>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Version>4.11.4.1</Version>
|
||||
<ApplicationIcon>app.ico</ApplicationIcon>
|
||||
<AssemblyName>TeslaLauncherService</AssemblyName>
|
||||
<RootNamespace>Tesla.Launcher.Service</RootNamespace>
|
||||
<Platforms>x64</Platforms>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<WindowsService>true</WindowsService>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -23,22 +20,26 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- net48 reference assemblies + GAC refs the framework-dependent build needs. -->
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.IO.Compression.FileSystem" />
|
||||
<Reference Include="System.ServiceProcess" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Generic host on .NET Framework: Microsoft.Extensions.Hosting(.WindowsServices)
|
||||
8.x ship a net462 target, so they run on net48 unchanged. -->
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.*" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.*" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="8.*" />
|
||||
<!-- Required by SecureConfig.cs for COM2/PlasmaIO serial output -->
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.5" />
|
||||
<!-- COM2 / PlasmaIO serial output in SecureConfig.cs -->
|
||||
<PackageReference Include="System.IO.Ports" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Tesla.Net wire types now come from the shared contract (net6 build),
|
||||
replacing the hand-maintained replica in LaunchModels_Shared.cs.
|
||||
SetPlatform pins the reference to AnyCPU: this project is x86, the
|
||||
contract is platform-neutral, and without the pin MSBuild's dynamic
|
||||
platform negotiation corrupts this project's restore (one-shot
|
||||
`dotnet build` of the solution then fails to resolve its packages). -->
|
||||
<ProjectReference Include="..\Contract\Tesla.Contract.csproj" SetPlatform="Platform=AnyCPU" />
|
||||
<ProjectReference Include="..\Contract\Tesla.Contract.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
|
||||
+5
-11
@@ -3,11 +3,12 @@
|
||||
:: TeslaLauncher — Unified Build / Package Script
|
||||
:: =============================================================================
|
||||
:: Publishes TeslaLauncherService.exe and TeslaLauncherAgent.exe as
|
||||
:: self-contained single-file win-x64 executables (net8) and assembles the
|
||||
:: installable TeslaLauncher\ package next to install.bat.
|
||||
:: framework-dependent net48 builds and assembles the installable TeslaLauncher\
|
||||
:: package next to install.bat. The target pod needs .NET Framework 4.8 (built
|
||||
:: into Windows 10/11) — there is no bundled runtime, so the package is small.
|
||||
::
|
||||
:: Requirements:
|
||||
:: .NET 8 SDK https://dotnet.microsoft.com/download/dotnet/8.0
|
||||
:: .NET SDK (6.0+) to drive the build https://dotnet.microsoft.com/download
|
||||
:: Internet access for NuGet restore (first build only)
|
||||
::
|
||||
:: Usage:
|
||||
@@ -31,7 +32,6 @@ setlocal enabledelayedexpansion
|
||||
|
||||
set ROOT=%~dp0
|
||||
set BUILD_DIR=%ROOT%TeslaLauncher
|
||||
set RID=win-x64
|
||||
|
||||
:: -- Parse arguments ----------------------------------------------------------
|
||||
set BUILD_SERVICE=1
|
||||
@@ -46,7 +46,7 @@ for %%a in (%*) do (
|
||||
|
||||
echo.
|
||||
echo ============================================================
|
||||
echo Tesla Launcher v0.1 - Build ^& Package (net8, %RID%)
|
||||
echo Tesla Launcher v0.1 - Build ^& Package (net48, framework-dependent)
|
||||
echo Output : %BUILD_DIR%
|
||||
echo ============================================================
|
||||
echo.
|
||||
@@ -75,9 +75,6 @@ echo [1/2] Publishing TeslaLauncherService (Session 0 Windows Service)...
|
||||
echo.
|
||||
dotnet publish "%ROOT%TeslaLauncherService.csproj" ^
|
||||
-c Release ^
|
||||
-r %RID% ^
|
||||
--self-contained true ^
|
||||
-p:PublishSingleFile=true ^
|
||||
-o "%BUILD_DIR%\Service"
|
||||
if errorlevel 1 (
|
||||
echo.
|
||||
@@ -98,9 +95,6 @@ if %BUILD_SERVICE%==1 (echo [2/2] Publishing TeslaLauncherAgent...) else (echo [
|
||||
echo.
|
||||
dotnet publish "%ROOT%TeslaLauncherAgent.csproj" ^
|
||||
-c Release ^
|
||||
-r %RID% ^
|
||||
--self-contained true ^
|
||||
-p:PublishSingleFile=true ^
|
||||
"-p:DefineConstants=WINFORMS" ^
|
||||
-o "%BUILD_DIR%\Agent"
|
||||
if errorlevel 1 (
|
||||
|
||||
@@ -120,9 +120,11 @@ echo C:\Games (Users: modify access)
|
||||
|
||||
:: ── STEP 2: Copy files ────────────────────────────────────────────────────────
|
||||
echo [2/8] Copying files...
|
||||
copy /Y "%SERVICE_SRC%\TeslaLauncherService.exe" "%INSTALL_DIR%\" >nul
|
||||
copy /Y "%AGENT_SRC%\TeslaLauncherAgent.exe" "%INSTALL_DIR%\" >nul
|
||||
copy /Y "%AGENT_SRC%\*.dll" "%INSTALL_DIR%\" >nul 2>&1
|
||||
:: net48 framework-dependent build: each folder holds the exe + its dependency
|
||||
:: DLLs + .config. Copy both folders into the install dir (shared DLLs overwrite
|
||||
:: identically; the two .exe.config files coexist).
|
||||
copy /Y "%SERVICE_SRC%\*.*" "%INSTALL_DIR%\" >nul
|
||||
copy /Y "%AGENT_SRC%\*.*" "%INSTALL_DIR%\" >nul
|
||||
|
||||
:: Install DirectX June 2010 runtime (required by games)
|
||||
if exist "%ROOT%\dx9201006\DXSETUP.exe" (
|
||||
|
||||
+8
-8
@@ -36,14 +36,14 @@ Global
|
||||
{467AA87A-FBD4-45D7-B8F8-9336C95884D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{467AA87A-FBD4-45D7-B8F8-9336C95884D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{467AA87A-FBD4-45D7-B8F8-9336C95884D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{910D4404-B3A2-4217-B61C-D43E7F22CDAA}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{910D4404-B3A2-4217-B61C-D43E7F22CDAA}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{910D4404-B3A2-4217-B61C-D43E7F22CDAA}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{910D4404-B3A2-4217-B61C-D43E7F22CDAA}.Release|Any CPU.Build.0 = Release|x64
|
||||
{916DCDA5-3379-4383-96F0-AC7B26FAF64E}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{916DCDA5-3379-4383-96F0-AC7B26FAF64E}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{916DCDA5-3379-4383-96F0-AC7B26FAF64E}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{916DCDA5-3379-4383-96F0-AC7B26FAF64E}.Release|Any CPU.Build.0 = Release|x64
|
||||
{910D4404-B3A2-4217-B61C-D43E7F22CDAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{910D4404-B3A2-4217-B61C-D43E7F22CDAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{910D4404-B3A2-4217-B61C-D43E7F22CDAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{910D4404-B3A2-4217-B61C-D43E7F22CDAA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{916DCDA5-3379-4383-96F0-AC7B26FAF64E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{916DCDA5-3379-4383-96F0-AC7B26FAF64E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{916DCDA5-3379-4383-96F0-AC7B26FAF64E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{916DCDA5-3379-4383-96F0-AC7B26FAF64E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0B2E3F1F-56C4-4B1A-AC26-4BF34AA10F1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0B2E3F1F-56C4-4B1A-AC26-4BF34AA10F1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0B2E3F1F-56C4-4B1A-AC26-4BF34AA10F1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
||||
Reference in New Issue
Block a user