const knex = require("knex"); const { IPALLOCATION_DB } = require("../config"); const crypto = require("node:crypto"); const moment = require("moment"); let IPDB = knex({ client: "sqlite3", connection: exports.IPALLOCATION_STORE_TYPE == "memory" ? ":memory:" : IPALLOCATION_DB, useNullAsDefault: true }); let flovitNumber = [ [ 8, 12, 24, 48, 52, 56 ], [ 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58, 61, 64, 67, 70, 73, 76, 79, 82 ] ]; async function read(filter) { return await IPDB.table("iptable").where(filter).first(); } async function has(filter) { return ( await IPDB.table("iptable").where(filter).count('* as key').first() ).key != 0; } async function flushAll() { await IPDB.table("iptable").delete(); } async function write(value,filter) { await IPDB.table("iptable").where(filter).update(value); } async function create(value) { await IPDB.table("iptable").insert(value); } async function remove(...filterArgs) { await IPDB.table("iptable").where(...filterArgs).delete(); } async function migrate() { if(!await IPDB.schema.hasTable("iptable")) { await IPDB.schema.createTable("iptable",function(table){ table.bigInteger("ipaddress").unsigned().primary(); table.text("owner").unique(); table.string("type", 50).defaultTo("client"); table.dateTime("created").defaultTo(IPDB.fn.now()); }); } }; function iptobin(a,b,c,d) { const bin = ((a | 0) << 24) | ((b | 0) << 16) | ((c | 0) << 8) | (d | 0); return bin; } function bintoip(bin) { if(typeof bin == "string") { bin = bin | 0; } const octet1 = (bin >>> 24) & 0xff; const octet2 = (bin >>> 16) & 0xff; const octet3 = (bin >>> 8) & 0xff; const octet4 = bin & 0xff; return [octet1,octet2,octet3,octet4]; } function randomMaskINIT() { if(typeof bin == "string") { bin = bin.split('.').map(e => e | 0); } let globalmask = crypto.randomInt(flovitNumber[0].length); let macromask = crypto.randomInt(flovitNumber[1].length); return [ flovitNumber[0][globalmask], flovitNumber[1][macromask], 0, 0 ] } async function init() { await migrate(); await flushAll(); await create({ ipaddress: 0, // globalmask & macromask owner: randomMaskINIT().join('.'), type: "system", created: moment().format() }); hook() } init.inited = false; async function getip(owner, type) { let call = await read({ owner, type }); return !call ? false : { ipaddress: call.ipaddress, date: call.created }; } async function setip(owner, type, ip) { await getip(owner, type) ? await write({ ipaddress: ip },{ owner, type }) : await create({ ipaddress: ip, owner, type }); } async function allocateIP(owner, type, changeOverlord) { let [a,b,c,d] = [ ,,, ]; if(changeOverlord) { [a,b,c,d] = randomMaskINIT(); }else{ let ipinfo = await read({ ipaddress: 0, type: "system" }); [a,b,c,d] = ipinfo.owner.split('.').map(e => e | 0); } while(1) { if(d != 255) { d++; }else if(c != 255){ c++; }else if(b != 255){ b++; }else if(a != 255){ a++; }else{ [a,b,c,d] = randomMaskINIT(); } let query = { ipaddress: iptobin(a,b,c,d) }; let result = await has(query); if(result == false) { await create({ ipaddress: iptobin(a,b,c,d), owner, type }); await write({ owner: [a,b,c,d].join('.') },{ type: "system", ipaddress: 0 }); break; }else{ console.log("Checking",[a,b,c,d].join('.')) } } return[a,b,c,d].join('.') } process.nextTick(init);