npm package: @hla4ts/session
Description: HLA 4 Federate Protocol Session Layer - State machine, heartbeats, reconnection
Latest version: 0.1.1

# @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

```bash
bun add @hla4ts/session
```

## Quick Start

```typescript
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

```mermaid
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: onMessage
```

## Session 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

```typescript
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

```typescript
session.id: bigint           // Session ID (0 if not established)
session.state: SessionState  // Current state
session.isOperational: boolean // True if can send/receive messages
```

#### Methods

##### `start(callbackListener)`

Start the session and connect to the RTI.

```typescript
await session.start({
  onHlaCallbackRequest: (seqNum: number, callback: Uint8Array) => {
    // Handle callback
  }
});
```

##### `resume()`

Resume a dropped session.

```typescript
const success = await session.resume();
```

##### `sendHeartbeat()`

Send a heartbeat message (useful for keeping connection alive).

```typescript
await session.sendHeartbeat();
```

##### `sendHlaCallRequest(encodedHlaCall)`

Send an HLA call and wait for the response.

```typescript
const response = await session.sendHlaCallRequest(encodedCall);
```

##### `sendHlaCallbackResponse(responseToSequenceNumber, encodedResponse)`

Send a response to an HLA callback.

```typescript
await session.sendHlaCallbackResponse(seqNum, encodedResponse);
```

##### `terminate(timeoutMs?)`

Gracefully terminate the session.

```typescript
await session.terminate();
```

##### `addStateListener(listener)`

Register a state change listener.

```typescript
session.addStateListener({
  onStateTransition: (oldState, newState, reason) => {
    console.log(`${oldState} -> ${newState}: ${reason}`);
  }
});
```

##### `setMessageSentListener(listener)`

Set a listener for outgoing messages (useful for heartbeat timing).

```typescript
session.setMessageSentListener({
  onMessageSent: () => {
    // Reset heartbeat timer
  }
});
```

## Error Handling

The session layer throws specific errors:

```typescript
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:

```typescript
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:

```typescript
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 cancel
```

## Message Encoding (Advanced)

For advanced use cases, you can encode/decode session control messages directly:

```typescript
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

```bash
cd packages/session
bun test
```

## Related Packages

- [`@hla4ts/transport`](../transport) - Transport layer (TCP/TLS)
- [`@hla4ts/proto`](../proto) - Protocol buffer types
- [`@hla4ts/hla-api`](../hla-api) - High-level HLA API facade

## References

- [IEEE 1516-2025](https://standards.ieee.org/standard/1516-2025.html) - HLA 4 Standard
- [Pitch FedProClient](https://github.com/Pitch-Technologies/FedProClient) - Reference implementation

## License

MIT