@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.
- package/README.md +386 -386
- package/package.json +2 -2
- package/src/constants.ts +57 -57
- package/src/frame-decoder.ts +136 -136
- package/src/index.ts +82 -82
- package/src/message-header.ts +141 -141
- package/src/message-type.ts +62 -62
- package/src/tcp-transport.ts +154 -154
- package/src/tls-transport.ts +193 -193
- package/src/transport.ts +99 -99
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hla4ts/transport",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "HLA 4 Federate Protocol transport layer with TLS and message framing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"test": "bun test"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@hla4ts/proto": "^0.1.
|
|
25
|
+
"@hla4ts/proto": "^0.1.1"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"typescript": "^5.3.3"
|
package/src/constants.ts
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Federate Protocol Constants
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/** Current Federate Protocol version */
|
|
6
|
-
export const FEDERATE_PROTOCOL_VERSION = 1;
|
|
7
|
-
|
|
8
|
-
/** Default ports for different transport protocols */
|
|
9
|
-
export const Ports = {
|
|
10
|
-
/** Plain TCP (unencrypted) */
|
|
11
|
-
TCP: 15164,
|
|
12
|
-
/** TLS over TCP (encrypted) */
|
|
13
|
-
TLS: 15165,
|
|
14
|
-
/** WebSocket (unencrypted) */
|
|
15
|
-
WS: 80,
|
|
16
|
-
/** WebSocket Secure (encrypted) */
|
|
17
|
-
WSS: 443,
|
|
18
|
-
} as const;
|
|
19
|
-
|
|
20
|
-
/** Transport protocol names */
|
|
21
|
-
export const Protocol = {
|
|
22
|
-
TCP: "tcp",
|
|
23
|
-
TLS: "tls",
|
|
24
|
-
WS: "websocket",
|
|
25
|
-
WSS: "websocketsecure",
|
|
26
|
-
} as const;
|
|
27
|
-
|
|
28
|
-
export type ProtocolType = (typeof Protocol)[keyof typeof Protocol];
|
|
29
|
-
|
|
30
|
-
/** New session status reason codes */
|
|
31
|
-
export const NewSessionStatus = {
|
|
32
|
-
/** Session created successfully */
|
|
33
|
-
SUCCESS: 0,
|
|
34
|
-
/** Server doesn't support the requested protocol version */
|
|
35
|
-
UNSUPPORTED_PROTOCOL_VERSION: 1,
|
|
36
|
-
/** Server is out of resources */
|
|
37
|
-
OUT_OF_RESOURCES: 2,
|
|
38
|
-
/** Bad message received */
|
|
39
|
-
BAD_MESSAGE: 3,
|
|
40
|
-
/** Other unspecified error */
|
|
41
|
-
OTHER_ERROR: 99,
|
|
42
|
-
} as const;
|
|
43
|
-
|
|
44
|
-
export type NewSessionStatusCode =
|
|
45
|
-
(typeof NewSessionStatus)[keyof typeof NewSessionStatus];
|
|
46
|
-
|
|
47
|
-
/** Resume status reason codes */
|
|
48
|
-
export const ResumeStatus = {
|
|
49
|
-
/** Resume successful */
|
|
50
|
-
SUCCESS: 0,
|
|
51
|
-
/** Session not found (expired or invalid) */
|
|
52
|
-
SESSION_NOT_FOUND: 1,
|
|
53
|
-
/** Resume not allowed in current state */
|
|
54
|
-
NOT_ALLOWED: 2,
|
|
55
|
-
} as const;
|
|
56
|
-
|
|
57
|
-
export type ResumeStatusCode = (typeof ResumeStatus)[keyof typeof ResumeStatus];
|
|
1
|
+
/**
|
|
2
|
+
* Federate Protocol Constants
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** Current Federate Protocol version */
|
|
6
|
+
export const FEDERATE_PROTOCOL_VERSION = 1;
|
|
7
|
+
|
|
8
|
+
/** Default ports for different transport protocols */
|
|
9
|
+
export const Ports = {
|
|
10
|
+
/** Plain TCP (unencrypted) */
|
|
11
|
+
TCP: 15164,
|
|
12
|
+
/** TLS over TCP (encrypted) */
|
|
13
|
+
TLS: 15165,
|
|
14
|
+
/** WebSocket (unencrypted) */
|
|
15
|
+
WS: 80,
|
|
16
|
+
/** WebSocket Secure (encrypted) */
|
|
17
|
+
WSS: 443,
|
|
18
|
+
} as const;
|
|
19
|
+
|
|
20
|
+
/** Transport protocol names */
|
|
21
|
+
export const Protocol = {
|
|
22
|
+
TCP: "tcp",
|
|
23
|
+
TLS: "tls",
|
|
24
|
+
WS: "websocket",
|
|
25
|
+
WSS: "websocketsecure",
|
|
26
|
+
} as const;
|
|
27
|
+
|
|
28
|
+
export type ProtocolType = (typeof Protocol)[keyof typeof Protocol];
|
|
29
|
+
|
|
30
|
+
/** New session status reason codes */
|
|
31
|
+
export const NewSessionStatus = {
|
|
32
|
+
/** Session created successfully */
|
|
33
|
+
SUCCESS: 0,
|
|
34
|
+
/** Server doesn't support the requested protocol version */
|
|
35
|
+
UNSUPPORTED_PROTOCOL_VERSION: 1,
|
|
36
|
+
/** Server is out of resources */
|
|
37
|
+
OUT_OF_RESOURCES: 2,
|
|
38
|
+
/** Bad message received */
|
|
39
|
+
BAD_MESSAGE: 3,
|
|
40
|
+
/** Other unspecified error */
|
|
41
|
+
OTHER_ERROR: 99,
|
|
42
|
+
} as const;
|
|
43
|
+
|
|
44
|
+
export type NewSessionStatusCode =
|
|
45
|
+
(typeof NewSessionStatus)[keyof typeof NewSessionStatus];
|
|
46
|
+
|
|
47
|
+
/** Resume status reason codes */
|
|
48
|
+
export const ResumeStatus = {
|
|
49
|
+
/** Resume successful */
|
|
50
|
+
SUCCESS: 0,
|
|
51
|
+
/** Session not found (expired or invalid) */
|
|
52
|
+
SESSION_NOT_FOUND: 1,
|
|
53
|
+
/** Resume not allowed in current state */
|
|
54
|
+
NOT_ALLOWED: 2,
|
|
55
|
+
} as const;
|
|
56
|
+
|
|
57
|
+
export type ResumeStatusCode = (typeof ResumeStatus)[keyof typeof ResumeStatus];
|
package/src/frame-decoder.ts
CHANGED
|
@@ -1,136 +1,136 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Frame Decoder
|
|
3
|
-
*
|
|
4
|
-
* Handles accumulating partial data from the network and extracting
|
|
5
|
-
* complete framed messages. This is necessary because TCP is a stream
|
|
6
|
-
* protocol and messages may arrive in fragments or multiple messages
|
|
7
|
-
* may arrive in a single chunk.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
HEADER_SIZE,
|
|
12
|
-
decodeHeader,
|
|
13
|
-
type MessageHeader,
|
|
14
|
-
} from "./message-header.ts";
|
|
15
|
-
import type { ReceivedMessage } from "./transport.ts";
|
|
16
|
-
|
|
17
|
-
/** Maximum allowed message size (16 MB) - protection against malformed packets */
|
|
18
|
-
const MAX_MESSAGE_SIZE = 16 * 1024 * 1024;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Frame decoder for length-prefixed messages
|
|
22
|
-
*
|
|
23
|
-
* Usage:
|
|
24
|
-
* ```ts
|
|
25
|
-
* const decoder = new FrameDecoder();
|
|
26
|
-
* decoder.onMessage = (msg) => console.log('Got message:', msg);
|
|
27
|
-
*
|
|
28
|
-
* // Feed data as it arrives from the socket
|
|
29
|
-
* socket.on('data', (chunk) => decoder.push(chunk));
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
export class FrameDecoder {
|
|
33
|
-
private buffer: Uint8Array = new Uint8Array(0);
|
|
34
|
-
private pendingHeader: MessageHeader | null = null;
|
|
35
|
-
|
|
36
|
-
/** Callback for complete messages */
|
|
37
|
-
public onMessage: ((message: ReceivedMessage) => void) | null = null;
|
|
38
|
-
|
|
39
|
-
/** Callback for decode errors */
|
|
40
|
-
public onError: ((error: Error) => void) | null = null;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Push incoming data into the decoder
|
|
44
|
-
* @param chunk Data received from the network
|
|
45
|
-
*/
|
|
46
|
-
push(chunk: Uint8Array): void {
|
|
47
|
-
// Append chunk to buffer
|
|
48
|
-
this.buffer = this.concat(this.buffer, chunk);
|
|
49
|
-
|
|
50
|
-
// Process as many complete messages as possible
|
|
51
|
-
this.processBuffer();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Reset the decoder state (e.g., after a connection reset)
|
|
56
|
-
*/
|
|
57
|
-
reset(): void {
|
|
58
|
-
this.buffer = new Uint8Array(0);
|
|
59
|
-
this.pendingHeader = null;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Get the number of bytes currently buffered
|
|
64
|
-
*/
|
|
65
|
-
get bufferedBytes(): number {
|
|
66
|
-
return this.buffer.length;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
private processBuffer(): void {
|
|
70
|
-
while (true) {
|
|
71
|
-
// If we don't have a header yet, try to read one
|
|
72
|
-
if (this.pendingHeader === null) {
|
|
73
|
-
if (this.buffer.length < HEADER_SIZE) {
|
|
74
|
-
// Not enough data for header yet
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
this.pendingHeader = decodeHeader(this.buffer.subarray(0, HEADER_SIZE));
|
|
80
|
-
} catch (error) {
|
|
81
|
-
this.onError?.(error as Error);
|
|
82
|
-
// Skip one byte and try again (attempt to resync)
|
|
83
|
-
this.buffer = this.buffer.subarray(1);
|
|
84
|
-
continue;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Validate packet size
|
|
88
|
-
if (this.pendingHeader.packetSize > MAX_MESSAGE_SIZE) {
|
|
89
|
-
this.onError?.(
|
|
90
|
-
new Error(
|
|
91
|
-
`Message too large: ${this.pendingHeader.packetSize} bytes (max: ${MAX_MESSAGE_SIZE})`
|
|
92
|
-
)
|
|
93
|
-
);
|
|
94
|
-
// Reset and skip this header
|
|
95
|
-
this.pendingHeader = null;
|
|
96
|
-
this.buffer = this.buffer.subarray(HEADER_SIZE);
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// We have a header, check if we have the complete message
|
|
102
|
-
const totalSize = this.pendingHeader.packetSize;
|
|
103
|
-
if (this.buffer.length < totalSize) {
|
|
104
|
-
// Not enough data for complete message yet
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Extract the complete message
|
|
109
|
-
const messageData = this.buffer.subarray(0, totalSize);
|
|
110
|
-
const payload = messageData.subarray(HEADER_SIZE);
|
|
111
|
-
|
|
112
|
-
// Create the received message
|
|
113
|
-
const message: ReceivedMessage = {
|
|
114
|
-
header: this.pendingHeader,
|
|
115
|
-
payload: new Uint8Array(payload), // Copy to avoid issues with buffer reuse
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
// Remove this message from buffer
|
|
119
|
-
this.buffer = this.buffer.subarray(totalSize);
|
|
120
|
-
this.pendingHeader = null;
|
|
121
|
-
|
|
122
|
-
// Emit the message
|
|
123
|
-
this.onMessage?.(message);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
private concat(a: Uint8Array, b: Uint8Array): Uint8Array {
|
|
128
|
-
if (a.length === 0) return b;
|
|
129
|
-
if (b.length === 0) return a;
|
|
130
|
-
|
|
131
|
-
const result = new Uint8Array(a.length + b.length);
|
|
132
|
-
result.set(a, 0);
|
|
133
|
-
result.set(b, a.length);
|
|
134
|
-
return result;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Frame Decoder
|
|
3
|
+
*
|
|
4
|
+
* Handles accumulating partial data from the network and extracting
|
|
5
|
+
* complete framed messages. This is necessary because TCP is a stream
|
|
6
|
+
* protocol and messages may arrive in fragments or multiple messages
|
|
7
|
+
* may arrive in a single chunk.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
HEADER_SIZE,
|
|
12
|
+
decodeHeader,
|
|
13
|
+
type MessageHeader,
|
|
14
|
+
} from "./message-header.ts";
|
|
15
|
+
import type { ReceivedMessage } from "./transport.ts";
|
|
16
|
+
|
|
17
|
+
/** Maximum allowed message size (16 MB) - protection against malformed packets */
|
|
18
|
+
const MAX_MESSAGE_SIZE = 16 * 1024 * 1024;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Frame decoder for length-prefixed messages
|
|
22
|
+
*
|
|
23
|
+
* Usage:
|
|
24
|
+
* ```ts
|
|
25
|
+
* const decoder = new FrameDecoder();
|
|
26
|
+
* decoder.onMessage = (msg) => console.log('Got message:', msg);
|
|
27
|
+
*
|
|
28
|
+
* // Feed data as it arrives from the socket
|
|
29
|
+
* socket.on('data', (chunk) => decoder.push(chunk));
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export class FrameDecoder {
|
|
33
|
+
private buffer: Uint8Array = new Uint8Array(0);
|
|
34
|
+
private pendingHeader: MessageHeader | null = null;
|
|
35
|
+
|
|
36
|
+
/** Callback for complete messages */
|
|
37
|
+
public onMessage: ((message: ReceivedMessage) => void) | null = null;
|
|
38
|
+
|
|
39
|
+
/** Callback for decode errors */
|
|
40
|
+
public onError: ((error: Error) => void) | null = null;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Push incoming data into the decoder
|
|
44
|
+
* @param chunk Data received from the network
|
|
45
|
+
*/
|
|
46
|
+
push(chunk: Uint8Array): void {
|
|
47
|
+
// Append chunk to buffer
|
|
48
|
+
this.buffer = this.concat(this.buffer, chunk);
|
|
49
|
+
|
|
50
|
+
// Process as many complete messages as possible
|
|
51
|
+
this.processBuffer();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Reset the decoder state (e.g., after a connection reset)
|
|
56
|
+
*/
|
|
57
|
+
reset(): void {
|
|
58
|
+
this.buffer = new Uint8Array(0);
|
|
59
|
+
this.pendingHeader = null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get the number of bytes currently buffered
|
|
64
|
+
*/
|
|
65
|
+
get bufferedBytes(): number {
|
|
66
|
+
return this.buffer.length;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private processBuffer(): void {
|
|
70
|
+
while (true) {
|
|
71
|
+
// If we don't have a header yet, try to read one
|
|
72
|
+
if (this.pendingHeader === null) {
|
|
73
|
+
if (this.buffer.length < HEADER_SIZE) {
|
|
74
|
+
// Not enough data for header yet
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
this.pendingHeader = decodeHeader(this.buffer.subarray(0, HEADER_SIZE));
|
|
80
|
+
} catch (error) {
|
|
81
|
+
this.onError?.(error as Error);
|
|
82
|
+
// Skip one byte and try again (attempt to resync)
|
|
83
|
+
this.buffer = this.buffer.subarray(1);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Validate packet size
|
|
88
|
+
if (this.pendingHeader.packetSize > MAX_MESSAGE_SIZE) {
|
|
89
|
+
this.onError?.(
|
|
90
|
+
new Error(
|
|
91
|
+
`Message too large: ${this.pendingHeader.packetSize} bytes (max: ${MAX_MESSAGE_SIZE})`
|
|
92
|
+
)
|
|
93
|
+
);
|
|
94
|
+
// Reset and skip this header
|
|
95
|
+
this.pendingHeader = null;
|
|
96
|
+
this.buffer = this.buffer.subarray(HEADER_SIZE);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// We have a header, check if we have the complete message
|
|
102
|
+
const totalSize = this.pendingHeader.packetSize;
|
|
103
|
+
if (this.buffer.length < totalSize) {
|
|
104
|
+
// Not enough data for complete message yet
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Extract the complete message
|
|
109
|
+
const messageData = this.buffer.subarray(0, totalSize);
|
|
110
|
+
const payload = messageData.subarray(HEADER_SIZE);
|
|
111
|
+
|
|
112
|
+
// Create the received message
|
|
113
|
+
const message: ReceivedMessage = {
|
|
114
|
+
header: this.pendingHeader,
|
|
115
|
+
payload: new Uint8Array(payload), // Copy to avoid issues with buffer reuse
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// Remove this message from buffer
|
|
119
|
+
this.buffer = this.buffer.subarray(totalSize);
|
|
120
|
+
this.pendingHeader = null;
|
|
121
|
+
|
|
122
|
+
// Emit the message
|
|
123
|
+
this.onMessage?.(message);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private concat(a: Uint8Array, b: Uint8Array): Uint8Array {
|
|
128
|
+
if (a.length === 0) return b;
|
|
129
|
+
if (b.length === 0) return a;
|
|
130
|
+
|
|
131
|
+
const result = new Uint8Array(a.length + b.length);
|
|
132
|
+
result.set(a, 0);
|
|
133
|
+
result.set(b, a.length);
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
136
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @hla4ts/transport - HLA 4 Federate Protocol Transport Layer
|
|
3
|
-
*
|
|
4
|
-
* This package provides transport implementations for the HLA 4 Federate Protocol,
|
|
5
|
-
* including message framing, TLS support, and connection management.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```ts
|
|
9
|
-
* import { TlsTransport, MessageType, encodeMessage } from '@hla4ts/transport';
|
|
10
|
-
*
|
|
11
|
-
* // Create a TLS transport
|
|
12
|
-
* const transport = new TlsTransport({
|
|
13
|
-
* host: 'rti.example.com',
|
|
14
|
-
* port: 15165,
|
|
15
|
-
* });
|
|
16
|
-
*
|
|
17
|
-
* // Set up event handlers
|
|
18
|
-
* transport.setEventHandlers({
|
|
19
|
-
* onMessage: (msg) => {
|
|
20
|
-
* console.log('Received:', MessageType[msg.header.messageType]);
|
|
21
|
-
* },
|
|
22
|
-
* onClose: () => console.log('Connection closed'),
|
|
23
|
-
* onError: (err) => console.error('Error:', err),
|
|
24
|
-
* });
|
|
25
|
-
*
|
|
26
|
-
* // Connect and send a message
|
|
27
|
-
* await transport.connect();
|
|
28
|
-
* const message = encodeMessage(
|
|
29
|
-
* 1, // sequence number
|
|
30
|
-
* 0n, // session ID (0 for new session)
|
|
31
|
-
* 0, // last received seq num
|
|
32
|
-
* MessageType.CTRL_NEW_SESSION, // message type
|
|
33
|
-
* payload // optional payload
|
|
34
|
-
* );
|
|
35
|
-
* await transport.send(message);
|
|
36
|
-
* ```
|
|
37
|
-
*
|
|
38
|
-
* @packageDocumentation
|
|
39
|
-
*/
|
|
40
|
-
|
|
41
|
-
// Message types
|
|
42
|
-
export { MessageType, isControlMessage, isHlaResponse, messageTypeName } from "./message-type.ts";
|
|
43
|
-
|
|
44
|
-
// Message header encoding/decoding
|
|
45
|
-
export {
|
|
46
|
-
HEADER_SIZE,
|
|
47
|
-
NO_SESSION_ID,
|
|
48
|
-
NO_SEQUENCE_NUMBER,
|
|
49
|
-
encodeHeader,
|
|
50
|
-
decodeHeader,
|
|
51
|
-
encodeMessage,
|
|
52
|
-
getPayloadSize,
|
|
53
|
-
type MessageHeader,
|
|
54
|
-
} from "./message-header.ts";
|
|
55
|
-
|
|
56
|
-
// Constants
|
|
57
|
-
export {
|
|
58
|
-
FEDERATE_PROTOCOL_VERSION,
|
|
59
|
-
Ports,
|
|
60
|
-
Protocol,
|
|
61
|
-
NewSessionStatus,
|
|
62
|
-
ResumeStatus,
|
|
63
|
-
type ProtocolType,
|
|
64
|
-
type NewSessionStatusCode,
|
|
65
|
-
type ResumeStatusCode,
|
|
66
|
-
} from "./constants.ts";
|
|
67
|
-
|
|
68
|
-
// Transport interface
|
|
69
|
-
export type {
|
|
70
|
-
Transport,
|
|
71
|
-
TransportOptions,
|
|
72
|
-
TlsOptions,
|
|
73
|
-
TransportEvents,
|
|
74
|
-
ReceivedMessage,
|
|
75
|
-
} from "./transport.ts";
|
|
76
|
-
|
|
77
|
-
// Frame decoder
|
|
78
|
-
export { FrameDecoder } from "./frame-decoder.ts";
|
|
79
|
-
|
|
80
|
-
// Transport implementations
|
|
81
|
-
export { TlsTransport } from "./tls-transport.ts";
|
|
82
|
-
export { TcpTransport } from "./tcp-transport.ts";
|
|
1
|
+
/**
|
|
2
|
+
* @hla4ts/transport - HLA 4 Federate Protocol Transport Layer
|
|
3
|
+
*
|
|
4
|
+
* This package provides transport implementations for the HLA 4 Federate Protocol,
|
|
5
|
+
* including message framing, TLS support, and connection management.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { TlsTransport, MessageType, encodeMessage } from '@hla4ts/transport';
|
|
10
|
+
*
|
|
11
|
+
* // Create a TLS transport
|
|
12
|
+
* const transport = new TlsTransport({
|
|
13
|
+
* host: 'rti.example.com',
|
|
14
|
+
* port: 15165,
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* // Set up event handlers
|
|
18
|
+
* transport.setEventHandlers({
|
|
19
|
+
* onMessage: (msg) => {
|
|
20
|
+
* console.log('Received:', MessageType[msg.header.messageType]);
|
|
21
|
+
* },
|
|
22
|
+
* onClose: () => console.log('Connection closed'),
|
|
23
|
+
* onError: (err) => console.error('Error:', err),
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // Connect and send a message
|
|
27
|
+
* await transport.connect();
|
|
28
|
+
* const message = encodeMessage(
|
|
29
|
+
* 1, // sequence number
|
|
30
|
+
* 0n, // session ID (0 for new session)
|
|
31
|
+
* 0, // last received seq num
|
|
32
|
+
* MessageType.CTRL_NEW_SESSION, // message type
|
|
33
|
+
* payload // optional payload
|
|
34
|
+
* );
|
|
35
|
+
* await transport.send(message);
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @packageDocumentation
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
// Message types
|
|
42
|
+
export { MessageType, isControlMessage, isHlaResponse, messageTypeName } from "./message-type.ts";
|
|
43
|
+
|
|
44
|
+
// Message header encoding/decoding
|
|
45
|
+
export {
|
|
46
|
+
HEADER_SIZE,
|
|
47
|
+
NO_SESSION_ID,
|
|
48
|
+
NO_SEQUENCE_NUMBER,
|
|
49
|
+
encodeHeader,
|
|
50
|
+
decodeHeader,
|
|
51
|
+
encodeMessage,
|
|
52
|
+
getPayloadSize,
|
|
53
|
+
type MessageHeader,
|
|
54
|
+
} from "./message-header.ts";
|
|
55
|
+
|
|
56
|
+
// Constants
|
|
57
|
+
export {
|
|
58
|
+
FEDERATE_PROTOCOL_VERSION,
|
|
59
|
+
Ports,
|
|
60
|
+
Protocol,
|
|
61
|
+
NewSessionStatus,
|
|
62
|
+
ResumeStatus,
|
|
63
|
+
type ProtocolType,
|
|
64
|
+
type NewSessionStatusCode,
|
|
65
|
+
type ResumeStatusCode,
|
|
66
|
+
} from "./constants.ts";
|
|
67
|
+
|
|
68
|
+
// Transport interface
|
|
69
|
+
export type {
|
|
70
|
+
Transport,
|
|
71
|
+
TransportOptions,
|
|
72
|
+
TlsOptions,
|
|
73
|
+
TransportEvents,
|
|
74
|
+
ReceivedMessage,
|
|
75
|
+
} from "./transport.ts";
|
|
76
|
+
|
|
77
|
+
// Frame decoder
|
|
78
|
+
export { FrameDecoder } from "./frame-decoder.ts";
|
|
79
|
+
|
|
80
|
+
// Transport implementations
|
|
81
|
+
export { TlsTransport } from "./tls-transport.ts";
|
|
82
|
+
export { TcpTransport } from "./tcp-transport.ts";
|