Skip to content

Commit

Permalink
no message
Browse files Browse the repository at this point in the history
  • Loading branch information
BoLaMN committed Dec 20, 2019
1 parent da0af08 commit 26ef36d
Show file tree
Hide file tree
Showing 9 changed files with 697 additions and 53 deletions.
319 changes: 319 additions & 0 deletions dist/dns.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,319 @@
var EventEmitter, Server, bitSlice, bufferify, bufferifyV4, bufferifyV6, createSocket, dns, domainify, functionify, isIPv6, lookup, parse, qnameify, resolve, response, responseBuffer,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;

EventEmitter = require`events`.EventEmitter;

createSocket = require('dgram').createSocket;

isIPv6 = require('net').isIPv6;

dns = require('dns');

bitSlice = function(b, offset, length) {
return b >>> 7 - (offset + length - 1) & ~(0xff << length);
};

bufferify = function(ip) {
if (isIPv6(ip)) {
return bufferifyV6(ip);
} else {
return bufferifyV4(ip);
}
};

bufferifyV4 = function(ip) {
var base, buf, i, result;
ip = ip.split('.').map(function(n) {
return parseInt(n, 10);
});
result = 0;
base = 1;
i = ip.length - 1;
while (i >= 0) {
result += ip[i] * base;
base *= 256;
i--;
}
buf = Buffer.alloc(4);
buf.writeUInt32BE(result);
return buf;
};

bufferifyV6 = function(rawIp) {
var countColons, hexIp, ip;
countColons = function(x) {
var n;
n = 0;
x.replace(/:/g, function(c) {
return n++;
});
return n;
};
ip = rawIp.replace(/\/\d{1,3}(?=%|$)/, '').replace(/%.*$/, '');
hexIp = ip.replace(/::/, function(two) {
return ':' + Array(7 - countColons(ip) + 1).join(':') + ':';
}).split(':').map(function(x) {
return Array(4 - x.length).fill('0').join('') + x;
}).join('');
return Buffer.from(hexIp, 'hex');
};

domainify = function(qname) {
var i, length, offset, parts;
parts = [];
i = 0;
while (i < qname.length && qname[i]) {
length = qname[i];
offset = i + 1;
parts.push(qname.slice(offset, offset + length).toString());
i = offset + length;
}
return parts.join('.');
};

qnameify = function(domain) {
var i, offset, qname;
qname = Buffer.alloc(domain.length + 2);
offset = 0;
domain = domain.split('.');
i = 0;
while (i < domain.length) {
qname[offset] = domain[i].length;
qname.write(domain[i], offset + 1, domain[i].length, 'ascii');
offset += qname[offset] + 1;
i++;
}
qname[qname.length - 1] = 0;
return qname;
};

functionify = function(val) {
return function(addr, callback) {
return callback(null, val);
};
};

parse = function(buf) {
var b, header, question;
header = {};
question = {};
b = buf.slice(2, 3).toString('binary', 0, 1).charCodeAt(0);
header.id = buf.slice(0, 2);
header.qr = bitSlice(b, 0, 1);
header.opcode = bitSlice(b, 1, 4);
header.aa = bitSlice(b, 5, 1);
header.tc = bitSlice(b, 6, 1);
header.rd = bitSlice(b, 7, 1);
b = buf.slice(3, 4).toString('binary', 0, 1).charCodeAt(0);
header.ra = bitSlice(b, 0, 1);
header.z = bitSlice(b, 1, 3);
header.rcode = bitSlice(b, 4, 4);
header.qdcount = buf.slice(4, 6);
header.ancount = buf.slice(6, 8);
header.nscount = buf.slice(8, 10);
header.arcount = buf.slice(10, 12);
question.qname = buf.slice(12, buf.length - 4);
question.qtype = buf.slice(buf.length - 4, buf.length - 2);
question.qclass = buf.slice(buf.length - 2, buf.length);
return {
header: header,
question: question
};
};

responseBuffer = function(query) {
var buf, header, i, length, offset, qname, question, rr;
question = query.question;
header = query.header;
qname = question.qname;
offset = 16 + qname.length;
length = offset;
i = 0;
while (i < query.rr.length) {
length += query.rr[i].qname.length + 10;
i++;
}
buf = Buffer.alloc(length);
header.id.copy(buf, 0, 0, 2);
buf[2] = 0x00 | header.qr << 7 | header.opcode << 3 | header.aa << 2 | header.tc << 1 | header.rd;
buf[3] = 0x00 | header.ra << 7 | header.z << 4 | header.rcode;
buf.writeUInt16BE(header.qdcount, 4);
buf.writeUInt16BE(header.ancount, 6);
buf.writeUInt16BE(header.nscount, 8);
buf.writeUInt16BE(header.arcount, 10);
qname.copy(buf, 12);
question.qtype.copy(buf, 12 + qname.length, question.qtype, 2);
question.qclass.copy(buf, 12 + qname.length + 2, question.qclass, 2);
i = 0;
while (i < query.rr.length) {
rr = query.rr[i];
rr.qname.copy(buf, offset);
offset += rr.qname.length;
buf.writeUInt16BE(rr.qtype, offset);
buf.writeUInt16BE(rr.qclass, offset + 2);
buf.writeUInt32BE(rr.ttl, offset + 4);
buf.writeUInt16BE(rr.rdlength, offset + 8);
buf = Buffer.concat([buf, rr.rdata]);
offset += 14;
i++;
}
return buf;
};

