@source-repo/rpc 3.0.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 +21 -0
- package/README.md +1208 -0
- package/dist/Logging/ILogger.d.ts +7 -0
- package/dist/Logging/ILogger.d.ts.map +1 -0
- package/dist/Logging/ILogger.js +2 -0
- package/dist/Logging/ILogger.js.map +1 -0
- package/dist/NodeRpcServer.d.ts +55 -0
- package/dist/NodeRpcServer.d.ts.map +1 -0
- package/dist/NodeRpcServer.js +46 -0
- package/dist/NodeRpcServer.js.map +1 -0
- package/dist/RPC/Auth.d.ts +98 -0
- package/dist/RPC/Auth.d.ts.map +1 -0
- package/dist/RPC/Auth.js +14 -0
- package/dist/RPC/Auth.js.map +1 -0
- package/dist/RPC/Codec.d.ts +24 -0
- package/dist/RPC/Codec.d.ts.map +1 -0
- package/dist/RPC/Codec.js +21 -0
- package/dist/RPC/Codec.js.map +1 -0
- package/dist/RPC/Compatibility.d.ts +39 -0
- package/dist/RPC/Compatibility.d.ts.map +1 -0
- package/dist/RPC/Compatibility.js +195 -0
- package/dist/RPC/Compatibility.js.map +1 -0
- package/dist/RPC/Core.d.ts +188 -0
- package/dist/RPC/Core.d.ts.map +1 -0
- package/dist/RPC/Core.js +354 -0
- package/dist/RPC/Core.js.map +1 -0
- package/dist/RPC/Expose.d.ts +90 -0
- package/dist/RPC/Expose.d.ts.map +1 -0
- package/dist/RPC/Expose.js +110 -0
- package/dist/RPC/Expose.js.map +1 -0
- package/dist/RPC/Idempotency.d.ts +90 -0
- package/dist/RPC/Idempotency.d.ts.map +1 -0
- package/dist/RPC/Idempotency.js +46 -0
- package/dist/RPC/Idempotency.js.map +1 -0
- package/dist/RPC/Introspection.d.ts +92 -0
- package/dist/RPC/Introspection.d.ts.map +1 -0
- package/dist/RPC/Introspection.js +188 -0
- package/dist/RPC/Introspection.js.map +1 -0
- package/dist/RPC/Introspection.types.json +1093 -0
- package/dist/RPC/Messages.d.ts +108 -0
- package/dist/RPC/Messages.d.ts.map +1 -0
- package/dist/RPC/Messages.js +30 -0
- package/dist/RPC/Messages.js.map +1 -0
- package/dist/RPC/Rpc.d.ts +51 -0
- package/dist/RPC/Rpc.d.ts.map +1 -0
- package/dist/RPC/Rpc.js +54 -0
- package/dist/RPC/Rpc.js.map +1 -0
- package/dist/RPC/RpcClientHandler.d.ts +129 -0
- package/dist/RPC/RpcClientHandler.d.ts.map +1 -0
- package/dist/RPC/RpcClientHandler.js +267 -0
- package/dist/RPC/RpcClientHandler.js.map +1 -0
- package/dist/RPC/RpcServerHandler.d.ts +226 -0
- package/dist/RPC/RpcServerHandler.d.ts.map +1 -0
- package/dist/RPC/RpcServerHandler.js +676 -0
- package/dist/RPC/RpcServerHandler.js.map +1 -0
- package/dist/RPC/Schema.d.ts +150 -0
- package/dist/RPC/Schema.d.ts.map +1 -0
- package/dist/RPC/Schema.js +198 -0
- package/dist/RPC/Schema.js.map +1 -0
- package/dist/RPC/Signing.d.ts +118 -0
- package/dist/RPC/Signing.d.ts.map +1 -0
- package/dist/RPC/Signing.js +171 -0
- package/dist/RPC/Signing.js.map +1 -0
- package/dist/RPC/Tokens.d.ts +49 -0
- package/dist/RPC/Tokens.d.ts.map +1 -0
- package/dist/RPC/Tokens.js +45 -0
- package/dist/RPC/Tokens.js.map +1 -0
- package/dist/RpcClient.d.ts +91 -0
- package/dist/RpcClient.d.ts.map +1 -0
- package/dist/RpcClient.js +145 -0
- package/dist/RpcClient.js.map +1 -0
- package/dist/RpcServer.d.ts +191 -0
- package/dist/RpcServer.d.ts.map +1 -0
- package/dist/RpcServer.js +293 -0
- package/dist/RpcServer.js.map +1 -0
- package/dist/Transports/Mqtt5Frame.d.ts +107 -0
- package/dist/Transports/Mqtt5Frame.d.ts.map +1 -0
- package/dist/Transports/Mqtt5Frame.js +162 -0
- package/dist/Transports/Mqtt5Frame.js.map +1 -0
- package/dist/Transports/MqttTransport.d.ts +279 -0
- package/dist/Transports/MqttTransport.d.ts.map +1 -0
- package/dist/Transports/MqttTransport.js +843 -0
- package/dist/Transports/MqttTransport.js.map +1 -0
- package/dist/Transports/Presence.d.ts +68 -0
- package/dist/Transports/Presence.d.ts.map +1 -0
- package/dist/Transports/Presence.js +21 -0
- package/dist/Transports/Presence.js.map +1 -0
- package/dist/Transports/SocketIoClientTransport.d.ts +89 -0
- package/dist/Transports/SocketIoClientTransport.d.ts.map +1 -0
- package/dist/Transports/SocketIoClientTransport.js +280 -0
- package/dist/Transports/SocketIoClientTransport.js.map +1 -0
- package/dist/Transports/SocketIoServerTransport.d.ts +135 -0
- package/dist/Transports/SocketIoServerTransport.d.ts.map +1 -0
- package/dist/Transports/SocketIoServerTransport.js +505 -0
- package/dist/Transports/SocketIoServerTransport.js.map +1 -0
- package/dist/Utilities/Converters.d.ts +22 -0
- package/dist/Utilities/Converters.d.ts.map +1 -0
- package/dist/Utilities/Converters.js +58 -0
- package/dist/Utilities/Converters.js.map +1 -0
- package/dist/Utilities/Filter.d.ts +7 -0
- package/dist/Utilities/Filter.d.ts.map +1 -0
- package/dist/Utilities/Filter.js +14 -0
- package/dist/Utilities/Filter.js.map +1 -0
- package/dist/Utilities/ReadableName.d.ts +38 -0
- package/dist/Utilities/ReadableName.d.ts.map +1 -0
- package/dist/Utilities/ReadableName.js +58 -0
- package/dist/Utilities/ReadableName.js.map +1 -0
- package/dist/Utilities/Switch.d.ts +21 -0
- package/dist/Utilities/Switch.d.ts.map +1 -0
- package/dist/Utilities/Switch.js +70 -0
- package/dist/Utilities/Switch.js.map +1 -0
- package/dist/Utilities/TryCatch.d.ts +11 -0
- package/dist/Utilities/TryCatch.d.ts.map +1 -0
- package/dist/Utilities/TryCatch.js +13 -0
- package/dist/Utilities/TryCatch.js.map +1 -0
- package/dist/index-web.d.ts +25 -0
- package/dist/index-web.d.ts.map +1 -0
- package/dist/index-web.js +28 -0
- package/dist/index-web.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { stringToUint8Array, uint8ArrayToString } from 'uint8array-extras';
|
|
2
|
+
import { MessageType } from '../RPC/Core.js';
|
|
3
|
+
import { RpcMessageType } from '../RPC/Messages.js';
|
|
4
|
+
/**
|
|
5
|
+
* Mapping between msgrpc messages and the MQTT 5 packet layout described in
|
|
6
|
+
* docs/mqtt5-frame-spec.md.
|
|
7
|
+
*
|
|
8
|
+
* The point is that a peer needs no msgrpc code to take part: where to reply and how to correlate
|
|
9
|
+
* come from the protocol's own Response Topic and Correlation Data, and everything else is a
|
|
10
|
+
* readable user property. Kept separate from the transport so the mapping can be read, and tested,
|
|
11
|
+
* without a broker.
|
|
12
|
+
*/
|
|
13
|
+
/** Control properties are prefixed so a broker or gateway injecting its own cannot be mistaken for one. */
|
|
14
|
+
export const MR = {
|
|
15
|
+
version: 'mr-v',
|
|
16
|
+
source: 'mr-src',
|
|
17
|
+
kind: 'mr-kind',
|
|
18
|
+
path: 'mr-path',
|
|
19
|
+
method: 'mr-method',
|
|
20
|
+
event: 'mr-event',
|
|
21
|
+
code: 'mr-code',
|
|
22
|
+
nonce: 'mr-nonce',
|
|
23
|
+
timestamp: 'mr-ts',
|
|
24
|
+
signature: 'mr-sig',
|
|
25
|
+
contractVersion: 'mr-ver',
|
|
26
|
+
/**
|
|
27
|
+
* Milliseconds the caller will still wait, counted from when it sent. Carried alongside MQTT's
|
|
28
|
+
* own messageExpiryInterval rather than instead of it: expiry is coarse (whole seconds), the
|
|
29
|
+
* broker decrements it, and it stops at the broker - it says nothing about how long a frame then
|
|
30
|
+
* sat in the receiving process. This is the caller's own statement, signed, and it survives
|
|
31
|
+
* relaying through a transport that does not speak MQTT at all.
|
|
32
|
+
*/
|
|
33
|
+
ttl: 'mr-ttl',
|
|
34
|
+
/**
|
|
35
|
+
* Names the command a request is an attempt at, when the caller distinguishes the two. Absent
|
|
36
|
+
* means the correlation data is the name, so a redelivered packet is the same command and a
|
|
37
|
+
* fresh attempt is a different one.
|
|
38
|
+
*/
|
|
39
|
+
idempotencyKey: 'mr-idem'
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Version 2 covers contentType, the error code, the declared contract version, the response topic,
|
|
43
|
+
* the ttl and the idempotency key in the signature; version 1 covered none of them, and a frame
|
|
44
|
+
* signed under one cannot verify under the other. Bumped rather than negotiated: a receiver that quietly accepted either
|
|
45
|
+
* would let an attacker choose the weaker.
|
|
46
|
+
*/
|
|
47
|
+
export const FRAME_VERSION = '2';
|
|
48
|
+
/** Frame versions this build will accept. A frame announcing anything else is refused, not guessed at. */
|
|
49
|
+
export const SUPPORTED_FRAME_VERSIONS = new Set([FRAME_VERSION]);
|
|
50
|
+
const requestKind = (method) => method === 'on' ? 'subscribe' : method === 'off' || method === 'removeListener' ? 'unsubscribe' : 'call';
|
|
51
|
+
/** Kinds that expect an answer, and so are the only ones entitled to say where it should go. */
|
|
52
|
+
export const isRequestKind = (kind) => kind === 'call' || kind === 'subscribe' || kind === 'unsubscribe';
|
|
53
|
+
/** Undefined for anything this layout has no representation for, which the transport drops. */
|
|
54
|
+
export const toOutboundFrame = (message) => {
|
|
55
|
+
const payload = message.payload;
|
|
56
|
+
if (!payload)
|
|
57
|
+
return undefined;
|
|
58
|
+
switch (payload.type) {
|
|
59
|
+
case RpcMessageType.CallInstanceMethod: {
|
|
60
|
+
const call = payload;
|
|
61
|
+
return {
|
|
62
|
+
kind: requestKind(call.method),
|
|
63
|
+
channel: 'req',
|
|
64
|
+
correlation: call.id,
|
|
65
|
+
path: call.path,
|
|
66
|
+
method: call.method,
|
|
67
|
+
version: call.version,
|
|
68
|
+
ttl: call.ttl,
|
|
69
|
+
idempotencyKey: call.idempotencyKey,
|
|
70
|
+
body: call.params
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
case RpcMessageType.success: {
|
|
74
|
+
const success = payload;
|
|
75
|
+
return { kind: 'result', channel: 'rsp', correlation: success.id, body: success.result };
|
|
76
|
+
}
|
|
77
|
+
case RpcMessageType.error: {
|
|
78
|
+
const error = payload;
|
|
79
|
+
return { kind: 'error', channel: 'rsp', correlation: error.id, code: error.code, body: error.error };
|
|
80
|
+
}
|
|
81
|
+
case RpcMessageType.event: {
|
|
82
|
+
const event = payload;
|
|
83
|
+
return { kind: 'event', channel: 'evt', event: event.event, path: event.path, body: event.params };
|
|
84
|
+
}
|
|
85
|
+
default:
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
/** Undefined when the frame does not describe anything this RPC layer can dispatch. */
|
|
90
|
+
export const fromInboundFrame = (frame) => {
|
|
91
|
+
switch (frame.kind) {
|
|
92
|
+
case 'call':
|
|
93
|
+
case 'subscribe':
|
|
94
|
+
case 'unsubscribe': {
|
|
95
|
+
if (!frame.correlation || !frame.path || !frame.method)
|
|
96
|
+
return undefined;
|
|
97
|
+
const payload = {
|
|
98
|
+
type: RpcMessageType.CallInstanceMethod,
|
|
99
|
+
id: frame.correlation,
|
|
100
|
+
path: frame.path,
|
|
101
|
+
method: frame.method,
|
|
102
|
+
version: frame.version,
|
|
103
|
+
ttl: frame.ttl,
|
|
104
|
+
idempotencyKey: frame.idempotencyKey,
|
|
105
|
+
// A caller that sends no payload means no arguments.
|
|
106
|
+
params: Array.isArray(frame.body) ? frame.body : frame.body === undefined || frame.body === null ? [] : [frame.body]
|
|
107
|
+
};
|
|
108
|
+
return { type: MessageType.RequestMessage, payload };
|
|
109
|
+
}
|
|
110
|
+
case 'result': {
|
|
111
|
+
if (!frame.correlation)
|
|
112
|
+
return undefined;
|
|
113
|
+
const payload = { type: RpcMessageType.success, id: frame.correlation, result: frame.body };
|
|
114
|
+
return { type: MessageType.ResponseMessage, payload };
|
|
115
|
+
}
|
|
116
|
+
case 'error': {
|
|
117
|
+
if (!frame.correlation)
|
|
118
|
+
return undefined;
|
|
119
|
+
const payload = {
|
|
120
|
+
type: RpcMessageType.error,
|
|
121
|
+
id: frame.correlation,
|
|
122
|
+
code: (frame.code ?? 'Exception'),
|
|
123
|
+
error: frame.body
|
|
124
|
+
};
|
|
125
|
+
return { type: MessageType.ErrorMessage, payload };
|
|
126
|
+
}
|
|
127
|
+
case 'event': {
|
|
128
|
+
if (!frame.event)
|
|
129
|
+
return undefined;
|
|
130
|
+
const payload = {
|
|
131
|
+
type: RpcMessageType.event,
|
|
132
|
+
event: frame.event,
|
|
133
|
+
path: frame.path,
|
|
134
|
+
params: Array.isArray(frame.body) ? frame.body : [frame.body]
|
|
135
|
+
};
|
|
136
|
+
return { type: MessageType.EventMessage, payload };
|
|
137
|
+
}
|
|
138
|
+
default:
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Read the control properties, refusing any that appear more than once.
|
|
144
|
+
*
|
|
145
|
+
* MQTT permits a repeated user property, and mqtt.js surfaces repeats as an array. Taking the
|
|
146
|
+
* first or the last would let a sender show one value to a check and a different one to the
|
|
147
|
+
* dispatcher, so a repeat is an ambiguity to refuse rather than resolve.
|
|
148
|
+
*/
|
|
149
|
+
export const readControlProperties = (properties) => {
|
|
150
|
+
const values = {};
|
|
151
|
+
for (const [key, value] of Object.entries(properties ?? {})) {
|
|
152
|
+
if (!key.startsWith('mr-'))
|
|
153
|
+
continue;
|
|
154
|
+
if (Array.isArray(value))
|
|
155
|
+
return { duplicate: key };
|
|
156
|
+
values[key] = value;
|
|
157
|
+
}
|
|
158
|
+
return { values };
|
|
159
|
+
};
|
|
160
|
+
export const correlationToString = (correlation) => (correlation ? uint8ArrayToString(correlation) : undefined);
|
|
161
|
+
export const correlationToBytes = (correlation) => (correlation ? stringToUint8Array(correlation) : undefined);
|
|
162
|
+
//# sourceMappingURL=Mqtt5Frame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Mqtt5Frame.js","sourceRoot":"","sources":["../../src/Transports/Mqtt5Frame.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import * as mqtt from 'mqtt';
|
|
2
|
+
import { GenericModule, IGenericModule, Message } from '../RPC/Core.js';
|
|
3
|
+
import { FrameCodec } from '../RPC/Codec.js';
|
|
4
|
+
import { MessageSigner, MessageVerifier, RpcIdentity } from '../RPC/Auth.js';
|
|
5
|
+
import { ReplayGuard } from '../RPC/Signing.js';
|
|
6
|
+
import { Channel } from './Mqtt5Frame.js';
|
|
7
|
+
/** v1 is the $-header layout; v2 is the MQTT 5 property layout, so the two never share a topic. */
|
|
8
|
+
export declare const defaultTopicPrefix: {
|
|
9
|
+
readonly 4: 'msgrpc/v1';
|
|
10
|
+
readonly 5: 'msgrpc/v2';
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* A peer name is interpolated into a topic, so it must not be able to change that topic's shape.
|
|
14
|
+
* A peer named '#' would otherwise subscribe to every other peer's traffic, and one named '+'
|
|
15
|
+
* would do the same one level down.
|
|
16
|
+
*/
|
|
17
|
+
export declare const isSafeTopicSegment: (value: unknown) => value is string;
|
|
18
|
+
/** A prefix may span levels, so '/' is allowed inside it, but wildcards still are not. */
|
|
19
|
+
export declare const isSafeTopicPrefix: (value: unknown) => value is string;
|
|
20
|
+
/**
|
|
21
|
+
* A topic something may be published to. Spans levels, but wildcards are only meaningful in a
|
|
22
|
+
* subscription and `$` opens the broker's own namespace, so neither belongs in a destination that
|
|
23
|
+
* arrived from somewhere else.
|
|
24
|
+
*/
|
|
25
|
+
export declare const isSafeTopicName: (value: unknown) => value is string;
|
|
26
|
+
export interface MqttTransportOptions {
|
|
27
|
+
/** Topic namespace. Traffic lives under <prefix>/rpc/<peer> and <prefix>/presence/<peer>. */
|
|
28
|
+
prefix?: string;
|
|
29
|
+
/** Peer name to subscribe as. Defaults to the transport's own name. */
|
|
30
|
+
topic?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Watch every peer's traffic instead of this one's, and report it rather than acting on it.
|
|
33
|
+
*
|
|
34
|
+
* There is no broker of ours on an MQTT network to hook the way a socket.io one can be, so the
|
|
35
|
+
* observation happens at the subscription: `<prefix>/rpc/+` under the 3.1.1 layout, and each of
|
|
36
|
+
* `<prefix>/{req,rsp,evt}/+` under MQTT 5. Everything decoded is emitted as
|
|
37
|
+
* `TransportEvent.relayed` and nothing is delivered - a tap answers no calls and runs no
|
|
38
|
+
* methods.
|
|
39
|
+
*
|
|
40
|
+
* **Give this its own transport rather than adding it to a working one.** A peer subscribed to
|
|
41
|
+
* both its own topic and the wildcard covering it has overlapping subscriptions, and a broker
|
|
42
|
+
* is permitted to deliver a matching message once per subscription - which for a request means
|
|
43
|
+
* running the method twice. A separate instance is a separate client id and a separate session,
|
|
44
|
+
* so the two never overlap. It follows that a tap needs a name of its own, and `presence: false`
|
|
45
|
+
* unless it should appear in everyone's peer list.
|
|
46
|
+
*
|
|
47
|
+
* Frames are reported without checking signatures: a tap holds no key for a conversation it is
|
|
48
|
+
* not part of, and what is on the wire is what it exists to show.
|
|
49
|
+
*/
|
|
50
|
+
tap?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Quality of service for RPC traffic. Defaults to 1, at least once: QoS 0 drops messages
|
|
53
|
+
* silently whenever the broker or link hiccups, which for RPC shows up as a call timeout.
|
|
54
|
+
* At-least-once permits duplicate delivery, which the RPC server suppresses by request id.
|
|
55
|
+
*/
|
|
56
|
+
qos?: 0 | 1 | 2;
|
|
57
|
+
/**
|
|
58
|
+
* Publish a retained last will, so peers learn when this one disappears instead of holding
|
|
59
|
+
* its event subscriptions forever. On by default.
|
|
60
|
+
*/
|
|
61
|
+
presence?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Ask the broker to keep this client's session, queueing QoS > 0 messages while it is
|
|
64
|
+
* disconnected. Worth enabling for servers, which should not lose requests across a restart.
|
|
65
|
+
* Off by default: a persistent session for a short-lived peer lingers on the broker.
|
|
66
|
+
*/
|
|
67
|
+
persistentSession?: boolean;
|
|
68
|
+
/** Broker connection options: credentials, TLS client certificates, clientId, keepalive. */
|
|
69
|
+
mqtt?: mqtt.IClientOptions;
|
|
70
|
+
/**
|
|
71
|
+
* Connect to an `mqtts://` or `wss://` broker without checking its certificate. Deliberately
|
|
72
|
+
* unsafe and named so: it accepts any certificate at all, so anything able to answer on the
|
|
73
|
+
* broker's address can read and rewrite everything this peer sends. For a development broker
|
|
74
|
+
* with a self-signed certificate; a plant should carry its own CA in `mqtt.ca` instead.
|
|
75
|
+
*/
|
|
76
|
+
allowInsecureTls?: boolean;
|
|
77
|
+
/** Sign every outgoing frame. See RPC/Signing.ts for ready-made HMAC and Ed25519 signers. */
|
|
78
|
+
sign?: MessageSigner;
|
|
79
|
+
/**
|
|
80
|
+
* Require and check a signature on every incoming frame. Unsigned, stale, replayed or
|
|
81
|
+
* badly-signed frames are dropped before they reach the RPC layer, and a verified peer gains
|
|
82
|
+
* a real identity that authorize() can act on.
|
|
83
|
+
*/
|
|
84
|
+
verify?: MessageVerifier;
|
|
85
|
+
/** How far an incoming frame's timestamp may differ from local time. Default 60000 ms. */
|
|
86
|
+
maxClockSkew?: number;
|
|
87
|
+
/** How many recent nonces to remember for replay detection. Default 5000. */
|
|
88
|
+
maxTrackedNonces?: number;
|
|
89
|
+
/**
|
|
90
|
+
* MQTT protocol version. 5 carries the reply address, correlation and method as packet
|
|
91
|
+
* properties, so a peer with no msgrpc code can take part and standard tooling can read the
|
|
92
|
+
* traffic. 4 (MQTT 3.1.1) keeps the older $-delimited header for brokers that need it.
|
|
93
|
+
*/
|
|
94
|
+
protocol?: 4 | 5;
|
|
95
|
+
/**
|
|
96
|
+
* MQTT 5 only: how long the broker holds a request that names no deadline of its own.
|
|
97
|
+
*
|
|
98
|
+
* A request from an RPC client carries the time its caller will still wait, and the expiry is
|
|
99
|
+
* taken from that instead - the two used to be independent, so a client that gave up after ten
|
|
100
|
+
* seconds could have its request delivered and executed twenty seconds later. This remains the
|
|
101
|
+
* answer for a request that says nothing, which is any third-party caller not sending `mr-ttl`.
|
|
102
|
+
*/
|
|
103
|
+
requestExpirySeconds?: number;
|
|
104
|
+
/**
|
|
105
|
+
* MQTT 5 only: decide whether a request may have its reply published where it asks.
|
|
106
|
+
*
|
|
107
|
+
* A request names a Response Topic and that is where the answer goes, which means a caller
|
|
108
|
+
* chooses a topic this peer then publishes to. Unset, the rule is that the topic must sit under
|
|
109
|
+
* this transport's own prefix - the boundary broker ACLs are usually drawn on. Supply this to
|
|
110
|
+
* widen it, or to narrow it to exactly the peer's own reply topic.
|
|
111
|
+
*/
|
|
112
|
+
allowResponseTopic?: (topic: string, source: string) => boolean;
|
|
113
|
+
/** MQTT 5 only: which of this peer's channels to subscribe to. Defaults to all three. */
|
|
114
|
+
channels?: Channel[];
|
|
115
|
+
/**
|
|
116
|
+
* MQTT 5 only. Join a shared subscription group so several processes can serve one peer name,
|
|
117
|
+
* with the broker distributing requests among them.
|
|
118
|
+
*
|
|
119
|
+
* Only the request channel is shared. A reply has to reach the requester waiting for it, and an
|
|
120
|
+
* event its particular subscriber, so sharing those would hand them to an arbitrary replica.
|
|
121
|
+
*/
|
|
122
|
+
sharedGroup?: string;
|
|
123
|
+
/**
|
|
124
|
+
* Distinguishes this replica's broker connection from its siblings'. A broker permits one
|
|
125
|
+
* connection per client id, and replicas share a peer name, so without this they would
|
|
126
|
+
* disconnect each other in a loop. Defaults to a random suffix.
|
|
127
|
+
*/
|
|
128
|
+
replicaId?: string;
|
|
129
|
+
/**
|
|
130
|
+
* MQTT 5 only: how long the broker keeps this peer's session after it disconnects. Bounds the
|
|
131
|
+
* queueing that makes a restart lossless, without leaving session state behind forever.
|
|
132
|
+
* Defaults to an hour for a persistent session and a minute otherwise.
|
|
133
|
+
*/
|
|
134
|
+
sessionExpirySeconds?: number;
|
|
135
|
+
}
|
|
136
|
+
export declare class MqttTransport extends GenericModule<Message, unknown, Message, unknown> {
|
|
137
|
+
url: string;
|
|
138
|
+
client?: mqtt.MqttClient;
|
|
139
|
+
connected: boolean;
|
|
140
|
+
/** Owned here rather than by a converter above, so the transport decides its own wire form. */
|
|
141
|
+
codec: FrameCodec;
|
|
142
|
+
readonly prefix: string;
|
|
143
|
+
readonly topic: string;
|
|
144
|
+
readonly qos: 0 | 1 | 2;
|
|
145
|
+
readonly presence: boolean;
|
|
146
|
+
readonly persistentSession: boolean;
|
|
147
|
+
readonly mqttOptions: mqtt.IClientOptions;
|
|
148
|
+
readonly protocol: 4 | 5;
|
|
149
|
+
readonly requestExpirySeconds: number;
|
|
150
|
+
readonly channels: Channel[];
|
|
151
|
+
readonly sharedGroup?: string;
|
|
152
|
+
readonly allowResponseTopic?: (topic: string, source: string) => boolean;
|
|
153
|
+
readonly tap: boolean;
|
|
154
|
+
readonly replicaId: string;
|
|
155
|
+
readonly sessionExpirySeconds: number;
|
|
156
|
+
/** A replica must not speak for the whole group; see the constructor. */
|
|
157
|
+
readonly announcePresence: boolean;
|
|
158
|
+
readonly sign?: MessageSigner;
|
|
159
|
+
readonly verify?: MessageVerifier;
|
|
160
|
+
readonly replayGuard: ReplayGuard;
|
|
161
|
+
/** Peer name -> identity established by verifying that peer's signature. */
|
|
162
|
+
peerIdentities: Map<string, RpcIdentity>;
|
|
163
|
+
/**
|
|
164
|
+
* Correlation -> where a request asked for its reply and in what encoding it arrived, so the
|
|
165
|
+
* answer goes back where it was asked for and in a form the caller can read. A third party that
|
|
166
|
+
* speaks JSON must not be answered in msgpack, and one that subscribed to a topic of its own
|
|
167
|
+
* choosing must not be answered on a topic we invented for it. Bounded, since the keys come off
|
|
168
|
+
* the wire.
|
|
169
|
+
*/
|
|
170
|
+
private pendingReplies;
|
|
171
|
+
private maxTrackedReplies;
|
|
172
|
+
constructor(name: string, url: string, options?: MqttTransportOptions, sources?: IGenericModule<unknown, unknown, Message, unknown>[]);
|
|
173
|
+
/**
|
|
174
|
+
* The broker connection, or an error saying there is none.
|
|
175
|
+
*
|
|
176
|
+
* Publishing used to go through `this.client?.publishAsync(...)`, which resolves to undefined
|
|
177
|
+
* when the transport is closed or has not opened yet - so an outgoing call was dropped on the
|
|
178
|
+
* floor and its caller learned nothing until the call timed out. A frame that cannot be sent is
|
|
179
|
+
* a failure worth reporting at once.
|
|
180
|
+
*/
|
|
181
|
+
private requireClient;
|
|
182
|
+
rpcTopic(peer: string): string;
|
|
183
|
+
channelTopic(channel: Channel, peer: string): string;
|
|
184
|
+
presenceTopic(peer: string): string;
|
|
185
|
+
private get presenceRoot();
|
|
186
|
+
open(): Promise<void>;
|
|
187
|
+
private connectedSince;
|
|
188
|
+
/** Consecutive connections that did not survive long enough to be doing anything useful. */
|
|
189
|
+
private shortConnections;
|
|
190
|
+
/**
|
|
191
|
+
* The 3.1.1 half of collision reporting, which has to be inferred rather than read.
|
|
192
|
+
*
|
|
193
|
+
* MQTT 5 says why it disconnected you; 3.1.1 has no reason codes, so a session taken over looks
|
|
194
|
+
* exactly like the link dropping. What it does not look like is a *stable* connection: two
|
|
195
|
+
* peers sharing a client id evict each other on sight, so both sit in a reconnect loop where no
|
|
196
|
+
* connection outlives the next one's arrival. A blip reconnects once and stays.
|
|
197
|
+
*
|
|
198
|
+
* Reported as a suspicion rather than a fact, because a network flapping this hard would look
|
|
199
|
+
* the same - and either way it is worth saying out loud.
|
|
200
|
+
*/
|
|
201
|
+
private noteConnectionLength;
|
|
202
|
+
private warnedAboutFlapping;
|
|
203
|
+
private warnAboutFlapping;
|
|
204
|
+
/** Said once: mqtt.js reconnects on its own, and two peers sharing a name take turns forever. */
|
|
205
|
+
private warnedAboutDisplacement;
|
|
206
|
+
private warnAboutDisplacement;
|
|
207
|
+
private onConnect;
|
|
208
|
+
private onBrokerMessage;
|
|
209
|
+
private receiveV5;
|
|
210
|
+
/**
|
|
211
|
+
* A frame this transport is only watching, decoded and announced.
|
|
212
|
+
*
|
|
213
|
+
* The v1 layout carries no properties, so the payload has to be decoded here before anything can
|
|
214
|
+
* be said about it - which is also the only work a tap does per frame, and it is skipped
|
|
215
|
+
* entirely when nothing is listening.
|
|
216
|
+
*/
|
|
217
|
+
private report;
|
|
218
|
+
/** The peer a topic addresses: <prefix>/<channel>/<peer>. */
|
|
219
|
+
private topicAddressee;
|
|
220
|
+
/**
|
|
221
|
+
* Hand a decoded frame to this peer's own handler, or on to whichever transport carries its
|
|
222
|
+
* addressee. The second case is a bridge: this transport is subscribed to a topic belonging to
|
|
223
|
+
* a peer that lives on another link, and its job is to pass the frame along unchanged - the
|
|
224
|
+
* source and any signature stay as the original sender wrote them.
|
|
225
|
+
*/
|
|
226
|
+
private deliver;
|
|
227
|
+
/** Peers this transport collects answers for, so the subscriptions are made once and dropped once. */
|
|
228
|
+
private readonly proxied;
|
|
229
|
+
private watchOnBehalfOf;
|
|
230
|
+
/** Stop collecting for a peer that has gone, so a departed browser leaves no subscription behind. */
|
|
231
|
+
stopWatchingFor(peer: string): Promise<void>;
|
|
232
|
+
/**
|
|
233
|
+
* A reason to refuse a response topic, or undefined to publish the answer there.
|
|
234
|
+
*
|
|
235
|
+
* The topic comes from whoever sent the request, and this peer is the one that will publish to
|
|
236
|
+
* it, so without a rule a caller could have a server publish anywhere the broker's ACLs let it -
|
|
237
|
+
* over another peer's presence, into `$SYS`, or onto a retained topic something else reads. The
|
|
238
|
+
* default rule is the transport's own prefix, since that is the boundary an operator already
|
|
239
|
+
* draws ACLs on.
|
|
240
|
+
*/
|
|
241
|
+
private refuseResponseTopic;
|
|
242
|
+
/**
|
|
243
|
+
* What is left of the caller's stated budget.
|
|
244
|
+
*
|
|
245
|
+
* MQTT 5 requires a server to hand on the Message Expiry Interval it received minus the time
|
|
246
|
+
* the message spent waiting in it, so for a request that was queued this is the caller's budget
|
|
247
|
+
* with the queueing already deducted - measured by the broker, with no clock of ours entering
|
|
248
|
+
* into it. Taken as an upper bound only: expiry is whole seconds and a broker of unknown
|
|
249
|
+
* quality set it, so it may shorten what the caller signed and never lengthen it.
|
|
250
|
+
*/
|
|
251
|
+
private remainingTtl;
|
|
252
|
+
/**
|
|
253
|
+
* Seconds the broker should hold a request: what its caller said it would wait, rounded up.
|
|
254
|
+
*
|
|
255
|
+
* Clamped to the four-byte field MQTT gives it - about 136 years - because the ttl comes from
|
|
256
|
+
* whatever number a caller set as its timeout, and a value that does not fit would be a packet
|
|
257
|
+
* the broker refuses rather than a request that waits a long time.
|
|
258
|
+
*/
|
|
259
|
+
private expiryFor;
|
|
260
|
+
private rememberReply;
|
|
261
|
+
/** One request, one answer: taking it also forgets it. */
|
|
262
|
+
private takeReply;
|
|
263
|
+
/** A peer may speak JSON while this one defaults to msgpack; contentType says which. */
|
|
264
|
+
private codecFor;
|
|
265
|
+
private verifyV5;
|
|
266
|
+
/**
|
|
267
|
+
* Returns a reason to reject, or undefined when the frame is authentic. Every check is a
|
|
268
|
+
* separate failure mode worth naming, because "message dropped" with no reason is the hardest
|
|
269
|
+
* kind of problem to diagnose on a plant network.
|
|
270
|
+
*/
|
|
271
|
+
private verifyFrame;
|
|
272
|
+
receive(message: Message, source: string, target: string): Promise<void>;
|
|
273
|
+
/** Maps an RPC message onto the MQTT 5 packet layout. See docs/mqtt5-frame-spec.md. */
|
|
274
|
+
private publishV5;
|
|
275
|
+
close(): Promise<void>;
|
|
276
|
+
getIdentity(source: string): RpcIdentity | undefined;
|
|
277
|
+
isTransport(): boolean;
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=MqttTransport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MqttTransport.d.ts","sourceRoot":"","sources":["../../src/Transports/MqttTransport.ts"],"names":[],"mappings":"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"}
|