mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-05-29 13:54:18 +00:00
Merge pull request #820 from balena-io/typescript-network
Convert network module to typescript
This commit is contained in:
commit
3e6e2fc9a2
107
package-lock.json
generated
107
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "balena-supervisor",
|
"name": "balena-supervisor",
|
||||||
"version": "8.4.1",
|
"version": "8.4.3",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -1125,6 +1125,27 @@
|
|||||||
"type-is": "~1.6.16"
|
"type-is": "~1.6.16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"bonjour": {
|
||||||
|
"version": "git+https://github.com/resin-io/bonjour.git#e018851dc823b4b3f670f658f71d0c1c7f3e637c",
|
||||||
|
"from": "git+https://github.com/resin-io/bonjour.git#fixed-mdns",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"array-flatten": "^2.1.0",
|
||||||
|
"deep-equal": "^1.0.1",
|
||||||
|
"dns-equal": "^1.0.0",
|
||||||
|
"dns-txt": "^2.0.2",
|
||||||
|
"multicast-dns": "git+https://github.com/resin-io-modules/multicast-dns.git#a15c63464eb43e8925b187ed5cb9de6892e8aacc",
|
||||||
|
"multicast-dns-service-types": "^1.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"array-flatten": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz",
|
||||||
|
"integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
@ -1274,6 +1295,12 @@
|
|||||||
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
|
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"buffer-indexof": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"buffer-xor": {
|
"buffer-xor": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
|
||||||
@ -2159,6 +2186,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"deep-equal": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"deep-extend": {
|
"deep-extend": {
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||||
@ -2402,6 +2435,31 @@
|
|||||||
"path-type": "^3.0.0"
|
"path-type": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dns-equal": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"dns-packet": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ip": "^1.1.0",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dns-txt": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
|
||||||
|
"integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"buffer-indexof": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"docker-delta": {
|
"docker-delta": {
|
||||||
"version": "2.2.2",
|
"version": "2.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/docker-delta/-/docker-delta-2.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/docker-delta/-/docker-delta-2.2.2.tgz",
|
||||||
@ -6471,6 +6529,21 @@
|
|||||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"multicast-dns": {
|
||||||
|
"version": "git+https://github.com/resin-io-modules/multicast-dns.git#a15c63464eb43e8925b187ed5cb9de6892e8aacc",
|
||||||
|
"from": "git+https://github.com/resin-io-modules/multicast-dns.git#listen-on-all-interfaces",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"dns-packet": "^1.0.1",
|
||||||
|
"thunky": "^0.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"multicast-dns-service-types": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"mute-stream": {
|
"mute-stream": {
|
||||||
"version": "0.0.5",
|
"version": "0.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz",
|
||||||
@ -6565,9 +6638,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"network-checker": {
|
"network-checker": {
|
||||||
"version": "0.0.6",
|
"version": "0.1.1",
|
||||||
"resolved": "http://registry.npmjs.org/network-checker/-/network-checker-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/network-checker/-/network-checker-0.1.1.tgz",
|
||||||
"integrity": "sha1-165Y5NuVJE0tJnbM1LIlJRf5Mq4=",
|
"integrity": "sha512-dc/LiwC0pp37njpe8TA+oRa5BWkH8+WyFVY0aeuDZqMLHq4kaLHqWJowEfKBI7KT39vmTapWJN0SoHxhx6aL4A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"bluebird": "^3.0.0",
|
"bluebird": "^3.0.0",
|
||||||
@ -8193,27 +8266,9 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"bluebird": "^3.0.0",
|
"bluebird": "^3.0.0",
|
||||||
|
"bonjour": "git+https://github.com/resin-io/bonjour.git#e018851dc823b4b3f670f658f71d0c1c7f3e637c",
|
||||||
"ip": "^1.1.4",
|
"ip": "^1.1.4",
|
||||||
"lodash": "^4.17.4"
|
"lodash": "^4.17.4"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"array-flatten": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz",
|
|
||||||
"integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY="
|
|
||||||
},
|
|
||||||
"bonjour": {
|
|
||||||
"version": "git+https://github.com/resin-io/bonjour.git#e018851dc823b4b3f670f658f71d0c1c7f3e637c",
|
|
||||||
"from": "git+https://github.com/resin-io/bonjour.git#e018851dc823b4b3f670f658f71d0c1c7f3e637c",
|
|
||||||
"requires": {
|
|
||||||
"array-flatten": "^2.1.0",
|
|
||||||
"deep-equal": "^1.0.1",
|
|
||||||
"dns-equal": "^1.0.0",
|
|
||||||
"dns-txt": "^2.0.2",
|
|
||||||
"multicast-dns": "git+https://github.com/resin-io-modules/multicast-dns.git#a15c63464eb43e8925b187ed5cb9de6892e8aacc",
|
|
||||||
"multicast-dns-service-types": "^1.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"resin-errors": {
|
"resin-errors": {
|
||||||
@ -10301,6 +10356,12 @@
|
|||||||
"integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=",
|
"integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"thunky": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "http://registry.npmjs.org/thunky/-/thunky-0.1.0.tgz",
|
||||||
|
"integrity": "sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"tildify": {
|
"tildify": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/tildify/-/tildify-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/tildify/-/tildify-1.0.0.tgz",
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
"mocha": "^5.1.1",
|
"mocha": "^5.1.1",
|
||||||
"mochainon": "^2.0.0",
|
"mochainon": "^2.0.0",
|
||||||
"mz": "^2.7.0",
|
"mz": "^2.7.0",
|
||||||
"network-checker": "~0.0.5",
|
"network-checker": "^0.1.1",
|
||||||
"pinejs-client": "^2.4.0",
|
"pinejs-client": "^2.4.0",
|
||||||
"prettier": "^1.14.3",
|
"prettier": "^1.14.3",
|
||||||
"register-coffee-coverage": "0.0.1",
|
"register-coffee-coverage": "0.0.1",
|
||||||
|
@ -1,107 +0,0 @@
|
|||||||
Promise = require 'bluebird'
|
|
||||||
_ = require 'lodash'
|
|
||||||
url = require 'url'
|
|
||||||
networkCheck = require 'network-checker'
|
|
||||||
os = require 'os'
|
|
||||||
fs = Promise.promisifyAll(require('fs'))
|
|
||||||
|
|
||||||
constants = require './lib/constants'
|
|
||||||
{ checkTruthy } = require './lib/validation'
|
|
||||||
blink = require './lib/blink'
|
|
||||||
{ EEXIST } = require './lib/errors'
|
|
||||||
|
|
||||||
networkPattern =
|
|
||||||
blinks: 4
|
|
||||||
pause: 1000
|
|
||||||
|
|
||||||
pauseConnectivityCheck = false
|
|
||||||
enableConnectivityCheck = true
|
|
||||||
|
|
||||||
# options: An object of net.connect options, with the addition of:
|
|
||||||
# timeout: 10s
|
|
||||||
checkHost = (options) ->
|
|
||||||
if !enableConnectivityCheck or pauseConnectivityCheck
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
return networkCheck.checkHost(options)
|
|
||||||
|
|
||||||
# Custom monitor that uses checkHost function above.
|
|
||||||
customMonitor = (options, fn) ->
|
|
||||||
networkCheck.monitor(checkHost, options, fn)
|
|
||||||
|
|
||||||
# enable: A Boolean to enable/disable the connectivity checks
|
|
||||||
exports.enableCheck = enableCheck = (enable) ->
|
|
||||||
enableConnectivityCheck = enable
|
|
||||||
|
|
||||||
# Call back for inotify triggered when the VPN status is changed.
|
|
||||||
vpnStatusInotifyCallback = ->
|
|
||||||
fs.lstatAsync(constants.vpnStatusPath + '/active')
|
|
||||||
.then ->
|
|
||||||
pauseConnectivityCheck = true
|
|
||||||
.catch ->
|
|
||||||
pauseConnectivityCheck = false
|
|
||||||
|
|
||||||
exports.startConnectivityCheck = _.once (apiEndpoint, enable, onChangeCallback) ->
|
|
||||||
exports.enableConnectivityCheck(enable)
|
|
||||||
if !apiEndpoint?
|
|
||||||
console.log('No API endpoint specified, skipping connectivity check')
|
|
||||||
return
|
|
||||||
parsedUrl = url.parse(apiEndpoint)
|
|
||||||
fs.mkdirAsync(constants.vpnStatusPath)
|
|
||||||
.catch EEXIST, (err) ->
|
|
||||||
console.log('VPN status path exists.')
|
|
||||||
.then ->
|
|
||||||
fs.watch(constants.vpnStatusPath, vpnStatusInotifyCallback)
|
|
||||||
|
|
||||||
# Manually trigger the call back to detect cases when VPN was switched on before the supervisor starts.
|
|
||||||
vpnStatusInotifyCallback() if enable
|
|
||||||
customMonitor
|
|
||||||
host: parsedUrl.hostname
|
|
||||||
port: parsedUrl.port ? (if parsedUrl.protocol is 'https:' then 443 else 80)
|
|
||||||
interval: 10 * 1000
|
|
||||||
(connected) ->
|
|
||||||
onChangeCallback?(connected)
|
|
||||||
if connected
|
|
||||||
console.log('Internet Connectivity: OK')
|
|
||||||
blink.pattern.stop()
|
|
||||||
else
|
|
||||||
console.log('Waiting for connectivity...')
|
|
||||||
blink.pattern.start(networkPattern)
|
|
||||||
|
|
||||||
# Callback function to enable/disable tcp pings
|
|
||||||
exports.enableConnectivityCheck = (val) ->
|
|
||||||
enabled = checkTruthy(val) ? true
|
|
||||||
enableCheck(enabled)
|
|
||||||
console.log("Connectivity check enabled: #{enabled}")
|
|
||||||
|
|
||||||
exports.connectivityCheckEnabled = Promise.method ->
|
|
||||||
return enableConnectivityCheck
|
|
||||||
|
|
||||||
exports.getIPAddresses = ->
|
|
||||||
# We get IP addresses but ignore:
|
|
||||||
# - docker and balena bridges (docker0, docker1, balena0, etc)
|
|
||||||
# - legacy rce bridges (rce0, etc)
|
|
||||||
# - tun interfaces like the legacy vpn
|
|
||||||
# - the resin VPN interface (resin-vpn)
|
|
||||||
# - loopback interface (lo)
|
|
||||||
# - the bridge for dnsmasq (resin-dns)
|
|
||||||
# - the docker network for the supervisor API (supervisor0)
|
|
||||||
# - custom docker network bridges (br- + 12 hex characters)
|
|
||||||
_.flatten(_.map(_.omitBy(os.networkInterfaces(), (interfaceFields, interfaceName) ->
|
|
||||||
/^(?:balena|docker|rce|tun)[0-9]+|tun[0-9]+|resin-vpn|lo|resin-dns|supervisor0|balena-redsocks|resin-redsocks|br-[0-9a-f]{12}$/.test(interfaceName))
|
|
||||||
, (validInterfaces) ->
|
|
||||||
_.map(_.pickBy(validInterfaces, family: 'IPv4'), 'address'))
|
|
||||||
)
|
|
||||||
|
|
||||||
exports.startIPAddressUpdate = do ->
|
|
||||||
_lastIPValues = null
|
|
||||||
return (callback, interval) ->
|
|
||||||
getAndReportIP = ->
|
|
||||||
ips = exports.getIPAddresses()
|
|
||||||
if !_.isEmpty(_.xor(ips , _lastIPValues))
|
|
||||||
_lastIPValues = ips
|
|
||||||
callback(ips)
|
|
||||||
setInterval( ->
|
|
||||||
getAndReportIP()
|
|
||||||
, interval)
|
|
||||||
getAndReportIP()
|
|
156
src/network.ts
Normal file
156
src/network.ts
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
import * as Bluebird from 'bluebird';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
import { fs } from 'mz';
|
||||||
|
import * as networkCheck from 'network-checker';
|
||||||
|
import * as os from 'os';
|
||||||
|
import * as url from 'url';
|
||||||
|
|
||||||
|
import * as constants from './lib/constants';
|
||||||
|
import { EEXIST } from './lib/errors';
|
||||||
|
import { checkTruthy } from './lib/validation';
|
||||||
|
|
||||||
|
import blink = require('./lib/blink');
|
||||||
|
|
||||||
|
const networkPattern = {
|
||||||
|
blinks: 4,
|
||||||
|
pause: 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
let isConnectivityCheckPaused = false;
|
||||||
|
let isConnectivityCheckEnabled = true;
|
||||||
|
|
||||||
|
function checkHost(
|
||||||
|
opts: networkCheck.ConnectOptions,
|
||||||
|
): boolean | PromiseLike<boolean> {
|
||||||
|
return (
|
||||||
|
!isConnectivityCheckEnabled ||
|
||||||
|
isConnectivityCheckPaused ||
|
||||||
|
networkCheck.checkHost(opts)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function customMonitor(
|
||||||
|
options: networkCheck.ConnectOptions,
|
||||||
|
fn: networkCheck.MonitorChangeFunction,
|
||||||
|
) {
|
||||||
|
return networkCheck.monitor(checkHost, options, fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function enableCheck(enable: boolean) {
|
||||||
|
isConnectivityCheckEnabled = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function vpnStatusInotifyCallback(): Promise<void> {
|
||||||
|
try {
|
||||||
|
await fs.lstat(constants.vpnStatusPath);
|
||||||
|
isConnectivityCheckPaused = true;
|
||||||
|
} catch {
|
||||||
|
isConnectivityCheckPaused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const startConnectivityCheck = _.once(
|
||||||
|
async (
|
||||||
|
apiEndpoint: string,
|
||||||
|
enable: boolean,
|
||||||
|
onChangeCallback?: networkCheck.MonitorChangeFunction,
|
||||||
|
) => {
|
||||||
|
enableConnectivityCheck(enable);
|
||||||
|
if (!apiEndpoint) {
|
||||||
|
console.log('No API endpoint specified, skipping connectivity check');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Bluebird.resolve(fs.mkdir(constants.vpnStatusPath))
|
||||||
|
.catch(EEXIST, () => {
|
||||||
|
console.log('VPN status path exists.');
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
fs.watch(constants.vpnStatusPath, vpnStatusInotifyCallback);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
vpnStatusInotifyCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsedUrl = url.parse(apiEndpoint);
|
||||||
|
const port = parseInt(parsedUrl.port!, 10);
|
||||||
|
|
||||||
|
customMonitor(
|
||||||
|
{
|
||||||
|
host: parsedUrl.hostname,
|
||||||
|
port: port || (parsedUrl.protocol === 'https' ? 443 : 80),
|
||||||
|
path: parsedUrl.path || '/',
|
||||||
|
interval: 10 * 1000,
|
||||||
|
},
|
||||||
|
connected => {
|
||||||
|
if (_.isFunction(onChangeCallback)) {
|
||||||
|
onChangeCallback(connected);
|
||||||
|
}
|
||||||
|
if (connected) {
|
||||||
|
console.log('Internet Connectivity: OK');
|
||||||
|
blink.pattern.stop();
|
||||||
|
} else {
|
||||||
|
console.log('Waiting for connectivity...');
|
||||||
|
blink.pattern.start(networkPattern);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export function enableConnectivityCheck(enable: boolean) {
|
||||||
|
const boolEnable = checkTruthy(enable);
|
||||||
|
enable = boolEnable != null ? boolEnable : true;
|
||||||
|
enableCheck(enable);
|
||||||
|
console.log(`Connectivity check enabled: ${enable}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const connectivityCheckEnabled = Bluebird.method(
|
||||||
|
() => isConnectivityCheckEnabled,
|
||||||
|
);
|
||||||
|
|
||||||
|
const IP_REGEX = /^(?:balena|docker|rce|tun)[0-9]+|tun[0-9]+|resin-vpn|lo|resin-dns|supervisor0|balena-redsocks|resin-redsocks|br-[0-9a-f]{12}$/;
|
||||||
|
export function getIPAddresses(): string[] {
|
||||||
|
// We get IP addresses but ignore:
|
||||||
|
// - docker and balena bridges (docker0, docker1, balena0, etc)
|
||||||
|
// - legacy rce bridges (rce0, etc)
|
||||||
|
// - tun interfaces like the legacy vpn
|
||||||
|
// - the resin VPN interface (resin-vpn)
|
||||||
|
// - loopback interface (lo)
|
||||||
|
// - the bridge for dnsmasq (resin-dns)
|
||||||
|
// - the docker network for the supervisor API (supervisor0)
|
||||||
|
// - custom docker network bridges (br- + 12 hex characters)
|
||||||
|
return _(os.networkInterfaces())
|
||||||
|
.omitBy((_interfaceFields, interfaceName) => IP_REGEX.test(interfaceName))
|
||||||
|
.flatMap(validInterfaces => {
|
||||||
|
return _(validInterfaces)
|
||||||
|
.pickBy({ family: 'IPv4' })
|
||||||
|
.map('address')
|
||||||
|
.value();
|
||||||
|
})
|
||||||
|
.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function startIPAddressUpdate(): (
|
||||||
|
callback: (ips: string[]) => void,
|
||||||
|
interval: number,
|
||||||
|
) => void {
|
||||||
|
let lastIPValues: string[] | null = null;
|
||||||
|
return (cb, interval) => {
|
||||||
|
const getAndReportIP = () => {
|
||||||
|
const ips = getIPAddresses();
|
||||||
|
if (
|
||||||
|
!_(ips)
|
||||||
|
.xor(lastIPValues)
|
||||||
|
.isEmpty()
|
||||||
|
) {
|
||||||
|
lastIPValues = ips;
|
||||||
|
cb(ips);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
setInterval(getAndReportIP, interval);
|
||||||
|
getAndReportIP();
|
||||||
|
};
|
||||||
|
}
|
2
typings/blinking.d.ts
vendored
2
typings/blinking.d.ts
vendored
@ -11,7 +11,7 @@ declare module 'blinking' {
|
|||||||
stop: () => void;
|
stop: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function blinking(ledFile: string): Blink;
|
function blinking(ledFile: string): { pattern: Blink };
|
||||||
|
|
||||||
export = blinking;
|
export = blinking;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user