Skip to content
Start free evaluation

PDComm.HsmsEndpoint

Class

A synchronous HSMS (SEMI E37) endpoint that exchanges SECS-II messages over TCP/IP.

public sealed class HsmsEndpoint : IDisposable

The endpoint creates no threads and no callbacks: your code drives it. Call HsmsEndpoint.Start, then repeatedly call HsmsEndpoint.Poll to advance timers and socket I/O and HsmsEndpoint.NextEvent to read state changes, received messages and failures. An active endpoint connects and sends Select.req by itself; a passive endpoint binds its listening socket in HsmsEndpoint.Create. For a ready-made polling loop, use HsmsWorker.

Every method takes an internal lock, so calls from several threads are serialized. HsmsEndpoint.Poll can hold the lock for up to HsmsOptions.ConnectTimeoutMilliseconds during a connection attempt.

The endpoint owns a native handle. For a graceful close, call HsmsEndpoint.Stop, keep polling and reading events until HsmsState.Closed is true, then call HsmsEndpoint.Dispose. Disposing earlier releases the resources without a graceful wire shutdown. Events returned by HsmsEndpoint.NextEvent own their data and stay valid after the endpoint is disposed.

Success of HsmsEndpoint.Request and similar methods only means the message was queued; the outcome arrives later as an event that carries the same HsmsToken.

PdcommRuntime.Initialize(libraryPath);
using var endpoint = HsmsEndpoint.Create("127.0.0.1:5000", options); // options.Mode == HsmsMode.Active
endpoint.Start();
HsmsToken request = default;
while (true)
{
    endpoint.Poll();
    if (request == default && endpoint.GetState().State == HsmsConnectionState.Selected)
    {
        request = endpoint.Request(1, 1, true, ReadOnlySpan<byte>.Empty); // S1F1 W
    }
    using HsmsEvent? next = endpoint.NextEvent();
    if (next?.GetInfo() is { Kind: HsmsEventKind.Received, IsReply: true } info && info.Token == request)
    {
        Console.WriteLine($"S{info.Header!.Value.Stream}F{info.Header.Value.Function}, {info.BodyLength} bytes");
        break;
    }
}

Members

Cancel

Method

Cancels an open transaction of this endpoint.

public bool Cancel(HsmsToken token)

A cancelled request completes with a HsmsFailureReason.Cancelled failure event. Cancelling a partially written message may close the connection; bytes already on the wire are not retracted.

Parameters

NameDescription
tokenThe token returned when the transaction started.

Returns

true if the transaction was open and is now cancelled; otherwise false.

Notes

  • Throws ObjectDisposedException: The endpoint has been disposed.
  • Throws PdcommException: The native call failed.

Create

Method

Creates an HSMS endpoint.

public static HsmsEndpoint Create(string numericAddress, HsmsOptions options)

Parameters

NameDescription
numericAddressA numeric IPv4 or IPv6 socket address such as 127.0.0.1:5000 or [::1]:5000; host names are not resolved. An active endpoint connects to it; a passive endpoint listens on it (port 0 selects a free port, see HsmsEndpoint.GetLocalAddress).
optionsThe role, session, timers and limits of the endpoint.

Returns

A new endpoint that the caller owns and must dispose.

Notes

  • Throws ArgumentNullException: numericAddress or options is null.
  • Throws EncoderFallbackException: numericAddress contains an unpaired surrogate.
  • Throws PdcommException: The address is not a numeric socket address or an option is zero or invalid (PdcommStatus.InvalidArgument), the limits are inconsistent (PdcommStatus.LimitExceeded), or a passive endpoint could not bind its socket (PdcommStatus.IoError).

Deselect

Method

Sends Deselect.req to end the selected HSMS session without closing the connection.

public HsmsToken Deselect()

Returns

The token of the control transaction; its outcome arrives as an event.

Notes

  • Throws ObjectDisposedException: The endpoint has been disposed.
  • Throws PdcommException: The session is not selected (PdcommStatus.InvalidState), or a Deselect is already pending (PdcommStatus.Backpressure).

Dispose

Method

Releases the native endpoint and closes its sockets.

public void Dispose()

Disposal does not perform a graceful HSMS shutdown; call HsmsEndpoint.Stop and drain events first for that. Events already taken from the endpoint stay valid. Calling this method more than once has no effect.

GetLocalAddress

Method

Gets the local socket address, for example the port a passive endpoint actually listens on.

public string GetLocalAddress()

Returns

The numeric local socket address, such as 127.0.0.1:50123.

Notes

  • Throws ObjectDisposedException: The endpoint has been disposed.
  • Throws PdcommException: No socket is open, for example on an active endpoint before it connects (PdcommStatus.IoError).

GetState

Method

Gets the endpoint's connection state.

public HsmsState GetState()

Returns

A snapshot of the endpoint state.

Notes

  • Throws ObjectDisposedException: The endpoint has been disposed.
  • Throws PdcommException: The native call failed.