response = function(query, ttl, to) {
var header, question, rrs;
response = {};
header = response.header = {};
question = response.question = {};
rrs = resolve(query.question.qname, ttl, to);
header.id = query.header.id;
header.ancount = rrs.length;
header.qr = 1;
header.opcode = 0;
header.aa = 0;
header.tc = 0;
header.rd = 1;
header.ra = 0;
header.z = 0;
header.rcode = 0;
header.qdcount = 1;
header.nscount = 0;
header.arcount = 0;
question.qname = query.question.qname;
question.qtype = query.question.qtype;
question.qclass = query.question.qclass;
response.rr = rrs;
return responseBuffer(response);
};

resolve = function(qname, ttl, to) {
var r;
r = {};
r.qname = qname;
r.qtype = to.length === 4 ? 1 : 28;
r.qclass = 1;
r.ttl = ttl;
r.rdlength = to.length;
r.rdata = to;
return [r];
};

lookup = function(addr, callback) {
if (net.isIP(addr)) {
return callback(null, addr);
}
return dns.lookup(addr, callback);
};

Server = (function(superClass) {
extend(Server, superClass);

function Server(proxy) {
var routes;
if (proxy == null) {
proxy = '8.8.8.8';
}
Server.__super__.constructor.apply(this, arguments);
this._socket = createSocket(isIPv6(proxy) ? 'udp6' : 'udp4');
routes = [];
this._socket.on('message', (function(_this) {
return function(message, rinfo) {
var domain, i, onerror, onproxy, query, respond, route, routeData;
query = parse(message);
domain = domainify(query.question.qname);
routeData = {
domain: domain,
rinfo: rinfo
};
_this.emit('resolve', routeData);
respond = function(buf) {
return _this._socket.send(buf, 0, buf.length, rinfo.port, rinfo.address);
};
onerror = function(err) {
return _this.emit('error', err);
};
onproxy = function() {
var sock;
sock = createSocket(isIPv6(proxy) ? 'udp6' : 'udp4');
sock.send(message, 0, message.length, 53, proxy);
sock.on('error', onerror);
return sock.on('message', function(response) {
respond(response);
return sock.close();
});
};
i = 0;
while (i < routes.length) {
if (routes[i].pattern.test(domain)) {
route = routes[i].route;
break;
}
i++;
}
if (!route) {
return onproxy();
}
return route(routeData, function(err, to) {
var toIp, ttl;
if (typeof to === 'string') {
toIp = to;
ttl = 1;
} else {
toIp = to.ip;
ttl = to.ttl;
}
if (err) {
return onerror(err);
}
if (!toIp) {
return onproxy();
}
return lookup(toIp, function(err, addr) {
if (err) {
return onerror(err);
}
_this.emit('route', domain, addr);
return respond(response(query, ttl, bufferify(addr)));
});
});
};
})(this));
}

Server.prototype.route = function(pattern, route) {
if (Array.isArray(pattern)) {
pattern.forEach((function(_this) {
return function(item) {
return _this.route(item, route);
};
})(this));
return this;
}
if (typeof pattern === 'function') {
return this.route('*', pattern);
}
if (typeof route === 'string') {
return this.route(pattern, functionify(route));
}
pattern = pattern === '*' ? /.?/ : new RegExp('^' + pattern.replace(/\./g, '\\.').replace(/\*\\\./g, '(.+)\\.') + '$', 'i');
routes.push({
pattern: pattern,
route: route
});
return this;
};

Server.prototype.listen = function(port) {
this._socket.bind(port || 53);
return this;
};

Server.prototype.close = function(callback) {
this._socket.close(callback);
return this;
};

return Server;

})(EventEmitter);
14 changes: 13 additions & 1 deletion dist/http/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,17 @@ module.exports = function(ip, port, url) {
}).post('/', cwmp(url));
srv = createServer(route);
srv.keepAliveTimeout = 30000;
return srv.listen(port, ip);
srv.on('error', function(e) {
var ref1;
if ((ref1 = e.code) === 'EADDRINUSE' || ref1 === 'EADDRNOTAVAIL') {
console.log(e.code + ', retrying...');
return setTimeout(function() {
srv.close();
return srv.listen(port);
}, 1000);
} else {
return console.error(e);
}
});
return srv.listen(port);
};
Loading

0 comments on commit 26ef36d

Please sign in to comment.