feat: add audited one-shot prepare gate
This commit is contained in:
@@ -1,32 +1,135 @@
|
||||
using MBN_STOCK_WEBVIEW.Core.Playout;
|
||||
using MBN_STOCK_WEBVIEW.Core.Playout.Scenes;
|
||||
using MBN_STOCK_WEBVIEW.Playout.Configuration;
|
||||
using MBN_STOCK_WEBVIEW.Playout.Diagnostics;
|
||||
using MBN_STOCK_WEBVIEW.Playout.Interop;
|
||||
using MBN_STOCK_WEBVIEW.Playout.Registration;
|
||||
using MBN_STOCK_WEBVIEW.Playout.Runtime;
|
||||
using MBN_STOCK_WEBVIEW.Playout.Safety;
|
||||
using System.Net;
|
||||
|
||||
namespace MBN_STOCK_WEBVIEW.Playout;
|
||||
|
||||
public static class PlayoutEngineFactory
|
||||
{
|
||||
public static IPlayoutEngine CreateDefault() =>
|
||||
Create(PlayoutOptionsLoader.Load());
|
||||
Create(
|
||||
PlayoutOptionsLoader.Load(),
|
||||
PlayoutLaunchAuthorization.CaptureFromEnvironment());
|
||||
|
||||
public static IPlayoutEngine Create(PlayoutOptions options)
|
||||
public static IPlayoutEngine Create(PlayoutOptions options) =>
|
||||
Create(options, PlayoutLaunchAuthorization.CaptureFromEnvironment());
|
||||
|
||||
public static IPlayoutEngine Create(
|
||||
PlayoutOptions options,
|
||||
PlayoutLaunchAuthorization launchAuthorization)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
ArgumentNullException.ThrowIfNull(launchAuthorization);
|
||||
ValidateGateAOptions(options, launchAuthorization);
|
||||
var validated = ValidatedPlayoutOptions.Create(options);
|
||||
ITornadoProcessProbe processProbe = new TornadoProcessProbe();
|
||||
Func<bool>? finalConnectSafetyCheck = null;
|
||||
var abandonOnTargetMismatch = false;
|
||||
var startMonitor = validated.Mode != PlayoutMode.Disabled;
|
||||
|
||||
if (launchAuthorization.IsGateA)
|
||||
{
|
||||
var safetyProbe = new WindowsPgmDiagnosticSafetyProbe();
|
||||
var request = new PgmConnectDiagnosticRequest(
|
||||
validated.Host,
|
||||
validated.Port,
|
||||
"PGM");
|
||||
var parsedHost = IPAddress.Parse(validated.Host);
|
||||
var baseline = safetyProbe.Capture(request, parsedHost);
|
||||
if (!baseline.IsEligible ||
|
||||
baseline.Identity is not { } identity ||
|
||||
identity.ProcessId != launchAuthorization.ExpectedPgmProcessId ||
|
||||
identity.StartTimeUtcTicks !=
|
||||
launchAuthorization.ExpectedPgmStartTimeUtcTicks)
|
||||
{
|
||||
throw new PlayoutConfigurationException(
|
||||
"Gate A could not confirm the exact approved PGM process and listener.");
|
||||
}
|
||||
|
||||
bool HasExactTarget()
|
||||
{
|
||||
try
|
||||
{
|
||||
var current = safetyProbe.Capture(request, parsedHost);
|
||||
return current.IsEligible && baseline.HasSameTarget(current);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
processProbe = new PgmCutsSequenceProcessProbe(
|
||||
safetyProbe,
|
||||
request,
|
||||
parsedHost,
|
||||
baseline);
|
||||
finalConnectSafetyCheck = HasExactTarget;
|
||||
abandonOnTargetMismatch = true;
|
||||
startMonitor = false;
|
||||
}
|
||||
|
||||
IStaDispatcher? dispatcher = validated.Mode is PlayoutMode.Test or PlayoutMode.Live
|
||||
? new StaDispatcher(validated.QueueCapacity)
|
||||
: null;
|
||||
return new TornadoPlayoutEngine(
|
||||
validated,
|
||||
new DynamicK3dSessionFactory(),
|
||||
new DynamicK3dSessionFactory(
|
||||
rollbackOnPrepareFailure: !launchAuthorization.IsGateA),
|
||||
new K3dRegistrationProbe(),
|
||||
new TornadoProcessProbe(),
|
||||
processProbe,
|
||||
dispatcher,
|
||||
new EnvironmentLiveAuthorization(),
|
||||
TimeProvider.System);
|
||||
launchAuthorization,
|
||||
TimeProvider.System,
|
||||
startMonitor,
|
||||
finalConnectSafetyCheck,
|
||||
abandonOnTargetMismatch,
|
||||
beforeSdkDispatchClaim: launchAuthorization.IsGateA
|
||||
? launchAuthorization.EnsureGateASdkDispatchAuthorized
|
||||
: null,
|
||||
launchAuthorization: launchAuthorization);
|
||||
}
|
||||
|
||||
internal static void ValidateGateAOptions(
|
||||
PlayoutOptions options,
|
||||
PlayoutLaunchAuthorization launchAuthorization)
|
||||
{
|
||||
if (!launchAuthorization.IsGateA)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var allowlist = (options.TestSceneAllowlist ?? [])
|
||||
.Select(static value => value?.Trim())
|
||||
.ToArray();
|
||||
if (options.Mode != PlayoutMode.Live ||
|
||||
!options.TrustedLiveOutputEnabled ||
|
||||
!string.Equals(options.Host?.Trim(), "127.0.0.1", StringComparison.Ordinal) ||
|
||||
options.Port != 30001 ||
|
||||
options.TcpMode != 1 ||
|
||||
options.ClientPort != 0 ||
|
||||
options.OutputChannel is not null ||
|
||||
options.LayoutIndex != 10 ||
|
||||
!PlayoutLaunchAuthorization.IsExactGateASceneDirectory(
|
||||
options.SceneDirectory) ||
|
||||
allowlist.Length != 1 ||
|
||||
!string.Equals(allowlist[0], "5001", StringComparison.Ordinal) ||
|
||||
options.ReconnectEnabled ||
|
||||
options.MaximumReconnectAttempts != 0 ||
|
||||
options.MaximumAutomaticRefreshesPerTakeIn != 0 ||
|
||||
options.LegacySceneFadeDuration != 6 ||
|
||||
options.LegacySceneBackgroundKind != LegacySceneBackgroundKind.None ||
|
||||
!string.IsNullOrWhiteSpace(options.LegacySceneBackgroundAssetPath))
|
||||
{
|
||||
throw new PlayoutConfigurationException(
|
||||
"Gate A requires the exact closed 5001-only Live configuration.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user