Files
UA-.NETStandard/samples/ConsoleReferenceServer
MarcandCopilot d65d416a80 Move the data channel code back into Opc.Ua.Core and delete the seam
Review feedback on UaSCBinaryClientChannel.cs:893 - "Everywhere we make it
look like a generic extension, but we only handle stream." That is correct, and
checking it against the only other transport settles it: Opc.Ua.Bindings.Quic
references none of ISecureChannelMessageHost, ISecureChannelMessageExtension,
SequenceNumberBudget or the send gate, because a QUIC data channel rides its own
stream and never becomes a UASC chunk. The seam had exactly one implementer and
no prospect of a second; it existed only because the engine sat in another
assembly.

So the engine comes home rather than the seam being dressed up as general. The
destinations are the ones commit cfaa34fa8 recorded as renames:

* Opc.Ua.Core.Channels/DataChannels/** (engine, framing, flow control,
  sequencing, scheduling, model and Services/) to Opc.Ua.Core/Stack/DataChannels
* IServerDataChannelTransport and InlineServerDataChannelTransport back to
  Opc.Ua.Server/Server, where the latter came from
* ChannelsEventIds folded into CoreEventIds, keeping 600/620 so existing log
  filters are unaffected

Deleted outright:

* ISecureChannelMessageExtension.cs, both interfaces. This also answers the
  request to rename that file after its interface: it no longer exists.
* UaSCBinaryChannel.MessageExtensions.cs, replaced by
  UaSCBinaryChannel.DataChannels.cs, which owns the DataChannelManager directly
  and dispatches STR after the existing decrypt, signature and sequence checks.
* DataChannelExtension, the adapter that existed only to bridge assemblies. Its
  IDataChannelTransport half is now a small private InlineDataChannelTransport
  that hands the channel to the engine.
* The Opc.Ua.Core.Channels project, its UA.slnx entry, its expected-packages
  line and its reference from the reference server Dockerfile. The package is
  new in this branch and never shipped, so nothing is owed compatibility.

EnableDataChannels and the channel accessors become ordinary members instead of
extension methods over a published seam, and the framing fault surfaces as
UaSCUaBinaryChannel.DataChannelProtocolFault, so a test no longer has to reach
through a registry to observe which rule was broken.

This supersedes the InternalsVisibleTo narrowing in 18a30770d: the types it made
internal are deleted here, and the entry it added to Opc.Ua.Core is removed.
SequenceNumberBudget stays internal, which the move now justifies on its own.
UaSCSecureChannelRegistry stays public because a server writing its own
IServerDataChannelTransport needs it, as the sample does.

Separately, per the review of the QUIC csproj, opc.quic now targets net8.0 as
well and opts into preview features there, so a net8.0 consumer can do the same
rather than being excluded. The three file wide NET9_0_OR_GREATER guards are
gone; only QuicServerConnectionOptions.HandshakeTimeout, which is genuinely
.NET 9+, stays guarded, and the listener's own admission expiry still bounds a
stalled handshake on net8.0.

UA.slnx builds pinned to net10.0 and 316 data channel tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5d026b47-265d-4c97-8715-26e207dfa03c
2026-08-12 12:55:08 +02:00
..

OPC Foundation UA .NET Standard Reference Server

Introduction

The console reference server can be configured using several console parameters. Some of these parameters are explained in more detail below.

To see all available parameters call console reference server with the parameter -h.

Reverse Connect

The OPC UA reverse connect feature allows an OPC UA server to initiate the connection to a client, rather than the traditional model where clients connect to servers. This is particularly useful in scenarios where the server is behind a firewall or NAT, making it difficult for clients to directly connect to it.

How to use Reverse Connect

To enable reverse connect mode, specify the client endpoint URL using the --rc or --reverseconnect parameter:

dotnet ConsoleReferenceServer.dll --rc=opc.tcp://localhost:65300

or

dotnet ConsoleReferenceServer.dll --reverseconnect=opc.tcp://localhost:65300

Example: Server and Client with Reverse Connect

  1. Start the client with reverse connect listener on port 65300:

    dotnet ConsoleReferenceClient.dll --rc=opc.tcp://localhost:65300 opc.tcp://localhost:62541/Quickstarts/ReferenceServer
    
  2. In a separate terminal, start the server with reverse connect to the client:

    dotnet ConsoleReferenceServer.dll --rc=opc.tcp://localhost:65300 -a
    

The server will establish a reverse connection to the client endpoint, and the client will use this connection to communicate with the server.

Additional Options

  • -a or --autoaccept: Auto accept untrusted certificates (for testing only)
  • -c or --console: Log to console
  • -l or --log: Log app output
  • -t or --timeout: Timeout in seconds to exit application

For the complete list of options, use --help.

X509 user identity certificates

The reference server validates X509 user identity tokens against its trusted-user certificate store (TrustedUserCertificates, by default %LocalApplicationData%/OPC Foundation/pki/trustedUser). An untrusted user certificate is rejected with BadIdentityTokenRejected — the --autoaccept option only auto-accepts the application/channel certificate, never user identity certificates.

To let a trusted client (for example the OPC Foundation Compliance Test Tool) authenticate with an X509 user token, its user certificate must be present in that store. To make provisioning easy, the server writes every rejected X509 user certificate to a dedicated review store, pki/rejectedUser (a sibling of pki/trustedUser). After one failing activation you can move the legitimate user certificate from pki/rejectedUser/certs into pki/trustedUser/certs (and any issuing CA into pki/issuerUser/certs) and reconnect. Deliberately-untrusted certificates simply stay out of the trusted store and continue to be rejected.