fix: multi-repo local dev (file:../ deps, package exports, missing deps)
This commit is contained in:
+24
@@ -0,0 +1,24 @@
|
||||
name: Build Status
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
os: [ubuntu-16.04, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: npm install
|
||||
- run: npm test
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 Mathias Buus
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
# nat-sampler
|
||||
|
||||
Sample addresses to figure out if a host + port is consistent
|
||||
|
||||
```
|
||||
npm install nat-sampler
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
``` js
|
||||
const NatSampler = require('nat-sampler')
|
||||
|
||||
const s = new NatSampler()
|
||||
|
||||
// add a sample
|
||||
const hits = s.add('127.0.0.1', 9090)
|
||||
|
||||
console.log('In there this many times:', hits)
|
||||
console.log('Estimated host + port', s.host, s.port)
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
#### `s = new NatSampler()`
|
||||
|
||||
Make a new sampler.
|
||||
|
||||
#### `hits = s.add(host, port)`
|
||||
|
||||
Add a sample of your host and port.
|
||||
Returns how many hits this entry has.
|
||||
|
||||
#### `s.host`
|
||||
|
||||
What the sampler thinks your host is.
|
||||
|
||||
If your host is unknown it will be `null`.
|
||||
|
||||
#### `s.port`
|
||||
|
||||
What the sampler thinks your port is.
|
||||
|
||||
If your port is random or unknown it will be `0`.
|
||||
|
||||
#### `s.size`
|
||||
|
||||
How many samples the sampler is basing this on.
|
||||
|
||||
## Error correction
|
||||
|
||||
The sampler applies some simple error correction to make sure bad samples do not mess it up.
|
||||
|
||||
* If it has `<=` 3 samples, it will disregard none outliers.
|
||||
* If it has `<=` 7 samples, it will disregard one outliers.
|
||||
* If it has `<=` 11 samples, it will disregard two outliers.
|
||||
* If it has `>` 11 samples, it will disregard three outliers.
|
||||
|
||||
At max it keeps 16 samples of `{ host, port }` pairs for the analysis.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
module.exports = class NatSampler {
|
||||
constructor () {
|
||||
this.host = null
|
||||
this.port = 0
|
||||
this.size = 0
|
||||
|
||||
this._a = null
|
||||
this._b = null
|
||||
this._threshold = 0
|
||||
this._top = 0
|
||||
this._samples = []
|
||||
}
|
||||
|
||||
add (host, port) {
|
||||
const a = this._bump(host, port, 2)
|
||||
const b = this._bump(host, 0, 1)
|
||||
|
||||
if (this._samples.length < 32) {
|
||||
this.size++
|
||||
this._threshold = this.size - (this.size < 4 ? 0 : this.size < 8 ? 1 : this.size < 12 ? 2 : 3)
|
||||
this._samples.push(a, b)
|
||||
this._top += 2
|
||||
} else {
|
||||
if (this._top === 32) this._top = 0
|
||||
|
||||
const oa = this._samples[this._top]
|
||||
this._samples[this._top++] = a
|
||||
oa.hits--
|
||||
|
||||
const ob = this._samples[this._top]
|
||||
this._samples[this._top++] = b
|
||||
ob.hits--
|
||||
}
|
||||
|
||||
if (this._a === null || this._a.hits < a.hits) this._a = a
|
||||
if (this._b === null || this._b.hits < b.hits) this._b = b
|
||||
|
||||
if (this._a.hits >= this._threshold) {
|
||||
this.host = this._a.host
|
||||
this.port = this._a.port
|
||||
} else if (this._b.hits >= this._threshold) {
|
||||
this.host = this._b.host
|
||||
this.port = 0
|
||||
} else {
|
||||
this.host = null
|
||||
this.port = 0
|
||||
}
|
||||
|
||||
return a.hits
|
||||
}
|
||||
|
||||
_bump (host, port, inc) {
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const j = (this._top - inc - (2 * i)) & 31
|
||||
if (j >= this._samples.length) return { host, port, hits: 1 }
|
||||
const s = this._samples[j]
|
||||
if (s.port === port && s.host === host) {
|
||||
s.hits++
|
||||
return s
|
||||
}
|
||||
}
|
||||
return { host, port, hits: 1 }
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "nat-sampler",
|
||||
"version": "1.0.1",
|
||||
"description": "Sample addresses to figure out if a host + port is consistent",
|
||||
"main": "index.js",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"standard": "^16.0.3",
|
||||
"tape": "^5.2.2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mafintosh/nat-sampler.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "standard && tape test.js"
|
||||
},
|
||||
"author": "Mathias Buus (@mafintosh)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/mafintosh/nat-sampler/issues"
|
||||
},
|
||||
"homepage": "https://github.com/mafintosh/nat-sampler"
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
const tape = require('tape')
|
||||
const NatSampler = require('./')
|
||||
|
||||
tape('small consistent samples', function (t) {
|
||||
const nat = new NatSampler()
|
||||
|
||||
t.same(nat.add('127.0.0.1', 9090), 1)
|
||||
t.same(nat.host, '127.0.0.1')
|
||||
t.same(nat.port, 9090)
|
||||
|
||||
t.same(nat.add('127.0.0.1', 9090), 2)
|
||||
t.same(nat.host, '127.0.0.1')
|
||||
t.same(nat.port, 9090)
|
||||
|
||||
t.same(nat.add('127.0.0.1', 9090), 3)
|
||||
t.same(nat.host, '127.0.0.1')
|
||||
t.same(nat.port, 9090)
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tape('small consistent samples with errors', function (t) {
|
||||
const nat = new NatSampler()
|
||||
|
||||
t.same(nat.add('127.0.0.1', 9090), 1)
|
||||
t.same(nat.host, '127.0.0.1')
|
||||
t.same(nat.port, 9090)
|
||||
|
||||
t.same(nat.add('127.0.0.1', 9091), 1)
|
||||
t.same(nat.host, '127.0.0.1')
|
||||
t.same(nat.port, 0)
|
||||
|
||||
t.same(nat.add('127.0.0.1', 9090), 2)
|
||||
t.same(nat.host, '127.0.0.1')
|
||||
t.same(nat.port, 0)
|
||||
|
||||
t.same(nat.add('127.0.0.1', 9090), 3)
|
||||
t.same(nat.host, '127.0.0.1')
|
||||
t.same(nat.port, 9090)
|
||||
|
||||
t.same(nat.add('127.0.0.1', 9091), 2)
|
||||
t.same(nat.host, '127.0.0.1')
|
||||
t.same(nat.port, 0)
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tape('host consistency', function (t) {
|
||||
const nat = new NatSampler()
|
||||
|
||||
t.same(nat.add('127.0.0.1', 9090), 1)
|
||||
t.same(nat.add('127.0.0.2', 9090), 1)
|
||||
t.same(nat.add('127.0.0.1', 9090), 2)
|
||||
t.same(nat.add('127.0.0.2', 9090), 2)
|
||||
|
||||
t.same(nat.host, null)
|
||||
t.same(nat.port, 0)
|
||||
|
||||
t.same(nat.add('127.0.0.1', 9090), 3)
|
||||
t.same(nat.host, null)
|
||||
t.same(nat.port, 0)
|
||||
|
||||
t.same(nat.add('127.0.0.1', 9090), 4)
|
||||
t.same(nat.host, null)
|
||||
t.same(nat.port, 0)
|
||||
|
||||
t.same(nat.add('127.0.0.1', 9090), 5)
|
||||
t.same(nat.host, null)
|
||||
t.same(nat.port, 0)
|
||||
|
||||
t.same(nat.add('127.0.0.1', 9091), 1)
|
||||
t.same(nat.host, '127.0.0.1')
|
||||
t.same(nat.port, 0)
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tape('can recover up to 3 errors', function (t) {
|
||||
const nat = new NatSampler()
|
||||
|
||||
for (let i = 0; i < 20; i++) nat.add('127.0.0.1', 9090)
|
||||
|
||||
t.same(nat.add('127.0.0.1', 9091), 1)
|
||||
t.same(nat.add('127.0.0.2', 9091), 1)
|
||||
t.same(nat.add('127.0.0.3', 9091), 1)
|
||||
t.same(nat.host, '127.0.0.1')
|
||||
t.same(nat.port, 9090)
|
||||
|
||||
for (let i = 0; i < 5; i++) nat.add('127.0.0.1', 9090)
|
||||
t.same(nat.host, '127.0.0.1')
|
||||
t.same(nat.port, 9090)
|
||||
|
||||
nat.add('127.0.0.1', 9095)
|
||||
t.same(nat.host, '127.0.0.1')
|
||||
t.same(nat.port, 0)
|
||||
|
||||
nat.add('127.0.0.2', 9095)
|
||||
t.same(nat.host, '127.0.0.1')
|
||||
t.same(nat.port, 0)
|
||||
|
||||
nat.add('127.0.0.2', 9095)
|
||||
t.same(nat.host, null)
|
||||
t.same(nat.port, 0)
|
||||
|
||||
t.end()
|
||||
})
|
||||
Reference in New Issue
Block a user