From c20d49f430b3b4ea5f83b8f472b3b832c382b7b0 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 2 Apr 2026 15:22:17 -0500 Subject: [PATCH] fix: restrict tieline creation when signal types are invalid --- .../Routing/TieLine.cs | 24 +++++++-------- .../Routing/TieLineConfig.cs | 30 ++++++++++++++++++- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Routing/TieLine.cs b/src/PepperDash.Essentials.Core/Routing/TieLine.cs index 42f024b4..87470eeb 100644 --- a/src/PepperDash.Essentials.Core/Routing/TieLine.cs +++ b/src/PepperDash.Essentials.Core/Routing/TieLine.cs @@ -1,6 +1,6 @@ -using Newtonsoft.Json; -using System; +using System; using System.Collections.Generic; +using Newtonsoft.Json; namespace PepperDash.Essentials.Core { @@ -21,24 +21,24 @@ namespace PepperDash.Essentials.Core //public int InUseCount { get { return DestinationUsingThis.Count; } } /// - /// Gets the type of this tie line. Will either be the type of the destination port - /// or the type of OverrideType when it is set. + /// Gets the type of this tie line. Returns the intersection of signal types supported by both + /// the source and destination ports (what signals can actually travel through this tie line), + /// or the OverrideType when it is set. /// public eRoutingSignalType Type { get { if (OverrideType.HasValue) return OverrideType.Value; - return DestinationPort.Type; + return SourcePort.Type & DestinationPort.Type; } } /// - /// Use this to override the Type property for the destination port. For example, - /// when the tie line is type AudioVideo, and the signal flow should be limited to - /// Audio-only or Video only, changing this type will alter the signal paths - /// available to the routing algorithm without affecting the actual Type - /// of the destination port. + /// Use this to override the Type property. For example, when both ports support AudioVideo + /// but the physical cable only carries Audio or Video, setting this will limit the signal + /// paths available to the routing algorithm without affecting the actual port types. + /// When set, this value is used instead of the calculated intersection of source and destination types. /// public eRoutingSignalType? OverrideType { get; set; } @@ -79,7 +79,7 @@ namespace PepperDash.Essentials.Core /// /// The source output port. /// The destination input port. - /// The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations. + /// The signal type to limit the link to. Overrides the calculated intersection of port types for routing calculations. public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType? overrideType) : this(sourcePort, destinationPort) { @@ -91,7 +91,7 @@ namespace PepperDash.Essentials.Core /// /// The source output port. /// The destination input port. - /// The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations. + /// The signal type to limit the link to. Overrides the calculated intersection of port types for routing calculations. public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType overrideType) : this(sourcePort, destinationPort) { diff --git a/src/PepperDash.Essentials.Core/Routing/TieLineConfig.cs b/src/PepperDash.Essentials.Core/Routing/TieLineConfig.cs index 156b39b1..606cb603 100644 --- a/src/PepperDash.Essentials.Core/Routing/TieLineConfig.cs +++ b/src/PepperDash.Essentials.Core/Routing/TieLineConfig.cs @@ -49,7 +49,9 @@ namespace PepperDash.Essentials.Core.Config public string DestinationPort { get; set; } /// - /// Optional override for the signal type of the tie line. If set, this overrides the destination port's type for routing calculations. + /// Optional override for the signal type of the tie line. If set, this overrides the calculated + /// intersection of source and destination port types for routing calculations. Useful when the + /// physical cable supports fewer signal types than both ports are capable of. /// [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] [JsonConverter(typeof(StringEnumConverter))] @@ -96,6 +98,32 @@ namespace PepperDash.Essentials.Core.Config return null; } + // Validate signal type compatibility + if (OverrideType.HasValue) + { + // When override type is specified, both ports must support it + if (!sourceOutputPort.Type.HasFlag(OverrideType.Value)) + { + LogError($"Override type '{OverrideType.Value}' is not supported by source port '{SourcePort}' (type: {sourceOutputPort.Type})"); + return null; + } + + if (!destinationInputPort.Type.HasFlag(OverrideType.Value)) + { + LogError($"Override type '{OverrideType.Value}' is not supported by destination port '{DestinationPort}' (type: {destinationInputPort.Type})"); + return null; + } + } + else + { + // Without override type, ports must have at least one common signal type flag + if ((sourceOutputPort.Type & destinationInputPort.Type) == 0) + { + LogError($"Incompatible signal types: source port '{SourcePort}' (type: {sourceOutputPort.Type}) has no common signal types with destination port '{DestinationPort}' (type: {destinationInputPort.Type})"); + return null; + } + } + return new TieLine(sourceOutputPort, destinationInputPort, OverrideType); }