/usr/lib/nodejs/node-xmpp/xmpp/srv.js is in libnode-node-xmpp 0.2.7-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | var dns = require('dns');
var EventEmitter = require('events').EventEmitter;
function compareNumbers(a, b) {
a = parseInt(a, 10);
b = parseInt(b, 10);
if (a < b)
return -1;
if (a > b)
return 1;
return 0;
}
function groupSrvRecords(addrs) {
var groups = {}; // by priority
addrs.forEach(function(addr) {
if (!groups.hasOwnProperty(addr.priority))
groups[addr.priority] = [];
groups[addr.priority].push(addr);
});
var result = [];
Object.keys(groups).sort(compareNumbers).forEach(function(priority) {
var group = groups[priority];
var totalWeight = 0;
group.forEach(function(addr) {
totalWeight += addr.weight;
});
var w = Math.floor(Math.random() * totalWeight);
totalWeight = 0;
var candidate = group[0];
group.forEach(function(addr) {
totalWeight += addr.weight;
if (w < totalWeight)
candidate = addr;
});
if (candidate)
result.push(candidate);
});
return result;
}
function resolveSrv(name, cb) {
dns.resolveSrv(name, function(err, addrs) {
if (err) {
/* no SRV record, try domain as A */
cb(err);
} else {
var pending = 0, error, results = [];
var cb1 = function(e, addrs1) {
error = error || e;
results = results.concat(addrs1);
pending--;
if (pending < 1) {
cb(results ? null : error, results);
}
};
groupSrvRecords(addrs).forEach(function(addr) {
resolveHost(addr.name, function(e, a) {
if (a)
a = a.map(function(a1) {
return { name: a1,
port: addr.port };
});
cb1(e, a);
});
pending++;
});
}
});
}
// one of both A & AAAA, in case of broken tunnels
function resolveHost(name, cb) {
var error, results = [];
var cb1 = function(e, addr) {
error = error || e;
if (addr)
results.push(addr);
cb((results.length > 0) ? null : error, results);
};
dns.lookup(name, cb1);
}
// connection attempts to multiple addresses in a row
function tryConnect(socket, addrs, listener) {
var onConnect = function() {
socket.removeListener('connect', onConnect);
socket.removeListener('error', onError);
// done!
listener.emit('connect');
};
var error;
var onError = function(e) {
error = e;
connectNext();
};
var connectNext = function() {
var addr = addrs.shift();
if (addr)
socket.connect(addr.port, addr.name);
else
listener.emit('error', error || new Error('No addresses to connect to'));
};
socket.addListener('connect', onConnect);
socket.addListener('error', onError);
connectNext();
}
// returns EventEmitter with 'connect' & 'error'
exports.connect = function(socket, services, domain, defaultPort) {
var listener = new EventEmitter();
var tryServices = function() {
var service = services.shift();
if (service) {
resolveSrv(service + '.' + domain, function(error, addrs) {
if (addrs)
tryConnect(socket, addrs, listener);
else
tryServices();
});
} else {
resolveHost(domain, function(error, addrs) {
if (addrs && addrs.length > 0) {
addrs = addrs.map(function(addr) {
return { name: addr,
port: defaultPort };
});
tryConnect(socket, addrs, listener);
} else if (error)
listener.emit('error', error);
else
listener.emit('error', new Error('No addresses resolved for ' + domain));
});
}
};
tryServices();
return listener;
};
|