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"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fastify/websocket": "^7.1.1",
|
||||
"@hyperswarm/dht": "^6.0.1",
|
||||
"@hyperswarm/dht-relay": "^0.3.0",
|
||||
"@lumeweb/cfg": "https://git.lumeweb.com/LumeWeb/cfg.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",
|
||||
"@skynetlabs/skynet-nodejs": "^2.6.0",
|
||||
"@solana/web3.js": "^1.47.3",
|
||||
"@types/acme-client": "^3.3.0",
|
||||
"@types/node": "^18.0.0",
|
||||
"@types/node-cron": "^3.0.2",
|
||||
|
@ -34,29 +31,25 @@
|
|||
"ajv": "^8.11.0",
|
||||
"async-mutex": "^0.3.2",
|
||||
"b4a": "^1.6.1",
|
||||
"chalk": "4.1.2",
|
||||
"compact-encoding": "^2.11.0",
|
||||
"date-fns": "^2.28.0",
|
||||
"dotenv": "^16.0.1",
|
||||
"ethers": "^5.6.9",
|
||||
"eventemitter2": "^6.4.9",
|
||||
"express": "^4.18.1",
|
||||
"fastify": "^4.10.2",
|
||||
"fetch-blob": "https://github.com/LumeWeb/fetch-blob.git",
|
||||
"hyperswarm": "^3.0.4",
|
||||
"json-stable-stringify": "^1.0.1",
|
||||
"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",
|
||||
"loglevel": "^1.8.1",
|
||||
"loglevel-plugin-prefix": "^0.8.4",
|
||||
"micro-ed25519-hdkey": "^0.1.2",
|
||||
"msgpackr": "^1.6.1",
|
||||
"node-cache": "^5.1.2",
|
||||
"node-cron": "^3.0.1",
|
||||
"node-fetch": "2",
|
||||
"p-timeout": "https://git.lumeweb.com/LumeWeb/p-timeout.git",
|
||||
"pino": "^8.8.0",
|
||||
"pino-pretty": "^9.1.1",
|
||||
"promise-retry": "^2.0.1",
|
||||
"protomux": "^3.4.0",
|
||||
"protomux-rpc": "^1.3.0",
|
||||
|
@ -68,7 +61,6 @@
|
|||
"devDependencies": {
|
||||
"@lumeweb/relay-types": "https://git.lumeweb.com/LumeWeb/relay-types.git",
|
||||
"@types/b4a": "^1.6.0",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/minimatch": "^3.0.5",
|
||||
"@types/node-fetch": "^2.6.2",
|
||||
"cli-progress": "^3.11.2",
|
||||
|
|
|
@ -3,9 +3,7 @@ import Config from "@lumeweb/cfg";
|
|||
import * as os from "os";
|
||||
import * as fs from "fs";
|
||||
import path from "path";
|
||||
import log from "loglevel";
|
||||
import chalk, { Chalk } from "chalk";
|
||||
import prefix from "loglevel-plugin-prefix";
|
||||
import { log } from "./log.js";
|
||||
|
||||
const config = new Config("lumeweb-relay");
|
||||
|
||||
|
@ -53,25 +51,6 @@ config.load({
|
|||
argv: true,
|
||||
});
|
||||
|
||||
log.setDefaultLevel(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}:`)}`;
|
||||
},
|
||||
});
|
||||
log.level = config.get("loglevel");
|
||||
|
||||
export default config;
|
||||
|
|
|
@ -21,7 +21,7 @@ export function getHDKey(): HDKey {
|
|||
return HDKey.fromMasterSeed(getSeed()).derive(BIP44_PATH);
|
||||
}
|
||||
|
||||
export function getKeyPair() {
|
||||
export function getKeyPair(): { publicKey: Uint8Array; secretKey: Uint8Array } {
|
||||
const key = getHDKey();
|
||||
|
||||
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 log from "loglevel";
|
||||
import fastify from "fastify";
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import { getKeyPair } from "../lib/seed.js";
|
||||
|
||||
let app: Express;
|
||||
let router = express.Router();
|
||||
let server: http.Server;
|
||||
|
||||
export function getRouter(): express.Router {
|
||||
return router;
|
||||
}
|
||||
|
||||
export function setRouter(newRouter: express.Router): void {
|
||||
router = newRouter;
|
||||
}
|
||||
let app: FastifyInstance;
|
||||
|
||||
export async function start() {
|
||||
app = express();
|
||||
server = http.createServer(app);
|
||||
resetRouter();
|
||||
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);
|
||||
});
|
||||
const keyPair = getKeyPair();
|
||||
app = fastify({
|
||||
logger: true,
|
||||
});
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
router(req, res, next);
|
||||
});
|
||||
}
|
||||
await app.listen({ port: 80, host: "0.0.0.0" });
|
||||
|
||||
export function getApp(): Express {
|
||||
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) => {
|
||||
app.get("/", (req, res) => {
|
||||
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";
|
||||
// @ts-ignore
|
||||
import Stream from "@hyperswarm/dht-relay/ws";
|
||||
import express, { Express } from "express";
|
||||
import config from "../config.js";
|
||||
import * as http from "http";
|
||||
import * as https from "https";
|
||||
import { get as getSwarm } from "./swarm.js";
|
||||
import WS from "ws";
|
||||
import { get as getSslManager } from "./ssl.js";
|
||||
// @ts-ignore
|
||||
import log from "loglevel";
|
||||
import { AddressInfo } from "net";
|
||||
// @ts-ignore
|
||||
import promiseRetry from "promise-retry";
|
||||
import fastify from "fastify";
|
||||
import * as http2 from "http2";
|
||||
import websocket from "@fastify/websocket";
|
||||
|
||||
export async function start() {
|
||||
const relayPort = config.uint("port");
|
||||
|
||||
const dht = getSwarm();
|
||||
let sslOptions: boolean | http2.SecureServerOptions = false;
|
||||
|
||||
const statusCodeServer = http.createServer(function (req, res) {
|
||||
// @ts-ignore
|
||||
res.writeHead(req.headers["x-status"] ?? 200, {
|
||||
"Content-Type": "text/plain",
|
||||
});
|
||||
res.end();
|
||||
if (getSslManager().enabled) {
|
||||
sslOptions = {
|
||||
SNICallback: () => getSslManager().context,
|
||||
} as http2.SecureServerOptions;
|
||||
}
|
||||
|
||||
let relayServer = fastify({
|
||||
http2: true,
|
||||
https: sslOptions as http2.SecureServerOptions,
|
||||
});
|
||||
|
||||
await new Promise((resolve) => {
|
||||
statusCodeServer.listen(25252, "0.0.0.0", function () {
|
||||
const address = statusCodeServer.address() as AddressInfo;
|
||||
log.info(
|
||||
"Status Code Server started on ",
|
||||
`${address.address}:${address.port}`
|
||||
);
|
||||
resolve(null);
|
||||
});
|
||||
relayServer.register(websocket);
|
||||
|
||||
relayServer.get("/", { websocket: true }, (connection) => {
|
||||
relay(dht, new Stream(false, connection.socket));
|
||||
});
|
||||
|
||||
let relayServer: https.Server | http.Server;
|
||||
|
||||
relayServer = http.createServer();
|
||||
|
||||
let wsServer = new WS.Server({ server: relayServer });
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
await relayServer.listen({ port: config.uint("port"), host: "0.0.0.0" });
|
||||
let address = relayServer.server.address() as AddressInfo;
|
||||
log.info(
|
||||
"DHT Relay Server started on ",
|
||||
`${address.address}:${address.port}`
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import jsonStringify from "json-stringify-deterministic";
|
|||
// @ts-ignore
|
||||
import crypto from "hypercore-crypto";
|
||||
import NodeCache from "node-cache";
|
||||
import { log } from "../../log.js";
|
||||
|
||||
export class RPCCache extends EventEmitter {
|
||||
private server: RPCServer;
|
||||
|
@ -18,6 +19,7 @@ export class RPCCache extends EventEmitter {
|
|||
this._swarm = getSwarm();
|
||||
this._dhtCache = new DHTCache(this._swarm, {
|
||||
protocol: "lumeweb.rpccache",
|
||||
logger: log.child({ module: "dht-cache" }),
|
||||
});
|
||||
this._data.on("del", (key: string) => {
|
||||
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