-
Notifications
You must be signed in to change notification settings - Fork 1
/
ipaddress.ts
103 lines (96 loc) · 3.42 KB
/
ipaddress.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { CODEPOINTS, decode } from "./encode.ts";
import { isDigit, isHexDigit } from "./utilities.ts";
export class IPAddress {
#isValid = false;
#isIpv6 = false;
constructor() {}
initIpv6Port(ipv6: Uint8Array, port: number): boolean {
this.#isValid = false;
if (port <= 0 || port >= (1 << 16)) {
throw new Error("Invalid [IPv6 address port=" + port + "]");
}
if (ipv6.length > 2 && ipv6[0] === CODEPOINTS["["] && ipv6.at(-1) === CODEPOINTS["]"]) {
ipv6 = ipv6.slice(1, ipv6.length - 1);
}
if (parseIpv6(ipv6) == null) {
throw new Error("Invalid IPv6 address " + decode(ipv6));
}
this.#isIpv6 = true;
this.#isValid = true;
return true;
}
isIpv6() {
return this.#isValid && this.#isIpv6;
}
}
// Thanks to Core-JS
export function parseIpv6(input: Uint8Array) {
const address = [0, 0, 0, 0, 0, 0, 0, 0];
let pieceIndex = 0;
let compress = null;
let pointer = 0;
let value, length, numbersSeen, ipv4Piece, number, swaps, swap;
if (input[pointer] === CODEPOINTS[":"]) {
if (input[1] !== CODEPOINTS[":"]) return;
pointer += 2;
pieceIndex++;
compress = pieceIndex;
}
while (input[pointer]) {
if (pieceIndex === 8) return;
if (input[pointer] === CODEPOINTS[":"]) {
if (compress != null) return;
pointer++;
pieceIndex++;
compress = pieceIndex;
continue;
}
value = length = 0;
while (length < 4 && isHexDigit(input[pointer])) {
value = value * 16 + parseInt(decode(input[pointer]), 16);
pointer++;
length++;
}
if (input[pointer] === CODEPOINTS["."]) {
if (length === 0) return;
pointer -= length;
if (pieceIndex > 6) return;
numbersSeen = 0;
while (input[pointer]) {
ipv4Piece = null;
if (numbersSeen > 0) {
if (input[pointer] === CODEPOINTS["."] && numbersSeen < 4) pointer++;
else return;
}
if (!isDigit(input[pointer])) return;
while (isDigit(input[pointer])) {
number = parseInt(decode(input[pointer]), 10);
if (ipv4Piece === null) ipv4Piece = number;
else if (ipv4Piece === 0) return;
else ipv4Piece = ipv4Piece * 10 + number;
if (ipv4Piece > 255) return;
pointer++;
}
address[pieceIndex] = address[pieceIndex] * 256 + (ipv4Piece || 0);
numbersSeen++;
if (numbersSeen === 2 || numbersSeen === 4) pieceIndex++;
}
if (numbersSeen !== 4) return;
break;
} else if (input[pointer] === CODEPOINTS[":"]) {
pointer++;
if (!input[pointer]) return;
} else if (input[pointer]) return;
address[pieceIndex++] = value;
}
if (compress !== null) {
swaps = pieceIndex - compress;
pieceIndex = 7;
while (pieceIndex !== 0 && swaps > 0) {
swap = address[pieceIndex];
address[pieceIndex--] = address[compress + swaps - 1];
address[compress + --swaps] = swap;
}
} else if (pieceIndex !== 8) return;
return address;
}