This is a working name compression
This commit is contained in:
parent
848a337f1d
commit
f90270014c
|
@ -38,6 +38,13 @@ func main() {
|
|||
}
|
||||
println(r.String())
|
||||
buf, _ := r.Pack()
|
||||
|
||||
dns.Compress(buf)
|
||||
r1 := new(dns.Msg)
|
||||
ok := r1.Unpack(buf)
|
||||
if ok {
|
||||
fmt.Printf("%s", r1.String())
|
||||
} else {
|
||||
fmt.Printf("%s", r1.String())
|
||||
fmt.Printf("Failed to unpack compressed msg")
|
||||
}
|
||||
}
|
||||
|
|
2
msg.go
2
msg.go
|
@ -290,6 +290,7 @@ Loop:
|
|||
return "", lenmsg, false
|
||||
}
|
||||
off = (c^0xC0)<<8 | int(c1)
|
||||
println("offset", off)
|
||||
default:
|
||||
// 0x80 and 0x40 are reserved
|
||||
return "", lenmsg, false
|
||||
|
@ -975,6 +976,7 @@ func (dns *Msg) Pack() (msg []byte, ok bool) {
|
|||
dh.Nscount = uint16(len(ns))
|
||||
dh.Arcount = uint16(len(extra))
|
||||
|
||||
// TODO: fix this MG
|
||||
// Could work harder to calculate message size,
|
||||
// but this is far more than we need and not
|
||||
// big enough to hurt the allocator.
|
||||
|
|
98
rawmsg.go
98
rawmsg.go
|
@ -5,9 +5,11 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const maxPointer = 2 << 13 // We have 14 bits for the offset
|
||||
|
||||
// Function defined in this subpackage work on []byte and but still
|
||||
// provide some higher level functions.
|
||||
|
||||
|
@ -18,16 +20,32 @@ func RawSetId(msg []byte, off int, id uint16) bool {
|
|||
}
|
||||
|
||||
type rawlabel struct {
|
||||
offset int // offset where this labels starts in the msg buf
|
||||
str string // the label, not this includes the length at the start
|
||||
offset int // offset where this labels starts in the msg buf
|
||||
name string // the label, not this includes the length at the start
|
||||
}
|
||||
|
||||
type rawmove struct {
|
||||
offset int // where to point to
|
||||
from int // where in the buffer set the pointer
|
||||
length int // used in calculating how much to shrink the message
|
||||
}
|
||||
|
||||
// Compress performs name comression in the dns message contained in buf.
|
||||
// It returns the number of dnames compressed.
|
||||
// It returns the number of bytes saved.
|
||||
func Compress(msg []byte) int {
|
||||
|
||||
// First we create a table of domain names to which we
|
||||
// can link. This is stored in 'table'
|
||||
// Once for another name the longest possible link is
|
||||
// found we save how we must change msg to perform this
|
||||
// compression. This is saved in 'moves'. After we
|
||||
// traversed the entire message, we perform all the
|
||||
// moves.
|
||||
// TODO: Maybe it should be optimized.
|
||||
|
||||
// Map the labels to the offset in the message
|
||||
table := make(map[string]int)
|
||||
moves := make([]rawmove, 0)
|
||||
l := make([]rawlabel, 127) // Max labels?
|
||||
i := 0
|
||||
|
||||
|
@ -42,23 +60,32 @@ Loop:
|
|||
if c == 0x00 {
|
||||
// Do all of the bookkeeping
|
||||
|
||||
name := ""
|
||||
poffset := 0 // Where to point to
|
||||
moffset := 0 // From where to insert the pointer
|
||||
for j := i-1; j >= 0; j-- {
|
||||
name = l[j].str + name
|
||||
if idx, ok := table[name]; !ok {
|
||||
table[name] = l[j].offset
|
||||
} else {
|
||||
poffset = idx
|
||||
moffset = l[j].offset
|
||||
}
|
||||
name := ""
|
||||
poffset := 0 // Where to point to
|
||||
moffset := 0 // From where to insert the pointer
|
||||
for j := i - 1; j >= 0; j-- {
|
||||
name = l[j].name + name
|
||||
if idx, ok := table[name]; !ok {
|
||||
table[name] = l[j].offset
|
||||
} else {
|
||||
poffset = idx
|
||||
moffset = l[j].offset
|
||||
}
|
||||
}
|
||||
if poffset != 0 {
|
||||
//println("We kunnen verwijzen naar", poffset, "vanaf", moffset, "voor", name)
|
||||
//println("met lengte", len(name)+1)
|
||||
// the +1 for the name is for the null byte at the end
|
||||
|
||||
// Discount for previous moves, reset the poffset counter
|
||||
for i := len(moves)-1; i >= 0; i-- {
|
||||
if poffset > moves[i].from {
|
||||
poffset -= (moves[i].length - 2)
|
||||
}
|
||||
}
|
||||
|
||||
moves = append(moves, rawmove{offset: poffset, from: moffset, length: len(name) + 1})
|
||||
}
|
||||
if poffset == 0 {
|
||||
println("niks gevonden, nieuw!")
|
||||
} else {
|
||||
println("We kunnen verwijzen naar", poffset, "vanaf", moffset)
|
||||
}
|
||||
|
||||
// end of the name
|
||||
if question {
|
||||
|
@ -66,33 +93,50 @@ Loop:
|
|||
off += 4 // type, class + 1
|
||||
question = false
|
||||
} else {
|
||||
// How to handle well known records here
|
||||
// NS, MX, CNAME? eatName() function?
|
||||
// In the "body" of the msg
|
||||
off += 2 + 2 + 4 + 1 // type, class, ttl + 1
|
||||
// we are at the rdlength
|
||||
rdlength, _ := unpackUint16(msg, off)
|
||||
off += int(rdlength) + 1 // Skip the rdata
|
||||
}
|
||||
off++
|
||||
off++
|
||||
if off+1 > len(msg) {
|
||||
break Loop
|
||||
}
|
||||
i = 0
|
||||
continue Loop
|
||||
continue Loop
|
||||
}
|
||||
|
||||
if off+c+1 > len(msg) {
|
||||
break Loop
|
||||
}
|
||||
// c is the mount to scan forward
|
||||
l[i] = rawlabel{offset: off, str: string(msg[off : off+c+1])}
|
||||
i++
|
||||
// If we are too deep in the message we cannot point to
|
||||
// it, so skip this label.
|
||||
if off < maxPointer {
|
||||
l[i] = rawlabel{offset: off, name: string(msg[off : off+c+1])}
|
||||
i++
|
||||
}
|
||||
// save the new names
|
||||
off += c + 1
|
||||
default:
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
fmt.Printf("table %v\n", table)
|
||||
// fmt.Printf("table %v\n", table)
|
||||
// fmt.Printf("moves %v\n", moves)
|
||||
|
||||
return 0
|
||||
saved := 0
|
||||
// Start at the back, easier to move
|
||||
for i := len(moves) - 1; i >= 0; i-- {
|
||||
fmt.Printf("%v\n", moves[i])
|
||||
// move the bytes
|
||||
copy(msg[moves[i].from+1:], msg[moves[i].from+moves[i].length-1:])
|
||||
// Now set the pointer at moves[i].from and moves[i].from+1
|
||||
fmt.Printf("bits %b\n", moves[i].offset^0xC000)
|
||||
msg[moves[i].from], msg[moves[i].from+1] = packUint16(uint16(moves[i].offset ^ 0xC000))
|
||||
saved += moves[i].length // minus something
|
||||
}
|
||||
return saved
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue