diff --git a/CHANGELOG.md b/CHANGELOG.md index e498e2d..3699c43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,6 +98,7 @@ Other changes | Version | Date | Comment | | -------------- | -------------- | -------- | +| 3.24.0 | 2017-08-05 | extended windows support `networkStats()`, `networkConnections()` | | 3.23.7 | 2017-07-11 | bug fix `diskLayout()` | | 3.23.6 | 2017-07-11 | added `cpuFlags()` to `getStaticData()`, bug fix `graphics()` (Win) | | 3.23.5 | 2017-06-29 | bug fix `inetChecksite()` | diff --git a/README.md b/README.md index a5dc8e6..20a853a 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ si.cpu() ## News and Changes ### Latest Activity +- Version 3.24.0: extended windows support `networkStats()`, `networkConnections()` - Version 3.23.0: added `memLayout`, `diskLayout`, extended windows support (`inetChecksite`) - Version 3.22.0: extended windows support (`users`, `inetLatency`) - Version 3.21.0: extended `time` (timezone), extended windows support (`battery`, `getAll...`) @@ -278,22 +279,22 @@ I also created a nice little command line tool called [mmon][mmon-github-url] ( | | [0].ip6 | X | X | X | ip6 address | | | [0].mac | X | X | X | MAC address | | | [0].internal | X | X | X | true if internal interface | -| si.networkInterfaceDefault(cb) | : string | X | X | | get name of default network interface | -| si.networkStats(iface,cb) | {...} | X | X | | current network stats of given interface
iface parameter is optional
defaults to first external network interface| -| | iface | X | X | | interface | +| si.networkInterfaceDefault(cb) | : string | X | X | X | get name of default network interface | +| si.networkStats(iface,cb) | {...} | X | X | X | current network stats of given interface
iface parameter is optional
defaults to first external network interface
Windows: no iface, only overall stats!| +| | iface | X | X | | interface (Windows: only overall stats)| | | operstate | X | X | | up / down | -| | rx | X | X | | received bytes overall | -| | tx | X | X | | transferred bytes overall| -| | rx_sec | X | X | | received bytes / second (* see notes) | -| | tx_sec | X | X | | transferred bytes per second (* see notes) | -| | ms | X | X | | interval length (for per second values) | -| si.networkConnections(cb) | [{...}] | X | X | | current network network connections
returns an array of all connections| -| | [0].protocol | X | X | | tcp or udp | -| | [0].localaddress | X | X | | local address | -| | [0].localport | X | X | | local port | -| | [0].peeraddress | X | X | | peer address | -| | [0].peerport | X | X | | peer port | -| | [0].state | X | X | | like ESTABLISHED, TIME_WAIT, ... | +| | rx | X | X | X | received bytes overall | +| | tx | X | X | X | transferred bytes overall| +| | rx_sec | X | X | X | received bytes / second (* see notes) | +| | tx_sec | X | X | X | transferred bytes per second (* see notes) | +| | ms | X | X | X | interval length (for per second values) | +| si.networkConnections(cb) | [{...}] | X | X | X | current network network connections
returns an array of all connections| +| | [0].protocol | X | X | X | tcp or udp | +| | [0].localaddress | X | X | X | local address | +| | [0].localport | X | X | X | local port | +| | [0].peeraddress | X | X | X | peer address | +| | [0].peerport | X | X | X | peer port | +| | [0].state | X | X | X | like ESTABLISHED, TIME_WAIT, ... | | si.inetChecksite(url, cb) | {...} | X | X | X | response-time (ms) to fetch given URL | | | url | X | X | X | given url | | | ok | X | X | X | status code OK (2xx, 3xx) | diff --git a/lib/network.js b/lib/network.js index 2f68d1f..b51c551 100644 --- a/lib/network.js +++ b/lib/network.js @@ -165,14 +165,12 @@ function networkStats(iface, callback) { return new Promise((resolve, reject) => { process.nextTick(() => { - if (_windows) { - let error = new Error(NOT_SUPPORTED); - if (callback) { callback(NOT_SUPPORTED) } - reject(error); - } _default_iface = _default_iface || getDefaultNetworkInterface(); iface = iface || _default_iface; // (_darwin ? 'en0' : 'eth0'); + if (_windows) { + iface = 'all' + } let result = { iface: iface, @@ -240,6 +238,24 @@ function networkStats(iface, callback) { }); }); } + if (_windows) { + cmd = "netstat -e"; + exec(cmd, function (error, stdout) { + const lines = stdout.split('\r\n'); + for (let i = 0; i < lines.length; i++) { + if (lines[i].toLowerCase().startsWith('bytes')) { + const parts = lines[i].substr(5).trim().replace(/ +/g, " ").split(' '); + if (parts.length > 1) { + rx = parseInt(parts[0]); + tx = parseInt(parts[1]); + result = calcNetworkSpeed(iface, rx, tx, operstate); + } + } + } + if (callback) { callback(result) } + resolve(result); + }); + } } else { result.rx = _network[iface].rx; result.tx = _network[iface].tx; @@ -262,12 +278,6 @@ function networkConnections(callback) { return new Promise((resolve, reject) => { process.nextTick(() => { - if (_windows) { - let error = new Error(NOT_SUPPORTED); - if (callback) { callback(NOT_SUPPORTED) } - reject(error); - } - let result = []; if (_linux) { let cmd = "netstat -tuna | grep 'ESTABLISHED\\|SYN_SENT\\|SYN_RECV\\|FIN_WAIT1\\|FIN_WAIT2\\|TIME_WAIT\\|CLOSE\\|CLOSE_WAIT\\|LAST_ACK\\|LISTEN\\|CLOSING\\|UNKNOWN\\|VERBUNDEN'"; @@ -406,6 +416,62 @@ function networkConnections(callback) { } }) } + if (_windows) { + let cmd = "netstat -na"; + exec(cmd, function (error, stdout) { + if (!error) { + + let lines = stdout.toString().split('\r\n'); + + lines.forEach(function (line) { + line = line.trim().replace(/ +/g, " ").split(' '); + if (line.length >= 4) { + let localip = line[1]; + let localport = ''; + let localaddress = line[1].split(':'); + if (localaddress.length > 1) { + localport = localaddress[localaddress.length - 1]; + localaddress.pop(); + localip = localaddress.join(':'); + } + let peerip = line[2]; + let peerport = ''; + let peeraddress = line[2].split(':'); + if (peeraddress.length > 1) { + peerport = peeraddress[peeraddress.length - 1]; + peeraddress.pop(); + peerip = peeraddress.join(':'); + } + let connstate = line[3]; + if (connstate === 'HERGESTELLT') connstate = 'ESTABLISHED'; + if (connstate.startsWith('ABH')) connstate = 'LISTEN'; + if (connstate === 'SCHLIESSEN_WARTEN') connstate = 'CLOSE_WAIT'; + if (connstate === 'WARTEND') connstate = 'TIME_WAIT'; + if (connstate === 'SYN_GESENDET') connstate = 'SYN_SENT'; + + if (connstate === 'LISTENING') connstate = 'LISTEN'; + if (connstate === 'SYN_RECEIVED') connstate = 'SYN_RECV'; + if (connstate === 'FIN_WAIT_1') connstate = 'FIN_WAIT1'; + if (connstate === 'FIN_WAIT_2') connstate = 'FIN_WAIT2'; + if (connstate) { + result.push({ + protocol: line[0].toLowerCase(), + localaddress: localip, + localport: localport, + peeraddress: peerip, + peerport: peerport, + state: connstate + }) + } + } + }); + if (callback) { + callback(result) + } + resolve(result); + } + }) + } }); }); }