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 00bd4d5 commit 7273656
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 126 deletions.
54 changes: 31 additions & 23 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 { Service } from 'bonjour-service';

interface LocalBalenaOsDevice {
address: string;
Expand All @@ -7,34 +8,41 @@ 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 services = await new Promise<Service[]>((resolve) => {
const bonjour = new Bonjour({}, async (err: string | Error) => {
await (await import('../errors')).handleError(err);
});
const resinSshServices: Service[] = [];
const browser = bonjour.find(avahiBalenaSshConfig, (service) =>
resinSshServices.push(service),
);
}
setTimeout(() => {
browser.stop();
bonjour.destroy();
resolve(resinSshServices);
}, 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 },
return 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 };
});
}));
}
135 changes: 34 additions & 101 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 @@ -261,7 +261,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 7273656

Please sign in to comment.