Add encoder for stream transports (TCP/TLS). (#23)

* Add encoder for stream transports (TCP/TLS).
Fixes #16.

* Add README text and return null on short buffer.
This commit is contained in:
Tom Pusateri 2018-02-04 20:58:34 +01:00 committed by silverwind
parent 600d4acd90
commit 7904e095e9
4 changed files with 85 additions and 1 deletions

View File

@ -9,7 +9,7 @@ npm install dns-packet
[![build status](https://travis-ci.org/mafintosh/dns-packet.svg?branch=master)](https://travis-ci.org/mafintosh/dns-packet)
## Usage
## UDP Usage
``` js
var packet = require('dns-packet')
@ -35,6 +35,10 @@ socket.on('message', function (message) {
socket.send(buf, 0, buf.length, 53, '8.8.8.8')
```
## TCP Usage
While DNS has traditionally been used over a datagram transport, it is increasingly being carried over TCP for larger responses commonly including DNSSEC responses and TCP/TLS for privacy reasons.
## API
#### `var buf = packets.encode(packet, [buf], [offset])`

30
example_tcp.js Normal file
View File

@ -0,0 +1,30 @@
'use strict'
const packet = require('./')
const net = require('net')
const buf = packet.streamEncode({
type: 'query',
id: 0xdead,
flags: packet.RECURSION_DESIRED,
questions: [{
type: 'A',
name: 'google.com'
}]
})
const client = new net.Socket()
client.connect(53, '8.8.8.8', function () {
console.log('Connected')
client.write(buf)
})
client.on('data', function (data) {
console.log('Received response')
console.log(packet.streamDecode(data))
client.destroy() // kill client after server's response
})
client.on('close', function () {
console.log('Connection closed')
})

View File

@ -811,6 +811,29 @@ exports.encodingLength = function (result) {
encodingLengthList(result.additionals || [], answer)
}
exports.streamEncode = function (result) {
const len = exports.encodingLength(result)
const buf = Buffer.allocUnsafe(len + 2)
exports.encode(result, buf, 2)
buf.writeUInt16BE(len, 0)
exports.streamEncode.bytes = len + 2
return buf
}
exports.streamEncode.bytes = 0
exports.streamDecode = function (buf) {
const len = buf.readUInt16BE(0)
if (buf.length < len + 2) {
return null
}
const result = exports.decode(buf, 2)
exports.streamDecode.bytes = exports.decode.bytes + 2
return result
}
exports.streamDecode.bytes = 0
function encodingLengthList (list, enc) {
let len = 0
for (let i = 0; i < list.length; i++) len += enc.encodingLength(list[i])

27
test.js
View File

@ -289,6 +289,33 @@ tape('name_encoding', function (t) {
t.end()
})
tape('stream', function (t) {
const val = {
type: 'query',
id: 45632,
flags: 0x8480,
answers: [{
type: 'A',
name: 'test2.example.net',
data: '198.51.100.1'
}]
}
const buf = packet.streamEncode(val)
const val2 = packet.streamDecode(buf)
t.same(buf.length, packet.streamEncode.bytes, 'streamEncode.bytes was set correctly')
t.same(packet.streamDecode.bytes, packet.streamEncode.bytes, 'streamDecode.bytes was set correctly')
t.ok(compare(t, val2.type, val.type), 'streamDecoded type match')
t.ok(compare(t, val2.id, val.id), 'streamDecoded id match')
t.ok(parseInt(val2.flags) === parseInt(val.flags & 0x7FFF), 'streamDecoded flags match')
const answer = val.answers[0]
const answer2 = val2.answers[0]
t.ok(compare(t, answer.type, answer2.type), 'streamDecoded RR type match')
t.ok(compare(t, answer.name, answer2.name), 'streamDecoded RR name match')
t.ok(compare(t, answer.data, answer2.data), 'streamDecoded RR rdata match')
t.end()
})
function testEncoder (t, rpacket, val) {
const buf = rpacket.encode(val)
const val2 = rpacket.decode(buf)