@sirena-lwm2m/coap 0.8.0
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/LICENSE +17 -0
- package/README.md +78 -0
- package/dist/api/exchange-context.d.ts +34 -0
- package/dist/api/exchange-context.d.ts.map +1 -0
- package/dist/api/exchange-context.js +2 -0
- package/dist/api/exchange-context.js.map +1 -0
- package/dist/api/headers.d.ts +10 -0
- package/dist/api/headers.d.ts.map +1 -0
- package/dist/api/headers.js +69 -0
- package/dist/api/headers.js.map +1 -0
- package/dist/api/index.d.ts +5 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +4 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/request.d.ts +11 -0
- package/dist/api/request.d.ts.map +1 -0
- package/dist/api/request.js +49 -0
- package/dist/api/request.js.map +1 -0
- package/dist/api/response.d.ts +11 -0
- package/dist/api/response.d.ts.map +1 -0
- package/dist/api/response.js +19 -0
- package/dist/api/response.js.map +1 -0
- package/dist/blockwise/block1-assembler.d.ts +26 -0
- package/dist/blockwise/block1-assembler.d.ts.map +1 -0
- package/dist/blockwise/block1-assembler.js +94 -0
- package/dist/blockwise/block1-assembler.js.map +1 -0
- package/dist/blockwise/block2-chunker.d.ts +23 -0
- package/dist/blockwise/block2-chunker.d.ts.map +1 -0
- package/dist/blockwise/block2-chunker.js +99 -0
- package/dist/blockwise/block2-chunker.js.map +1 -0
- package/dist/blockwise/index.d.ts +8 -0
- package/dist/blockwise/index.d.ts.map +1 -0
- package/dist/blockwise/index.js +5 -0
- package/dist/blockwise/index.js.map +1 -0
- package/dist/blockwise/middleware.d.ts +7 -0
- package/dist/blockwise/middleware.d.ts.map +1 -0
- package/dist/blockwise/middleware.js +120 -0
- package/dist/blockwise/middleware.js.map +1 -0
- package/dist/blockwise/option.d.ts +12 -0
- package/dist/blockwise/option.d.ts.map +1 -0
- package/dist/blockwise/option.js +55 -0
- package/dist/blockwise/option.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/message/index.d.ts +21 -0
- package/dist/message/index.d.ts.map +1 -0
- package/dist/message/index.js +79 -0
- package/dist/message/index.js.map +1 -0
- package/dist/observability.d.ts +44 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +71 -0
- package/dist/observability.js.map +1 -0
- package/dist/observe-notification.d.ts +21 -0
- package/dist/observe-notification.d.ts.map +1 -0
- package/dist/observe-notification.js +87 -0
- package/dist/observe-notification.js.map +1 -0
- package/dist/observe.d.ts +10 -0
- package/dist/observe.d.ts.map +1 -0
- package/dist/observe.js +3 -0
- package/dist/observe.js.map +1 -0
- package/dist/option-parser/index.d.ts +30 -0
- package/dist/option-parser/index.d.ts.map +1 -0
- package/dist/option-parser/index.js +125 -0
- package/dist/option-parser/index.js.map +1 -0
- package/dist/router/app.d.ts +8 -0
- package/dist/router/app.d.ts.map +1 -0
- package/dist/router/app.js +25 -0
- package/dist/router/app.js.map +1 -0
- package/dist/router/content-format.d.ts +7 -0
- package/dist/router/content-format.d.ts.map +1 -0
- package/dist/router/content-format.js +23 -0
- package/dist/router/content-format.js.map +1 -0
- package/dist/router/index.d.ts +9 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +5 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/radix.d.ts +16 -0
- package/dist/router/radix.d.ts.map +1 -0
- package/dist/router/radix.js +69 -0
- package/dist/router/radix.js.map +1 -0
- package/dist/router/router.d.ts +38 -0
- package/dist/router/router.d.ts.map +1 -0
- package/dist/router/router.js +111 -0
- package/dist/router/router.js.map +1 -0
- package/dist/router.d.ts +2 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +2 -0
- package/dist/router.js.map +1 -0
- package/dist/security.d.ts +3 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +2 -0
- package/dist/security.js.map +1 -0
- package/dist/store/index.d.ts +26 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +68 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/sqlite-store.d.ts +10 -0
- package/dist/store/sqlite-store.d.ts.map +1 -0
- package/dist/store/sqlite-store.js +75 -0
- package/dist/store/sqlite-store.js.map +1 -0
- package/dist/store.d.ts +5 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +3 -0
- package/dist/store.js.map +1 -0
- package/dist/transport/dtls.d.ts +38 -0
- package/dist/transport/dtls.d.ts.map +1 -0
- package/dist/transport/dtls.js +151 -0
- package/dist/transport/dtls.js.map +1 -0
- package/dist/transport/events.d.ts +34 -0
- package/dist/transport/events.d.ts.map +1 -0
- package/dist/transport/events.js +2 -0
- package/dist/transport/events.js.map +1 -0
- package/dist/transport/index.d.ts +10 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +5 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/tcp-connection.d.ts +18 -0
- package/dist/transport/tcp-connection.d.ts.map +1 -0
- package/dist/transport/tcp-connection.js +72 -0
- package/dist/transport/tcp-connection.js.map +1 -0
- package/dist/transport/tcp-frame.d.ts +17 -0
- package/dist/transport/tcp-frame.d.ts.map +1 -0
- package/dist/transport/tcp-frame.js +112 -0
- package/dist/transport/tcp-frame.js.map +1 -0
- package/dist/transport/tcp-stream.d.ts +21 -0
- package/dist/transport/tcp-stream.d.ts.map +1 -0
- package/dist/transport/tcp-stream.js +52 -0
- package/dist/transport/tcp-stream.js.map +1 -0
- package/dist/transport/udp.d.ts +97 -0
- package/dist/transport/udp.d.ts.map +1 -0
- package/dist/transport/udp.js +994 -0
- package/dist/transport/udp.js.map +1 -0
- package/dist/transport.d.ts +3 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +2 -0
- package/dist/transport.js.map +1 -0
- package/docs/api-reference.md +536 -0
- package/docs/blockwise.md +117 -0
- package/docs/observability.md +206 -0
- package/docs/observe.md +203 -0
- package/docs/releasing.md +106 -0
- package/docs/router.md +170 -0
- package/docs/store.md +212 -0
- package/docs/tcp-transport.md +89 -0
- package/docs/udp-transport.md +81 -0
- package/examples/slice-1.ts +12 -0
- package/examples/slice-2.ts +96 -0
- package/examples/slice-3-psk.ts +70 -0
- package/examples/slice-3-x509.ts +85 -0
- package/examples/slice-4.ts +45 -0
- package/examples/slice-5-firmware.ts +207 -0
- package/examples/slice-6-temperature.ts +163 -0
- package/examples/slice-7-file-store.ts +92 -0
- package/examples/slice-7-otel.ts +123 -0
- package/package.json +73 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { encodeOptions, decodeOptions } from '../option-parser/index.js';
|
|
2
|
+
export class TcpFrameDecodeError extends Error {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = 'TcpFrameDecodeError';
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
// RFC 8323 §3.2: Len field encoding
|
|
9
|
+
// Len 0–12 = literal (options+payload length)
|
|
10
|
+
// Len 13 = 8-bit extended (actual = extended byte + 13)
|
|
11
|
+
// Len 14 = 16-bit extended (actual = extended uint16 BE + 269)
|
|
12
|
+
// Len 15 = 32-bit extended (actual = extended uint32 BE + 65805)
|
|
13
|
+
function encodeLenField(len) {
|
|
14
|
+
if (len <= 12) {
|
|
15
|
+
return { nibble: len, extended: new Uint8Array(0) };
|
|
16
|
+
}
|
|
17
|
+
else if (len <= 268) {
|
|
18
|
+
return { nibble: 13, extended: new Uint8Array([len - 13]) };
|
|
19
|
+
}
|
|
20
|
+
else if (len <= 65804) {
|
|
21
|
+
const v = len - 269;
|
|
22
|
+
return { nibble: 14, extended: new Uint8Array([(v >> 8) & 0xff, v & 0xff]) };
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
const v = len - 65805;
|
|
26
|
+
return {
|
|
27
|
+
nibble: 15,
|
|
28
|
+
extended: new Uint8Array([
|
|
29
|
+
(v >>> 24) & 0xff,
|
|
30
|
+
(v >>> 16) & 0xff,
|
|
31
|
+
(v >>> 8) & 0xff,
|
|
32
|
+
v & 0xff,
|
|
33
|
+
]),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function encodeTcpFrame(frame) {
|
|
38
|
+
const tkl = frame.token.length;
|
|
39
|
+
const encodedOpts = encodeOptions(frame.options);
|
|
40
|
+
const hasPayload = frame.payload.length > 0;
|
|
41
|
+
const optPayloadLen = encodedOpts.length + (hasPayload ? 1 + frame.payload.length : 0);
|
|
42
|
+
const { nibble, extended } = encodeLenField(optPayloadLen);
|
|
43
|
+
// byte 0: Len(4-bit) | TKL(4-bit)
|
|
44
|
+
const byte0 = ((nibble & 0x0f) << 4) | (tkl & 0x0f);
|
|
45
|
+
const totalLen = 1 + extended.length + 1 + tkl + optPayloadLen;
|
|
46
|
+
const result = new Uint8Array(totalLen);
|
|
47
|
+
let pos = 0;
|
|
48
|
+
result[pos++] = byte0;
|
|
49
|
+
result.set(extended, pos);
|
|
50
|
+
pos += extended.length;
|
|
51
|
+
result[pos++] = frame.code & 0xff;
|
|
52
|
+
result.set(frame.token, pos);
|
|
53
|
+
pos += tkl;
|
|
54
|
+
result.set(encodedOpts, pos);
|
|
55
|
+
pos += encodedOpts.length;
|
|
56
|
+
if (hasPayload) {
|
|
57
|
+
result[pos++] = 0xff;
|
|
58
|
+
result.set(frame.payload, pos);
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
export function decodeTcpFrame(buf) {
|
|
63
|
+
if (buf.length < 1)
|
|
64
|
+
return null;
|
|
65
|
+
const byte0 = buf[0];
|
|
66
|
+
const lenNibble = (byte0 >> 4) & 0x0f;
|
|
67
|
+
const tkl = byte0 & 0x0f;
|
|
68
|
+
let pos = 1;
|
|
69
|
+
let optPayloadLen;
|
|
70
|
+
if (lenNibble <= 12) {
|
|
71
|
+
optPayloadLen = lenNibble;
|
|
72
|
+
}
|
|
73
|
+
else if (lenNibble === 13) {
|
|
74
|
+
if (buf.length < pos + 1)
|
|
75
|
+
return null;
|
|
76
|
+
optPayloadLen = buf[pos] + 13;
|
|
77
|
+
pos += 1;
|
|
78
|
+
}
|
|
79
|
+
else if (lenNibble === 14) {
|
|
80
|
+
if (buf.length < pos + 2)
|
|
81
|
+
return null;
|
|
82
|
+
optPayloadLen = ((buf[pos] << 8) | buf[pos + 1]) + 269;
|
|
83
|
+
pos += 2;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
// lenNibble === 15
|
|
87
|
+
if (buf.length < pos + 4)
|
|
88
|
+
return null;
|
|
89
|
+
const v = (buf[pos] * 0x1000000) +
|
|
90
|
+
((buf[pos + 1] << 16) | (buf[pos + 2] << 8) | buf[pos + 3]);
|
|
91
|
+
pos += 4;
|
|
92
|
+
if (v > Number.MAX_SAFE_INTEGER - 65805) {
|
|
93
|
+
throw new TcpFrameDecodeError('Extended Len=15 value exceeds Number.MAX_SAFE_INTEGER');
|
|
94
|
+
}
|
|
95
|
+
optPayloadLen = v + 65805;
|
|
96
|
+
}
|
|
97
|
+
// Need: Code byte + TKL bytes + optPayloadLen bytes
|
|
98
|
+
const totalNeeded = pos + 1 + tkl + optPayloadLen;
|
|
99
|
+
if (buf.length < totalNeeded)
|
|
100
|
+
return null;
|
|
101
|
+
const code = buf[pos++];
|
|
102
|
+
const token = buf.slice(pos, pos + tkl);
|
|
103
|
+
pos += tkl;
|
|
104
|
+
const optPayloadBuf = buf.slice(pos, pos + optPayloadLen);
|
|
105
|
+
const { options, payloadOffset } = decodeOptions(optPayloadBuf, 0);
|
|
106
|
+
const payload = optPayloadBuf.slice(payloadOffset);
|
|
107
|
+
return {
|
|
108
|
+
frame: { code, token, options, payload },
|
|
109
|
+
bytesConsumed: totalNeeded,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=tcp-frame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcp-frame.js","sourceRoot":"","sources":["../../src/transport/tcp-frame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAYzE,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,oCAAoC;AACpC,8CAA8C;AAC9C,2DAA2D;AAC3D,iEAAiE;AACjE,mEAAmE;AAEnE,SAAS,cAAc,CAAC,GAAW;IACjC,IAAI,GAAG,IAAI,EAAE,EAAE,CAAC;QACd,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IACtD,CAAC;SAAM,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,UAAU,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;IAC9D,CAAC;SAAM,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;QACpB,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC;IAC/E,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC;QACtB,OAAO;YACL,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,IAAI,UAAU,CAAC;gBACvB,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;gBACjB,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;gBACjB,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI;gBAChB,CAAC,GAAG,IAAI;aACT,CAAC;SACH,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAe;IAC5C,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;IAC/B,MAAM,WAAW,GAAG,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5C,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvF,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,cAAc,CAAC,aAAa,CAAC,CAAC;IAE3D,kCAAkC;IAClC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IAEpD,MAAM,QAAQ,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,GAAG,GAAG,GAAG,aAAa,CAAC;IAC/D,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;IACxC,IAAI,GAAG,GAAG,CAAC,CAAC;IAEZ,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC;IACtB,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAAC,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC;IAClD,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;IAClC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAAC,GAAG,IAAI,GAAG,CAAC;IACzC,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAAC,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC;IAExD,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;QACrB,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAe;IAC5C,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAEhC,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACrB,MAAM,SAAS,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IACtC,MAAM,GAAG,GAAG,KAAK,GAAG,IAAI,CAAC;IAEzB,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,aAAqB,CAAC;IAE1B,IAAI,SAAS,IAAI,EAAE,EAAE,CAAC;QACpB,aAAa,GAAG,SAAS,CAAC;IAC5B,CAAC;SAAM,IAAI,SAAS,KAAK,EAAE,EAAE,CAAC;QAC5B,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,aAAa,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QAC9B,GAAG,IAAI,CAAC,CAAC;IACX,CAAC;SAAM,IAAI,SAAS,KAAK,EAAE,EAAE,CAAC;QAC5B,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,aAAa,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;QACvD,GAAG,IAAI,CAAC,CAAC;IACX,CAAC;SAAM,CAAC;QACN,mBAAmB;QACnB,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,MAAM,CAAC,GACL,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;YACtB,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAC9D,GAAG,IAAI,CAAC,CAAC;QACT,IAAI,CAAC,GAAG,MAAM,CAAC,gBAAgB,GAAG,KAAK,EAAE,CAAC;YACxC,MAAM,IAAI,mBAAmB,CAAC,uDAAuD,CAAC,CAAC;QACzF,CAAC;QACD,aAAa,GAAG,CAAC,GAAG,KAAK,CAAC;IAC5B,CAAC;IAED,oDAAoD;IACpD,MAAM,WAAW,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,aAAa,CAAC;IAClD,IAAI,GAAG,CAAC,MAAM,GAAG,WAAW;QAAE,OAAO,IAAI,CAAC;IAE1C,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IACxB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;IACxC,GAAG,IAAI,GAAG,CAAC;IAEX,MAAM,aAAa,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,aAAa,CAAC,CAAC;IAC1D,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,aAAa,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IAEnE,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAEnD,OAAO;QACL,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE;QACxC,aAAa,EAAE,WAAW;KAC3B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import net from 'node:net';
|
|
3
|
+
import type { Logger } from './udp.js';
|
|
4
|
+
export interface ExchangeHandle {
|
|
5
|
+
token: Uint8Array;
|
|
6
|
+
createdAt: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class TcpFrameStream extends EventEmitter {
|
|
9
|
+
private readonly log;
|
|
10
|
+
private accumulator;
|
|
11
|
+
private readonly exchanges;
|
|
12
|
+
constructor({ socket, logger }: {
|
|
13
|
+
socket: net.Socket;
|
|
14
|
+
logger: Logger;
|
|
15
|
+
});
|
|
16
|
+
protected _onData(chunk: Buffer): void;
|
|
17
|
+
registerExchange(token: Uint8Array): void;
|
|
18
|
+
resolveExchange(token: Uint8Array): ExchangeHandle | undefined;
|
|
19
|
+
activeCount(): number;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=tcp-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcp-stream.d.ts","sourceRoot":"","sources":["../../src/transport/tcp-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,GAAG,MAAM,UAAU,CAAC;AAG3B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqC;gBAEnD,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;QAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAmBtE,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAWtC,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAKzC,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,cAAc,GAAG,SAAS;IAS9D,WAAW,IAAI,MAAM;CAGtB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { decodeTcpFrame, TcpFrameDecodeError } from './tcp-frame.js';
|
|
3
|
+
export class TcpFrameStream extends EventEmitter {
|
|
4
|
+
log;
|
|
5
|
+
accumulator = Buffer.alloc(0);
|
|
6
|
+
exchanges = new Map();
|
|
7
|
+
constructor({ socket, logger }) {
|
|
8
|
+
super();
|
|
9
|
+
this.log = logger;
|
|
10
|
+
socket.on('data', (chunk) => {
|
|
11
|
+
try {
|
|
12
|
+
this._onData(chunk);
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
if (err instanceof TcpFrameDecodeError) {
|
|
16
|
+
this.log.error('tcp frame decode error', { err: err.message });
|
|
17
|
+
this.accumulator = Buffer.alloc(0);
|
|
18
|
+
this.emit('frame-error', err);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
throw err;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
_onData(chunk) {
|
|
27
|
+
this.accumulator = Buffer.concat([this.accumulator, chunk]);
|
|
28
|
+
while (this.accumulator.length > 0) {
|
|
29
|
+
const result = decodeTcpFrame(this.accumulator);
|
|
30
|
+
if (result === null)
|
|
31
|
+
break;
|
|
32
|
+
this.accumulator = this.accumulator.subarray(result.bytesConsumed);
|
|
33
|
+
this.emit('frame', result.frame);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
registerExchange(token) {
|
|
37
|
+
const key = Buffer.from(token).toString('hex');
|
|
38
|
+
this.exchanges.set(key, { token, createdAt: Date.now() });
|
|
39
|
+
}
|
|
40
|
+
resolveExchange(token) {
|
|
41
|
+
const key = Buffer.from(token).toString('hex');
|
|
42
|
+
const handle = this.exchanges.get(key);
|
|
43
|
+
if (handle !== undefined) {
|
|
44
|
+
this.exchanges.delete(key);
|
|
45
|
+
}
|
|
46
|
+
return handle;
|
|
47
|
+
}
|
|
48
|
+
activeCount() {
|
|
49
|
+
return this.exchanges.size;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=tcp-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tcp-stream.js","sourceRoot":"","sources":["../../src/transport/tcp-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AASrE,MAAM,OAAO,cAAe,SAAQ,YAAY;IAC7B,GAAG,CAAS;IACrB,WAAW,GAAW,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7B,SAAS,GAAG,IAAI,GAAG,EAA0B,CAAC;IAE/D,YAAY,EAAE,MAAM,EAAE,MAAM,EAA0C;QACpE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC;QAElB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAClC,IAAI,CAAC;gBACH,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;oBACvC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,wBAAwB,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;oBAC/D,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBACnC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;gBAChC,CAAC;qBAAM,CAAC;oBACN,MAAM,GAAG,CAAC;gBACZ,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAES,OAAO,CAAC,KAAa;QAC7B,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;QAE5D,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAChD,IAAI,MAAM,KAAK,IAAI;gBAAE,MAAM;YAC3B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YACnE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,gBAAgB,CAAC,KAAiB;QAChC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC/C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,eAAe,CAAC,KAAiB;QAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;IAC7B,CAAC;CACF"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import type { TransactionStore } from '../store/index.js';
|
|
3
|
+
import { Request } from '../api/index.js';
|
|
4
|
+
import type { ExchangeContext, Peer } from '../api/index.js';
|
|
5
|
+
import type { CoapMetrics } from '../observability.js';
|
|
6
|
+
export interface Logger {
|
|
7
|
+
debug(msg: string, meta?: object): void;
|
|
8
|
+
info(msg: string, meta?: object): void;
|
|
9
|
+
warn(msg: string, meta?: object): void;
|
|
10
|
+
error(msg: string, meta?: object): void;
|
|
11
|
+
}
|
|
12
|
+
export interface ListenAddress {
|
|
13
|
+
host: string;
|
|
14
|
+
port: number;
|
|
15
|
+
}
|
|
16
|
+
export type ResolvedAddress = {
|
|
17
|
+
host: string;
|
|
18
|
+
port: number;
|
|
19
|
+
transport: 'udp' | 'tcp' | 'dtls' | 'tls';
|
|
20
|
+
};
|
|
21
|
+
export interface PskSecurityOptions {
|
|
22
|
+
mode: 'psk';
|
|
23
|
+
psk: (identity: string) => Buffer | null;
|
|
24
|
+
sessionCacheSize?: number;
|
|
25
|
+
}
|
|
26
|
+
export interface X509SecurityOptions {
|
|
27
|
+
mode: 'x509';
|
|
28
|
+
key: string | Buffer;
|
|
29
|
+
cert: string | Buffer;
|
|
30
|
+
ca?: string | Buffer;
|
|
31
|
+
requestClientCert?: boolean;
|
|
32
|
+
sessionCacheSize?: number;
|
|
33
|
+
}
|
|
34
|
+
export type SecurityOptions = PskSecurityOptions | X509SecurityOptions;
|
|
35
|
+
export declare function parseListenAddress(addr: string | ListenAddress): ResolvedAddress;
|
|
36
|
+
export interface ServerOptions {
|
|
37
|
+
listen: Array<string | ListenAddress>;
|
|
38
|
+
security?: SecurityOptions;
|
|
39
|
+
store?: TransactionStore;
|
|
40
|
+
logger?: Logger;
|
|
41
|
+
metrics?: CoapMetrics;
|
|
42
|
+
queueSize?: number;
|
|
43
|
+
drainTimeoutMs?: number;
|
|
44
|
+
ackTimeoutMs?: number;
|
|
45
|
+
ackRandomFactor?: number;
|
|
46
|
+
maxRetransmit?: number;
|
|
47
|
+
nonTimeoutMs?: number;
|
|
48
|
+
nstart?: number;
|
|
49
|
+
perEndpointLruCap?: number;
|
|
50
|
+
}
|
|
51
|
+
export interface StoreSummaryEntry {
|
|
52
|
+
transport: 'udp' | 'tcp' | 'dtls' | 'tls';
|
|
53
|
+
isDefault: boolean;
|
|
54
|
+
}
|
|
55
|
+
export interface DtlsHandshakeEvent {
|
|
56
|
+
peer: Peer;
|
|
57
|
+
durationMs: number;
|
|
58
|
+
}
|
|
59
|
+
export interface TlsHandshakeEvent {
|
|
60
|
+
peer: Peer;
|
|
61
|
+
durationMs: number;
|
|
62
|
+
}
|
|
63
|
+
export interface UpdateTlsOptions {
|
|
64
|
+
cert: string | Buffer;
|
|
65
|
+
key: string | Buffer;
|
|
66
|
+
}
|
|
67
|
+
export interface Server extends EventEmitter {
|
|
68
|
+
start(): Promise<void>;
|
|
69
|
+
stop(opts?: {
|
|
70
|
+
drainTimeoutMs?: number;
|
|
71
|
+
}): Promise<void>;
|
|
72
|
+
on(event: 'request', listener: (req: Request, ctx: ExchangeContext) => void): this;
|
|
73
|
+
on(event: 'response', listener: (ctx: ExchangeContext) => void): this;
|
|
74
|
+
on(event: 'exchange-error', listener: (err: Error) => void): this;
|
|
75
|
+
on(event: 'message-dropped', listener: (reason: string) => void): this;
|
|
76
|
+
on(event: 'dtls-handshake', listener: (event: DtlsHandshakeEvent) => void): this;
|
|
77
|
+
on(event: 'tls-handshake', listener: (event: TlsHandshakeEvent) => void): this;
|
|
78
|
+
on(event: string, listener: (...args: unknown[]) => void): this;
|
|
79
|
+
isReady(): boolean;
|
|
80
|
+
activeExchanges(): number;
|
|
81
|
+
listenerSummary(): Array<{
|
|
82
|
+
host: string;
|
|
83
|
+
port: number;
|
|
84
|
+
transport: 'udp' | 'tcp' | 'dtls' | 'tls';
|
|
85
|
+
}>;
|
|
86
|
+
storeSummary(): StoreSummaryEntry[];
|
|
87
|
+
/**
|
|
88
|
+
* Rotate the TLS certificate and key for all active TLS listeners.
|
|
89
|
+
*
|
|
90
|
+
* Only affects new TLS handshakes — existing TLSSockets are not renegotiated.
|
|
91
|
+
* If called before start(), the new certs are stored and picked up by start().
|
|
92
|
+
* A no-op on servers with no TLS (coaps+tcp://) listeners.
|
|
93
|
+
*/
|
|
94
|
+
updateTls(opts: UpdateTlsOptions): void;
|
|
95
|
+
}
|
|
96
|
+
export declare function createServer(options: ServerOptions): Server;
|
|
97
|
+
//# sourceMappingURL=udp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"udp.d.ts","sourceRoot":"","sources":["../../src/transport/udp.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAY,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,IAAI,EAAkB,MAAM,iBAAiB,CAAC;AAY7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAavD,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AASD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,eAAe,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAA;CAAE,CAAC;AAExG,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,eAAe,GAAG,kBAAkB,GAAG,mBAAmB,CAAC;AAEvE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,eAAe,CAkBhF;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,aAAa,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,IAAI,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,IAAI,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,MAAO,SAAQ,YAAY;IAC1C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI,CAAC;IACnF,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI,CAAC;IACtE,EAAE,CAAC,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IAClE,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACvE,EAAE,CAAC,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAAG,IAAI,CAAC;IACjF,EAAE,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,IAAI,CAAC;IAC/E,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IAChE,OAAO,IAAI,OAAO,CAAC;IACnB,eAAe,IAAI,MAAM,CAAC;IAC1B,eAAe,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAA;KAAE,CAAC,CAAC;IACpG,YAAY,IAAI,iBAAiB,EAAE,CAAC;IACpC;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACzC;AAuiCD,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAE3D"}
|