Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/test-bare.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Test Bare Status
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
strategy:
matrix:
node-version: [lts/*]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm install -g bare
- run: npm install
- run: npm run test-bare
2 changes: 1 addition & 1 deletion .github/workflows/test-node.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Test Status
name: Test Node Status
on:
push:
branches:
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package-lock.json
node_modules
.idea
,DS_Store
.DS_Store
120 changes: 109 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,121 @@
# Hyper Cmd Lib Net
# hyper-cmd-lib-net

Network Library to Interface with Hyperswarm and local connections. Supports both UDP and TCP connections.
Pipe local and remote (hyperdht) TCP/UDP streams together.

## Install
```
npm i @holesail/hyper-cmd-lib-net
```

`npm i @holesail/hyper-cmd-lib-net`
## Usage

```js
const { createTcpProxy } = require('@holesail/hyper-cmd-lib-net')

const proxy = createTcpProxy(
() => tunnel.createStream(),
{ port: 8080, host: '127.0.0.1' },
() => console.log('listening on', proxy.address())
)
```

## API

#### `connPiper`
#### `connPiper(a, bFactory, [opts])`

Pipe two duplex streams together, and destroy both the moment either one closes or
errors.

`bFactory()` is called once to make the second stream. Throw, or return `null`, to
reject the connection — `a` gets destroyed and `bFactory` is never called again.

```js
connPiper(a, () => b, {
logger: null, // { debug, info, warn, error }, defaults to a no-op logger
onDestroy: (err) => {} // called once, when the pipe is torn down
})
```

#### `const proxy = createTcpProxy(remoteTunnel, opts, onListen)`

Start a TCP server. Every accepted connection is piped to a fresh `remoteTunnel()`
stream using `connPiper` above.

```js
createTcpProxy(
() => tunnel.createStream(),
{
port: 0,
host: '127.0.0.1',
logger: null,
onDestroy: (err) => {}
},
() => {}
)
```

Returns the underlying `net.Server`. `proxy.close()` also destroys any connections
still open, so it doesn't need `'close'` listeners on every socket to fully shut down.

#### `pipeTcpServer(remoteStream, leftover, opts)`

The other direction of `createTcpProxy` — connects out to a local TCP service and pipes
it to `remoteStream`.

```js
pipeTcpServer(remoteStream, leftoverBuffer, {
port: 3000,
host: '127.0.0.1'
})
```

`leftover` is a buffer of bytes already read off `remoteStream` (eg while sniffing a
protocol) that gets written to the local socket before piping starts. Pass `null` if
there isn't any.

#### UDP framing

UDP has no stream boundaries, so the two helpers below speak a small length-prefixed
framing over the tunnel instead: 4 bytes big-endian length, then that many bytes of
payload. They're meant to be run as a pair, one on each end of a tunnel.

#### `const { proxySocket, clients } = createUdpFramedProxy(createTunnel, opts, onBind)`

Bind a UDP socket. Every distinct sender (by `address:port`) gets its own tunnel
stream, made lazily via `createTunnel()` on its first packet.

```js
createUdpFramedProxy(
() => tunnel.createStream(),
{
port: 0,
host: '127.0.0.1',
maxFrameSize: 65535,
logger: null
},
() => {}
)
```

`clients` is a `Map` of `address:port` -> `{ stream, rinfo, buffer }`. A frame bigger
than `maxFrameSize` destroys that client's tunnel and evicts it — the next packet from
the same client just starts a new one.

#### `udpPiper`
#### `pipeUdpFramedServer(stream, leftover, opts)`

#### `udpConnect`
The other end of the pair. Unframes packets off `stream` and forwards them as plain
UDP to a local service, framing replies back onto `stream`.

#### `createTcpProxy`
```js
pipeUdpFramedServer(remoteStream, leftoverBuffer, {
port: 53,
host: '127.0.0.1',
maxFrameSize: 65535
})
```

#### `pipeTcpServer`
A clean `end` on `stream` ends the local socket, no drama. An `error`, or a frame over
`maxFrameSize`, destroys it.

#### `createUdpFramedProxy`
## License

#### `pipeUdpFramedServer`
Apache-2.0
Loading
Loading