Compare commits

...

7 Commits

Author SHA1 Message Date
Derrick Hammer f86c924299
*Update deps 2022-12-19 08:51:52 -05:00
Derrick Hammer f164f7a6d3
*Pass child pino logger to dht-cache 2022-12-19 08:51:35 -05:00
Derrick Hammer 3fffc08d54
*switch to pino logger 2022-12-19 08:19:43 -05:00
Derrick Hammer f597afac6a
*Implement new SSl support with SSLManager class
*Rewrite relay servers to use fastify
*Remove status code server, it will be a plugin
2022-12-19 08:09:25 -05:00
Derrick Hammer ef03883605
*switch app to using fastify 2022-12-19 07:13:11 -05:00
Derrick Hammer 84b69e09af
*Update return type on getKeyPair 2022-12-19 07:12:10 -05:00
Derrick Hammer f7a696a65f
*Remove unneeded packages 2022-12-19 06:46:14 -05:00
9 changed files with 238 additions and 1341 deletions

View File

@ -18,15 +18,12 @@
"barebuild": "yarn run compile && npm run package" "barebuild": "yarn run compile && npm run package"
}, },
"dependencies": { "dependencies": {
"@fastify/websocket": "^7.1.1",
"@hyperswarm/dht": "^6.0.1", "@hyperswarm/dht": "^6.0.1",
"@hyperswarm/dht-relay": "^0.3.0", "@hyperswarm/dht-relay": "^0.3.0",
"@lumeweb/cfg": "https://git.lumeweb.com/LumeWeb/cfg.git", "@lumeweb/cfg": "https://git.lumeweb.com/LumeWeb/cfg.git",
"@lumeweb/dht-cache": "https://git.lumeweb.com/LumeWeb/dht-cache.git", "@lumeweb/dht-cache": "https://git.lumeweb.com/LumeWeb/dht-cache.git",
"@lumeweb/kernel-utils": "https://github.com/LumeWeb/kernel-utils.git",
"@lumeweb/pokt-rpc-endpoints": "https://github.com/LumeWeb/pokt-rpc-endpoints.git",
"@scure/bip39": "^1.1.0", "@scure/bip39": "^1.1.0",
"@skynetlabs/skynet-nodejs": "^2.6.0",
"@solana/web3.js": "^1.47.3",
"@types/acme-client": "^3.3.0", "@types/acme-client": "^3.3.0",
"@types/node": "^18.0.0", "@types/node": "^18.0.0",
"@types/node-cron": "^3.0.2", "@types/node-cron": "^3.0.2",
@ -34,29 +31,25 @@
"ajv": "^8.11.0", "ajv": "^8.11.0",
"async-mutex": "^0.3.2", "async-mutex": "^0.3.2",
"b4a": "^1.6.1", "b4a": "^1.6.1",
"chalk": "4.1.2",
"compact-encoding": "^2.11.0", "compact-encoding": "^2.11.0",
"date-fns": "^2.28.0", "date-fns": "^2.28.0",
"dotenv": "^16.0.1", "dotenv": "^16.0.1",
"ethers": "^5.6.9", "ethers": "^5.6.9",
"eventemitter2": "^6.4.9", "eventemitter2": "^6.4.9",
"express": "^4.18.1",
"fastify": "^4.10.2", "fastify": "^4.10.2",
"fetch-blob": "https://github.com/LumeWeb/fetch-blob.git", "fetch-blob": "https://github.com/LumeWeb/fetch-blob.git",
"hyperswarm": "^3.0.4", "hyperswarm": "^3.0.4",
"json-stable-stringify": "^1.0.1", "json-stable-stringify": "^1.0.1",
"json-stringify-deterministic": "^1.0.7", "json-stringify-deterministic": "^1.0.7",
"libskynet": "https://github.com/LumeWeb/libskynet.git",
"libskynetnode": "https://github.com/LumeWeb/libskynetnode.git",
"loady": "https://github.com/LumeWeb/loady.git", "loady": "https://github.com/LumeWeb/loady.git",
"loglevel": "^1.8.1",
"loglevel-plugin-prefix": "^0.8.4",
"micro-ed25519-hdkey": "^0.1.2", "micro-ed25519-hdkey": "^0.1.2",
"msgpackr": "^1.6.1", "msgpackr": "^1.6.1",
"node-cache": "^5.1.2", "node-cache": "^5.1.2",
"node-cron": "^3.0.1", "node-cron": "^3.0.1",
"node-fetch": "2", "node-fetch": "2",
"p-timeout": "https://git.lumeweb.com/LumeWeb/p-timeout.git", "p-timeout": "https://git.lumeweb.com/LumeWeb/p-timeout.git",
"pino": "^8.8.0",
"pino-pretty": "^9.1.1",
"promise-retry": "^2.0.1", "promise-retry": "^2.0.1",
"protomux": "^3.4.0", "protomux": "^3.4.0",
"protomux-rpc": "^1.3.0", "protomux-rpc": "^1.3.0",
@ -68,7 +61,6 @@
"devDependencies": { "devDependencies": {
"@lumeweb/relay-types": "https://git.lumeweb.com/LumeWeb/relay-types.git", "@lumeweb/relay-types": "https://git.lumeweb.com/LumeWeb/relay-types.git",
"@types/b4a": "^1.6.0", "@types/b4a": "^1.6.0",
"@types/express": "^4.17.13",
"@types/minimatch": "^3.0.5", "@types/minimatch": "^3.0.5",
"@types/node-fetch": "^2.6.2", "@types/node-fetch": "^2.6.2",
"cli-progress": "^3.11.2", "cli-progress": "^3.11.2",

View File

@ -3,9 +3,7 @@ import Config from "@lumeweb/cfg";
import * as os from "os"; import * as os from "os";
import * as fs from "fs"; import * as fs from "fs";
import path from "path"; import path from "path";
import log from "loglevel"; import { log } from "./log.js";
import chalk, { Chalk } from "chalk";
import prefix from "loglevel-plugin-prefix";
const config = new Config("lumeweb-relay"); const config = new Config("lumeweb-relay");
@ -53,25 +51,6 @@ config.load({
argv: true, argv: true,
}); });
log.setDefaultLevel(config.get("loglevel")); log.level = config.get("loglevel");
const colors = {
TRACE: chalk.magenta,
DEBUG: chalk.cyan,
INFO: chalk.blue,
WARN: chalk.yellow,
ERROR: chalk.red,
} as { [level: string]: Chalk };
prefix.reg(log);
log.enableAll();
prefix.apply(log, {
format(level, name, timestamp) {
return `${chalk.gray(`[${timestamp}]`)} ${colors[level.toUpperCase()](
level
)} ${chalk.green(`${name}:`)}`;
},
});
export default config; export default config;

View File

@ -21,7 +21,7 @@ export function getHDKey(): HDKey {
return HDKey.fromMasterSeed(getSeed()).derive(BIP44_PATH); return HDKey.fromMasterSeed(getSeed()).derive(BIP44_PATH);
} }
export function getKeyPair() { export function getKeyPair(): { publicKey: Uint8Array; secretKey: Uint8Array } {
const key = getHDKey(); const key = getHDKey();
return { publicKey: key.publicKeyRaw, secretKey: key.privateKey }; return { publicKey: key.publicKeyRaw, secretKey: key.privateKey };

8
src/log.ts Normal file
View File

@ -0,0 +1,8 @@
import pino from "pino";
import pretty from "pino-pretty";
const stream = pretty({
colorize: true,
});
export const log = pino(stream);

View File

@ -1,60 +1,24 @@
import express, { Express } from "express";
import http from "http";
import { AddressInfo } from "net"; import { AddressInfo } from "net";
import log from "loglevel"; import log from "loglevel";
import fastify from "fastify";
import type { FastifyInstance } from "fastify";
import { getKeyPair } from "../lib/seed.js"; import { getKeyPair } from "../lib/seed.js";
let app: Express; let app: FastifyInstance;
let router = express.Router();
let server: http.Server;
export function getRouter(): express.Router {
return router;
}
export function setRouter(newRouter: express.Router): void {
router = newRouter;
}
export async function start() { export async function start() {
app = express(); const keyPair = getKeyPair();
server = http.createServer(app); app = fastify({
resetRouter(); logger: true,
await new Promise((resolve) => {
server.listen(80, "0.0.0.0", function () {
const address = server.address() as AddressInfo;
log.info(
"HTTP/App Server started on ",
`${address.address}:${address.port}`
);
resolve(null);
});
}); });
app.use(function (req, res, next) { await app.listen({ port: 80, host: "0.0.0.0" });
router(req, res, next);
});
}
export function getApp(): Express { app.get("/", (req, res) => {
return app;
}
export function getServer(): http.Server {
return server;
}
export function resetRouter(): void {
setRouter(newRouter());
}
function newRouter(): express.Router {
const router = express.Router();
let keyPair = getKeyPair();
router.get("/", (req, res) => {
res.send(Buffer.from(keyPair.publicKey).toString("hex")); res.send(Buffer.from(keyPair.publicKey).toString("hex"));
}); });
return router; const address = app.server.address() as AddressInfo;
log.info("HTTP/App Server started on ", `${address.address}:${address.port}`);
} }

View File

@ -4,60 +4,44 @@ import DHT from "@hyperswarm/dht";
import { relay } from "@hyperswarm/dht-relay"; import { relay } from "@hyperswarm/dht-relay";
// @ts-ignore // @ts-ignore
import Stream from "@hyperswarm/dht-relay/ws"; import Stream from "@hyperswarm/dht-relay/ws";
import express, { Express } from "express";
import config from "../config.js"; import config from "../config.js";
import * as http from "http";
import * as https from "https";
import { get as getSwarm } from "./swarm.js"; import { get as getSwarm } from "./swarm.js";
import WS from "ws"; import { get as getSslManager } from "./ssl.js";
// @ts-ignore // @ts-ignore
import log from "loglevel"; import log from "loglevel";
import { AddressInfo } from "net"; import { AddressInfo } from "net";
// @ts-ignore // @ts-ignore
import promiseRetry from "promise-retry"; import promiseRetry from "promise-retry";
import fastify from "fastify";
import * as http2 from "http2";
import websocket from "@fastify/websocket";
export async function start() { export async function start() {
const relayPort = config.uint("port"); const relayPort = config.uint("port");
const dht = getSwarm(); const dht = getSwarm();
let sslOptions: boolean | http2.SecureServerOptions = false;
const statusCodeServer = http.createServer(function (req, res) { if (getSslManager().enabled) {
// @ts-ignore sslOptions = {
res.writeHead(req.headers["x-status"] ?? 200, { SNICallback: () => getSslManager().context,
"Content-Type": "text/plain", } as http2.SecureServerOptions;
}); }
res.end();
let relayServer = fastify({
http2: true,
https: sslOptions as http2.SecureServerOptions,
}); });
await new Promise((resolve) => { relayServer.register(websocket);
statusCodeServer.listen(25252, "0.0.0.0", function () {
const address = statusCodeServer.address() as AddressInfo; relayServer.get("/", { websocket: true }, (connection) => {
log.info( relay(dht, new Stream(false, connection.socket));
"Status Code Server started on ",
`${address.address}:${address.port}`
);
resolve(null);
});
}); });
let relayServer: https.Server | http.Server; await relayServer.listen({ port: config.uint("port"), host: "0.0.0.0" });
let address = relayServer.server.address() as AddressInfo;
relayServer = http.createServer(); log.info(
"DHT Relay Server started on ",
let wsServer = new WS.Server({ server: relayServer }); `${address.address}:${address.port}`
);
wsServer.on("connection", (socket: any) => {
relay(dht, new Stream(false, socket));
});
await new Promise((resolve) => {
relayServer.listen(relayPort, "0.0.0.0", function () {
const address = relayServer.address() as AddressInfo;
log.info(
"DHT Relay Server started on ",
`${address.address}:${address.port}`
);
resolve(null);
});
});
} }

View File

@ -8,6 +8,7 @@ import jsonStringify from "json-stringify-deterministic";
// @ts-ignore // @ts-ignore
import crypto from "hypercore-crypto"; import crypto from "hypercore-crypto";
import NodeCache from "node-cache"; import NodeCache from "node-cache";
import { log } from "../../log.js";
export class RPCCache extends EventEmitter { export class RPCCache extends EventEmitter {
private server: RPCServer; private server: RPCServer;
@ -18,6 +19,7 @@ export class RPCCache extends EventEmitter {
this._swarm = getSwarm(); this._swarm = getSwarm();
this._dhtCache = new DHTCache(this._swarm, { this._dhtCache = new DHTCache(this._swarm, {
protocol: "lumeweb.rpccache", protocol: "lumeweb.rpccache",
logger: log.child({ module: "dht-cache" }),
}); });
this._data.on("del", (key: string) => { this._data.on("del", (key: string) => {
try { try {

66
src/modules/ssl.ts Normal file
View File

@ -0,0 +1,66 @@
import * as tls from "tls";
import b4a from "b4a";
import log from "loglevel";
import config from "../config.js";
export type SSLManagerRenewHandler = (domain: string) => Promise<boolean>;
class SSLManager {
private _context?: tls.SecureContext;
private _key?: Buffer;
private _cert?: Buffer;
private _domain: string;
private _renewHandler?: SSLManagerRenewHandler;
constructor(domain: string) {
this._domain = domain;
}
get context(): tls.SecureContext {
return this._context as tls.SecureContext;
}
set privateKey(key: Buffer) {
this._key = key;
this._maybeUpdateContext();
}
set cert(cert: Buffer) {
this._cert = cert;
this._maybeUpdateContext();
}
private _maybeUpdateContext() {
if (b4a.isBuffer(this._cert) && b4a.isBuffer(this._key)) {
this._context = tls.createSecureContext({
cert: this._cert,
key: this._key,
});
}
}
public async renew(): Promise<boolean> {
let result = false;
try {
result = (await this._renewHandler?.(this._domain)) as boolean;
} catch (e) {
log.error((e as Error).message);
}
return result;
}
get enabled() {
return config.bool("ssl") && this._renewHandler;
}
}
let sslManager: SSLManager;
export function get(): SSLManager {
if (!sslManager) {
sslManager = new SSLManager(config.get("domain"));
}
return sslManager;
}

1340
yarn.lock

File diff suppressed because it is too large Load Diff