Skip to content

Commit 4e3f1ae

Browse files
starkwangtargos
authored andcommitted
net: port isIPv6 to JS
Porting isIPv6() to JS makes it 10%-250% faster in most cases and reduces some C++ code. This change also adds tests for some edge cases. PR-URL: #22673 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Roman Reiss <[email protected]>
1 parent 0c32428 commit 4e3f1ae

File tree

4 files changed

+312
-10
lines changed

4 files changed

+312
-10
lines changed

lib/internal/net.js

+22-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,33 @@
11
'use strict';
22

33
const Buffer = require('buffer').Buffer;
4-
const { isIPv6 } = process.binding('cares_wrap');
54
const { writeBuffer } = process.binding('fs');
65
const errors = require('internal/errors');
76

8-
const octet = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';
9-
const re = new RegExp(`^${octet}[.]${octet}[.]${octet}[.]${octet}$`);
7+
// IPv4 Segment
8+
const v4Seg = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';
9+
const v4Str = `(${v4Seg}[.]){3}${v4Seg}`;
10+
const IPv4Reg = new RegExp(`^${v4Str}$`);
11+
12+
// IPv6 Segment
13+
const v6Seg = '(?:[0-9a-fA-F]{1,4})';
14+
const IPv6Reg = new RegExp('^(' +
15+
`(?:${v6Seg}:){7}(?:${v6Seg}|:)|` +
16+
`(?:${v6Seg}:){6}(?:${v4Str}|:${v6Seg}|:)|` +
17+
`(?:${v6Seg}:){5}(?::${v4Str}|(:${v6Seg}){1,2}|:)|` +
18+
`(?:${v6Seg}:){4}(?:(:${v6Seg}){0,1}:${v4Str}|(:${v6Seg}){1,3}|:)|` +
19+
`(?:${v6Seg}:){3}(?:(:${v6Seg}){0,2}:${v4Str}|(:${v6Seg}){1,4}|:)|` +
20+
`(?:${v6Seg}:){2}(?:(:${v6Seg}){0,3}:${v4Str}|(:${v6Seg}){1,5}|:)|` +
21+
`(?:${v6Seg}:){1}(?:(:${v6Seg}){0,4}:${v4Str}|(:${v6Seg}){1,6}|:)|` +
22+
`(?::((?::${v6Seg}){0,5}:${v4Str}|(?::${v6Seg}){1,7}|:))` +
23+
')(%[0-9a-zA-Z]{1,})?$');
1024

1125
function isIPv4(s) {
12-
return re.test(s);
26+
return IPv4Reg.test(s);
27+
}
28+
29+
function isIPv6(s) {
30+
return IPv6Reg.test(s);
1331
}
1432

