querysub 0.647.0 → 0.648.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/package.json
CHANGED
|
@@ -29,15 +29,22 @@ const MAX_CHANGE_IDENTITY_TIMEOUT = timeInMinute * 5;
|
|
|
29
29
|
const MOUNT_WAIT_TIMEOUT = timeInMinute * 3;
|
|
30
30
|
|
|
31
31
|
let callerInfo = new Map<CallerContext, {
|
|
32
|
-
reconnectNodeId: string | Promise<string
|
|
33
|
-
|
|
32
|
+
reconnectNodeId: string | Promise<string>;
|
|
33
|
+
reconnectNodeIdPromiseObj: PromiseObj<string> | undefined;
|
|
34
34
|
certCommonName: string;
|
|
35
35
|
machineId: string;
|
|
36
36
|
cert: CertInfo;
|
|
37
37
|
pubKey: Buffer;
|
|
38
38
|
pubKeyShort: number;
|
|
39
39
|
}>();
|
|
40
|
-
|
|
40
|
+
|
|
41
|
+
function getCallerInfoAssert(callerContext: CallerContext) {
|
|
42
|
+
let info = callerInfo.get(callerContext);
|
|
43
|
+
if (!info) {
|
|
44
|
+
throw new Error(`Internal error, caller did not updated their identity. Is this an HTTPS call (instead of a websocket call)? The caller should import the server controller, which imports this function, which will add a client hook to always update the identity`);
|
|
45
|
+
}
|
|
46
|
+
return info;
|
|
47
|
+
}
|
|
41
48
|
|
|
42
49
|
/** Gets the nodeId of the caller suitable for reconnecting (to the same process).
|
|
43
50
|
* - Also useful for logs, to identify a node on the network.
|
|
@@ -51,37 +58,19 @@ export function IdentityController_getReconnectNodeId(callerContext: CallerConte
|
|
|
51
58
|
let info = callerInfo.get(callerContext);
|
|
52
59
|
if (!info) {
|
|
53
60
|
if (allowUndefined) return undefined;
|
|
54
|
-
|
|
61
|
+
info = getCallerInfoAssert(callerContext);
|
|
55
62
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
63
|
+
if (typeof info.reconnectNodeId === "string") {
|
|
64
|
+
return info.reconnectNodeId;
|
|
65
|
+
}
|
|
66
|
+
return undefined;
|
|
59
67
|
}
|
|
60
68
|
export async function IdentityController_getReconnectNodeIdAssert(callerContext: CallerContext): Promise<string> {
|
|
61
69
|
if (!isClientNodeId(callerContext.nodeId)) {
|
|
62
70
|
return callerContext.nodeId;
|
|
63
71
|
}
|
|
64
|
-
let info =
|
|
65
|
-
|
|
66
|
-
throw new Error(callerInfoErrorString);
|
|
67
|
-
}
|
|
68
|
-
let valueBase = info.reconnectNodeId;
|
|
69
|
-
let value: string | Error | undefined;
|
|
70
|
-
if (valueBase instanceof Promise) {
|
|
71
|
-
value = await valueBase;
|
|
72
|
-
} else {
|
|
73
|
-
value = valueBase;
|
|
74
|
-
}
|
|
75
|
-
if (value instanceof Error) {
|
|
76
|
-
throw value;
|
|
77
|
-
}
|
|
78
|
-
if (!value) {
|
|
79
|
-
console.error(`Caller did not mount before connecting. This call requires the caller to be listening.`, {
|
|
80
|
-
callerNodeId: callerContext.nodeId,
|
|
81
|
-
});
|
|
82
|
-
throw new Error(`Caller did not mount before connecting. This call requires the caller to be listening.`);
|
|
83
|
-
}
|
|
84
|
-
return value;
|
|
72
|
+
let info = getCallerInfoAssert(callerContext);
|
|
73
|
+
return await info.reconnectNodeId;
|
|
85
74
|
}
|
|
86
75
|
export function IdentityController_getSecureIP(callerContext: CallerContext): string {
|
|
87
76
|
return getNodeIdIP(callerContext.nodeId);
|
|
@@ -95,9 +84,11 @@ export function IdentityController_getCurrentReconnectNodeId(): string | undefin
|
|
|
95
84
|
|
|
96
85
|
export function debugNodeId(nodeId: string) {
|
|
97
86
|
let info = Array.from(callerInfo.entries()).find(x => x[0].nodeId === nodeId);
|
|
98
|
-
let
|
|
99
|
-
if (typeof
|
|
100
|
-
|
|
87
|
+
let reconnectNodeId = info?.[1].reconnectNodeId;
|
|
88
|
+
if (typeof reconnectNodeId !== "string") {
|
|
89
|
+
return nodeId;
|
|
90
|
+
}
|
|
91
|
+
return reconnectNodeId;
|
|
101
92
|
};
|
|
102
93
|
(globalThis as any).debugNodeId = debugNodeId;
|
|
103
94
|
|
|
@@ -118,21 +109,19 @@ export function IdentityController_getMachineId(callerContext: CallerContext, al
|
|
|
118
109
|
let info = callerInfo.get(callerContext);
|
|
119
110
|
if (!info) {
|
|
120
111
|
if (allowEmpty) return "";
|
|
121
|
-
|
|
112
|
+
info = getCallerInfoAssert(callerContext);
|
|
122
113
|
}
|
|
123
114
|
return info.machineId;
|
|
124
115
|
}
|
|
125
116
|
|
|
126
117
|
export type CertInfo = { certPEM: Buffer | string; issuerPEM: Buffer | string; };
|
|
127
118
|
export function IdentityController_getCertInfo(callerContext: CallerContext): CertInfo {
|
|
128
|
-
let info =
|
|
129
|
-
if (!info) throw new Error(callerInfoErrorString);
|
|
119
|
+
let info = getCallerInfoAssert(callerContext);
|
|
130
120
|
return info.cert;
|
|
131
121
|
}
|
|
132
122
|
|
|
133
123
|
export function IdentityController_getPubKeyShort(callerContext: CallerContext): number {
|
|
134
|
-
let info =
|
|
135
|
-
if (!info) throw new Error(callerInfoErrorString);
|
|
124
|
+
let info = getCallerInfoAssert(callerContext);
|
|
136
125
|
return info.pubKeyShort;
|
|
137
126
|
}
|
|
138
127
|
export const IdentityController_getOwnPubKeyShort = lazy((): number => {
|
|
@@ -149,7 +138,7 @@ export interface ChangeIdentityPayload {
|
|
|
149
138
|
serverId: string;
|
|
150
139
|
mountedPort: number | undefined;
|
|
151
140
|
debugEntryPoint: string | undefined;
|
|
152
|
-
|
|
141
|
+
callerIsNode: boolean;
|
|
153
142
|
}
|
|
154
143
|
class IdentityControllerBase {
|
|
155
144
|
// IMPORTANT! We HAVE to call changeIdentity NOT JUST because we can't use peer certificates in the browser, BUT, also
|
|
@@ -167,7 +156,7 @@ class IdentityControllerBase {
|
|
|
167
156
|
throw new Error(`Signed payload too old, ${payload.time} < ${signedThreshold} from ${caller.localNodeId} (${caller.nodeId})`);
|
|
168
157
|
}
|
|
169
158
|
|
|
170
|
-
if (payload.
|
|
159
|
+
if (payload.callerIsNode && payload.serverId !== getOwnNodeId()) {
|
|
171
160
|
// This is extremely common when we reuse ports, which we do frequently for the edge nodes.
|
|
172
161
|
throw new Error(`You tried to contact another server. We are ${getOwnNodeId()}, you tried to contact ${payload.serverId}.`);
|
|
173
162
|
}
|
|
@@ -180,7 +169,7 @@ class IdentityControllerBase {
|
|
|
180
169
|
throw new Error(`Identity is for another server! The connection is calling us ${localNodeId}, but signature is for ${payload.serverId}`);
|
|
181
170
|
}
|
|
182
171
|
// If they're calling from the browser, then they're not going to be able to use our machine ID, etc. However, they should be calling an actual https node, so it should still be secure for them.
|
|
183
|
-
if (payload.
|
|
172
|
+
if (payload.callerIsNode) {
|
|
184
173
|
let calledMachineId = getMachineId(payload.serverId, getDomain());
|
|
185
174
|
if (calledMachineId !== "127-0-0-1" && calledMachineId !== getOwnMachineId(getDomain())) {
|
|
186
175
|
throw new Error(`Tried to call a different machine. We are ${getOwnMachineId(getDomain())}, they called ${calledMachineId}`);
|
|
@@ -202,19 +191,22 @@ class IdentityControllerBase {
|
|
|
202
191
|
// to use HTTPS, so connecting over the IP won't work! (unless they turn off certificate validation,
|
|
203
192
|
// which we shouldn't do...)
|
|
204
193
|
let certCommonName = getCommonName(payload.cert);
|
|
205
|
-
let reconnectNodeId: string | Promise<string
|
|
206
|
-
let
|
|
194
|
+
let reconnectNodeId: string | Promise<string>;
|
|
195
|
+
let reconnectNodeIdPromiseObj: PromiseObj<string> | undefined;
|
|
207
196
|
if (payload.mountedPort) {
|
|
208
197
|
reconnectNodeId = getNodeId(certCommonName, payload.mountedPort);
|
|
209
198
|
} else {
|
|
210
|
-
|
|
211
|
-
reconnectNodeId =
|
|
212
|
-
resolveReconnectNodeId = pending.resolve;
|
|
199
|
+
reconnectNodeIdPromiseObj = new PromiseObj<string>();
|
|
200
|
+
reconnectNodeId = reconnectNodeIdPromiseObj.promise;
|
|
213
201
|
setTimeout(() => {
|
|
214
|
-
|
|
202
|
+
reconnectNodeIdPromiseObj?.reject(new Error(`Caller did not call setMountedPort within ${formatTime(MOUNT_WAIT_TIMEOUT)} of connecting. This call requires the caller to be listening.`));
|
|
215
203
|
}, MOUNT_WAIT_TIMEOUT);
|
|
216
204
|
}
|
|
217
205
|
|
|
206
|
+
if (!payload.callerIsNode) {
|
|
207
|
+
reconnectNodeIdPromiseObj?.reject(new Error(`The caller says they are a client, so they are never going to have a reconnect node id`));
|
|
208
|
+
}
|
|
209
|
+
|
|
218
210
|
let pubKey = getPublicIdentifier(payload.cert);
|
|
219
211
|
let machineId = getMachineId(getCommonName(payload.certIssuer), getDomain());
|
|
220
212
|
|
|
@@ -223,7 +215,7 @@ class IdentityControllerBase {
|
|
|
223
215
|
machineId,
|
|
224
216
|
certCommonName,
|
|
225
217
|
reconnectNodeId,
|
|
226
|
-
|
|
218
|
+
reconnectNodeIdPromiseObj,
|
|
227
219
|
pubKey,
|
|
228
220
|
pubKeyShort: getShortNumber(pubKey),
|
|
229
221
|
});
|
|
@@ -249,11 +241,11 @@ class IdentityControllerBase {
|
|
|
249
241
|
@measureFnc
|
|
250
242
|
public async setMountedPort(mountedPort: number) {
|
|
251
243
|
const caller = SocketFunction.getCaller();
|
|
252
|
-
let info =
|
|
253
|
-
if (
|
|
244
|
+
let info = getCallerInfoAssert(caller);
|
|
245
|
+
if (typeof info.reconnectNodeId === "string") throw new Error(`Already have reconnectNodeId, not sure why we are being given another, Have ${info.reconnectNodeId}, given port: ${mountedPort}`);
|
|
254
246
|
let reconnectNodeId = getNodeId(info.certCommonName, mountedPort);
|
|
255
247
|
info.reconnectNodeId = reconnectNodeId;
|
|
256
|
-
info.
|
|
248
|
+
info.reconnectNodeIdPromiseObj?.resolve(reconnectNodeId);
|
|
257
249
|
console.info(`Caller mounted after connecting, set reconnect node id`, {
|
|
258
250
|
clientId: caller.nodeId,
|
|
259
251
|
reconnectNodeId,
|
|
@@ -290,7 +282,7 @@ const changeIdentityOnce = cacheWeak(async function changeIdentityOnce(connectio
|
|
|
290
282
|
certIssuer: issuer.cert.toString(),
|
|
291
283
|
mountedPort: getNodeIdLocation(SocketFunction.mountedNodeId)?.port,
|
|
292
284
|
debugEntryPoint: isServer() ? process.argv[1] : "browser",
|
|
293
|
-
|
|
285
|
+
callerIsNode: isServer() && !isIpDomain(nodeId),
|
|
294
286
|
};
|
|
295
287
|
let signature = sign(threadKeyCert, payload);
|
|
296
288
|
await timeoutToError(
|
|
@@ -302,13 +294,9 @@ const changeIdentityOnce = cacheWeak(async function changeIdentityOnce(connectio
|
|
|
302
294
|
logErrors((async () => {
|
|
303
295
|
await SocketFunction.mountPromise;
|
|
304
296
|
let mountedPort = getNodeIdLocation(SocketFunction.mountedNodeId)?.port;
|
|
305
|
-
if (!mountedPort)
|
|
297
|
+
if (!mountedPort) throw new Error(`Mounted after connecting to ${nodeId}, but no mounted port found? mounted node id: ${SocketFunction.mountedNodeId}`);
|
|
306
298
|
console.info(`Mounted after connecting to ${nodeId}, sending mounted port ${mountedPort}`);
|
|
307
|
-
await
|
|
308
|
-
MAX_CHANGE_IDENTITY_TIMEOUT,
|
|
309
|
-
IdentityController.nodes[nodeId].setMountedPort(mountedPort),
|
|
310
|
-
() => new Error(`Timeout calling setMountedPort for ${nodeId}`)
|
|
311
|
-
);
|
|
299
|
+
await IdentityController.nodes[nodeId].setMountedPort(mountedPort);
|
|
312
300
|
})());
|
|
313
301
|
}
|
|
314
302
|
});
|