From 83d522ce96aaa72026a9a3acf20ecf99dcc53e75 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Sun, 13 Mar 2022 23:39:29 +0200 Subject: [PATCH] fix: rendezvous address resolution --- packages/concordia-pinner/package.json | 1 + packages/concordia-pinner/src/app.js | 14 +++--- packages/concordia-pinner/src/index.js | 12 ++--- .../concordia-pinner/src/utils/ipfsUtils.js | 49 +++++++++++++++---- yarn.lock | 17 +++++-- 5 files changed, 67 insertions(+), 26 deletions(-) diff --git a/packages/concordia-pinner/package.json b/packages/concordia-pinner/package.json index 9dc8ef7..907146f 100644 --- a/packages/concordia-pinner/package.json +++ b/packages/concordia-pinner/package.json @@ -30,6 +30,7 @@ "libp2p-webrtc-star": "~0.21.1", "lodash": "^4.17.20", "morgan": "^1.10.0", + "multiaddr": "~10.0.1", "orbit-db": "~0.26.0", "orbit-db-identity-provider": "~0.3.1", "rimraf": "~3.0.2", diff --git a/packages/concordia-pinner/src/app.js b/packages/concordia-pinner/src/app.js index 2145b21..44e10ab 100644 --- a/packages/concordia-pinner/src/app.js +++ b/packages/concordia-pinner/src/app.js @@ -1,17 +1,17 @@ import express from 'express'; -import morgan from 'morgan'; +import morgan from 'morgan'; //TODO: replace morgan with something else import _ from 'lodash'; import fs from 'fs'; import path from 'path'; import isReachable from 'is-reachable'; import { pinnerApiPort } from 'concordia-shared/src/environment/interpolated/pinner'; import getWeb3ProviderUrl from 'concordia-shared/src/utils/web3'; -import { getResolvedRendezvousUrl } from './utils/ipfsUtils'; +import { getResolvedRendezvousMultiaddress } from './utils/ipfsUtils'; import { logger, logsDirectoryPath } from './utils/logger'; const POLLING_INTERVAL = 1000; const accessLogStream = fs.createWriteStream(path.join(logsDirectoryPath, 'access.log'), { flags: 'a' }); -logger.info('Service setting up.'); +logger.info('Initializing API service.'); const responseBody = { ipfs: { @@ -23,9 +23,11 @@ const responseBody = { timestamp: 0, }; -getResolvedRendezvousUrl().then(({ address }) => { - logger.info(`Resolved rendezvous URL to: ${address}`); - responseBody.rendezvous.url = address; +getResolvedRendezvousMultiaddress().then((multiaddress) => { + const { address, port } = multiaddress.nodeAddress(); + const rendezvousUrl = `http://${address}:${port}`; + logger.info(`Resolved rendezvous URL to: ${rendezvousUrl}`); + responseBody.rendezvous.url = rendezvousUrl; }); const getStats = async (orbit) => { diff --git a/packages/concordia-pinner/src/index.js b/packages/concordia-pinner/src/index.js index f2d7743..430e7b8 100644 --- a/packages/concordia-pinner/src/index.js +++ b/packages/concordia-pinner/src/index.js @@ -20,7 +20,7 @@ process.on('unhandledRejection', async (error) => { } if (ipfsSingleton) { - await ipfsSingleton.stop(); + await ipfsSingleton.stop(); } // Don't swallow other errors @@ -71,16 +71,16 @@ const handleWeb3LogEvent = (web3, eventJsonInterface, orbit) => (error, result) }; const main = async () => { - logger.info('Initializing IPFS and orbitDb.'); + logger.info('Initializing IPFS and OrbitDB.'); const web3 = new Web3(new Web3.providers.WebsocketProvider(getWeb3ProviderUrl())); getDeployedContract(web3) .then(({ contract, contractAddress }) => getIpfsOptions() .then((ipfsOptions) => IPFS.create(ipfsOptions)) - .then((ipfs) => { - ipfsSingleton = ipfs; - return ipfs; - }) + .then((ipfs) => { + ipfsSingleton = ipfs; + return ipfs; + }) .then((ipfs) => createOrbitInstance(ipfs, contractAddress)) .then((orbit) => openExistingUsersDatabases(contract, orbit) .then(() => { diff --git a/packages/concordia-pinner/src/utils/ipfsUtils.js b/packages/concordia-pinner/src/utils/ipfsUtils.js index 3491c5f..aab7f58 100644 --- a/packages/concordia-pinner/src/utils/ipfsUtils.js +++ b/packages/concordia-pinner/src/utils/ipfsUtils.js @@ -1,21 +1,50 @@ import dns from 'dns'; import util from 'util'; +import { Multiaddr } from 'multiaddr'; import { rendezvousHost, rendezvousPort } from 'concordia-shared/src/environment/interpolated/rendezvous'; import { logger } from './logger'; const dnsLookup = util.promisify(dns.lookup); -export const getResolvedRendezvousUrl = async () => { - if (rendezvousHost.startsWith('/docker/')) { - return dnsLookup(rendezvousHost.substring('/docker/'.length), { family: 4 }) - .then((resolvedDomain) => `/ip4/${resolvedDomain.address}`) - .catch((error) => logger.error(new Error(`DNS lookup of ${rendezvousHost} failed.\n${error}`))); +const isMultiaddr = (input) => { + try { + // eslint-disable-next-line no-new + new Multiaddr(input); + return true; + } catch (e) { + logger.error(new Error(`Invalid rendezvous multiaddress ${input}!`)); + return false; } +}; + +// eslint-disable-next-line consistent-return +const getRendezvousMultiaddress = () => { + const host = rendezvousHost.startsWith('/docker/') ? rendezvousHost.substring('/docker/'.length) : rendezvousHost; + + const multiaddress = `${host}/tcp/${rendezvousPort}/wss/p2p-webrtc-star`; + if (isMultiaddr(multiaddress)) return new Multiaddr(multiaddress); + process.exit(1); // Invalid multiaddress - exiting with error +}; + +export const getResolvedRendezvousMultiaddress = async () => { + const rendezvousMultiaddress = getRendezvousMultiaddress(); + const { address } = rendezvousMultiaddress.nodeAddress(); - return Promise.resolve(rendezvousHost); + // Address is a domain to be resolved to IP + if (rendezvousMultiaddress.toString().includes('/dns4/')) { + try { + const resolvedDomain = await dnsLookup(address); + return Promise.resolve(new Multiaddr(`/ip4/${resolvedDomain.address}/tcp/${rendezvousPort}/wss/p2p-webrtc-star`)); + } catch (error) { + logger.error(new Error(`DNS lookup of ${address} failed.\n${error}`)); + process.exit(2); + } + } + return Promise.resolve(rendezvousMultiaddress); }; -export const getSwarmAddresses = async () => getResolvedRendezvousUrl() - .then((resolvedRendezvousHost) => [ - `${resolvedRendezvousHost}/tcp/${rendezvousPort}/wss/p2p-webrtc-star`, - ]); +// TODO: currently this only works for a single rendezvous +export const getSwarmAddresses = async () => getResolvedRendezvousMultiaddress() + .then((resolvedRendezvousMultiaddress) => [ + resolvedRendezvousMultiaddress.toString(), + ]).catch((error) => logger.error(new Error(`getSwarmAddresses failed.\n${error}`))); diff --git a/yarn.lock b/yarn.lock index 455939f..11236b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5917,7 +5917,7 @@ dns-equal@^1.0.0: resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= -dns-over-http-resolver@^1.0.0: +dns-over-http-resolver@^1.0.0, dns-over-http-resolver@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/dns-over-http-resolver/-/dns-over-http-resolver-1.2.3.tgz#194d5e140a42153f55bb79ac5a64dd2768c36af9" integrity sha512-miDiVSI6KSNbi4SVifzO/reD8rMnxgrlnkrlkugOLQpWQTe2qMdHsZp5DmfKjxNE+/T3VAAYLQUZMv9SMr6+AA== @@ -12813,6 +12813,18 @@ multiaddr@^9.0.1: uint8arrays "^2.1.3" varint "^6.0.0" +multiaddr@~10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/multiaddr/-/multiaddr-10.0.1.tgz#0d15848871370860a4d266bb44d93b3dac5d90ef" + integrity sha512-G5upNcGzEGuTHkzxezPrrD6CaIHR9uo+7MwqhNVcXTs33IInon4y7nMiGxl2CY5hG7chvYQUQhz5V52/Qe3cbg== + dependencies: + dns-over-http-resolver "^1.2.3" + err-code "^3.0.1" + is-ip "^3.1.0" + multiformats "^9.4.5" + uint8arrays "^3.0.0" + varint "^6.0.0" + multibase@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" @@ -16936,9 +16948,6 @@ snake-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== - dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" snapdragon-node@^2.0.1: version "2.1.1"