Skip to content

Commit 742ae61

Browse files
committed
lib,src: port isIPv4() to js
Removes a few lines of C++ code while making `isIPv4()` about 3x faster. `isIPv6()` and `isIP()` for the IPv6 case stay about the same. I removed the homegrown `isIPv4()` in lib/dns.js that utilized a lookup table. It is in fact a little faster than the new `isIPv4()` function but: 1. The difference is only measurable at around 10M iterations, and 2. The function is a "probably IPv4" heuristic, not a proper validator. PR-URL: #18398 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jan Krems <jan.krems@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Richard Lau <riclau@uk.ibm.com>
1 parent 1598ec7 commit 742ae61

File tree

4 files changed

+26
-44
lines changed

4 files changed

+26
-44
lines changed

lib/dns.js

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
const util = require('util');
2525

2626
const cares = process.binding('cares_wrap');
27-
const { isLegalPort } = require('internal/net');
27+
const { isIP, isIPv4, isLegalPort } = require('internal/net');
2828
const { customPromisifyArgs } = require('internal/util');
2929
const errors = require('internal/errors');
3030
const {
@@ -38,7 +38,6 @@ const {
3838
GetNameInfoReqWrap,
3939
QueryReqWrap,
4040
ChannelWrap,
41-
isIP
4241
} = cares;
4342

4443
function errnoException(err, syscall, hostname) {
@@ -66,30 +65,6 @@ function errnoException(err, syscall, hostname) {
6665
}
6766

6867
const IANA_DNS_PORT = 53;
69-
const digits = [
70-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15
71-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31
72-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47
73-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48-63
74-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64-79
75-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-95
76-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 96-111
77-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 112-127
78-
];
79-
function isIPv4(str) {
80-
if (!digits[str.charCodeAt(0)]) return false;
81-
if (str.length === 1) return false;
82-
if (str.charCodeAt(1) === 46/*'.'*/)
83-
return true;
84-
else if (!digits[str.charCodeAt(1)])
85-
return false;
86-
if (str.length === 2) return false;
87-
if (str.charCodeAt(2) === 46/*'.'*/)
88-
return true;
89-
else if (!digits[str.charCodeAt(2)])
90-
return false;
91-
return (str.length > 3 && str.charCodeAt(3) === 46/*'.'*/);
92-
}
9368

9469

9570
function onlookup(err, addresses) {

lib/internal/net.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
11
'use strict';
22

33
const Buffer = require('buffer').Buffer;
4+
const { isIPv6 } = process.binding('cares_wrap');
45
const { writeBuffer } = process.binding('fs');
56

7+
const octet = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';
8+
const re = new RegExp(`^${octet}[.]${octet}[.]${octet}[.]${octet}$`);
9+
10+
function isIPv4(s) {
11+
return re.test(s);
12+
}
13+
14+
function isIP(s) {
15+
if (isIPv4(s)) return 4;
16+
if (isIPv6(s)) return 6;
17+
return 0;
18+
}
19+
620
// Check that the port number is not NaN when coerced to a number,
721
// is an integer and that it falls within the legal range of port numbers.
822
function isLegalPort(port) {
@@ -33,6 +47,9 @@ function makeSyncWrite(fd) {
3347
}
3448

3549
module.exports = {
50+
isIP,
51+
isIPv4,
52+
isIPv6,
3653
isLegalPort,
3754
makeSyncWrite,
3855
normalizedArgsSymbol: Symbol('normalizedArgs')

lib/net.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,14 @@ const stream = require('stream');
2626
const util = require('util');
2727
const internalUtil = require('internal/util');
2828
const {
29+
isIP,
30+
isIPv4,
31+
isIPv6,
2932
isLegalPort,
3033
normalizedArgsSymbol,
3134
makeSyncWrite
3235
} = require('internal/net');
3336
const assert = require('assert');
34-
const cares = process.binding('cares_wrap');
3537
const {
3638
UV_EADDRINUSE,
3739
UV_EINVAL,
@@ -1066,7 +1068,7 @@ function lookupAndConnect(self, options) {
10661068
var localAddress = options.localAddress;
10671069
var localPort = options.localPort;
10681070

1069-
if (localAddress && !cares.isIP(localAddress)) {
1071+
if (localAddress && !isIP(localAddress)) {
10701072
throw new errors.TypeError('ERR_INVALID_IP_ADDRESS', localAddress);
10711073
}
10721074

@@ -1091,7 +1093,7 @@ function lookupAndConnect(self, options) {
10911093
port |= 0;
10921094

10931095
// If host is an IP, skip performing a lookup
1094-
var addressType = cares.isIP(host);
1096+
var addressType = isIP(host);
10951097
if (addressType) {
10961098
nextTick(self[async_id_symbol], function() {
10971099
if (self.connecting)
@@ -1775,9 +1777,9 @@ module.exports = {
17751777
connect,
17761778
createConnection: connect,
17771779
createServer,
1778-
isIP: cares.isIP,
1779-
isIPv4: cares.isIPv4,
1780-
isIPv6: cares.isIPv6,
1780+
isIP: isIP,
1781+
isIPv4: isIPv4,
1782+
isIPv6: isIPv6,
17811783
Server,
17821784
Socket,
17831785
Stream: Socket, // Legacy naming

src/cares_wrap.cc

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1886,16 +1886,6 @@ int ParseIP(const char* ip, ParseIPResult* result = nullptr) {
18861886
return 0;
18871887
}
18881888

1889-
void IsIP(const FunctionCallbackInfo<Value>& args) {
1890-
node::Utf8Value ip(args.GetIsolate(), args[0]);
1891-
args.GetReturnValue().Set(ParseIP(*ip));
1892-
}
1893-
1894-
void IsIPv4(const FunctionCallbackInfo<Value>& args) {
1895-
node::Utf8Value ip(args.GetIsolate(), args[0]);
1896-
args.GetReturnValue().Set(4 == ParseIP(*ip));
1897-
}
1898-
18991889
void IsIPv6(const FunctionCallbackInfo<Value>& args) {
19001890
node::Utf8Value ip(args.GetIsolate(), args[0]);
19011891
args.GetReturnValue().Set(6 == ParseIP(*ip));
@@ -2138,8 +2128,6 @@ void Initialize(Local<Object> target,
21382128

21392129
env->SetMethod(target, "getaddrinfo", GetAddrInfo);
21402130
env->SetMethod(target, "getnameinfo", GetNameInfo);
2141-
env->SetMethod(target, "isIP", IsIP);
2142-
env->SetMethod(target, "isIPv4", IsIPv4);
21432131
env->SetMethod(target, "isIPv6", IsIPv6);
21442132
env->SetMethod(target, "canonicalizeIP", CanonicalizeIP);
21452133

0 commit comments

Comments
 (0)