Skip to content

Instantly share code, notes, and snippets.

@icedraco
Last active September 1, 2015 16:26
Show Gist options
  • Select an option

  • Save icedraco/231b2e10e8027937cd6a to your computer and use it in GitHub Desktop.

Select an option

Save icedraco/231b2e10e8027937cd6a to your computer and use it in GitHub Desktop.
JavaScript class that converts and allocates IP addresses in a given range
/**
* Responsible for allocating and deallocating IP addresses in a given range.
*/
var ip = require('./iptools.js');
/**
* @param {string} network IPv4 address of the network address (e.g. "10.0.0.0")
* @param {number} prefix (optional) Network prefix (e.g. 24 for a 10.0.0.0/24 net)
* @constructor
*/
function IpAllocator(network, prefix) {
var self = this;
self.prefix = prefix || 24;
self.networkBits = ip.ip4ToInt(network, self.prefix);
self.maxHostIndex = ip.maxHosts(self.prefix);
self.nextHostIndex = 1;
self.allocatedHosts = [];
self.freeHosts = [];
self.reservedHosts = [];
//-----------------------------------------------------------------------//
//--- High-Level Methods ------------------------------------------------//
//-----------------------------------------------------------------------//
/**
* Allocate a new free address
*
* NOTE: "0.0.0.0" is returned if no free addresses left (i.e.: isEmpty())
*
* @return {string} IPv4 address of the allocated IP, or "0.0.0.0" if N/A
*/
self.allocate = function() {
var host = self.freeHosts.shift() || self.nextHost();
if (host > 0) {
self.allocatedHosts.push(host);
}
return ip.intToIp4(host);
};
/**
* Reserve a specific IP address from being allocated
*
* NOTE: If the address was already allocated or it does not belong to the
* given network, it will not be reserved!
*
* @param {string} addr IP address
* @return {boolean} TRUE if reserved or FALSE if failed to do so
*/
self.reserve = function(addr) {
if (!addr) {
return false; // address not specified
}
if (ip.ip4ToInt(addr, self.prefix) != self.networkBits) {
return false; // addr does not belong to the same network
}
var host = ip.ip4ToInt(addr);
if (self.isHostAllocated(host)) {
return false; // already allocated - cannot reserve
}
if (self.freeHosts.indexOf(host) >= 0) {
// found in freeHosts - remove it form there
self.freeHosts = self.freeHosts.filter(function(e){ return e != host });
}
else {
// nextHostIndex hasn't yet reached it - advance it
var next;
while ((next = self.nextHost()) < host) {
self.freeHosts.push(next);
}
assert(next == host);
}
self.reservedHosts.push(host);
return true; // reserved
};
/**
* Free a previously allocated address and make it available for allocation
* @param {string} addr Previously allocated IPv4 address
*/
self.free = function(addr) {
var host = ip.ip4ToInt(addr);
var isAllocated = self.isHostAllocated(host);
if (isAllocated) {
self.allocatedHosts = self.allocatedHosts.filter(function(e){ return e != host });
self.freeHosts.push(host);
}
return isAllocated;
};
/**
* @return {boolean} TRUE if all the addresses have been allocated
*/
self.isEmpty = function() {
return self.nextHostIndex > self.maxHostIndex;
};
//-----------------------------------------------------------------------//
//--- Low-Level Methods -------------------------------------------------//
//-----------------------------------------------------------------------//
self.nextHost = function() {
return self.isEmpty()
? 0
: self.networkBits + self.nextHostIndex++;
};
self.isHostAllocated = function(host) {
return self.allocatedHosts.indexOf(host) >= 0;
};
}
//------------------------------------------------------------------------------
// Exports
//------------------------------------------------------------------------------
module.exports.IpAllocator = IpAllocator;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment