merge the header/version to util.js
This commit is contained in:
parent
bb19c7110a
commit
6c463282d0
|
|
@ -1,82 +0,0 @@
|
||||||
// Copyright 2022 The Ip2Region Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a Apache2.0-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// xdb header class
|
|
||||||
// @Author Lion <chenxin619315@gmail.com>
|
|
||||||
|
|
||||||
const XdbStructure20 = 2;
|
|
||||||
const XdbStructure30 = 3;
|
|
||||||
const xdbIPv4Id = 4;
|
|
||||||
const xdbIPv6Id = 6;
|
|
||||||
|
|
||||||
const HeaderInfoLength = 256;
|
|
||||||
const VectorIndexRows = 256;
|
|
||||||
const VectorIndexCols = 256;
|
|
||||||
const VectorIndexSize = 8;
|
|
||||||
|
|
||||||
class Header {
|
|
||||||
constructor(buff) {
|
|
||||||
this.version = buff.readUInt16LE(0);
|
|
||||||
this.indexPolicy = buff.readUInt16LE(2);
|
|
||||||
this.createdAt = buff.readUInt32LE(4);
|
|
||||||
this.startIndexPtr = buff.readUInt32LE(8);
|
|
||||||
this.endIndexPtr = buff.readUInt32LE(12);
|
|
||||||
|
|
||||||
// since IPv6 supporting
|
|
||||||
this.ipVersion = buff.readUInt16LE(16);
|
|
||||||
this.runtimePtrBytes = buff.readUInt16LE(18);
|
|
||||||
|
|
||||||
// keep the raw data
|
|
||||||
this.buff = buff;
|
|
||||||
}
|
|
||||||
|
|
||||||
version() {
|
|
||||||
return this.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
indexPolicy() {
|
|
||||||
return this.indexPolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
createdAt() {
|
|
||||||
return this.createdAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
startIndexPtr() {
|
|
||||||
return this.startIndexPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
endIndexPtr() {
|
|
||||||
return this.endIndexPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ipVersion() {
|
|
||||||
return this.ipVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
runtimePtrBytes() {
|
|
||||||
return this.runtimePtrBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
buff() {
|
|
||||||
return this.buff;
|
|
||||||
}
|
|
||||||
|
|
||||||
toString() {
|
|
||||||
return `{
|
|
||||||
"version":${this.version},
|
|
||||||
"index_policy":${this.indexPolicy},
|
|
||||||
"start_index_ptr": ${this.startIndexPtr},
|
|
||||||
"end_index_ptr": ${this.endIndexPtr},
|
|
||||||
"ipVersion": ${this.ipVersion},
|
|
||||||
"runtime_ptr_bytes": ${this.runtimePtrBytes}
|
|
||||||
}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
XdbStructure20, XdbStructure30, xdbIPv4Id, xdbIPv6Id,
|
|
||||||
HeaderInfoLength, VectorIndexRows, VectorIndexCols, VectorIndexSize,
|
|
||||||
Header
|
|
||||||
}
|
|
||||||
|
|
@ -5,17 +5,17 @@
|
||||||
// version test script
|
// version test script
|
||||||
// @Author Lion <chenxin619315@gmail.com>
|
// @Author Lion <chenxin619315@gmail.com>
|
||||||
|
|
||||||
const version = require('../version');
|
const util = require('../util');
|
||||||
|
|
||||||
test('const print', () => {
|
test('const print', () => {
|
||||||
console.log("IPv4: ", version.IPv4.toString());
|
console.log("IPv4: ", util.IPv4.toString());
|
||||||
console.log("IPv6: ", version.IPv6.toString());
|
console.log("IPv6: ", util.IPv6.toString());
|
||||||
});
|
});
|
||||||
|
|
||||||
test("test version from name", () => {
|
test("test version from name", () => {
|
||||||
let vs = ["v4", "ipv4", "v4x", "v6", "ipv6", "v6x"];
|
let vs = ["v4", "ipv4", "v4x", "v6", "ipv6", "v6x"];
|
||||||
vs.forEach(ele => {
|
vs.forEach(ele => {
|
||||||
let v = version.versionFromName(ele);
|
let v = util.versionFromName(ele);
|
||||||
console.log(`versionFrom(${ele})`, v == null ? null : v.toString());
|
console.log(`versionFrom(${ele})`, v == null ? null : v.toString());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -5,10 +5,165 @@
|
||||||
// util functions
|
// util functions
|
||||||
// @Author Lion <chenxin619315@gmail.com>
|
// @Author Lion <chenxin619315@gmail.com>
|
||||||
|
|
||||||
const header = require('./header');
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
// --
|
// --- header
|
||||||
|
const XdbStructure20 = 2;
|
||||||
|
const XdbStructure30 = 3;
|
||||||
|
const XdbIPv4Id = 4;
|
||||||
|
const XdbIPv6Id = 6;
|
||||||
|
|
||||||
|
const HeaderInfoLength = 256;
|
||||||
|
const VectorIndexRows = 256;
|
||||||
|
const VectorIndexCols = 256;
|
||||||
|
const VectorIndexSize = 8;
|
||||||
|
|
||||||
|
class Header {
|
||||||
|
constructor(buff) {
|
||||||
|
this.version = buff.readUInt16LE(0);
|
||||||
|
this.indexPolicy = buff.readUInt16LE(2);
|
||||||
|
this.createdAt = buff.readUInt32LE(4);
|
||||||
|
this.startIndexPtr = buff.readUInt32LE(8);
|
||||||
|
this.endIndexPtr = buff.readUInt32LE(12);
|
||||||
|
|
||||||
|
// since IPv6 supporting
|
||||||
|
this.ipVersion = buff.readUInt16LE(16);
|
||||||
|
this.runtimePtrBytes = buff.readUInt16LE(18);
|
||||||
|
|
||||||
|
// keep the raw data
|
||||||
|
this.buff = buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
version() {
|
||||||
|
return this.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
indexPolicy() {
|
||||||
|
return this.indexPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
createdAt() {
|
||||||
|
return this.createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
startIndexPtr() {
|
||||||
|
return this.startIndexPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
endIndexPtr() {
|
||||||
|
return this.endIndexPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipVersion() {
|
||||||
|
return this.ipVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
runtimePtrBytes() {
|
||||||
|
return this.runtimePtrBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
buff() {
|
||||||
|
return this.buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return `{
|
||||||
|
"version":${this.version},
|
||||||
|
"index_policy":${this.indexPolicy},
|
||||||
|
"start_index_ptr": ${this.startIndexPtr},
|
||||||
|
"end_index_ptr": ${this.endIndexPtr},
|
||||||
|
"ipVersion": ${this.ipVersion},
|
||||||
|
"runtime_ptr_bytes": ${this.runtimePtrBytes}
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
// ---
|
||||||
|
// version
|
||||||
|
class Version {
|
||||||
|
constructor(id, name, bytes, indexSize, ip_compare_func) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.bytes = bytes;
|
||||||
|
this.indexSize = indexSize;
|
||||||
|
this.ip_compare_func = ip_compare_func;
|
||||||
|
}
|
||||||
|
|
||||||
|
id() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
name() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes() {
|
||||||
|
return this.bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
indexSize() {
|
||||||
|
return this.indexSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
compareFunc() {
|
||||||
|
return this.ip_compare_func;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipCompare(ip1, ip2) {
|
||||||
|
return this.ip_compare_func(ip1, ip2);
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return `{"id": ${this.id}, "name": "${this.name}", "bytes":${this.bytes}, "index_size": ${this.indexSize}}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 14 = 4 + 4 + 2 + 4
|
||||||
|
const IPv4 = new Version(XdbIPv4Id, "IPv4", 4, 14, function(ip1, ip2){
|
||||||
|
});
|
||||||
|
|
||||||
|
// 38 = 16 + 16 + 2 + 4
|
||||||
|
const IPv6 = new Version(XdbIPv6Id, "IPv6", 6, 38, function(ip1, ip2){
|
||||||
|
});
|
||||||
|
|
||||||
|
function versionFromName(name) {
|
||||||
|
let n = name.toUpperCase();
|
||||||
|
if (n == "V4" || n == "IPV4") {
|
||||||
|
return IPv4;
|
||||||
|
} else if (n == "V6" || n == "IPV6") {
|
||||||
|
return IPv6;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function versionFromHeader(h) {
|
||||||
|
let v = h.version();
|
||||||
|
|
||||||
|
// old structure with ONLY IPv4 supporting
|
||||||
|
if (v == XdbStructure20) {
|
||||||
|
return IPv4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// structure 3.0 with IPv6 supporting
|
||||||
|
if (v != XdbStructure30) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ipVer = h.ipVersion();
|
||||||
|
if (ipVer == XdbIPv4Id) {
|
||||||
|
return IPv4;
|
||||||
|
} else if (ipVer == XdbIPv6Id) {
|
||||||
|
return IPv6;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ---
|
||||||
|
|
||||||
|
// ---
|
||||||
// parse the specified string ip and return its bytes
|
// parse the specified string ip and return its bytes
|
||||||
|
|
||||||
// parse ipv4 address
|
// parse ipv4 address
|
||||||
|
|
@ -113,7 +268,6 @@ function parseIP(ipString) {
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
// bytes ip to humen-readable string ip
|
// bytes ip to humen-readable string ip
|
||||||
|
|
||||||
|
|
@ -212,12 +366,12 @@ function ipCompare(ip1, ip2) {
|
||||||
|
|
||||||
// load header from xdb file
|
// load header from xdb file
|
||||||
function loadHeader(fd) {
|
function loadHeader(fd) {
|
||||||
const buffer = Buffer.alloc(header.HeaderInfoLength);
|
const buffer = Buffer.alloc(HeaderInfoLength);
|
||||||
const rBytes = fs.readSync(fd, buffer, 0, header.HeaderInfoLength, 0);
|
const rBytes = fs.readSync(fd, buffer, 0, HeaderInfoLength, 0);
|
||||||
if (rBytes != header.HeaderInfoLength) {
|
if (rBytes != HeaderInfoLength) {
|
||||||
throw new Error(`incomplete read (${rBytes} read, ${header.HeaderInfoLength} expected)`);
|
throw new Error(`incomplete read (${rBytes} read, ${header.HeaderInfoLength} expected)`);
|
||||||
}
|
}
|
||||||
return new header.Header(buffer);
|
return new Header(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadHeaderFromFile(dbPath) {
|
function loadHeaderFromFile(dbPath) {
|
||||||
|
|
@ -228,9 +382,9 @@ function loadHeaderFromFile(dbPath) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadVectorIndex(fd) {
|
function loadVectorIndex(fd) {
|
||||||
const vBytes = header.VectorIndexCols * header.VectorIndexRows * header.VectorIndexSize;
|
const vBytes = VectorIndexCols * VectorIndexRows * VectorIndexSize;
|
||||||
const buffer = Buffer.alloc(vBytes);
|
const buffer = Buffer.alloc(vBytes);
|
||||||
const rBytes = fs.readSync(fd, buffer, 0, vBytes, header.HeaderInfoLength);
|
const rBytes = fs.readSync(fd, buffer, 0, vBytes, HeaderInfoLength);
|
||||||
if (rBytes != vBytes) {
|
if (rBytes != vBytes) {
|
||||||
throw new Error(`incomplete read (${rBytes} read, ${vBytes} expected)`);
|
throw new Error(`incomplete read (${rBytes} read, ${vBytes} expected)`);
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +415,18 @@ function loadContentFromFile(dbPath) {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
// header
|
||||||
|
XdbStructure20, XdbStructure30, XdbIPv4Id, XdbIPv6Id,
|
||||||
|
HeaderInfoLength, VectorIndexRows, VectorIndexCols, VectorIndexSize,
|
||||||
|
Header,
|
||||||
|
|
||||||
|
// version
|
||||||
|
Version, IPv4, IPv6,
|
||||||
|
versionFromName, versionFromHeader,
|
||||||
|
|
||||||
|
// utils
|
||||||
parseIP, ipToString, ipBytesString, ipCompare,
|
parseIP, ipToString, ipBytesString, ipCompare,
|
||||||
loadHeader, loadHeaderFromFile,
|
loadHeader, loadHeaderFromFile,
|
||||||
loadVectorIndex, loadVectorIndexFromFile,
|
loadVectorIndex, loadVectorIndexFromFile,
|
||||||
|
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
// Copyright 2022 The Ip2Region Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a Apache2.0-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// version module
|
|
||||||
// @Author Lion <chenxin619315@gmail.com>
|
|
||||||
|
|
||||||
const header = require('./header');
|
|
||||||
|
|
||||||
class Version {
|
|
||||||
constructor(id, name, bytes, indexSize, ip_compare_func) {
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
this.bytes = bytes;
|
|
||||||
this.indexSize = indexSize;
|
|
||||||
this.ip_compare_func = ip_compare_func;
|
|
||||||
}
|
|
||||||
|
|
||||||
id() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
name() {
|
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes() {
|
|
||||||
return this.bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
indexSize() {
|
|
||||||
return this.indexSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
compareFunc() {
|
|
||||||
return this.ip_compare_func;
|
|
||||||
}
|
|
||||||
|
|
||||||
ipCompare(ip1, ip2) {
|
|
||||||
return this.ip_compare_func(ip1, ip2);
|
|
||||||
}
|
|
||||||
|
|
||||||
toString() {
|
|
||||||
return `{"id": ${this.id}, "name": "${this.name}", "bytes":${this.bytes}, "index_size": ${this.indexSize}}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 14 = 4 + 4 + 2 + 4
|
|
||||||
const IPv4 = new Version(header.xdbIPv4Id, "IPv4", 4, 14, function(ip1, ip2){
|
|
||||||
});
|
|
||||||
|
|
||||||
// 38 = 16 + 16 + 2 + 4
|
|
||||||
const IPv6 = new Version(header.xdbIPv6Id, "IPv6", 6, 38, function(ip1, ip2){
|
|
||||||
});
|
|
||||||
|
|
||||||
function versionFromName(name) {
|
|
||||||
let n = name.toUpperCase();
|
|
||||||
if (n == "V4" || n == "IPV4") {
|
|
||||||
return IPv4;
|
|
||||||
} else if (n == "V6" || n == "IPV6") {
|
|
||||||
return IPv6;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function versionFromHeader(h) {
|
|
||||||
let v = h.version();
|
|
||||||
|
|
||||||
// old structure with ONLY IPv4 supporting
|
|
||||||
if (v == header.XdbStructure20) {
|
|
||||||
return IPv4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// structure 3.0 with IPv6 supporting
|
|
||||||
if (v != header.XdbStructure30) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ipVer = h.ipVersion();
|
|
||||||
if (ipVer == header.xdbIPv4Id) {
|
|
||||||
return IPv4;
|
|
||||||
} else if (ipVer == header.xdbIPv6Id) {
|
|
||||||
return IPv6;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
Version, IPv4, IPv6,
|
|
||||||
versionFromName, versionFromHeader
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue