2018-12-03 06:54:37 +00:00
|
|
|
import { Request, parseInput } from "./request";
|
|
|
|
import { RDATARecord, RecourceRecord } from "./record";
|
2018-12-03 06:59:29 +00:00
|
|
|
import { MonitoringPlugin, QuestionPlugin, DnsCore, AnswerHandler, ListenerPlugin, StoragePlugin, Record } from "./core";
|
2018-12-03 06:54:37 +00:00
|
|
|
import assert = require("assert");
|
|
|
|
import { RecordTypes } from "./types";
|
|
|
|
import { Question } from "./question";
|
|
|
|
|
|
|
|
function fromHex(data: string) {
|
|
|
|
return Buffer.from(data.replace(/\s/g, ""), "hex");
|
|
|
|
}
|
|
|
|
|
|
|
|
const itr = 100000;
|
|
|
|
console.log("All tests x" + itr);
|
|
|
|
|
|
|
|
let reqData = fromHex("E835 0100 0001 0000 0000 0000 07 6578616D706c65 03636F6D 00 0001 0001");
|
|
|
|
console.time("input parser")
|
|
|
|
for (let i = 0; i < itr; i++) {
|
|
|
|
parseInput(reqData);
|
|
|
|
}
|
|
|
|
console.timeEnd("input parser")
|
|
|
|
|
|
|
|
console.time("complete")
|
|
|
|
for (let i = 0; i < itr; i++) {
|
|
|
|
let request = new Request(reqData, "")
|
|
|
|
let rr = new RDATARecord()
|
|
|
|
rr.CLASS = 1
|
|
|
|
rr.NAME = "example.com"
|
|
|
|
rr.TTL = 1600
|
|
|
|
rr.TYPE = 1
|
|
|
|
rr.RDATA = fromHex("0A 00 00 01")
|
|
|
|
request.addAnswer(rr)
|
|
|
|
request.serialize()
|
|
|
|
}
|
|
|
|
console.timeEnd("complete")
|
|
|
|
|
|
|
|
console.time("complete 10 answers")
|
|
|
|
for (let i = 0; i < itr; i++) {
|
|
|
|
let request = new Request(reqData, "")
|
|
|
|
let rr = new RDATARecord()
|
|
|
|
rr.CLASS = 1
|
|
|
|
rr.NAME = "example.com"
|
|
|
|
rr.TTL = 1600
|
|
|
|
rr.TYPE = 1
|
|
|
|
rr.RDATA = fromHex("0A 00 00 01")
|
|
|
|
for (let i = 0; i < 10; i++) request.addAnswer(rr);
|
|
|
|
request.serialize()
|
|
|
|
}
|
|
|
|
console.timeEnd("complete 10 answers")
|
|
|
|
|
|
|
|
class TestMonitoringPlugin implements MonitoringPlugin {
|
|
|
|
constructor() { }
|
|
|
|
async init(core) { }
|
2018-12-03 07:30:42 +00:00
|
|
|
priority = 0
|
2018-12-03 06:54:37 +00:00
|
|
|
onRequest(domain, hostname, type) { }
|
|
|
|
}
|
|
|
|
|
|
|
|
class ARR extends RecourceRecord {
|
|
|
|
TYPE = RecordTypes.A
|
|
|
|
|
|
|
|
constructor(domain: string, ip: string) {
|
|
|
|
super();
|
|
|
|
this.NAME = domain
|
|
|
|
this.TTL = 1600
|
|
|
|
let data = Buffer.alloc(4)
|
|
|
|
let idx = 0;
|
|
|
|
ip.split(".").forEach(e => {
|
|
|
|
data.writeUInt8(Number(e), idx);
|
|
|
|
idx++;
|
|
|
|
})
|
|
|
|
this.dataLock = () => {
|
|
|
|
return {
|
|
|
|
length: 4,
|
|
|
|
serialize: (buffer, offset) => {
|
|
|
|
data.copy(buffer, offset);
|
|
|
|
return offset + 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class TestQuestionPlugin implements QuestionPlugin {
|
|
|
|
private Core: DnsCore
|
2018-12-03 07:30:42 +00:00
|
|
|
question_types = [RecordTypes.A]
|
|
|
|
priority = 0
|
2018-12-03 06:54:37 +00:00
|
|
|
async init(core) {
|
|
|
|
this.Core = core;
|
|
|
|
}
|
|
|
|
|
|
|
|
async handleQuestion(question: Question, request: AnswerHandler, next: () => void) {
|
2018-12-03 07:30:42 +00:00
|
|
|
assert(this.question_types.find(e => e === <any>question.QTYPE), "Handler was called with not supported question type")
|
2018-12-03 06:54:37 +00:00
|
|
|
let parts = question.QNAME.split(".")
|
|
|
|
let domain = parts.splice(-2, 2).join(".")
|
|
|
|
let hostname = parts.join(".");
|
|
|
|
hostname = hostname !== "" ? hostname : "*"
|
|
|
|
let records = await this.Core.storageManager.getRecords(domain, hostname, question.QTYPE)
|
|
|
|
records.forEach(e => request.addAnswer(new ARR(question.QNAME, e.value)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class TestListenerPlugin implements ListenerPlugin {
|
|
|
|
async init(core) { }
|
2018-12-03 07:30:42 +00:00
|
|
|
priority = 0;
|
2018-12-03 06:54:37 +00:00
|
|
|
callback: (data: Buffer, sender: string, max_size?: number) => Promise<Buffer>;
|
|
|
|
registerCallback(callback) {
|
|
|
|
this.callback = callback;
|
|
|
|
}
|
|
|
|
|
|
|
|
sendRequest(message: Buffer) {
|
|
|
|
return this.callback(message, "localhost")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class TestStoragePlugin implements StoragePlugin {
|
|
|
|
re: Record = { domain: "example.com", hostname: "test", type: RecordTypes.A, value: "10.0.0.1", ttl: 1600 }
|
|
|
|
|
|
|
|
constructor(record?: Record, private count: number = 1) {
|
|
|
|
if (record)
|
|
|
|
this.re = record;
|
|
|
|
}
|
|
|
|
|
2018-12-03 07:30:42 +00:00
|
|
|
priority = 0
|
|
|
|
no_cache = false
|
|
|
|
record_types = [RecordTypes.A]
|
2018-12-03 06:54:37 +00:00
|
|
|
isResponsible(domain: string) {
|
|
|
|
// console.log("Is responsible")
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
async init(core) { }
|
|
|
|
|
|
|
|
async getRecords(domain, hostname, type) {
|
|
|
|
if (domain !== this.re.domain || hostname !== this.re.hostname || type != this.re.type) return undefined;
|
|
|
|
let r = [];
|
|
|
|
for (let i = 0; i < this.count; i++) {
|
|
|
|
r.push(this.re);
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
async getAllRecordsForDomain(domain) {
|
|
|
|
if (domain !== this.re.domain) return undefined;
|
|
|
|
return [this.re];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let core = new DnsCore();
|
|
|
|
|
|
|
|
let listener = new TestListenerPlugin();
|
|
|
|
core.addListener(listener)
|
|
|
|
core.addMonitoring(new TestMonitoringPlugin());
|
|
|
|
core.addQuestion(new TestQuestionPlugin())
|
|
|
|
|
|
|
|
let storage = new TestStoragePlugin({
|
|
|
|
domain: "example.com",
|
|
|
|
hostname: "test",
|
|
|
|
type: RecordTypes.A,
|
|
|
|
ttl: 500,
|
|
|
|
value: "10.0.0.1"
|
|
|
|
}, 3)
|
|
|
|
core.addStorage(storage);
|
|
|
|
|
|
|
|
core.start().then(async () => {
|
|
|
|
let reqData = fromHex("E835 0100 0001 0000 0000 0000 04 74657374 07 6578616D706c65 03 636F6D 00 0001 0001");
|
|
|
|
console.time("core handler");
|
|
|
|
for (let i = 0; i < itr; i++) {
|
|
|
|
await listener.sendRequest(reqData)
|
|
|
|
}
|
|
|
|
console.timeEnd("core handler");
|
|
|
|
});
|