IsPending

Method

Determines whether a transaction of this endpoint is still open.

public bool IsPending(HsmsToken token)

Parameters

NameDescription
tokenThe token returned when the transaction started.

Returns

true if the transaction has not completed yet; otherwise false.

Notes

  • Throws ObjectDisposedException: The endpoint has been disposed.
  • Throws PdcommException: The native call failed.

Linktest

Method

Sends Linktest.req to check that the connection is alive.

public HsmsToken Linktest()

Returns

The token of the control transaction; a failure within T6 arrives as a HsmsEventKind.Failed event.

Notes

  • Throws ObjectDisposedException: The endpoint has been disposed.
  • Throws PdcommException: No connection is open (PdcommStatus.InvalidState), or a Linktest is already pending (PdcommStatus.Backpressure).

NextEvent

Method

Takes the next queued event.

public HsmsEvent? NextEvent()

An empty queue does not mean the session is finished; keep polling.

Returns

The next event, which the caller owns and must dispose, or null when no event is queued.

Notes

  • Throws ObjectDisposedException: The endpoint has been disposed.
  • Throws PdcommException: The event could not be allocated (PdcommStatus.AllocationFailed; the event stays queued, so retry), or the endpoint is poisoned.

Poll

Method

Advances timers, connection handling and socket I/O.

public nuint Poll()

Can block for up to HsmsOptions.ConnectTimeoutMilliseconds during a connection attempt.

Returns

The number of internal actions performed, at most HsmsOptions.PollBudget. This is not the number of events produced, and zero does not mean the session is finished.

Notes

  • Throws ObjectDisposedException: The endpoint has been disposed.
  • Throws PdcommException: The event queues are full (PdcommStatus.Backpressure; read events with HsmsEndpoint.NextEvent first), or the endpoint failed.

Reply

Method

Queues the reply to a received primary message.

public void Reply(HsmsEvent primary, byte stream, byte function, bool replyExpected, ReadOnlySpan<byte> body)

Parameters

NameDescription
primaryThe received primary event that expects a reply.
streamThe reply's stream number, normally the primary's stream.
functionThe reply's function number, normally the primary's function plus one, or 0 to abort.
replyExpectedWhether to set the W bit on the reply; normally false.
bodyOne complete encoded SECS-II item, or an empty span for a header-only reply.

Notes

  • Throws ArgumentNullException: primary is null.
  • Throws ObjectDisposedException: The endpoint or primary has been disposed.
  • Throws PdcommException: primary belongs to another endpoint or connection (PdcommStatus.StaleToken), was already answered or is not a primary that expects a reply (PdcommStatus.InvalidArgument), the body exceeds the frame or item limits (PdcommStatus.LimitExceeded), or the reply cannot be queued.

Request

Method

Queues a primary data message.

public HsmsToken Request(byte stream, byte function, bool replyExpected, ReadOnlySpan<byte> body)

The body is copied. Success means the message was queued. If replyExpected is true, a HsmsEventKind.Received reply or a HsmsEventKind.Failed event with the returned token completes the transaction; otherwise a HsmsEventKind.W0Written event reports the local write.

Parameters

NameDescription
streamThe SECS-II stream number (0 to 127).
functionThe SECS-II function number; primary messages use odd numbers.
replyExpectedWhether to set the W bit and wait for a reply within T3.
bodyOne complete encoded SECS-II item, or an empty span for a header-only message.

Returns

The token that identifies the transaction in later events.

Notes

  • Throws ObjectDisposedException: The endpoint has been disposed.
  • Throws PdcommException: The session is not selected (PdcommStatus.InvalidState), too many transactions or bytes are queued (PdcommStatus.Backpressure), the body exceeds the frame or item limits (PdcommStatus.LimitExceeded), or the body is not a valid SECS-II item.

Select

Method

Sends Select.req to select the HSMS session.

public HsmsToken Select()

An active endpoint selects automatically after connecting; use this method to select again.

Returns

The token of the control transaction; its outcome arrives as an event.

Notes

  • Throws ObjectDisposedException: The endpoint has been disposed.
  • Throws PdcommException: The connection is not in the HsmsConnectionState.NotSelected state (PdcommStatus.InvalidState), or a Select is already pending (PdcommStatus.Backpressure).

Start

Method

Starts connecting (active) or listening (passive).

public void Start()

Notes

  • Throws ObjectDisposedException: The endpoint has been disposed.
  • Throws PdcommException: The endpoint cannot start in its current state.

Stop

Method

Begins a graceful shutdown of the connection.

public void Stop()

Keep calling HsmsEndpoint.Poll and HsmsEndpoint.NextEvent until HsmsEndpoint.GetState reports HsmsState.Closed; the shutdown is bounded by HsmsOptions.ShutdownTimeoutMilliseconds.

Notes

  • Throws ObjectDisposedException: The endpoint has been disposed.
  • Throws PdcommException: The endpoint cannot stop in its current state.