Skip to content

Commit

Permalink
Fixed Everything that was broken :)
Browse files Browse the repository at this point in the history
  • Loading branch information
Johny Jose committed Nov 12, 2011
1 parent 56d531b commit 7b207d4
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 76 deletions.
20 changes: 10 additions & 10 deletions lib/ndns-poller-client.js
Expand Up @@ -9,17 +9,17 @@ var os = require('os');
var dgram = require('dgram');
var Buffer = require('buffer').Buffer;

var UPDATE_LOAD_THRESHOLD = 0.1;
var UPDATE_LOAD_THRESHOLD = 0.05;
var ALWAYS_UPDATE_THRESHOLD = 0.6;
var LAST_SENT_LOAD_METRIC = 0;
var myHostName = '';

//
// Check if the load has changed beyond threhold and then new data to the server
//
function checkAndSend(servHostname, servPortNumber, myHostName) {
if(Maths.abs(getLoadMetric()-LAST_SENT_LOAD_METRIC)>UPDATE_LOAD_THRESHOLD || getLoadMetric()>=ALWAYS_UPDATE_THRESHOLD) {
sendData(servHostname, servPortNumber, myHostname);
function checkAndSend(servHostname, servPortNumber) {
if( Math.abs ( getLoadMetric() - LAST_SENT_LOAD_METRIC ) > UPDATE_LOAD_THRESHOLD || getLoadMetric() >= ALWAYS_UPDATE_THRESHOLD) {
sendData(servHostname, servPortNumber);
}
}

Expand All @@ -31,18 +31,18 @@ exports.startPoller = function (servHostname, servPortNumber, hostName) {
sendData(servHostname, servPortNumber);
setInterval(function() {
checkAndSend(servHostname, servPortNumber);
}, 60000);
}, 1000);
};

//
// Send load data to the server identified by host and port
//
function sendData(hostname, port) {
console.log('seding data to '+hostname+' and '+port+'\n');
function sendData(servHostName, port) {
console.log('sending data to '+servHostName+' and '+port+'\n');
var sock = dgram.createSocket('udp4');
LAST_SENT_LOAD_METRIC = getLoadMetric();
var buf = new Buffer("{'Hostname':"+myHostName+",'LoadMetric': "+LAST_SENT_LOAD_METRIC"}");
sock.send(buf, 0, buf.length, port, hostname);
var buf = new Buffer("{'Hostname': '"+myHostName+"','LoadMetric': "+LAST_SENT_LOAD_METRIC+"}");
sock.send(buf, 0, buf.length, port, servHostName);
sock.close();
}

Expand All @@ -51,6 +51,6 @@ function sendData(hostname, port) {
//
function getLoadMetric() {
var loadAvg = os.loadavg();
return (0.5*loadAvg[0] + 0.3333*loadAvg[1] + 0.16667*loadAvg[2]);
return loadAvg[0];
}

142 changes: 113 additions & 29 deletions lib/ndns-poller-dispatcher.js
@@ -1,16 +1,17 @@
//
// DISPATCHER SERVER FOR THE NDNS LOAD BALANCER
// DNS SERVER FOR THE NDNS LOAD BALANCER
//
// Dispatches a DNS query to a load balancer or web server
// Performs load balancing using Round Robin/Dynamic/Hybrid strategy
//

var dgram = require('dgram');
var ndns = require('../lib/ndns');
var util = require('util');
var server = ndns.createServer('udp4');
var client = ndns.createClient('udp4');
var p_type_syms = ndns.p_type_syms;


var BIND_PORT = 53;
var POLL_PORT = 5000;

// Zone file information
var zone = {}
Expand All @@ -22,13 +23,18 @@ addToTree(zone, ["in","aiesec"],
{ name: 'aiesec.in', rr: 'NS', ttl: '86400', dclass: 'IN', value: 'ns1.bluehost.com.' },
{ name: 'aiesec.in', rr: 'NS', ttl: '86400', dclass: 'IN', value: 'ns2.bluehost.com.' },
{ name: 'aiesec.in', rr: 'MX', ttl: '14400', dclass: 'IN', value: '0 aiesec.in' },
{ name: 'aiesec.in', rr: 'A', ttl: '14400', dclass: 'IN', value: '74.220.219.81' },
{ name: 'aiesec.in', rr: 'A', ttl: '14400', dclass: 'IN', value: ['74.220.219.81', '74.220.219.82','127.0.0.1','127.0.0.2'] , balance: 'dyn' },
{ name: 'ns1.bluehost.com.', rr: 'A', ttl: '14400', dclass: 'IN', value: '127.0.0.1' },
{ name: 'ns2.bluehost.com.', rr: 'A', ttl: '14400', dclass: 'IN', value: '127.0.0.2' },
] } );
addToTree(zone, ["com","google"],
{ '*' : [
{ name: ['ns1.google.com','ns2.google.com','ns3.google.com','ns4.google.com'], rr: 'NS', ttl: '14400', dclass: 'IN', value: ['216.239.32.10','216.239.34.10','216.239.36.10','216.239.38.10'], index: 0, balance: 'rr' }
]
} );
addToTree(zone, ["in","ac","lnmiit","proxy"],
{ '*' : [
{ name: 'proxy.lnmiit.ac.in', rr:'A', ttl: '14400', dclass: 'IN', value: '172.22.2.211' }
{ name: 'proxy.lnmiit.ac.in', rr:'A', ttl: '14400', dclass: 'IN', value: ['172.22.2.211','172.22.2.212'], index: 0, balance: 'rr' }
] } );

