@hla4ts/session
v0.1.1
Published
HLA 4 Federate Protocol Session Layer - State machine, heartbeats, reconnection
Maintainers
Readme
@hla4ts/session
HLA 4 Federate Protocol Session Layer
This package provides session management for the HLA 4 Federate Protocol, handling connection establishment, state machine, heartbeats, request/response correlation, and session resumption.
Overview
The session layer sits between the transport layer and the HLA API layer, providing:
- Session lifecycle management - NEW → STARTING → RUNNING ⇄ DROPPED → TERMINATED
- Request/response correlation - Matches HLA call responses to requests
- Heartbeat support - Keep-alive mechanism for connection health
- Session resumption - Reconnect and resume after network drops
- Timeout management - Connection and response timeouts
Installation
bun add @hla4ts/sessionQuick Start
import { Session, SessionState } from '@hla4ts/session';
import { TlsTransport } from '@hla4ts/transport';
// Create transport and session
const transport = new TlsTransport({
host: 'rti.example.com',
port: 15165,
});
const session = new Session(transport, {
connectionTimeout: 30000,
responseTimeout: 180000,
});
// Listen for state changes
session.addStateListener({
onStateTransition: (oldState, newState, reason) => {
console.log(`Session: ${oldState} -> ${newState} (${reason})`);
// Handle connection drops
if (newState === SessionState.DROPPED) {
session.resume().catch((err) => {
console.error('Resume failed:', err);
session.terminate();
});
}
}
});
// Start the session
await session.start({
onHlaCallbackRequest: (seqNum, callbackData) => {
// Process the callback (decode protobuf, handle it, encode response)
const response = processCallback(callbackData);
session.sendHlaCallbackResponse(seqNum, response);
}
});
// Send HLA calls
const response = await session.sendHlaCallRequest(encodedCall);
// When done
await session.terminate();Sequence Diagram
sequenceDiagram
participant App as Federate Code
participant Session
participant Transport
participant RTI
App->>Session: start(callbackListener)
Session->>Transport: CTRL_NEW_SESSION
Transport-->>RTI: framed message
RTI-->>Transport: CTRL_NEW_SESSION_STATUS
Transport-->>Session: onMessage
App->>Session: sendHlaCallRequest(bytes)
Session->>Transport: HLA_CALL_REQUEST
RTI-->>Transport: HLA_CALL_RESPONSE
Transport-->>Session: onMessageSession States
The session follows a well-defined state machine:
┌───────┐
│ NEW │────────────────────┐
└───┬───┘ │
│ start() │
▼ │
┌──────────┐ │
│ STARTING │─────────────────┤
└────┬─────┘ │
│ success │ failure
▼ │
┌─────────┐ │
│ RUNNING │◄─────────────┐ │
└────┬────┘ │ │
│ │ │
│ connection lost │ resume()
▼ │ │
┌─────────┐ ┌────┴────┐
│ DROPPED │────────►│ RESUMING│
└────┬────┘ └────┬────┘
│ │
│ terminate() │ failure
▼ │
┌─────────────┐ │
│ TERMINATING │ │
└──────┬──────┘ │
│ │
▼ ▼
┌────────────┐◄──────────┘
│ TERMINATED │
└────────────┘State Descriptions
| State | Description |
|-------|-------------|
| NEW | Session created but not started |
| STARTING | Connecting to RTI, establishing session |
| RUNNING | Session active, can send/receive HLA messages |
| DROPPED | Connection lost, can attempt resume |
| RESUMING | Attempting to resume dropped session |
| TERMINATING | Graceful shutdown in progress |
| TERMINATED | Session ended, cannot be reused |
API Reference
Session Class
Constructor
new Session(transport: Transport, options?: SessionOptions)Options:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| connectionTimeout | number | 30000 | Timeout for initial connection (ms) |
| responseTimeout | number | 180000 | Timeout for server responses (ms) |
| maxRetryAttempts | number | 3 | Max connection retry attempts |
| messageQueueSize | number | 1000 | Size of outgoing message queue |
| rateLimitEnabled | boolean | false | Enable rate limiting |
| heartbeatInterval | number | 10000 | Heartbeat check interval (ms) |
Properties
session.id: bigint // Session ID (0 if not established)
session.state: SessionState // Current state
session.isOperational: boolean // True if can send/receive messagesMethods
start(callbackListener)
Start the session and connect to the RTI.
await session.start({
onHlaCallbackRequest: (seqNum: number, callback: Uint8Array) => {
// Handle callback
}
});resume()
Resume a dropped session.
const success = await session.resume();sendHeartbeat()
Send a heartbeat message (useful for keeping connection alive).
await session.sendHeartbeat();sendHlaCallRequest(encodedHlaCall)
Send an HLA call and wait for the response.
const response = await session.sendHlaCallRequest(encodedCall);sendHlaCallbackResponse(responseToSequenceNumber, encodedResponse)
Send a response to an HLA callback.
await session.sendHlaCallbackResponse(seqNum, encodedResponse);terminate(timeoutMs?)
Gracefully terminate the session.
await session.terminate();addStateListener(listener)
Register a state change listener.
session.addStateListener({
onStateTransition: (oldState, newState, reason) => {
console.log(`${oldState} -> ${newState}: ${reason}`);
}
});setMessageSentListener(listener)
Set a listener for outgoing messages (useful for heartbeat timing).
session.setMessageSentListener({
onMessageSent: () => {
// Reset heartbeat timer
}
});Error Handling
The session layer throws specific errors:
import {
SessionLostError,
SessionAlreadyTerminatedError,
SessionIllegalStateError,
BadMessageError,
ConnectionTimeoutError,
ResponseTimeoutError,
} from '@hla4ts/session';
try {
await session.start(listener);
} catch (err) {
if (err instanceof ConnectionTimeoutError) {
console.error('Could not connect to RTI');
} else if (err instanceof SessionLostError) {
console.error('Session lost:', err.message);
}
}Sequence Numbers
The package exports utilities for working with Federate Protocol sequence numbers:
import {
SequenceNumber,
AtomicSequenceNumber,
isValidSequenceNumber,
nextSequenceNumber,
NO_SEQUENCE_NUMBER,
INITIAL_SEQUENCE_NUMBER,
MAX_SEQUENCE_NUMBER,
} from '@hla4ts/session';
// Mutable sequence number
const seq = new SequenceNumber(0);
seq.increment(); // Returns 1
seq.getAndIncrement(); // Returns 1, then increments to 2
// For concurrent access
const atomic = new AtomicSequenceNumber(0);
atomic.compareAndSet(0, 1); // Returns true if successful
// Utilities
isValidSequenceNumber(100); // true
isValidSequenceNumber(-1); // false
nextSequenceNumber(MAX_SEQUENCE_NUMBER); // Returns 0 (wrap-around)Timers
The package includes timer utilities for session management:
import { TimeoutTimer, OneShotTimer } from '@hla4ts/session';
// Periodic timeout timer
const timer = TimeoutTimer.createLazy(30000); // 30 second timeout
timer.start(() => {
console.log('Timeout!');
});
timer.extend(); // Reset the timeout
timer.pause(); // Stop checking
timer.resume(); // Resume checking
timer.cancel(); // Permanently cancel
// One-shot timer
const oneShot = new OneShotTimer();
oneShot.schedule(() => {
console.log('Fired!');
}, 5000);
oneShot.clear(); // Cancel before it fires
oneShot.cancel(); // Permanently cancelMessage Encoding (Advanced)
For advanced use cases, you can encode/decode session control messages directly:
import {
createNewSessionMessage,
createHeartbeatMessage,
createHlaCallRequestMessage,
decodeHlaCallResponse,
decodeHlaCallbackRequest,
} from '@hla4ts/session';
// Create a new session message
const newSessionMsg = createNewSessionMessage();
// Create an HLA call request
const callMsg = createHlaCallRequestMessage(
sequenceNumber,
sessionId,
lastReceivedSequenceNumber,
protobufPayload
);
// Decode an HLA call response
const response = decodeHlaCallResponse(payload);
console.log(response.responseToSequenceNumber);
console.log(response.hlaServiceReturnValueOrException);Testing
cd packages/session
bun testRelated Packages
@hla4ts/transport- Transport layer (TCP/TLS)@hla4ts/proto- Protocol buffer types@hla4ts/hla-api- High-level HLA API facade
References
- IEEE 1516-2025 - HLA 4 Standard
- Pitch FedProClient - Reference implementation
License
MIT
