Skip to content

Connect an unlisted transport only when it opts in - #190

Merged
lo-simon merged 10 commits into
sony:masterfrom
garethsb:feature/connect-shared-params
Oct 7, 2026
Merged

lo-simon merged 10 commits into
sony:masterfrom
garethsb:feature/connect-shared-params

Conversation

@garethsb

@garethsb garethsb commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Builds on #188. This is the version to merge; #188 can close once this is in.

Summary

Same-name copy is what WebSocket already does, and what ext_ parameters already do. RTP, MQTT and MXL each need their own Sender-to-Receiver mapping, so it is not the fallback for every transport makeConnection does not already list.

  • A transport opts in with copySharedParams oneToOne on its TRANSPORTS entry. makeConnection then copies each parameter name that the Sender's active transport_params and the Receiver's staged transport_params both have. ext_ parameters stay on their existing path. getSharedParams is that intersection, using the same merge as getExtParams.
  • Anything else is refused before a PATCH. A label in the register is not an opt-in: DASH stays refused. Setting sender_id, master_enable and activate_immediate and leaving transport_params alone is not a connection.
  • Active and Staged show and edit a generic card per leg for an opted-in transport, labelled from the parameter names. Anything else still shows "Unknown Type". The Receiver edit form does not offer a transport file for an opted-in transport.
  • verbatim on the makeConnection update stays, so a string copied from the Sender, such as "11", is not sent as a number.

Test plan

  • yarn lint-check
  • yarn test --watchAll=false --testPathPattern 'ConnectionsList.test|dataProvider.test|GenericTransportParamInput.test|makeConnection.test' (4 suites, 63 tests). This covers staged-text coercion, a verbatim copied string staying a string, DASH and an unrecognised transport being refused, an opted-in transport copying shared parameter names, RTP keeping its own parameter list, and the transport-file hint for RTP, DASH, MQTT, WebSocket, MXL, and an unrecognised transport.
  • WebSocket and MXL example nodes registered, and Active and Staged reviewed for those transports and for RTP. Connection authorization shows its title, and its tick and cross match Master Enable. The Transport File heading stays when there is no file.

@garethsb
garethsb marked this pull request as draft October 2, 2026 12:57
@garethsb
garethsb force-pushed the feature/connect-shared-params branch 3 times, most recently from 0a464d4 to 6966331 Compare October 2, 2026 19:10
@garethsb
garethsb marked this pull request as ready for review October 2, 2026 19:10
@garethsb

garethsb commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor Author

@lhoward, would love your review on this (scope grew while I was working on it, of course)

Opt in by adding transport to the TRANSPORTS register in Development/src/components/ParameterRegisters.js.

'urn:x-padl:transport:example': {
    label: 'Example',
    oneToOne: true,
},

The key is the transport URN base your Senders and Receivers actually advertise, without a .subclassification or /version suffix.

With oneToOne: true, Connect copies each parameter name that is on both the Sender's active transport_params and the Receiver's staged transport_params. The names have to match. ext_ parameters are copied anyway, from the names on the Receiver. Active and Staged then show one generic card per leg, labelled from those names.

That is the wrong tool if a Sender parameter has to be renamed onto the Receiver, the way RTP copies destination_ip to multicast_ip. That needs an explicit list in oneToOneTransportParams in makeConnection.js, and that list wins over the flag.

Until the entry is there, Connect stops with Cannot connect transport … and no PATCH is sent.

One consequence of registering it: any transport in TRANSPORTS other than RTP is treated as not using a transport file, so the Receiver edit page hides that field.

@lhoward

lhoward commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

This comment was generated by Claude and reviewed by me.

Looks good, and works against our hardware from the matrix with local TRANSPORTS entries for our two transports. One gap: with a null previous value, text typed into the generic card is coerced by content, so a Dante channel name such as 05 goes as the number 5, which the Receiver refuses. Could stagedTextPatchValue consult /constraints when the previous value is null (pattern or a string enum means string, minimum/maximum means number) before falling back to the current rule? I'll publish those constraints on our side.

