Skip to content

Commit

Permalink
Replace resin-discoverable-services with bonjour-service
Browse files Browse the repository at this point in the history
Instead of using the more generic resin-discoverable-services lib which is unmantained
and currently has several vulnerabilities and forks for fixing issues (that were later on fixed upstream)
we directly talk with mDNS using standard (and currently mantained) bonjour-service.

Change-type: patch
  • Loading branch information
otaviojacobi committed Jul 10, 2024
1 parent bcb7fb8 commit 6e2df0d
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 133 deletions.
53 changes: 29 additions & 24 deletions lib/utils/discover.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { enumerateServices, findServices } from 'resin-discoverable-services';
import Bonjour from 'bonjour-service';
import type { Browser } from 'bonjour-service';

interface LocalBalenaOsDevice {
address: string;
Expand All @@ -7,34 +8,38 @@ interface LocalBalenaOsDevice {
port: number;
}

// Although we only check for 'balena-ssh', we know, implicitly, that balenaOS
// devices come with 'rsync' installed that can be used over SSH.
const avahiBalenaSshTag = 'resin-ssh';
const avahiBalenaSshConfig = {
type: 'ssh',
name: '_resin-device._sub',
protocol: 'tcp' as const,
};

const avahiBalenaSshSubtype = 'resin-device';

export async function discoverLocalBalenaOsDevices(
timeout = 4000,
): Promise<LocalBalenaOsDevice[]> {
const availableServices = await enumerateServices();
const serviceDefinitions = Array.from(availableServices)
.filter((s) => Array.from(s.tags).includes(avahiBalenaSshTag))
.map((s) => s.service);

if (serviceDefinitions.length === 0) {
throw new Error(
`Could not find any available '${avahiBalenaSshTag}' services`,
);
}
const bonjour = new Bonjour({}, async (err: string | Error) => {
await (await import('../errors')).handleError(err);
});
const browser = await new Promise<Browser>((resolve) => {
const browser = bonjour.find(avahiBalenaSshConfig);
setTimeout(() => {
resolve(browser);
}, timeout);
});

const services = await findServices(serviceDefinitions, timeout);
return services.map(function (service) {
// User referer address to get device IP. This will work fine assuming that
// a device only advertises own services.
const {
referer: { address },
browser.stop();
bonjour.destroy();
return browser.services
.filter(
({ subtypes, referer }) =>
subtypes?.includes(avahiBalenaSshSubtype) && referer != null,
)
.map(({ referer, host, port }) => ({
// We ensure referer is not null on the filter above
address: referer!.address,
host,
port,
} = service;

return { address, host, port };
});
}));
}
144 changes: 37 additions & 107 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
],
"assets": [
"build/auth/pages/*.ejs",
"node_modules/resin-discoverable-services/services/**/*",
"node_modules/balena-sdk/node_modules/balena-pine/**/*",
"node_modules/balena-pine/**/*",
"node_modules/pinejs-client-core/**/*",
Expand Down Expand Up @@ -218,6 +217,7 @@
"balena-settings-storage": "^8.1.0",
"bluebird": "^3.7.2",
"body-parser": "^1.19.1",
"bonjour-service": "^1.2.1",
"chalk": "^3.0.0",
"chokidar": "^3.5.2",
"cli-truncate": "^2.1.0",
Expand Down Expand Up @@ -262,7 +262,6 @@
"request": "^2.88.2",
"resin-cli-form": "^3.0.0",
"resin-cli-visuals": "^2.0.0",
"resin-discoverable-services": "^2.0.5",
"resin-doodles": "^0.2.0",
"resin-stream-logger": "^0.1.2",
"rimraf": "^3.0.2",
Expand Down

0 comments on commit 6e2df0d

Please sign in to comment.