// Add to tree function
Expand All @@ -49,11 +55,11 @@ function getRR(name) {
console.log("Domain not found");
break;
} else {
console.log('->'+label);
//console.log('->'+label);
root = root[label];
}
}
console.log(util.inspect(root['*'].length)+ " records found");
//console.log(util.inspect(root['*'].length)+ " records found");
if (root != zone)
return root['*'];
else
Expand All @@ -63,7 +69,7 @@ function getRR(name) {
// Check if this RR record should be returned for Question q
function checkQuestions(q, rr){
var result = false;
console.log(p_type_syms[q.type] + " - " + util.inspect(rr['rr']));
//console.log(p_type_syms[q.type] + " - " + util.inspect(rr['rr']));
if( p_type_syms[q.type] == rr['rr']) {
result = true;
} else if ( q.type == 255 ) {
Expand All @@ -76,7 +82,7 @@ function checkQuestions(q, rr){

// Add a RR record to response
function addRR(res, rr){
console.log("Adding "+ rr);
//console.log("Adding "+ rr);
if(rr['rr'] == 'SOA' ){
var param = rr['value'].split(" ");
res.addRR(rr['name'],
Expand Down Expand Up @@ -133,14 +139,75 @@ function addRR(res, rr){

}
else {
res.addRR(rr['name'],
rr['ttl'],
rr['dclass'],
rr['rr'],
rr['value']);
if (rr['rr'] == 'NS') {

// No load balancing
if (rr['balance'] == null){
res.addRR(rr['name'],
rr['ttl'],
rr['dclass'],
rr['rr'],
rr['value']);
}
//Implementation of Round Robin scheduling
else if (rr['balance'] == 'rr' && rr['value'] instanceof Array ) {

if( rr['index'] == null) rr['index'] = 0;

var index = parseInt(rr['index']);
res.addRR((rr['name'] instanceof Array)? rr['name'][index]: rr['name'],
rr['ttl'],
rr['dclass'],
rr['rr'],
rr['value'][index]);
rr['index'] = (index+1)%rr['value'].length;
}
//Implementation of Dynamic Load Balancing
else if (rr['balance'] == 'dyn' && rr['value'] instanceof Array ) {

if( rr['index'] == null) rr['index'] = 0;
var index = parseInt(rr['index']);

var fast_server = ndns.poller.server.getServerWithMinLoad(rr['name']);
console.log(rr['name'] + " fast server : " + fast_server );


// Fallback to Round Robin if no dynamic load information is available
if(fast_server == undefined){

res.addRR(rr['name'],
rr['ttl'],
rr['dclass'],
rr['rr'],
rr['value'][index]);

rr['index'] = (index+1)%rr['value'].length;
} else {

if(fast_server != rr['value'][index]) {
//Find new index
var found = false;
for( var i = 0; i < rr['value'].length; i++){
if(rr['value'][i] == fast_server){
found = true;
index = i;
break;
}
}
if(found)
rr['index'] == index;
else
console.log("ERROR! IP DOES NOT EXIST IN ZONE RECORDS");

}

// Return value at index
res.addRR(rr['name'],
rr['ttl'],
rr['dclass'],
rr['rr'],
rr['value'][index]);
}
//console.log(util.inspect(fast_server));
}
}
}
// Create DNS RR response
Expand All @@ -159,7 +226,7 @@ function createResponse (req, res, root) {

// Iterate over each record
for( var k = 0; k < root.length; k++) {
console.log("Section: "+i+", Question: "+j+", Record: "+k);
//console.log("Section: "+i+", Question: "+j+", Record: "+k);
// Check if this RR should be returned for the DNS Query Question
// Returns answers to query questions
if(checkQuestions(req.q[j], root[k]) && i == 0) {
Expand All @@ -179,37 +246,54 @@ function createResponse (req, res, root) {
}
res.header.qr = 1; //DNS query - 0 , DNS response - 1
res.header.ra = 1; //recursion available
res.header.aa = 0; //authoritative answer
res.header.aa = 1; //authoritative answer
res.header.rd = 0; //recursion desired
res.header.qdcount = req.q.length; //Question Count

res.header.ancount = count[0]; //Answer Count
res.header.nscount = count[1]; //Nameserver Record Count
res.header.arcount = count[2]; //Additional Record Count

console.log(util.inspect(res));
//console.log(util.inspect(res));
}
server.on("request", function(req, res) {


// DNS Server implementation

var dns_server = ndns.createServer('udp4');

// Polling Server Startup
ndns.poller.server.createServer(POLL_PORT);
ndns.poller.client.startPoller('127.0.0.1', POLL_PORT, 'aiesec.in');

dns_server.on("request", function(req, res) {
res.setHeader(req.header);

for (var i = 0; i < req.q.length; i++)
res.addQuestion(req.q[i]);
console.log(util.inspect(req.q));
//console.log(util.inspect(req.q));
if (req.q.length > 0) {
var name = req.q[0].name;
if (name == ".")
name = "";

var root = getRR(name);

createResponse(req, res, root);
if(root)
createResponse(req, res, root)
else{
res.header.rcode = 0x8;
res.header.qr = 1;
res.header.ra = 1;
res.header.aa = 0;
res.header.rd = 0;
res.header.ancount = 0;
res.header.nscount = 0;
res.header.arcount = 0;
}
}
res.send();

console.log("Response sent");
//console.log(util.inspect(res));

//console.log("Response sent");
});

server.bind(BIND_PORT);
dns_server.bind(BIND_PORT);

0 comments on commit 7b207d4

Please sign in to comment.