@hla4ts/transport 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,141 +1,141 @@
1
- /**
2
- * Federate Protocol Message Header
3
- *
4
- * The message header is a 24-byte structure that precedes every message
5
- * in the Federate Protocol. It contains:
6
- *
7
- * - packetSize (4 bytes): Total size of the packet including header
8
- * - sequenceNumber (4 bytes): Monotonically increasing sequence number
9
- * - sessionId (8 bytes): Unique session identifier
10
- * - lastReceivedSequenceNumber (4 bytes): ACK for flow control
11
- * - messageType (4 bytes): Type of message (see MessageType enum)
12
- */
13
-
14
- import { MessageType } from "./message-type.ts";
15
-
16
- /** Size of the message header in bytes */
17
- export const HEADER_SIZE = 24;
18
-
19
- /** Special value indicating no session ID */
20
- export const NO_SESSION_ID = 0n;
21
-
22
- /** Special value indicating no sequence number */
23
- export const NO_SEQUENCE_NUMBER = 0;
24
-
25
- /**
26
- * Decoded message header
27
- */
28
- export interface MessageHeader {
29
- /** Total packet size including header */
30
- packetSize: number;
31
- /** Message sequence number */
32
- sequenceNumber: number;
33
- /** Session identifier */
34
- sessionId: bigint;
35
- /** Last received sequence number (for ACK) */
36
- lastReceivedSequenceNumber: number;
37
- /** Type of message */
38
- messageType: MessageType;
39
- }
40
-
41
- /**
42
- * Encode a message header into a 24-byte buffer
43
- */
44
- export function encodeHeader(
45
- payloadSize: number,
46
- sequenceNumber: number,
47
- sessionId: bigint,
48
- lastReceivedSequenceNumber: number,
49
- messageType: MessageType
50
- ): Uint8Array {
51
- const packetSize = HEADER_SIZE + payloadSize;
52
- const buffer = new ArrayBuffer(HEADER_SIZE);
53
- const view = new DataView(buffer);
54
-
55
- // All values are big-endian (network byte order)
56
- view.setUint32(0, packetSize, false);
57
- view.setUint32(4, sequenceNumber, false);
58
- view.setBigUint64(8, sessionId, false);
59
- view.setUint32(16, lastReceivedSequenceNumber, false);
60
- view.setUint32(20, messageType, false);
61
-
62
- return new Uint8Array(buffer);
63
- }
64
-
65
- /**
66
- * Decode a message header from a 24-byte buffer
67
- * @throws Error if buffer is too small or contains invalid data
68
- */
69
- export function decodeHeader(buffer: Uint8Array): MessageHeader {
70
- if (buffer.length < HEADER_SIZE) {
71
- throw new Error(
72
- `Buffer too small for header: expected ${HEADER_SIZE} bytes, got ${buffer.length}`
73
- );
74
- }
75
-
76
- const view = new DataView(
77
- buffer.buffer,
78
- buffer.byteOffset,
79
- buffer.byteLength
80
- );
81
-
82
- const packetSize = view.getUint32(0, false);
83
- if (packetSize < HEADER_SIZE) {
84
- throw new Error(`Invalid packet size: ${packetSize} (minimum is ${HEADER_SIZE})`);
85
- }
86
-
87
- const sequenceNumber = view.getUint32(4, false);
88
- const sessionId = view.getBigUint64(8, false);
89
- const lastReceivedSequenceNumber = view.getUint32(16, false);
90
- const messageTypeValue = view.getUint32(20, false);
91
-
92
- // Validate message type
93
- if (!Object.values(MessageType).includes(messageTypeValue)) {
94
- throw new Error(`Unknown message type: ${messageTypeValue}`);
95
- }
96
-
97
- return {
98
- packetSize,
99
- sequenceNumber,
100
- sessionId,
101
- lastReceivedSequenceNumber,
102
- messageType: messageTypeValue as MessageType,
103
- };
104
- }
105
-
106
- /**
107
- * Get the payload size from a header
108
- */
109
- export function getPayloadSize(header: MessageHeader): number {
110
- return header.packetSize - HEADER_SIZE;
111
- }
112
-
113
- /**
114
- * Encode a complete message (header + payload)
115
- */
116
- export function encodeMessage(
117
- sequenceNumber: number,
118
- sessionId: bigint,
119
- lastReceivedSequenceNumber: number,
120
- messageType: MessageType,
121
- payload?: Uint8Array
122
- ): Uint8Array {
123
- const payloadSize = payload?.length ?? 0;
124
- const header = encodeHeader(
125
- payloadSize,
126
- sequenceNumber,
127
- sessionId,
128
- lastReceivedSequenceNumber,
129
- messageType
130
- );
131
-
132
- if (payloadSize === 0) {
133
- return header;
134
- }
135
-
136
- // Combine header and payload
137
- const message = new Uint8Array(HEADER_SIZE + payloadSize);
138
- message.set(header, 0);
139
- message.set(payload!, HEADER_SIZE);
140
- return message;
141
- }
1
+ /**
2
+ * Federate Protocol Message Header
3
+ *
4
+ * The message header is a 24-byte structure that precedes every message
5
+ * in the Federate Protocol. It contains:
6
+ *
7
+ * - packetSize (4 bytes): Total size of the packet including header
8
+ * - sequenceNumber (4 bytes): Monotonically increasing sequence number
9
+ * - sessionId (8 bytes): Unique session identifier
10
+ * - lastReceivedSequenceNumber (4 bytes): ACK for flow control
11
+ * - messageType (4 bytes): Type of message (see MessageType enum)
12
+ */
13
+
14
+ import { MessageType } from "./message-type.ts";
15
+
16
+ /** Size of the message header in bytes */
17
+ export const HEADER_SIZE = 24;
18
+
19
+ /** Special value indicating no session ID */
20
+ export const NO_SESSION_ID = 0n;
21
+
22
+ /** Special value indicating no sequence number */
23
+ export const NO_SEQUENCE_NUMBER = 0;
24
+
25
+ /**
26
+ * Decoded message header
27
+ */
28
+ export interface MessageHeader {
29
+ /** Total packet size including header */
30
+ packetSize: number;
31
+ /** Message sequence number */
32
+ sequenceNumber: number;
33
+ /** Session identifier */
34
+ sessionId: bigint;
35
+ /** Last received sequence number (for ACK) */
36
+ lastReceivedSequenceNumber: number;
37
+ /** Type of message */
38
+ messageType: MessageType;
39
+ }
40
+
41
+ /**
42
+ * Encode a message header into a 24-byte buffer
43
+ */
44
+ export function encodeHeader(
45
+ payloadSize: number,
46
+ sequenceNumber: number,
47
+ sessionId: bigint,
48
+ lastReceivedSequenceNumber: number,
49
+ messageType: MessageType
50
+ ): Uint8Array {
51
+ const packetSize = HEADER_SIZE + payloadSize;
52
+ const buffer = new ArrayBuffer(HEADER_SIZE);
53
+ const view = new DataView(buffer);
54
+
55
+ // All values are big-endian (network byte order)
56
+ view.setUint32(0, packetSize, false);
57
+ view.setUint32(4, sequenceNumber, false);
58
+ view.setBigUint64(8, sessionId, false);
59
+ view.setUint32(16, lastReceivedSequenceNumber, false);
60
+ view.setUint32(20, messageType, false);
61
+
62
+ return new Uint8Array(buffer);
63
+ }
64
+
65
+ /**
66
+ * Decode a message header from a 24-byte buffer
67
+ * @throws Error if buffer is too small or contains invalid data
68
+ */
69
+ export function decodeHeader(buffer: Uint8Array): MessageHeader {
70
+ if (buffer.length < HEADER_SIZE) {
71
+ throw new Error(
72
+ `Buffer too small for header: expected ${HEADER_SIZE} bytes, got ${buffer.length}`
73
+ );
74
+ }
75
+
76
+ const view = new DataView(
77
+ buffer.buffer,
78
+ buffer.byteOffset,
79
+ buffer.byteLength
80
+ );
81
+
82
+ const packetSize = view.getUint32(0, false);
83
+ if (packetSize < HEADER_SIZE) {
84
+ throw new Error(`Invalid packet size: ${packetSize} (minimum is ${HEADER_SIZE})`);
85
+ }
86
+
87
+ const sequenceNumber = view.getUint32(4, false);
88
+ const sessionId = view.getBigUint64(8, false);
89
+ const lastReceivedSequenceNumber = view.getUint32(16, false);
90
+ const messageTypeValue = view.getUint32(20, false);
91
+
92
+ // Validate message type
93
+ if (!Object.values(MessageType).includes(messageTypeValue)) {
94
+ throw new Error(`Unknown message type: ${messageTypeValue}`);
95
+ }
96
+
97
+ return {
98
+ packetSize,
99
+ sequenceNumber,
100
+ sessionId,
101
+ lastReceivedSequenceNumber,
102
+ messageType: messageTypeValue as MessageType,
103
+ };
104
+ }
105
+
106
+ /**
107
+ * Get the payload size from a header
108
+ */
109
+ export function getPayloadSize(header: MessageHeader): number {
110
+ return header.packetSize - HEADER_SIZE;
111
+ }
112
+
113
+ /**
114
+ * Encode a complete message (header + payload)
115
+ */
116
+ export function encodeMessage(
117
+ sequenceNumber: number,
118
+ sessionId: bigint,
119
+ lastReceivedSequenceNumber: number,
120
+ messageType: MessageType,
121
+ payload?: Uint8Array
122
+ ): Uint8Array {
123
+ const payloadSize = payload?.length ?? 0;
124
+ const header = encodeHeader(
125
+ payloadSize,
126
+ sequenceNumber,
127
+ sessionId,
128
+ lastReceivedSequenceNumber,
129
+ messageType
130
+ );
131
+
132
+ if (payloadSize === 0) {
133
+ return header;
134
+ }
135
+
136
+ // Combine header and payload
137
+ const message = new Uint8Array(HEADER_SIZE + payloadSize);
138
+ message.set(header, 0);
139
+ message.set(payload!, HEADER_SIZE);
140
+ return message;
141
+ }
@@ -1,62 +1,62 @@
1
- /**
2
- * Federate Protocol Message Types
3
- *
4
- * These message types are defined in the IEEE 1516-2025 Federate Protocol specification.
5
- * They are used in the message header to indicate the type of message being sent.
6
- */
7
-
8
- export enum MessageType {
9
- // Session Management (Control Messages)
10
- /** Client → Server: Request to create a new session */
11
- CTRL_NEW_SESSION = 1,
12
- /** Server → Client: Response with session creation status */
13
- CTRL_NEW_SESSION_STATUS = 2,
14
- /** Bidirectional: Keep-alive ping */
15
- CTRL_HEARTBEAT = 3,
16
- /** Bidirectional: Keep-alive pong */
17
- CTRL_HEARTBEAT_RESPONSE = 4,
18
- /** Client → Server: Request to terminate session */
19
- CTRL_TERMINATE_SESSION = 5,
20
- /** Server → Client: Confirmation of session termination */
21
- CTRL_SESSION_TERMINATED = 6,
22
-
23
- // Reconnection
24
- /** Client → Server: Request to resume a dropped session */
25
- CTRL_RESUME_REQUEST = 10,
26
- /** Server → Client: Response with resume status */
27
- CTRL_RESUME_STATUS = 11,
28
-
29
- // HLA Calls and Callbacks
30
- /** Client → Server: HLA RTI service call (protobuf CallRequest) */
31
- HLA_CALL_REQUEST = 20,
32
- /** Server → Client: HLA RTI service response (protobuf CallResponse) */
33
- HLA_CALL_RESPONSE = 21,
34
- /** Server → Client: HLA callback to federate (protobuf CallbackRequest) */
35
- HLA_CALLBACK_REQUEST = 22,
36
- /** Client → Server: HLA callback acknowledgment (protobuf CallbackResponse) */
37
- HLA_CALLBACK_RESPONSE = 23,
38
- }
39
-
40
- /**
41
- * Check if a message type is a control message (session management)
42
- */
43
- export function isControlMessage(type: MessageType): boolean {
44
- return type < MessageType.HLA_CALL_REQUEST;
45
- }
46
-
47
- /**
48
- * Check if a message type is an HLA response
49
- */
50
- export function isHlaResponse(type: MessageType): boolean {
51
- return (
52
- type === MessageType.HLA_CALL_RESPONSE ||
53
- type === MessageType.HLA_CALLBACK_RESPONSE
54
- );
55
- }
56
-
57
- /**
58
- * Get a human-readable name for a message type
59
- */
60
- export function messageTypeName(type: MessageType): string {
61
- return MessageType[type] ?? `UNKNOWN(${type})`;
62
- }
1
+ /**
2
+ * Federate Protocol Message Types
3
+ *
4
+ * These message types are defined in the IEEE 1516-2025 Federate Protocol specification.
5
+ * They are used in the message header to indicate the type of message being sent.
6
+ */
7
+
8
+ export enum MessageType {
9
+ // Session Management (Control Messages)
10
+ /** Client → Server: Request to create a new session */
11
+ CTRL_NEW_SESSION = 1,
12
+ /** Server → Client: Response with session creation status */
13
+ CTRL_NEW_SESSION_STATUS = 2,
14
+ /** Bidirectional: Keep-alive ping */
15
+ CTRL_HEARTBEAT = 3,
16
+ /** Bidirectional: Keep-alive pong */
17
+ CTRL_HEARTBEAT_RESPONSE = 4,
18
+ /** Client → Server: Request to terminate session */
19
+ CTRL_TERMINATE_SESSION = 5,
20
+ /** Server → Client: Confirmation of session termination */
21
+ CTRL_SESSION_TERMINATED = 6,
22
+
23
+ // Reconnection
24
+ /** Client → Server: Request to resume a dropped session */
25
+ CTRL_RESUME_REQUEST = 10,
26
+ /** Server → Client: Response with resume status */
27
+ CTRL_RESUME_STATUS = 11,
28
+
29
+ // HLA Calls and Callbacks
30
+ /** Client → Server: HLA RTI service call (protobuf CallRequest) */
31
+ HLA_CALL_REQUEST = 20,
32
+ /** Server → Client: HLA RTI service response (protobuf CallResponse) */
33
+ HLA_CALL_RESPONSE = 21,
34
+ /** Server → Client: HLA callback to federate (protobuf CallbackRequest) */
35
+ HLA_CALLBACK_REQUEST = 22,
36
+ /** Client → Server: HLA callback acknowledgment (protobuf CallbackResponse) */
37
+ HLA_CALLBACK_RESPONSE = 23,
38
+ }
39
+
40
+ /**
41
+ * Check if a message type is a control message (session management)
42
+ */
43
+ export function isControlMessage(type: MessageType): boolean {
44
+ return type < MessageType.HLA_CALL_REQUEST;
45
+ }
46
+
47
+ /**
48
+ * Check if a message type is an HLA response
49
+ */
50
+ export function isHlaResponse(type: MessageType): boolean {
51
+ return (
52
+ type === MessageType.HLA_CALL_RESPONSE ||
53
+ type === MessageType.HLA_CALLBACK_RESPONSE
54
+ );
55
+ }
56
+
57
+ /**
58
+ * Get a human-readable name for a message type
59
+ */
60
+ export function messageTypeName(type: MessageType): string {
61
+ return MessageType[type] ?? `UNKNOWN(${type})`;
62
+ }