ipip-ipdb
Version:
IPIP.net 官方支持的 IP 数据库 ipdb 格式查询代码
133 lines (108 loc) • 3.51 kB
JavaScript
var fs = require('fs');
var net = require('net');
var ip = require('./ip');
module.exports = class Reader {
constructor (name) {
var data = fs.readFileSync(name);
var metaLength = data.readInt32BE();
var buf = Buffer.alloc(metaLength);
data.copy(buf, 0, 4, 4+metaLength)
this.meta = JSON.parse(buf.toString());
this.body = Buffer.alloc(this.meta.total_size);
data.copy(this.body, 0, 4 + metaLength);
this.v4offset = 0;
}
_readNode(node, idx) {
var off = idx * 4 + node * 8;
return this.body.readUInt32BE(off, true);
}
findNode(addr) {
var bit_count = 0;
var ipv = ip.parse(addr)
if (ipv.length == 16) {
bit_count = 128
} else {
bit_count = 32
}
var idx = 0
var node = 0
if (bit_count == 32) {
if (this.v4offset == 0) {
var i = 0
while (i < 96){
if (i >= 80) {
node = this._readNode(node, 1)
} else{
node = this._readNode(node, 0)
}
i += 1
}
this.v4offset = node;
} else {
node = this.v4offset;
}
}
while (idx < bit_count) {
if (node > this.meta.node_count) {
break;
}
node = this._readNode(node, (1 & (ipv[idx >> 3] >> 7 - (idx % 8))))
idx += 1
}
if (node > this.meta.node_count) {
return node;
} else {
return -1;
}
}
bytes2long(a, b, c, d) {
return (a << 24) | (b << 16) | (c << 8) | d;
}
resolveNode(node) {
var resolved = node - this.meta.node_count + this.meta.node_count * 8;
var size = this.bytes2long(0, 0, this.body[resolved], this.body[resolved + 1])
if ((resolved+2+size) > this.body.length) {
throw Error("database is error");
}
var buf = Buffer.alloc(size);
this.body.copy(buf, 0, resolved+2, resolved + 2+size);
return buf
}
isIPv4() {
return (this.meta.ip_version & 0x01) == 0x01;
}
isIPv6() {
return (this.meta.ip_version & 0x02) == 0x02;
}
fields() {
return this.meta.fields;
}
languages() {
var ls = [];
for (var key in this.meta.languages) {
ls.push(key);
}
return ls;
}
buildTime() {
return this.meta.build;
}
find(addr, language) {
if (language === undefined) {
throw Error("param language is undefined");
}
if (net.isIPv4(addr) && !this.isIPv4()) {
throw Error("database not support ipv4");
} else if (net.isIPv6(addr) && !this.isIPv6()) {
throw Error("database not support ipv6");
}
var node = this.findNode(addr);
if (node <= 0) {
return [];
}
var buf = this.resolveNode(node);
var tmp = buf.toString().split("\t");
var off = this.meta.languages[language];
return tmp.slice(off, off + this.meta.fields.length);
}
}