diff --git a/docs/protocol.md b/docs/protocol.md index 6e704eb..7368311 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -50,3 +50,8 @@ Properties: - **string `name`:** The name of the table. - **object `table`:** The requested table. + +### Event `end` +Explicitly tells the receiver that the send is going away. + +_(this event has no properties)_ diff --git a/package-lock.json b/package-lock.json index c141749..8a4e558 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "nexline": "^1.2.2", "p-reflect": "^3.0.0", "p-retry": "^5.0.0", + "powahroot": "^1.1.1", "systeminformation": "^5.9.4", "tweetnacl": "^1.0.3" } @@ -39,11 +40,32 @@ "resolved": "https://registry.npmjs.org/applause-cli/-/applause-cli-1.7.0.tgz", "integrity": "sha512-zO/nBR9x37Iqlm3R2Glo0NyDIevwbDPrISprK61Z/M01Xvm5dFkL2FZAONxxHctT9QoF71fiY22sFRuq8Sqxug==" }, + "node_modules/await-fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/await-fs/-/await-fs-1.0.0.tgz", + "integrity": "sha1-QAnTAIYz/WYlqgCfCm8aujY38wE=", + "engines": { + "node": ">=7.10.0" + } + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/crypto-js": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" }, + "node_modules/event-emitter-es6": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/event-emitter-es6/-/event-emitter-es6-1.1.5.tgz", + "integrity": "sha1-75UxGy4Xqjm+djsDHOSvfunLeEk=" + }, "node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -62,6 +84,11 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" }, + "node_modules/html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==" + }, "node_modules/iconv-lite": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", @@ -103,6 +130,15 @@ "node": ">= 8.0.0" } }, + "node_modules/nightink": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/nightink/-/nightink-0.1.3.tgz", + "integrity": "sha512-eGlInN79j0g/QdTf8GFwuUvGbIsgWBfcNop219q9Nbf8WUlplDu7AriHoyKY+B0IeAB9zWg59NlBlJUIqmpEiQ==", + "dependencies": { + "await-fs": "^1.0.0", + "html-entities": "^1.2.1" + } + }, "node_modules/noble-secp256k1": { "version": "1.2.10", "resolved": "https://registry.npmjs.org/noble-secp256k1/-/noble-secp256k1-1.2.10.tgz", @@ -134,6 +170,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/powahroot": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/powahroot/-/powahroot-1.1.1.tgz", + "integrity": "sha512-w27bFTVzKrcuTiC15ToPJEQORTRS6Mt7Aj+bav7ih9T2lvU4V3OTv5YVexGqZX2yM2X/VHDtP9Oy3rUM07CKHg==", + "dependencies": { + "cookie": "^0.4.2", + "event-emitter-es6": "^1.1.5", + "nightink": "^0.1.3" + }, + "funding": { + "type": "liberapay", + "url": "https://liberapay.com/sbrl" + } + }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -206,11 +256,26 @@ "resolved": "https://registry.npmjs.org/applause-cli/-/applause-cli-1.7.0.tgz", "integrity": "sha512-zO/nBR9x37Iqlm3R2Glo0NyDIevwbDPrISprK61Z/M01Xvm5dFkL2FZAONxxHctT9QoF71fiY22sFRuq8Sqxug==" }, + "await-fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/await-fs/-/await-fs-1.0.0.tgz", + "integrity": "sha1-QAnTAIYz/WYlqgCfCm8aujY38wE=" + }, + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + }, "crypto-js": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" }, + "event-emitter-es6": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/event-emitter-es6/-/event-emitter-es6-1.1.5.tgz", + "integrity": "sha1-75UxGy4Xqjm+djsDHOSvfunLeEk=" + }, "fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -226,6 +291,11 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" }, + "html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==" + }, "iconv-lite": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", @@ -261,6 +331,15 @@ "iconv-lite": "^0.5.0" } }, + "nightink": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/nightink/-/nightink-0.1.3.tgz", + "integrity": "sha512-eGlInN79j0g/QdTf8GFwuUvGbIsgWBfcNop219q9Nbf8WUlplDu7AriHoyKY+B0IeAB9zWg59NlBlJUIqmpEiQ==", + "requires": { + "await-fs": "^1.0.0", + "html-entities": "^1.2.1" + } + }, "noble-secp256k1": { "version": "1.2.10", "resolved": "https://registry.npmjs.org/noble-secp256k1/-/noble-secp256k1-1.2.10.tgz", @@ -280,6 +359,16 @@ "retry": "^0.13.1" } }, + "powahroot": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/powahroot/-/powahroot-1.1.1.tgz", + "integrity": "sha512-w27bFTVzKrcuTiC15ToPJEQORTRS6Mt7Aj+bav7ih9T2lvU4V3OTv5YVexGqZX2yM2X/VHDtP9Oy3rUM07CKHg==", + "requires": { + "cookie": "^0.4.2", + "event-emitter-es6": "^1.1.5", + "nightink": "^0.1.3" + } + }, "retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", diff --git a/package.json b/package.json index 760d454..033fb70 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "nexline": "^1.2.2", "p-reflect": "^3.0.0", "p-retry": "^5.0.0", + "powahroot": "^1.1.1", "systeminformation": "^5.9.4", "tweetnacl": "^1.0.3" } diff --git a/src/lib/SystemQuery.mjs b/src/lib/SystemQuery.mjs index a81bde8..6a08bb8 100644 --- a/src/lib/SystemQuery.mjs +++ b/src/lib/SystemQuery.mjs @@ -2,6 +2,8 @@ import { once, EventEmitter } from 'events'; +import log from '../../lib/io/NamespacedLog.mjs'; const l = log("systemquery"); + import Agent from './agent/Agent.mjs'; import InfoBroker from './core/InfoBroker.mjs'; @@ -46,7 +48,7 @@ class SystemQuery extends EventEmitter { await peer.send("query-response", { name: msg.name, table }); } async handle_query_response(peer, msg) { - + l.log(`query-response from ${peer.id_short}`, msg); } async capture_query_response(event_name, ac) { diff --git a/src/lib/agent/subsystems/http/HttpSubsystem.mjs b/src/lib/agent/subsystems/http/HttpSubsystem.mjs new file mode 100644 index 0000000..77eb5d5 --- /dev/null +++ b/src/lib/agent/subsystems/http/HttpSubsystem.mjs @@ -0,0 +1,18 @@ +"use strict"; + +import http from 'http'; + +class HttpSubsystem { + constructor(agent) { + this.agent = agent; + } + + init(port, address = `127.0.0.1`) { + this.http = http.createServer((req, res) => { + + }); + this. + } +} + +export default HttpSubsystem; diff --git a/src/lib/agent/subsystems/http/ServerSentEventStream.mjs b/src/lib/agent/subsystems/http/ServerSentEventStream.mjs new file mode 100644 index 0000000..7e14efd --- /dev/null +++ b/src/lib/agent/subsystems/http/ServerSentEventStream.mjs @@ -0,0 +1,26 @@ +"use strict"; + +class ServerSentEventStream { + constructor(response) { + this.response = response; + this.next_id = 0; + + this.response.writeHead(200, { + "content-type": "text/event-stream", + "cache-control": "no-store" + }); + this.response.flushHeaders(); + } + + write(event_name, data) { + this.response.write(`id: ${this.next_id++}\n`); + this.response.write(`event: ${event_name}\n`); + this.response.write(`data: ${data}\n\n`); + } + + write_json(event_name, data_obj) { + return this.write(event_name, JSON.stringify(data_obj)); + } +} + +export default ServerSentEventStream; diff --git a/src/lib/agent/subsystems/http/routes.mjs b/src/lib/agent/subsystems/http/routes.mjs new file mode 100644 index 0000000..abc4a3c --- /dev/null +++ b/src/lib/agent/subsystems/http/routes.mjs @@ -0,0 +1,13 @@ +"use strict"; + +import ServerRouter from 'powahroot/Server.mjs'; + +import route_table from './routes/table.mjs'; + +export default function(agent) { + const router = new ServerRouter(); + + router.on(`/api/table/:table_name`, route_table.bind(this, agent)); + + return router; +} diff --git a/src/lib/agent/subsystems/http/routes/table.mjs b/src/lib/agent/subsystems/http/routes/table.mjs new file mode 100644 index 0000000..b86f07c --- /dev/null +++ b/src/lib/agent/subsystems/http/routes/table.mjs @@ -0,0 +1,5 @@ +"use strict"; + +export default function(agent, context, next) { + +} diff --git a/src/subcommands/agent/config.default.toml b/src/subcommands/agent/config.default.toml index 46ba867..88e9087 100644 --- a/src/subcommands/agent/config.default.toml +++ b/src/subcommands/agent/config.default.toml @@ -24,3 +24,13 @@ peer_retries = 5 # Wait this number of seconds before giving up on receiving a table from peers. # Decimal values are allowed, and will be rounded to the nearest millisecond. table_timeout = 5 + +[net.http] +## +# Settings for the HTTP server that serves the web interface and HTTP API +## +# The address to bind to. +# IMPORTANT: Remember that this is unencrypted HTTP! You should put it behind a reverse proxy to do TLS termination. +bind_address = "::1" +# The port to listen on +port = 5253