Compare commits
7 Commits
ce5d66095f
...
f86c924299
Author | SHA1 | Date |
---|---|---|
Derrick Hammer | f86c924299 | |
Derrick Hammer | f164f7a6d3 | |
Derrick Hammer | 3fffc08d54 | |
Derrick Hammer | f597afac6a | |
Derrick Hammer | ef03883605 | |
Derrick Hammer | 84b69e09af | |
Derrick Hammer | f7a696a65f |
14
package.json
14
package.json
|
@ -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",
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
import pino from "pino";
|
||||||
|
import pretty from "pino-pretty";
|
||||||
|
|
||||||
|
const stream = pretty({
|
||||||
|
colorize: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const log = pino(stream);
|
|
@ -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}`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue