pairnet 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/eslint.config.js +3 -0
- package/index.js +10 -4
- package/lib/protocol.js +11 -11
- package/package.json +21 -27
- package/promisified/server-close.js +2 -2
- package/promisified/server-listen.js +2 -2
- package/.eslintrc +0 -3
- package/promisified/disconnect-socket.js +0 -11
- package/streams/infinite-queue.js +0 -37
package/eslint.config.js
ADDED
package/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const crypto = require("crypto");
|
|
4
4
|
const tls = require("tls");
|
|
5
|
-
const
|
|
5
|
+
const makeDebug = require("debug-instanced")("pairnet");
|
|
6
6
|
const matchValue = require("match-value");
|
|
7
7
|
const pipe = require("@promistream/pipe");
|
|
8
8
|
const simpleSink = require("@promistream/simple-sink");
|
|
@@ -40,7 +40,7 @@ function createQueryError(message) {
|
|
|
40
40
|
return error;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
async function makeClientSocket({ hostname, port, options, onQuery, protocolConfiguration }) {
|
|
43
|
+
async function makeClientSocket({ hostname, port, options, onQuery, protocolConfiguration, debug }) {
|
|
44
44
|
let socket = tls.connect({
|
|
45
45
|
host: hostname,
|
|
46
46
|
port: port,
|
|
@@ -53,7 +53,9 @@ async function makeClientSocket({ hostname, port, options, onQuery, protocolConf
|
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
let api = await handleProtocol(socket, {
|
|
56
|
+
debug,
|
|
56
57
|
protocolConfiguration: protocolConfiguration,
|
|
58
|
+
role: "client",
|
|
57
59
|
onQuery: onQuery
|
|
58
60
|
});
|
|
59
61
|
|
|
@@ -77,6 +79,8 @@ module.exports = {
|
|
|
77
79
|
createMemoryStorage: createMemoryStorage,
|
|
78
80
|
createFileStorage: createFileStorage,
|
|
79
81
|
createPeer: async function createPeer(_options) {
|
|
82
|
+
let debug = makeDebug("peer");
|
|
83
|
+
|
|
80
84
|
let { storage, generateClientHello, onClientHello, onServerHello } = validateOptions(arguments, {
|
|
81
85
|
storage: [ required, isStorageProvider ],
|
|
82
86
|
generateClientHello: [ required, isFunction ],
|
|
@@ -148,7 +152,7 @@ module.exports = {
|
|
|
148
152
|
debug(`[pair] Initiating pairing connection to ${hostname}:${port}...`);
|
|
149
153
|
|
|
150
154
|
let socket = await makeClientSocket({
|
|
151
|
-
hostname, port, protocolConfiguration,
|
|
155
|
+
debug, hostname, port, protocolConfiguration,
|
|
152
156
|
// We don't care about anything other than pairing messages in this mode, which are in the form of a query reply
|
|
153
157
|
onQuery: () => {}
|
|
154
158
|
});
|
|
@@ -201,7 +205,7 @@ module.exports = {
|
|
|
201
205
|
|
|
202
206
|
// connect with client certificate made from own identity, and validate server pubkey
|
|
203
207
|
let socket = await makeClientSocket({
|
|
204
|
-
hostname, port, protocolConfiguration,
|
|
208
|
+
debug, hostname, port, protocolConfiguration,
|
|
205
209
|
onQuery: onQuery
|
|
206
210
|
});
|
|
207
211
|
|
|
@@ -252,7 +256,9 @@ module.exports = {
|
|
|
252
256
|
debug(`[server] Is trusted: ${isPaired}`);
|
|
253
257
|
|
|
254
258
|
let api = await handleProtocol(socket, {
|
|
259
|
+
debug,
|
|
255
260
|
protocolConfiguration,
|
|
261
|
+
role: "server",
|
|
256
262
|
onQuery: async (query) => {
|
|
257
263
|
return matchValue(query.type, {
|
|
258
264
|
PAIR: async () => {
|
package/lib/protocol.js
CHANGED
|
@@ -5,16 +5,13 @@ const decodeCBOR = require("@promistream/decode-cbor");
|
|
|
5
5
|
const pipe = require("@promistream/pipe");
|
|
6
6
|
const fromNodeStream = require("@promistream/from-node-stream");
|
|
7
7
|
const map = require("@promistream/map");
|
|
8
|
-
const
|
|
8
|
+
const simpleQueue = require("@promistream/simple-queue");
|
|
9
9
|
const simpleSink = require("@promistream/simple-sink");
|
|
10
10
|
const createDebugStream = require("@promistream/debug");
|
|
11
11
|
const objid = require("@joepie91/objid");
|
|
12
12
|
|
|
13
|
-
const debug = require("debug")("pairnet:protocol");
|
|
14
|
-
|
|
15
13
|
const createSender = require("./sender");
|
|
16
14
|
const createReplyTracker = require("./reply-tracker");
|
|
17
|
-
const disconnectSocket = require("../promisified/disconnect-socket");
|
|
18
15
|
const filter = require("@promistream/filter");
|
|
19
16
|
|
|
20
17
|
let NORMAL_QUERY_TYPE = "q";
|
|
@@ -45,10 +42,10 @@ async function evaluateQuery(query, handler) {
|
|
|
45
42
|
}
|
|
46
43
|
}
|
|
47
44
|
|
|
48
|
-
module.exports = async function handleProtocol(socket, { onQuery, protocolConfiguration } = {}) {
|
|
49
|
-
debug(
|
|
45
|
+
module.exports = async function handleProtocol(socket, { debug, onQuery, protocolConfiguration, role } = {}) {
|
|
46
|
+
debug(`Attaching semantic protocol handler (role = ${role})`);
|
|
50
47
|
|
|
51
|
-
let writeQueue =
|
|
48
|
+
let writeQueue = simpleQueue([], { autoEnd: false });
|
|
52
49
|
let replyTracker = createReplyTracker();
|
|
53
50
|
let negotiationCompleted = false;
|
|
54
51
|
|
|
@@ -85,15 +82,16 @@ module.exports = async function handleProtocol(socket, { onQuery, protocolConfig
|
|
|
85
82
|
// createDebugStream(`pairnet:protocol:receive-pipeline ${objid(socket)}`),
|
|
86
83
|
]);
|
|
87
84
|
|
|
88
|
-
let clientHelloQuery = (
|
|
85
|
+
let clientHelloQuery = (role === "client")
|
|
89
86
|
? sender.sendNegotiationQuery(await protocolConfiguration.generateClientHello())._queryID.toString("hex") // FIXME: Hacky
|
|
90
87
|
: null;
|
|
91
88
|
|
|
92
89
|
// We read messages for as long as negotiation has not been completed yet
|
|
90
|
+
// TODO[security]: verify that we don't allow server/client confusion anywhere
|
|
93
91
|
await pipe([
|
|
94
92
|
incomingMessageStream,
|
|
95
93
|
simpleSink(async (message) => {
|
|
96
|
-
debug("Received message:", message);
|
|
94
|
+
debug("Received message (negotiation phase):", message);
|
|
97
95
|
|
|
98
96
|
let isNegotiationMessage = NEGOTIATION_TYPES.has(message.t);
|
|
99
97
|
let isReplyMessage = REPLY_TYPES.has(message.t);
|
|
@@ -107,7 +105,7 @@ module.exports = async function handleProtocol(socket, { onQuery, protocolConfig
|
|
|
107
105
|
|
|
108
106
|
if (helloDecision === false) {
|
|
109
107
|
// Connection rejected
|
|
110
|
-
return
|
|
108
|
+
return writeQueue.end();
|
|
111
109
|
} else {
|
|
112
110
|
debug(`[readLoop] Negotiation completed on client side; detaching sink...`);
|
|
113
111
|
return null;
|
|
@@ -140,6 +138,8 @@ module.exports = async function handleProtocol(socket, { onQuery, protocolConfig
|
|
|
140
138
|
let eventStream = pipe([
|
|
141
139
|
incomingMessageStream,
|
|
142
140
|
filter(async (message) => {
|
|
141
|
+
debug("Received message (operating phase):", message);
|
|
142
|
+
|
|
143
143
|
let isReplyMessage = REPLY_TYPES.has(message.t);
|
|
144
144
|
|
|
145
145
|
if (message.t === NORMAL_QUERY_TYPE) {
|
|
@@ -186,6 +186,6 @@ module.exports = async function handleProtocol(socket, { onQuery, protocolConfig
|
|
|
186
186
|
return {
|
|
187
187
|
eventStream: eventStream,
|
|
188
188
|
sender: sender,
|
|
189
|
-
disconnect: () =>
|
|
189
|
+
disconnect: () => writeQueue.end()
|
|
190
190
|
};
|
|
191
191
|
};
|
package/package.json
CHANGED
|
@@ -1,47 +1,41 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pairnet",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "node --test"
|
|
8
|
+
},
|
|
6
9
|
"keywords": [],
|
|
7
10
|
"author": "Sven Slootweg <admin@cryto.net>",
|
|
8
11
|
"license": "WTFPL",
|
|
9
12
|
"dependencies": {
|
|
10
|
-
"@joepie91/consumable": "^1.0.1",
|
|
11
13
|
"@joepie91/objid": "^1.0.1",
|
|
12
|
-
"@promistream/aborted": "^0.1.2",
|
|
13
14
|
"@promistream/decode-cbor": "^0.1.0",
|
|
14
15
|
"@promistream/encode-cbor": "^0.1.0",
|
|
15
|
-
"@promistream/filter": "^0.1.
|
|
16
|
-
"@promistream/from-node-stream": "^0.1.
|
|
17
|
-
"@promistream/map": "^0.1.
|
|
18
|
-
"@promistream/pipe": "^0.1.
|
|
19
|
-
"@promistream/simple-
|
|
20
|
-
"@promistream/simple-
|
|
21
|
-
"@validatem/core": "^0.
|
|
16
|
+
"@promistream/filter": "^0.1.3",
|
|
17
|
+
"@promistream/from-node-stream": "^0.1.6",
|
|
18
|
+
"@promistream/map": "^0.1.10",
|
|
19
|
+
"@promistream/pipe": "^0.1.8",
|
|
20
|
+
"@promistream/simple-queue": "^0.1.7",
|
|
21
|
+
"@promistream/simple-sink": "^0.3.5",
|
|
22
|
+
"@validatem/core": "^0.6.3",
|
|
22
23
|
"@validatem/error": "^1.1.0",
|
|
23
24
|
"@validatem/is-function": "^0.1.0",
|
|
24
25
|
"@validatem/is-integer": "^0.1.0",
|
|
25
26
|
"@validatem/is-non-empty-string": "^0.1.0",
|
|
26
|
-
"@validatem/is-positive": "^1.0.0",
|
|
27
27
|
"@validatem/required": "^0.1.1",
|
|
28
|
-
"cbor": "^
|
|
29
|
-
"
|
|
30
|
-
"debug": "^
|
|
28
|
+
"cbor": "^10.0.12",
|
|
29
|
+
"debug": "^4.4.3",
|
|
30
|
+
"debug-instanced": "^1.0.0",
|
|
31
31
|
"match-value": "^1.1.0",
|
|
32
|
-
"nanoid": "^3.3.
|
|
33
|
-
"p-defer": "^3",
|
|
34
|
-
"
|
|
35
|
-
"range": "^0.0.3",
|
|
36
|
-
"sanitize-filename": "^1.6.3"
|
|
32
|
+
"nanoid": "^3.3.18",
|
|
33
|
+
"p-defer": "^3.0.0",
|
|
34
|
+
"sanitize-filename": "^1.6.4"
|
|
37
35
|
},
|
|
38
36
|
"devDependencies": {
|
|
39
|
-
"@joepie91/eslint-config": "^
|
|
40
|
-
"@promistream/debug": "^0.1.
|
|
41
|
-
"
|
|
42
|
-
"@promistream/spy": "^0.1.0"
|
|
43
|
-
},
|
|
44
|
-
"scripts": {
|
|
45
|
-
"test": "node --test"
|
|
37
|
+
"@joepie91/eslint-config": "^2.0.3",
|
|
38
|
+
"@promistream/debug": "^0.1.2",
|
|
39
|
+
"eslint": "^10.8.1"
|
|
46
40
|
}
|
|
47
|
-
}
|
|
41
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const { once } = require("node:events");
|
|
4
4
|
const debug = require("debug")("pairnet:server-listen");
|
|
5
5
|
|
|
6
6
|
module.exports = async function serverListen(server, port, hostname) {
|
|
7
7
|
server.listen(port, hostname);
|
|
8
|
-
await
|
|
8
|
+
await once(server, "listening");
|
|
9
9
|
debug(`[createServer] Listening on ${hostname}:${port}...`);
|
|
10
10
|
};
|
package/.eslintrc
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const debug = require("debug")("pairnet");
|
|
4
|
-
const pEvent = require("p-event");
|
|
5
|
-
|
|
6
|
-
module.exports = async function disconnect(socket) {
|
|
7
|
-
debug(`[disconnectSocket] Disconnecting...`);
|
|
8
|
-
socket.destroySoon();
|
|
9
|
-
await pEvent(socket, "close");
|
|
10
|
-
debug(`[disconnectSocket] Disconnected!`);
|
|
11
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const simpleSource = require("@promistream/simple-source");
|
|
4
|
-
const Aborted = require("@promistream/aborted");
|
|
5
|
-
const pDefer = require("p-defer");
|
|
6
|
-
|
|
7
|
-
module.exports = function createInfiniteQueue(initialItems = []) {
|
|
8
|
-
let queue = initialItems.slice();
|
|
9
|
-
let defers = [];
|
|
10
|
-
|
|
11
|
-
return {
|
|
12
|
-
push: function (value) {
|
|
13
|
-
if (defers.length > 0) {
|
|
14
|
-
defers.shift().resolve(value);
|
|
15
|
-
} else {
|
|
16
|
-
queue.push(value);
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
stream: simpleSource({
|
|
20
|
-
onRequest: () => {
|
|
21
|
-
if (queue.length > 0) {
|
|
22
|
-
return queue.shift();
|
|
23
|
-
} else {
|
|
24
|
-
let defer = pDefer();
|
|
25
|
-
defers.push(defer);
|
|
26
|
-
return defer.promise;
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
onAbort: (reason) => {
|
|
30
|
-
for (let defer of defers) {
|
|
31
|
-
// TODO: Test properly
|
|
32
|
-
defer.reject(new Aborted("Stream was aborted"));
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
})
|
|
36
|
-
};
|
|
37
|
-
};
|