Nit: transportIsOneToOne uses unversionedParameter where transportOmitsTransportFile uses the parsed base.

@garethsb

garethsb commented Oct 3, 2026

Copy link
Copy Markdown
Contributor Author

The heuristics in stagedTextPatchValue are smarter than they were but your example perfectly demonstrates why heuristics aren't good enough. How about we solve this a different way and get the human at the keyboard to tell us whether they meant "05" or 5? The GenericTransportParamInput could gain the means to indicate the intended type. The dataProvider.js layer could keep some heuristics or not.

And the inconsistent transport* functions... yeah, those need making consistent.

Will also revisit what we do with transport_file both whether or or not it's displayed for unrecognised/generic transport types, and then if the Media Type needs to be editable too... and what we do in makeConnection... can we use the Content-Type of the sender's /transporttype. All theoretical but if we're supporting generic transport types, would be nice...

@garethsb
garethsb force-pushed the feature/connect-shared-params branch from 6966331 to 03f6aea Compare October 5, 2026 12:50
@garethsb

garethsb commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

@lhoward @lo-simon

The branch is rewritten on top of "Send the values copied from a Sender as they are", and force-pushed, so comments on the previous commits will not line up with the files. Four commits:

  1. Connect an unlisted transport only when it opts in
  2. Edit transport parameters as typed values
  3. Keep a transport file's type with its data
  4. Show friendly names for activation modes

Addressing Luke's comment on handling the Dante channel name: the staged value is now submitted as the type on the control. The generic card has a choice of string, integer, number or boolean, so "05" as a string stays "05". A number or integer field uses JSON.parse. "05" and "0x2a" do not parse, so the previous value stays. There is no content heuristic and no /constraints lookup. (Using /constraints as pre-validation in some way is a separate topic.) Same-name copy still sends the Sender's values as they are. The verbatim flag has been dropped at the same time as the heuristic coercion.

The transport helpers all read the URN base (parseTransportUrn). rtp.mcast uses the rtp entry for same-name copy and for the transport file. The label lookup is unchanged, so RTP Multicast still has its own friendly name for example.

oneToOne and the transport file are separate. A registered transport with no transportFile hides the type and data on the Receiver show and edit pages (DASH, MQTT, WebSocket, MXL). RTP's entry is transportFile: 'application/sdp', used when a file is present and no type was given. An unrecognised transport still shows the fields. Connect keeps the transport file's Content-Type with the data, parameters stripped, and uses that registered default only when the header is missing. The PATCH sends the type on the form. Clearing the data clears the type. Changing only the type leaves the data.

Activation modes use Immediate, Scheduled Relative and Scheduled Absolute when Friendly Names is on, in the field and in the menu. An empty choice on a Sender or Receiver stores null. The channel-mapping editor uses the same names and has no empty choice, because POST /map/activations/ requires a mode.

@garethsb

garethsb commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

Some screenshots, showing the new explicit support for "auto" and null:

RTP

image

WebSocket, showing some ext_ parameters with the GenericTransportParamInput also used for uncustomized transports like Luke's ones

image

@garethsb
garethsb force-pushed the feature/connect-shared-params branch 4 times, most recently from 1037dc6 to cf6e083 Compare October 6, 2026 09:49
@garethsb

garethsb commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

These screenshots are what an RTP receiver with both FEC and RTCP support now looks like vs. what it would look like if it were using the new Generic Transport Params support.