1533
function isIP(s) {

src/cares_wrap.cc

-6
Original file line numberDiff line numberDiff line change
@@ -1955,11 +1955,6 @@ int ParseIP(const char* ip, ParseIPResult* result = nullptr) {
19551955
return 0;
19561956
}
19571957

1958-
void IsIPv6(const FunctionCallbackInfo<Value>& args) {
1959-
node::Utf8Value ip(args.GetIsolate(), args[0]);
1960-
args.GetReturnValue().Set(6 == ParseIP(*ip));
1961-
}
1962-
19631958
void CanonicalizeIP(const FunctionCallbackInfo<Value>& args) {
19641959
v8::Isolate* isolate = args.GetIsolate();
19651960
node::Utf8Value ip(isolate, args[0]);
@@ -2208,7 +2203,6 @@ void Initialize(Local<Object> target,
22082203

22092204
env->SetMethod(target, "getaddrinfo", GetAddrInfo);
22102205
env->SetMethod(target, "getnameinfo", GetNameInfo);
2211-
env->SetMethodNoSideEffect(target, "isIPv6", IsIPv6);
22122206
env->SetMethodNoSideEffect(target, "canonicalizeIP", CanonicalizeIP);
22132207

22142208
env->SetMethod(target, "strerror", StrError);

test/parallel/test-net-isipv4.js

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
require('../common');
3+
const assert = require('assert');
4+
const net = require('net');
5+
6+
const v4 = [
7+
'0.0.0.0',
8+
'8.8.8.8',
9+
'127.0.0.1',
10+
'100.100.100.100',
11+
'192.168.0.1',
12+
'18.101.25.153',
13+
'123.23.34.2',
14+
'172.26.168.134',
15+
'212.58.241.131',
16+
'128.0.0.0',
17+
'23.71.254.72',
18+
'223.255.255.255',
19+
'192.0.2.235',
20+
'99.198.122.146',
21+
'46.51.197.88',
22+
'173.194.34.134'
23+
];
24+
25+
const v4not = [
26+
'.100.100.100.100',
27+
'100..100.100.100.',
28+
'100.100.100.100.',
29+
'999.999.999.999',
30+
'256.256.256.256',
31+
'256.100.100.100.100',
32+
'123.123.123',
33+
'http://123.123.123',
34+
'1000.2.3.4',
35+
'999.2.3.4',
36+
'0000000192.168.0.200',
37+
'192.168.0.2000000000'
38+
];
39+
40+
v4.forEach((ip) => {
41+
assert.strictEqual(net.isIPv4(ip), true);
42+
});
43+
44+
v4not.forEach((ip) => {
45+
assert.strictEqual(net.isIPv4(ip), false);
46+
});

test/parallel/test-net-isipv6.js

+244
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
'use strict';
2+
require('../common');
3+
const assert = require('assert');
4+
const net = require('net');
5+
6+
const v6 = [
7+
'::',
8+
'1::',
9+
'::1',
10+
'1::8',
11+
'1::7:8',
12+
'1:2:3:4:5:6:7:8',
13+
'1:2:3:4:5:6::8',
14+
'1:2:3:4:5:6:7::',
15+
'1:2:3:4:5::7:8',
16+
'1:2:3:4:5::8',
17+
'1:2:3::8',
18+
'1::4:5:6:7:8',
19+
'1::6:7:8',
20+
'1::3:4:5:6:7:8',
21+
'1:2:3:4::6:7:8',
22+
'1:2::4:5:6:7:8',
23+
'::2:3:4:5:6:7:8',
24+
'1:2::8',
25+
'2001:0000:1234:0000:0000:C1C0:ABCD:0876',
26+
'3ffe:0b00:0000:0000:0001:0000:0000:000a',
27+
'FF02:0000:0000:0000:0000:0000:0000:0001',
28+
'0000:0000:0000:0000:0000:0000:0000:0001',
29+
'0000:0000:0000:0000:0000:0000:0000:0000',
30+
'::ffff:192.168.1.26',
31+
'2::10',
32+
'ff02::1',
33+
'fe80::',
34+
'2002::',
35+
'2001:db8::',
36+
'2001:0db8:1234::',
37+
'::ffff:0:0',
38+
'::ffff:192.168.1.1',
39+
'1:2:3:4::8',
40+
'1::2:3:4:5:6:7',
41+
'1::2:3:4:5:6',
42+
'1::2:3:4:5',
43+
'1::2:3:4',
44+
'1::2:3',
45+
'::2:3:4:5:6:7',
46+
'::2:3:4:5:6',
47+
'::2:3:4:5',
48+
'::2:3:4',
49+
'::2:3',
50+
'::8',
51+
'1:2:3:4:5:6::',
52+
'1:2:3:4:5::',
53+
'1:2:3:4::',
54+
'1:2:3::',
55+
'1:2::',
56+
'1:2:3:4::7:8',
57+
'1:2:3::7:8',
58+
'1:2::7:8',
59+
'1:2:3:4:5:6:1.2.3.4',
60+
'1:2:3:4:5::1.2.3.4',
61+
'1:2:3:4::1.2.3.4',
62+
'1:2:3::1.2.3.4',
63+
'1:2::1.2.3.4',
64+
'1::1.2.3.4',
65+
'1:2:3:4::5:1.2.3.4',
66+
'1:2:3::5:1.2.3.4',
67+
'1:2::5:1.2.3.4',
68+
'1::5:1.2.3.4',
69+
'1::5:11.22.33.44',
70+
'fe80::217:f2ff:254.7.237.98',
71+
'fe80::217:f2ff:fe07:ed62',
72+
'2001:DB8:0:0:8:800:200C:417A',
73+
'FF01:0:0:0:0:0:0:101',
74+
'0:0:0:0:0:0:0:1',
75+
'0:0:0:0:0:0:0:0',
76+
'2001:DB8::8:800:200C:417A',
77+
'FF01::101',
78+
'0:0:0:0:0:0:13.1.68.3',
79+
'0:0:0:0:0:FFFF:129.144.52.38',
80+
'::13.1.68.3',
81+
'::FFFF:129.144.52.38',
82+
'fe80:0000:0000:0000:0204:61ff:fe9d:f156',
83+
'fe80:0:0:0:204:61ff:fe9d:f156',
84+
'fe80::204:61ff:fe9d:f156',
85+
'fe80:0:0:0:204:61ff:254.157.241.86',
86+
'fe80::204:61ff:254.157.241.86',
87+
'fe80::1',
88+
'2001:0db8:85a3:0000:0000:8a2e:0370:7334',
89+
'2001:db8:85a3:0:0:8a2e:370:7334',
90+
'2001:db8:85a3::8a2e:370:7334',
91+
'2001:0db8:0000:0000:0000:0000:1428:57ab',
92+
'2001:0db8:0000:0000:0000::1428:57ab',
93+
'2001:0db8:0:0:0:0:1428:57ab',
94+
'2001:0db8:0:0::1428:57ab',
95+
'2001:0db8::1428:57ab',
96+
'2001:db8::1428:57ab',
97+
'::ffff:12.34.56.78',
98+
'::ffff:0c22:384e',
99+
'2001:0db8:1234:0000:0000:0000:0000:0000',
100+
'2001:0db8:1234:ffff:ffff:ffff:ffff:ffff',
101+
'2001:db8:a::123',
102+
'::ffff:192.0.2.128',
103+
'::ffff:c000:280',
104+
'a:b:c:d:e:f:f1:f2',
105+
'a:b:c::d:e:f:f1',
106+
'a:b:c::d:e:f',
107+
'a:b:c::d:e',
108+
'a:b:c::d',
109+
'::a',
110+
'::a:b:c',
111+
'::a:b:c:d:e:f:f1',
112+
'a::',
113+
'a:b:c::',
114+
'a:b:c:d:e:f:f1::',
115+
'a:bb:ccc:dddd:000e:00f:0f::',
116+
'0:a:0:a:0:0:0:a',
117+
'0:a:0:0:a:0:0:a',
118+
'2001:db8:1:1:1:1:0:0',
119+
'2001:db8:1:1:1:0:0:0',
120+
'2001:db8:1:1:0:0:0:0',
121+
'2001:db8:1:0:0:0:0:0',
122+
'2001:db8:0:0:0:0:0:0',
123+
'2001:0:0:0:0:0:0:0',
124+
'A:BB:CCC:DDDD:000E:00F:0F::',
125+
'0:0:0:0:0:0:0:a',
126+
'0:0:0:0:a:0:0:0',
127+
'0:0:0:a:0:0:0:0',
128+
'a:0:0:a:0:0:a:a',
129+
'a:0:0:a:0:0:0:a',
130+
'a:0:0:0:a:0:0:a',
131+
'a:0:0:0:a:0:0:0',
132+
'a:0:0:0:0:0:0:0',
133+
'fe80::7:8%eth0',
134+
'fe80::7:8%1'
135+
];
136+
137+
const v6not = [
138+
'',
139+
'1:',
140+
':1',
141+
'11:36:12',
142+
'02001:0000:1234:0000:0000:C1C0:ABCD:0876',
143+
'2001:0000:1234:0000:00001:C1C0:ABCD:0876',
144+
'2001:0000:1234: 0000:0000:C1C0:ABCD:0876',
145+
'2001:1:1:1:1:1:255Z255X255Y255',
146+
'3ffe:0b00:0000:0001:0000:0000:000a',
147+
'FF02:0000:0000:0000:0000:0000:0000:0000:0001',
148+
'3ffe:b00::1::a',
149+
'::1111:2222:3333:4444:5555:6666::',
150+
'1:2:3::4:5::7:8',
151+
'12345::6:7:8',
152+
'1::5:400.2.3.4',
153+
'1::5:260.2.3.4',
154+
'1::5:256.2.3.4',
155+
'1::5:1.256.3.4',
156+
'1::5:1.2.256.4',
157+
'1::5:1.2.3.256',
158+
'1::5:300.2.3.4',
159+
'1::5:1.300.3.4',
160+
'1::5:1.2.300.4',
161+
'1::5:1.2.3.300',
162+
'1::5:900.2.3.4',
163+
'1::5:1.900.3.4',
164+
'1::5:1.2.900.4',
165+
'1::5:1.2.3.900',
166+
'1::5:300.300.300.300',
167+
'1::5:3000.30.30.30',
168+
'1::400.2.3.4',
169+
'1::260.2.3.4',
170+
'1::256.2.3.4',
171+
'1::1.256.3.4',
172+
'1::1.2.256.4',
173+
'1::1.2.3.256',
174+
'1::300.2.3.4',
175+
'1::1.300.3.4',
176+
'1::1.2.300.4',
177+
'1::1.2.3.300',
178+
'1::900.2.3.4',
179+
'1::1.900.3.4',
180+
'1::1.2.900.4',
181+
'1::1.2.3.900',
182+
'1::300.300.300.300',
183+
'1::3000.30.30.30',
184+
'::400.2.3.4',
185+
'::260.2.3.4',
186+
'::256.2.3.4',
187+
'::1.256.3.4',
188+
'::1.2.256.4',
189+
'::1.2.3.256',
190+
'::300.2.3.4',
191+
'::1.300.3.4',
192+
'::1.2.300.4',
193+
'::1.2.3.300',
194+
'::900.2.3.4',
195+
'::1.900.3.4',
196+
'::1.2.900.4',
197+
'::1.2.3.900',
198+
'::300.300.300.300',
199+
'::3000.30.30.30',
200+
'2001:DB8:0:0:8:800:200C:417A:221',
201+
'FF01::101::2',
202+
'1111:2222:3333:4444::5555:',
203+
'1111:2222:3333::5555:',
204+
'1111:2222::5555:',
205+
'1111::5555:',
206+
'::5555:',
207+
':::',
208+
'1111:',
209+
':',
210+
':1111:2222:3333:4444::5555',
211+
':1111:2222:3333::5555',
212+
':1111:2222::5555',
213+
':1111::5555',
214+
':::5555',
215+
'1.2.3.4:1111:2222:3333:4444::5555',
216+
'1.2.3.4:1111:2222:3333::5555',
217+
'1.2.3.4:1111:2222::5555',
218+
'1.2.3.4:1111::5555',
219+
'1.2.3.4::5555',
220+
'1.2.3.4::',
221+
'fe80:0000:0000:0000:0204:61ff:254.157.241.086',
222+
'123',
223+
'ldkfj',
224+
'2001::FFD3::57ab',
225+
'2001:db8:85a3::8a2e:37023:7334',
226+
'2001:db8:85a3::8a2e:370k:7334',
227+
'1:2:3:4:5:6:7:8:9',
228+
'1::2::3',
229+
'1:::3:4:5',
230+
'1:2:3::4:5:6:7:8:9',
231+
'::ffff:2.3.4',
232+
'::ffff:257.1.2.3',
233+
'::ffff:12345678901234567890.1.26',
234+
'2001:0000:1234:0000:0000:C1C0:ABCD:0876 0',
235+
'02001:0000:1234:0000:0000:C1C0:ABCD:0876'
236+
];
237+
238+
v6.forEach((ip) => {
239+
assert.strictEqual(net.isIPv6(ip), true);
240+
});
241+
242+
v6not.forEach((ip) => {
243+
assert.strictEqual(net.isIPv6(ip), false);
244+
});

0 commit comments

Comments
 (0)