From 01bd749d4adce1df87bb46f1880a045770def631 Mon Sep 17 00:00:00 2001 From: lion Date: Sat, 11 Oct 2025 19:34:24 +0800 Subject: [PATCH] ipv6 parse and to string alpha version --- binding/javascript/tests/ip.test.js | 5 +- binding/javascript/util.js | 76 +++++++++++++++++++++++------ 2 files changed, 63 insertions(+), 18 deletions(-) diff --git a/binding/javascript/tests/ip.test.js b/binding/javascript/tests/ip.test.js index 6aa4496..5552716 100644 --- a/binding/javascript/tests/ip.test.js +++ b/binding/javascript/tests/ip.test.js @@ -23,7 +23,8 @@ test('parse ip address', () => { return; } - let toStr = ipBytes == null ? '0' : util.ipToString(ipBytes); - console.log(`parseIP(${ipString}): {Bytes: ${ipBytes.length}, String: ${toStr}`); + let to_Str = ipBytes == null ? '0' : util.ipToString(ipBytes); + let toByte = ipBytes == null ? '0' : util.ipBytesString(ipBytes); + console.log(`parseIP(${ipString}): {Bytes: ${toByte}, String: ${to_Str}`); }); }); \ No newline at end of file diff --git a/binding/javascript/util.js b/binding/javascript/util.js index 0d15bf2..7c927dc 100644 --- a/binding/javascript/util.js +++ b/binding/javascript/util.js @@ -5,7 +5,6 @@ // util functions // @Author Lion -const { exec } = require('child_process'); const header = require('./header'); const fs = require('fs'); @@ -44,21 +43,48 @@ function _parse_ipv6_addr(v6String) { throw new Error('invalid ipv6 address'); } - var s, v, dc_num = 0; + let dc_num = 0, offset = 0; const ipBytes = Buffer.alloc(16); for (var i = 0; i < ps.length; i++) { - s = ps[i].trim(); + let s = ps[i].trim(); if (s.length == 0) { // Double colon - dc_num++; + // ONLY one double colon allow + if (dc_num > 0) { + throw new Error('invalid ipv6 address: multi double colon detected'); + } + + let start = i, mIdx = ps.length - 1; + // clear all the consecutive spaces + for (i++;;) { + s = ps[i].trim(); + if (s.length > 0) { + i--; + break; + } + + if (i >= mIdx) { + break; + } + + i++; + } + + dc_num = 1; + // padding = 8 - start - left + let padding = 8 - start - (mIdx - i); + // console.log(`i=${i}, padding=${padding}`); + offset += 2 * padding; + continue; } - v = parseInt(s, 16); - if (v < 0 || v > 0xFFFE) { + let v = parseInt(s, 16); + if (v < 0 || v > 0xFFFF) { throw new Error(`invalid ipv6 part '${ps[i]}' should >= 0 and <= 65534`); } - // @TODO: keep coding - ipBytes.writeUint16BE(v, i); + // console.log(`${i}: v=${v}, offset=${offset}`); + ipBytes.writeUint16BE(v, offset); + offset += 2; } return ipBytes; @@ -86,23 +112,27 @@ function parseIP(ipString) { // bytes ip to humen-readable string ip // ipv4 bytes to string -// function _ipv4_to_string(v4Bytes) { -// return v4Bytes.join('.'); -// } +function _ipv4_to_string(v4Bytes) { + return v4Bytes.join('.'); +} // ipv6 bytes to string function _ipv6_to_string(v6Bytes) { - return null; + // @TODO: double colon compress + let ps = []; + for (var i = 0; i < v6Bytes.length; i += 2) { + ps.push(v6Bytes.readUint16BE(i).toString(16)); + } + return ps.join(':'); } function ipToString(ipBytes) { if (!Buffer.isBuffer(ipBytes)) { - throw new Error('invalid bytes ip, not Buffer'); + throw new Error('invalid bytes ip, not a Buffer'); } if (ipBytes.length == 4) { - // return _ipv4_to_string(ipBytes); - return ipBytes.join('.'); + return _ipv4_to_string(ipBytes); } else if (ipBytes.length == 16) { return _ipv6_to_string(ipBytes); } else { @@ -110,6 +140,20 @@ function ipToString(ipBytes) { } } +// print ip bytes +function ipBytesString(ipBytes) { + if (!Buffer.isBuffer(ipBytes)) { + throw new Error('invalid bytes ip, not a Buffer'); + } + + let ps = []; + for (var i = 0; i < ipBytes.length; i++) { + ps.push(ipBytes[i] & 0xFF); + } + + return ps.join('.'); +} + // compare two byte ips // returns: -1 if ip1 < ip2, 1 if ip1 > ip2 or 0 function ipCompare(ip1, ip2) { @@ -168,7 +212,7 @@ function loadContentFromFile(dbPath) { } module.exports = { - parseIP, ipToString, ipCompare, + parseIP, ipToString, ipBytesString, ipCompare, loadHeader, loadHeaderFromFile, loadVectorIndex, loadVectorIndexFromFile, loadContent, loadContentFromFile