Things to note:

  • in the custom RTP implementation:
    • auto and null options shown only as appropriate based on the schemas
    • select inputs (drop-down menu choices) for enums like FEC Mode
    • parameters ordered sensibly based on IS-05 parameter set groupings
  • in the generic implementation:
    • auto and null permitted everywhere
    • initial type of each parameter is chosen based on current values but is changeable between string/integer/number/boolean (because if the current value is null or "auto" there's no way to know the 'main' type)
    • parameters ordered alphabetically
image (10) image (11)

lhoward and others added 9 commits October 6, 2026 18:23
makeConnection copies the parameters listed for the Sender's transport. A
transport with no list, such as a manufacturer's own, which IS-05 v1.2 allows,
left that list undefined, so connecting failed with a TypeError before any
request was made.

For such a transport, copy each parameter that the Sender's active
transport_params and the Receiver's staged transport_params both have.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T8cahEd4GfsHQ89sNrmP4p
A PATCH to a Receiver turns a string that reads as a number into a number,
which suits a value typed into a text input. The values makeConnection copies
from the Sender already have the type the Sender gave them, so a string
parameter such as a channel name of "11" or "05" must stay a string.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T8cahEd4GfsHQ89sNrmP4p
Same-name copy is what WebSocket already does. RTP, MQTT and MXL each
need their own mapping, so makeConnection refuses a transport with no
explicit list and no oneToOne flag.

Signed-off-by: Gareth Sylvester-Bradley <garethsb@nvidia.com>
Known parameters submit the JSON type they should keep. A staged string
such as "" or "11" is not reinterpreted. An opted-in transport is edited
on one card per leg.

Signed-off-by: Gareth Sylvester-Bradley <garethsb@nvidia.com>
The Content-Type from the sender's transport file is kept with the data
and sent on connect. A registered transport that does not use a file
hides the type and data.

Signed-off-by: Gareth Sylvester-Bradley <garethsb@nvidia.com>
Immediate, Scheduled Relative and Scheduled Absolute follow the Friendly
Names setting in the field and in the menu. An empty choice stores null.
The channel-mapping editor uses the same names. POST /map/activations/
requires a mode, so that menu has no empty choice.

Signed-off-by: Gareth Sylvester-Bradley <garethsb@nvidia.com>
A select cannot hold null, so the null row submits null. auto and null
follow the real values after one separator, in that order, whether they
came from the props or from choices. The closed field shows the word null.
The subscription create menu uses the same word style for an empty
resource path, and keeps that row first.

Signed-off-by: Gareth Sylvester-Bradley <garethsb@nvidia.com>
GenericReceiverEdit and GenericSenderEdit show the parameters the node
sent, so they are enough for general use. oneToOne remains the connect
opt-in.

Signed-off-by: Gareth Sylvester-Bradley <garethsb@nvidia.com>
A text filter uses a comma to separate alternatives. Basic query cannot
express that, so the value is left out of the request and the field is
marked. With RQL on, a match button joins a receiver's media types or
event types into that string so the input can show them.

Signed-off-by: Gareth Sylvester-Bradley <garethsb@nvidia.com>
@garethsb
garethsb force-pushed the feature/connect-shared-params branch from 4c52966 to 9d95d6b Compare October 6, 2026 17:25
@garethsb

garethsb commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Rebased on tip of sony:master with two extra commits:

  • c55feb9 which uses the Generic* cards for all transports now
  • 9d95d6b which fixes an existing FilterPanel bug with array values used as filters (e.g. Receiver caps.media_types applied to Flows) and warns the user if they try comma-separated value filters with basic query syntax (not strictly related to this PR but touched some of the same code... please don't "squash merge" this PR! 😅)

IS-05 requires type with data even when the type is unchanged. The staged
diff was omitting it after the hard-coded application/sdp was removed.

Co-authored-by: Simon Lo <simon.lo@sony.com>
Signed-off-by: Gareth Sylvester-Bradley <garethsb@nvidia.com>

@lo-simon lo-simon left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@lo-simon
lo-simon merged commit 9d1fe26 into sony:master Oct 7, 2026
4 checks passed
@garethsb
garethsb deleted the feature/connect-shared-params branch October 7, 2026 18:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants