Skip to content

Commit fb58588

Browse files
Initial commit
0 parents  commit fb58588

8 files changed

Lines changed: 801 additions & 0 deletions

File tree

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* text=auto eol=lf

.github/workflows/test-node.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Lint Test
2+
on:
3+
push:
4+
branches:
5+
- main
6+
pull_request:
7+
branches:
8+
- main
9+
jobs:
10+
build:
11+
strategy:
12+
matrix:
13+
node-version: [lts/*]
14+
os: [ubuntu-latest, macos-latest, windows-latest]
15+
runs-on: ${{ matrix.os }}
16+
steps:
17+
- uses: actions/checkout@v3
18+
- name: Use Node.js ${{ matrix.node-version }}
19+
uses: actions/setup-node@v3
20+
with:
21+
node-version: ${{ matrix.node-version }}
22+
- run: npm install
23+
- run: npm run test

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules
2+
package-lock.json
3+
.idea
4+
.DS_Store

.prettierrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"prettier-config-holepunch"

LICENSE

Lines changed: 661 additions & 0 deletions
Large diffs are not rendered by default.

NOTICE

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Copyright (C) 2026 LIVEPORT P2P SOLUTIONS PVT. LTD.
2+
3+
This program is free software: you can redistribute it and/or modify
4+
it under the terms of the GNU Affero General Public License as
5+
published by the Free Software Foundation, either version 3 of the
6+
License, or (at your option) any later version.
7+
8+
This program is distributed in the hope that it will be useful,
9+
but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
GNU Affero General Public License for more details.
12+
13+
You should have received a copy of the GNU Affero General Public License
14+
along with this program. If not, see <https://www.gnu.org/licenses/>.

index.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
const { TextEncoder, TextDecoder } = require('bare-encoding')
2+
3+
const CAPABILITY_LEN = 32
4+
const HEADER_LEN = CAPABILITY_LEN + 1
5+
6+
const MODE_TUNNEL = 0
7+
const MODE_PROBE = 1
8+
9+
const PROBE_FIXED_LEN = 4
10+
const MAX_HOST_LEN = 255
11+
12+
const utf8Encoder = new TextEncoder()
13+
const utf8Decoder = new TextDecoder('utf-8')
14+
15+
function encodeHeader(capability, mode) {
16+
if (capability.length !== CAPABILITY_LEN) {
17+
throw new Error(`capability must be ${CAPABILITY_LEN} bytes`)
18+
}
19+
if (!Number.isInteger(mode) || mode < 0 || mode > 255) {
20+
throw new Error('mode must be a byte (0-255)')
21+
}
22+
const out = new Uint8Array(HEADER_LEN)
23+
out.set(capability, 0)
24+
out[CAPABILITY_LEN] = mode
25+
return out
26+
}
27+
28+
function decodeHeader(bytes) {
29+
if (bytes.length < HEADER_LEN) return null
30+
return {
31+
capability: bytes.subarray(0, CAPABILITY_LEN),
32+
mode: bytes[CAPABILITY_LEN],
33+
leftover: bytes.subarray(HEADER_LEN)
34+
}
35+
}
36+
37+
function encodeProbeResponse({ port = 0, host = '', udp = false } = {}) {
38+
const hostBytes = utf8Encoder.encode(String(host))
39+
if (hostBytes.length > MAX_HOST_LEN) {
40+
throw new Error(`host exceeds ${MAX_HOST_LEN} bytes`)
41+
}
42+
const portInt = +port | 0
43+
if (portInt < 0 || portInt > 0xffff) {
44+
throw new Error('port must fit in uint16')
45+
}
46+
const out = new Uint8Array(PROBE_FIXED_LEN + hostBytes.length)
47+
out[0] = (portInt >>> 8) & 0xff
48+
out[1] = portInt & 0xff
49+
out[2] = udp ? 1 : 0
50+
out[3] = hostBytes.length
51+
out.set(hostBytes, PROBE_FIXED_LEN)
52+
return out
53+
}
54+
55+
function decodeProbeResponse(bytes) {
56+
if (bytes.length < PROBE_FIXED_LEN) return null
57+
const hostLen = bytes[3]
58+
const total = PROBE_FIXED_LEN + hostLen
59+
if (bytes.length < total) return null
60+
return {
61+
port: (bytes[0] << 8) | bytes[1],
62+
udp: bytes[2] === 1,
63+
host: utf8Decoder.decode(bytes.subarray(PROBE_FIXED_LEN, total)),
64+
leftover: bytes.subarray(total)
65+
}
66+
}
67+
68+
module.exports = {
69+
CAPABILITY_LEN,
70+
HEADER_LEN,
71+
MODE_TUNNEL,
72+
MODE_PROBE,
73+
encodeHeader,
74+
decodeHeader,
75+
encodeProbeResponse,
76+
decodeProbeResponse
77+
}

package.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "@holesail/protocol",
3+
"version": "1.0.0",
4+
"description": "protocol for Holesail stream verification",
5+
"license": "AGPL-3.0",
6+
"author": "supersuryaansh",
7+
"type": "commonjs",
8+
"main": "index.js",
9+
"scripts": {
10+
"format": "prettier . --write",
11+
"test": "prettier . --check"
12+
},
13+
"dependencies": {
14+
"bare-encoding": "^1.0.3"
15+
},
16+
"devDependencies": {
17+
"prettier": "^3.8.3",
18+
"prettier-config-holepunch": "^2.0.0"
19+
}
20+
}

0 commit comments

Comments
 (0)