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: https://github.com/nodejs/node/pull/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>
This commit is contained in:
parent
1598ec73df
commit
742ae6141c
27
lib/dns.js
27
lib/dns.js
@ -24,7 +24,7 @@
|
||||
const util = require('util');
|
||||
|
||||
const cares = process.binding('cares_wrap');
|
||||
const { isLegalPort } = require('internal/net');
|
||||
const { isIP, isIPv4, isLegalPort } = require('internal/net');
|
||||
const { customPromisifyArgs } = require('internal/util');
|
||||
const errors = require('internal/errors');
|
||||
const {
|
||||
@ -38,7 +38,6 @@ const {
|
||||
GetNameInfoReqWrap,
|
||||
QueryReqWrap,
|
||||
ChannelWrap,
|
||||
isIP
|
||||
} = cares;
|
||||
|
||||
function errnoException(err, syscall, hostname) {
|
||||
@ -66,30 +65,6 @@ function errnoException(err, syscall, hostname) {
|
||||
}
|
||||
|
||||
const IANA_DNS_PORT = 53;
|
||||
const digits = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48-63
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64-79
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-95
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 96-111
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 112-127
|
||||
];
|
||||
function isIPv4(str) {
|
||||
if (!digits[str.charCodeAt(0)]) return false;
|
||||
if (str.length === 1) return false;
|
||||
if (str.charCodeAt(1) === 46/*'.'*/)
|
||||
return true;
|
||||
else if (!digits[str.charCodeAt(1)])
|
||||
return false;
|
||||
if (str.length === 2) return false;
|
||||
if (str.charCodeAt(2) === 46/*'.'*/)
|
||||
return true;
|
||||
else if (!digits[str.charCodeAt(2)])
|
||||
return false;
|
||||
return (str.length > 3 && str.charCodeAt(3) === 46/*'.'*/);
|
||||
}
|
||||
|
||||
|
||||
function onlookup(err, addresses) {
|
||||
|
@ -1,8 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
const Buffer = require('buffer').Buffer;
|
||||
const { isIPv6 } = process.binding('cares_wrap');
|
||||
const { writeBuffer } = process.binding('fs');
|
||||
|
||||
const octet = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';
|
||||
const re = new RegExp(`^${octet}[.]${octet}[.]${octet}[.]${octet}$`);
|
||||
|
||||
function isIPv4(s) {
|
||||
return re.test(s);
|
||||
}
|
||||
|
||||
function isIP(s) {
|
||||
if (isIPv4(s)) return 4;
|
||||
if (isIPv6(s)) return 6;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check that the port number is not NaN when coerced to a number,
|
||||
// is an integer and that it falls within the legal range of port numbers.
|
||||
function isLegalPort(port) {
|
||||
@ -33,6 +47,9 @@ function makeSyncWrite(fd) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isIP,
|
||||
isIPv4,
|
||||
isIPv6,
|
||||
isLegalPort,
|
||||
makeSyncWrite,
|
||||
normalizedArgsSymbol: Symbol('normalizedArgs')
|
||||
|
14
lib/net.js
14
lib/net.js
@ -26,12 +26,14 @@ const stream = require('stream');
|
||||
const util = require('util');
|
||||
const internalUtil = require('internal/util');
|
||||
const {
|
||||
isIP,
|
||||
isIPv4,
|
||||
isIPv6,
|
||||
isLegalPort,
|
||||
normalizedArgsSymbol,
|
||||
makeSyncWrite
|
||||
} = require('internal/net');
|
||||
const assert = require('assert');
|
||||
const cares = process.binding('cares_wrap');
|
||||
const {
|
||||
UV_EADDRINUSE,
|
||||
UV_EINVAL,
|
||||
@ -1066,7 +1068,7 @@ function lookupAndConnect(self, options) {
|
||||
var localAddress = options.localAddress;
|
||||
var localPort = options.localPort;
|
||||
|
||||
if (localAddress && !cares.isIP(localAddress)) {
|
||||
if (localAddress && !isIP(localAddress)) {
|
||||
throw new errors.TypeError('ERR_INVALID_IP_ADDRESS', localAddress);
|
||||
}
|
||||
|
||||
@ -1091,7 +1093,7 @@ function lookupAndConnect(self, options) {
|
||||
port |= 0;
|
||||
|
||||
// If host is an IP, skip performing a lookup
|
||||
var addressType = cares.isIP(host);
|
||||
var addressType = isIP(host);
|
||||
if (addressType) {
|
||||
nextTick(self[async_id_symbol], function() {
|
||||
if (self.connecting)
|
||||
@ -1775,9 +1777,9 @@ module.exports = {
|
||||
connect,
|
||||
createConnection: connect,
|
||||
createServer,
|
||||
isIP: cares.isIP,
|
||||
isIPv4: cares.isIPv4,
|
||||
isIPv6: cares.isIPv6,
|
||||
isIP: isIP,
|
||||
isIPv4: isIPv4,
|
||||
isIPv6: isIPv6,
|
||||
Server,
|
||||
Socket,
|
||||
Stream: Socket, // Legacy naming
|
||||
|
@ -1886,16 +1886,6 @@ int ParseIP(const char* ip, ParseIPResult* result = nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void IsIP(const FunctionCallbackInfo<Value>& args) {
|
||||
node::Utf8Value ip(args.GetIsolate(), args[0]);
|
||||
args.GetReturnValue().Set(ParseIP(*ip));
|
||||
}
|
||||
|
||||
void IsIPv4(const FunctionCallbackInfo<Value>& args) {
|
||||
node::Utf8Value ip(args.GetIsolate(), args[0]);
|
||||
args.GetReturnValue().Set(4 == ParseIP(*ip));
|
||||
}
|
||||
|
||||
void IsIPv6(const FunctionCallbackInfo<Value>& args) {
|
||||
node::Utf8Value ip(args.GetIsolate(), args[0]);
|
||||
args.GetReturnValue().Set(6 == ParseIP(*ip));
|
||||
@ -2138,8 +2128,6 @@ void Initialize(Local<Object> target,
|
||||
|
||||
env->SetMethod(target, "getaddrinfo", GetAddrInfo);
|
||||
env->SetMethod(target, "getnameinfo", GetNameInfo);
|
||||
env->SetMethod(target, "isIP", IsIP);
|
||||
env->SetMethod(target, "isIPv4", IsIPv4);
|
||||
env->SetMethod(target, "isIPv6", IsIPv6);
|
||||
env->SetMethod(target, "canonicalizeIP", CanonicalizeIP);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user