From 61fc8046bf01d2d337cfb54238e97f59836554d7 Mon Sep 17 00:00:00 2001 From: Undyingwraith Date: Tue, 28 May 2024 18:26:22 +0200 Subject: [PATCH] Fix connection issues --- packages/core/package.json | 2 +- .../core/src/components/pages/AppContext.tsx | 13 +++---- packages/core/src/createRemoteIpfsService.ts | 2 +- packages/core/src/service/INodeService.ts | 6 --- .../ProfileManager/BaseProfileManager.ts | 6 +-- .../service/ProfileManager/IProfileManager.ts | 6 +++ .../ProfileManager/RemoteProfileManager.ts | 9 +++-- .../ProfileManager/SimpleProfileManager.ts | 2 +- packages/desktop/electron.vite.config.ts | 8 ++-- packages/desktop/package.json | 6 +-- packages/desktop/src/main/index.ts | 20 +++++----- packages/desktop/src/preload/index.ts | 38 ++++++++++++++----- packages/tools/package.json | 2 +- packages/webui/package.json | 4 +- yarn.lock | 22 +++++------ 15 files changed, 82 insertions(+), 64 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 6cc5168..f8498e7 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -38,7 +38,7 @@ "@mui/icons-material": "^5.15.15", "@mui/material": "^5.15.15", "@preact/signals-react": "^2.0.1", - "helia": "^4.2.1", + "helia": "^4.2.2", "i18next": "^23.11.2", "minidenticons": "^4.2.1", "multiformats": "^13.1.0", diff --git a/packages/core/src/components/pages/AppContext.tsx b/packages/core/src/components/pages/AppContext.tsx index 2008bff..1d05ce4 100644 --- a/packages/core/src/components/pages/AppContext.tsx +++ b/packages/core/src/components/pages/AppContext.tsx @@ -15,7 +15,7 @@ import { ProfileSelector } from "../molecules/ProfileSelector"; import { AppBar } from "../organisms/AppBar"; import { LoadScreen } from "../molecules/LoadScreen"; import { SimpleProfileManager } from '../../service/ProfileManager/SimpleProfileManager'; -import { IProfileManager } from '../../service/ProfileManager'; +import { IProfileManager, RemoteProfileManager } from '../../service/ProfileManager'; import { useTranslation } from '../../hooks/useTranslation'; export interface IAppContext { @@ -43,7 +43,6 @@ export function AppContextProvider(props: PropsWithChildren) { const _t = useTranslation(); const profileManager = useSignal(undefined); - const node = useSignal(undefined); const state = useSignal(LoadState.Idle); const darkMode = useSignal(true); @@ -59,14 +58,12 @@ export function AppContextProvider(props: PropsWithChildren) { state.value = LoadState.Starting; if (isRemoteProfile(currentProfile)) { - node.value = await props.nodeService.createRemote(currentProfile.url); + profileManager.value = new RemoteProfileManager(currentProfile); } if (isInternalProfile(currentProfile)) { - node.value = await props.nodeService.create(currentProfile); + profileManager.value = new SimpleProfileManager(await props.nodeService.create(currentProfile), currentProfile); } - const manager = new SimpleProfileManager(node.value!, currentProfile); - profileManager.value = manager; - await manager.start(); + await profileManager.value!.start(); state.value = LoadState.Ready; } catch (ex) { @@ -81,7 +78,6 @@ export function AppContextProvider(props: PropsWithChildren) { state.value = LoadState.Stopping; try { await profileManager.value!.stop(); - node.value = undefined; profileManager.value = undefined; } catch (ex) { console.error(ex); @@ -130,6 +126,7 @@ export function AppContextProvider(props: PropsWithChildren) { }); const profile = useComputed(() => profileManager.value?.profile); + const node = useComputed(() => profileManager.value?.ipfs); return useComputed(() => ( diff --git a/packages/core/src/createRemoteIpfsService.ts b/packages/core/src/createRemoteIpfsService.ts index 9e8ef6c..dd3d56f 100644 --- a/packages/core/src/createRemoteIpfsService.ts +++ b/packages/core/src/createRemoteIpfsService.ts @@ -1,7 +1,7 @@ import { IFileInfo, IIpfsService } from './service'; import { create } from 'kubo-rpc-client'; -export async function createRemoteIpfsService(url: string): Promise { +export async function createRemoteIpfsService(url?: string): Promise { const node = create({ url: url }); const connString = (await node.config.get('Addresses.Gateway')) as string; const port = connString.substring(connString.lastIndexOf('/') + 1); diff --git a/packages/core/src/service/INodeService.ts b/packages/core/src/service/INodeService.ts index 72ecfa1..961fe60 100644 --- a/packages/core/src/service/INodeService.ts +++ b/packages/core/src/service/INodeService.ts @@ -10,10 +10,4 @@ export interface INodeService { * @param profile profile to start with. */ create(profile?: IInternalProfile): Promise; - - /** - * Connects to a remote IIpfsService. - * @param url url to connect to. - */ - createRemote(url?: string): Promise; } diff --git a/packages/core/src/service/ProfileManager/BaseProfileManager.ts b/packages/core/src/service/ProfileManager/BaseProfileManager.ts index eef4936..61507c9 100644 --- a/packages/core/src/service/ProfileManager/BaseProfileManager.ts +++ b/packages/core/src/service/ProfileManager/BaseProfileManager.ts @@ -7,8 +7,8 @@ import { IProfile } from '../Profile/IProfile'; import { MovieIndexFetcher, SeriesIndexFetcher } from '../indexer'; import { IProfileManager, ProfileManagerState } from "./IProfileManager"; -export abstract class BaseProfileManager implements IProfileManager { - protected constructor(public readonly profile: IProfile) { +export abstract class BaseProfileManager implements IProfileManager { + protected constructor(public readonly profile: TProfile) { for (const lib of this.profile.libraries) { this.libraries.set(lib.name, new Signal(lib)); } @@ -44,7 +44,7 @@ export abstract class BaseProfileManager implements IProfileManager { protected abstract stopNode(): Promise; - protected ipfs: IIpfsService | undefined; + public ipfs: IIpfsService | undefined; private triggerUpdate(): void { diff --git a/packages/core/src/service/ProfileManager/IProfileManager.ts b/packages/core/src/service/ProfileManager/IProfileManager.ts index 4f584e5..42d2dad 100644 --- a/packages/core/src/service/ProfileManager/IProfileManager.ts +++ b/packages/core/src/service/ProfileManager/IProfileManager.ts @@ -2,6 +2,7 @@ import { ReadonlySignal } from '@preact/signals-react'; import { ILibrary } from '../Library'; import { IProfile } from '../Profile'; import { ITask } from '../ITask'; +import { IIpfsService } from '../IIpfsService'; /** * Manages a profile. @@ -36,6 +37,11 @@ export interface IProfileManager { * The profile of the service. */ profile: IProfile; + + /** + * Ipfs service of the profile if started. + */ + ipfs: undefined | IIpfsService; } export enum ProfileManagerState { diff --git a/packages/core/src/service/ProfileManager/RemoteProfileManager.ts b/packages/core/src/service/ProfileManager/RemoteProfileManager.ts index 45da178..8fe50b5 100644 --- a/packages/core/src/service/ProfileManager/RemoteProfileManager.ts +++ b/packages/core/src/service/ProfileManager/RemoteProfileManager.ts @@ -1,16 +1,17 @@ +import { createRemoteIpfsService } from '../../createRemoteIpfsService'; import { IRemoteProfile } from "../Profile/IRemoteProfile"; import { BaseProfileManager } from "./BaseProfileManager"; -export class RemoteProfileManager extends BaseProfileManager { +export class RemoteProfileManager extends BaseProfileManager { constructor(profile: IRemoteProfile) { super(profile); } - protected startNode() { - return Promise.reject(); + protected async startNode() { + this.ipfs = await createRemoteIpfsService(this.profile.url); } protected stopNode() { - return Promise.reject(); + return Promise.resolve(); } } diff --git a/packages/core/src/service/ProfileManager/SimpleProfileManager.ts b/packages/core/src/service/ProfileManager/SimpleProfileManager.ts index 041d913..96d5f5f 100644 --- a/packages/core/src/service/ProfileManager/SimpleProfileManager.ts +++ b/packages/core/src/service/ProfileManager/SimpleProfileManager.ts @@ -2,7 +2,7 @@ import { IIpfsService } from '../IIpfsService'; import { IProfile } from '../Profile/IProfile'; import { BaseProfileManager } from './BaseProfileManager'; -export class SimpleProfileManager extends BaseProfileManager { +export class SimpleProfileManager extends BaseProfileManager { constructor(ipfs: IIpfsService, profile: IProfile) { super(profile); this.ipfs = ipfs; diff --git a/packages/desktop/electron.vite.config.ts b/packages/desktop/electron.vite.config.ts index 4bedb77..1d9c7e4 100644 --- a/packages/desktop/electron.vite.config.ts +++ b/packages/desktop/electron.vite.config.ts @@ -1,6 +1,6 @@ -import { resolve } from 'path' -import { defineConfig, externalizeDepsPlugin } from 'electron-vite' -import react from '@vitejs/plugin-react' +import { resolve } from 'path'; +import { defineConfig, externalizeDepsPlugin } from 'electron-vite'; +import react from '@vitejs/plugin-react'; export default defineConfig({ main: { @@ -47,4 +47,4 @@ export default defineConfig({ }), ], } -}) +}); diff --git a/packages/desktop/package.json b/packages/desktop/package.json index daa96ca..7a5b977 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -58,18 +58,18 @@ "@preact/signals-react-transform": "^0.3.1", "@rollup/plugin-commonjs": "^25.0.7", "@types/express": "^4", - "@types/node": "^20.12.10", + "@types/node": "^20.12.12", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.2.1", "electron": "30.0.7", "electron-builder": "^24.13.3", - "electron-vite": "^2.1.0", + "electron-vite": "^2.2.0", "eslint": "^8.57.0", "eslint-plugin-react": "^7.34.1", "prettier": "^3.2.5", "typescript": "^5.4.5", - "vite": "^5.0.0", + "vite": "^5.2.11", "vite-plugin-commonjs": "^0.10.1" } } diff --git a/packages/desktop/src/main/index.ts b/packages/desktop/src/main/index.ts index a667def..de0a390 100644 --- a/packages/desktop/src/main/index.ts +++ b/packages/desktop/src/main/index.ts @@ -1,12 +1,12 @@ -import { app, shell, BrowserWindow } from 'electron' -import { join } from 'path' -import { electronApp, optimizer, is } from '@electron-toolkit/utils' -import icon from '../../resources/icon.png?asset' +import { app, shell, BrowserWindow } from 'electron'; +import { join } from 'path'; +import { electronApp, optimizer, is } from '@electron-toolkit/utils'; +import icon from '../../resources/icon.png?asset'; //import { fileURLToPath } from 'url' process.on('uncaughtException', function (error) { process.stdout.write(error.name + ': ' + error.message + '\n' + (error.stack != undefined ? error.stack + '\n' : '')); -}) +}); function createWindow(): void { // Create the browser window. @@ -19,7 +19,7 @@ function createWindow(): void { webPreferences: { nodeIntegration: false, contextIsolation: true, - preload: join(__dirname, '../preload/index.mjs'), + preload: join(__dirname, '../preload/index.mjs'), //preload: fileURLToPath(new URL('../preload/index.cjs', import.meta.url)), sandbox: false, // https://www.electronjs.org/docs/latest/tutorial/esm#summary-esm-support-matrix }, @@ -60,7 +60,7 @@ app.whenReady().then(() => { // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils app.on('browser-window-created', (_, window) => { optimizer.watchWindowShortcuts(window); - }) + }); createWindow(); @@ -69,16 +69,16 @@ app.whenReady().then(() => { // dock icon is clicked and there are no other windows open. if (BrowserWindow.getAllWindows().length === 0) createWindow(); }); -}) +}); // Quit when all windows are closed, except on macOS. There, it's common // for applications and their menu bar to stay active until the user quits // explicitly with Cmd + Q. app.on('window-all-closed', () => { if (process.platform !== 'darwin') { - app.quit() + app.quit(); } -}) +}); // In this file you can include the rest of your app"s specific main process // code. You can also put them in separate files and require them here. diff --git a/packages/desktop/src/preload/index.ts b/packages/desktop/src/preload/index.ts index 8f58533..c39034b 100644 --- a/packages/desktop/src/preload/index.ts +++ b/packages/desktop/src/preload/index.ts @@ -1,4 +1,4 @@ -import { noise } from '@chainsafe/libp2p-noise'; +import { noise, pureJsCrypto } from '@chainsafe/libp2p-noise'; import { yamux } from '@chainsafe/libp2p-yamux'; import { mplex } from '@libp2p/mplex'; import { bitswap, trustlessGateway } from '@helia/block-brokers'; @@ -23,6 +23,15 @@ import { CID } from 'multiformats'; import { gossipsub } from '@chainsafe/libp2p-gossipsub'; import { pubsubPeerDiscovery } from '@libp2p/pubsub-peer-discovery'; import { mdns } from '@libp2p/mdns'; +import { identify, identifyPush } from '@libp2p/identify'; +import { keychain } from '@libp2p/keychain'; +import { ping } from '@libp2p/ping'; +import { dcutr } from '@libp2p/dcutr'; +import { autoNAT } from '@libp2p/autonat'; +import { ipnsSelector } from 'ipns/selector'; +import { ipnsValidator } from 'ipns/validator'; +import { uPnPNAT } from '@libp2p/upnp-nat'; +import * as libp2pInfo from 'libp2p/version'; function getProfileFolder(name: string): string { return `./profiles/${name}`; @@ -30,6 +39,7 @@ function getProfileFolder(name: string): string { const nodeService: INodeService = { async create(profile: IInternalProfile): Promise { + const agentVersion = `helia/2.0.0 ${libp2pInfo.name}/${libp2pInfo.version} UserAgent=${process.version}`; const datastore = new LevelDatastore(`${getProfileFolder(profile.name)}/data`); await datastore.open(); const blockstore = new FsBlockstore(`${getProfileFolder(profile.name)}/blocks`); @@ -74,7 +84,9 @@ const nodeService: INodeService = { mdns(), ], connectionEncryption: [ - noise(), + noise({ + crypto: pureJsCrypto + }), ], streamMuxers: [ yamux(), @@ -82,15 +94,26 @@ const nodeService: INodeService = { ], services: { relay: circuitRelayServer({ - advertise: true + advertise: true, }), dht: kadDHT({ - protocol: '/ipfs/kad/1.0.0', peerInfoMapper: removePrivateAddressesMapper, - allowQueryWithZeroPeers: true, + validators: { + ipns: ipnsValidator + }, + selectors: { + ipns: ipnsSelector + } }), + identify: identify({ agentVersion }), + identifyPush: identifyPush({ agentVersion }), + keychain: keychain(), + ping: ping(), + autoNAT: autoNAT(), + dcutr: dcutr(), + upnp: uPnPNAT(), pubsub: gossipsub({ - allowPublishToZeroTopicPeers: true, + allowPublishToZeroTopicPeers: true, canRelayMessage: true, }), }, @@ -102,9 +125,6 @@ const nodeService: INodeService = { }); console.log(helia.libp2p.getMultiaddrs().map(a => a.toString())); - helia.libp2p.addEventListener('peer:connect', console.log); - helia.libp2p.addEventListener('peer:disconnect', console.log); - helia.libp2p.addEventListener('peer:discovery', console.log); const fs = unixfs(helia); diff --git a/packages/tools/package.json b/packages/tools/package.json index bd9123b..2f052a0 100644 --- a/packages/tools/package.json +++ b/packages/tools/package.json @@ -18,6 +18,6 @@ "@types/cli-progress": "^3.11.5", "@types/fluent-ffmpeg": "^2.1.24", "@types/yargs": "^17.0.32", - "vite-node": "^1.5.0" + "vite-node": "^1.6.0" } } diff --git a/packages/webui/package.json b/packages/webui/package.json index cb8fda8..2b24978 100644 --- a/packages/webui/package.json +++ b/packages/webui/package.json @@ -19,7 +19,7 @@ "crypto": "^1.0.1", "crypto-browserify": "^3.12.0", "datastore-idb": "^2.1.9", - "helia": "^4.2.1", + "helia": "^4.2.2", "i18next": "^23.11.2", "i18next-browser-languagedetector": "^7.2.1", "ipmc-core": "workspace:^", @@ -36,7 +36,7 @@ "@types/react": "^18.3.1", "@types/react-dom": "^18.3.0", "typescript": "^5.4.5", - "vite": "^5.0.0", + "vite": "^5.2.11", "vite-plugin-node-polyfills": "^0.21.0" }, "packageManager": "yarn@4.0.2" diff --git a/yarn.lock b/yarn.lock index e835345..d477a22 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3027,7 +3027,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^20.12.10, @types/node@npm:^20.9.0": +"@types/node@npm:*, @types/node@npm:^20.12.12, @types/node@npm:^20.9.0": version: 20.12.12 resolution: "@types/node@npm:20.12.12" dependencies: @@ -5464,7 +5464,7 @@ __metadata: languageName: node linkType: hard -"electron-vite@npm:^2.1.0": +"electron-vite@npm:^2.2.0": version: 2.2.0 resolution: "electron-vite@npm:2.2.0" dependencies: @@ -6979,7 +6979,7 @@ __metadata: languageName: node linkType: hard -"helia@npm:^4.2.1, helia@npm:^4.2.2": +"helia@npm:^4.2.2": version: 4.2.2 resolution: "helia@npm:4.2.2" dependencies: @@ -7415,7 +7415,7 @@ __metadata: "@preact/signals-react": "npm:^2.0.1" "@types/react": "npm:^18.3.1" "@types/react-dom": "npm:^18.3.0" - helia: "npm:^4.2.1" + helia: "npm:^4.2.2" i18next: "npm:^23.11.2" minidenticons: "npm:^4.2.1" multiformats: "npm:^13.1.0" @@ -7454,7 +7454,7 @@ __metadata: "@preact/signals-react-transform": "npm:^0.3.1" "@rollup/plugin-commonjs": "npm:^25.0.7" "@types/express": "npm:^4" - "@types/node": "npm:^20.12.10" + "@types/node": "npm:^20.12.12" "@types/react": "npm:^18.3.1" "@types/react-dom": "npm:^18.3.0" "@vitejs/plugin-react": "npm:^4.2.1" @@ -7463,7 +7463,7 @@ __metadata: electron: "npm:30.0.7" electron-builder: "npm:^24.13.3" electron-updater: "npm:6.2.1" - electron-vite: "npm:^2.1.0" + electron-vite: "npm:^2.2.0" eslint: "npm:^8.57.0" eslint-plugin-react: "npm:^7.34.1" express: "npm:^4.19.2" @@ -7477,7 +7477,7 @@ __metadata: react-dom: "npm:^18.3.1" ts-node: "npm:^10.9.2" typescript: "npm:^5.4.5" - vite: "npm:^5.0.0" + vite: "npm:^5.2.11" vite-plugin-commonjs: "npm:^0.10.1" languageName: unknown linkType: soft @@ -7493,7 +7493,7 @@ __metadata: fluent-ffmpeg: "npm:^2.1.2" ipmc-core: "workspace:^" kubo-rpc-client: "npm:^4.1.1" - vite-node: "npm:^1.5.0" + vite-node: "npm:^1.6.0" yargs: "npm:^17.7.2" languageName: unknown linkType: soft @@ -7517,7 +7517,7 @@ __metadata: crypto: "npm:^1.0.1" crypto-browserify: "npm:^3.12.0" datastore-idb: "npm:^2.1.9" - helia: "npm:^4.2.1" + helia: "npm:^4.2.2" i18next: "npm:^23.11.2" i18next-browser-languagedetector: "npm:^7.2.1" ipmc-core: "workspace:^" @@ -7529,7 +7529,7 @@ __metadata: styled-components: "npm:^6.1.8" typescript: "npm:^5.4.5" util: "npm:^0.12.5" - vite: "npm:^5.0.0" + vite: "npm:^5.2.11" vite-plugin-node-polyfills: "npm:^0.21.0" web-streams-polyfill: "npm:^4.0.0" languageName: unknown @@ -11967,7 +11967,7 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:1.6.0, vite-node@npm:^1.5.0": +"vite-node@npm:1.6.0, vite-node@npm:^1.6.0": version: 1.6.0 resolution: "vite-node@npm:1.6.0" dependencies: