a go dns packet parser

increase performance of encode domain

Before
```
goos: darwin
goarch: arm64
pkg: tangled.sh/seiso.moe/magna
cpu: Apple M2
BenchmarkDecodeDomainSimple-8 15712374 77.80 ns/op
BenchmarkDecodeDomainCompressed-8 13250395 90.30 ns/op
BenchmarkEncodeDomainSimple-8 11716813 102.7 ns/op
BenchmarkEncodeDomainWithCompression-8 6848320 174.9 ns/op
PASS
ok tangled.sh/seiso.moe/magna 6.471s
```

After
```
goos: darwin
goarch: arm64
pkg: tangled.sh/seiso.moe/magna
cpu: Apple M2
BenchmarkDecodeDomainSimple-8 15675970 77.08 ns/op
BenchmarkDecodeDomainCompressed-8 13399174 89.80 ns/op
BenchmarkEncodeDomainSimple-8 16123866 72.83 ns/op
BenchmarkEncodeDomainWithCompression-8 11180266 107.2 ns/op
PASS
ok tangled.sh/seiso.moe/magna 6.341s
```

+29 -17
+29 -17
domain_name.go
··· 88 88 return append(bytes, 0) 89 89 } 90 90 91 - labelIndices := []int{0} 92 - for i, r := range domain_name { 93 - if r == '.' { 94 - labelIndices = append(labelIndices, i+1) 95 - } 91 + clean_domain := strings.TrimSuffix(domain_name, ".") 92 + if clean_domain == "" { 93 + return append(bytes, 0) 96 94 } 97 95 98 - for i := 0; i < len(labelIndices); i++ { 99 - suffix := domain_name[labelIndices[i]:] 96 + start := 0 97 + for start < len(clean_domain) { 98 + suffix := clean_domain[start:] 100 99 101 100 if offset, found := (*offsets)[suffix]; found { 102 - pointer := 0xC000 | offset 103 - return binary.BigEndian.AppendUint16(bytes, pointer) 101 + if offset > 0x3FFF { 102 + end := strings.IndexByte(suffix, '.') 103 + if end == -1 { 104 + end = len(suffix) 105 + } 106 + } else { 107 + pointer := 0xC000 | offset 108 + return binary.BigEndian.AppendUint16(bytes, pointer) 109 + } 104 110 } 105 111 106 112 currentPos := uint16(len(bytes)) ··· 108 114 (*offsets)[suffix] = currentPos 109 115 } 110 116 111 - start := labelIndices[i] 112 - end := len(domain_name) 113 - if i+1 < len(labelIndices) { 114 - end = labelIndices[i+1] - 1 117 + end := strings.IndexByte(suffix, '.') 118 + var label string 119 + nextStart := len(clean_domain) 120 + 121 + if end == -1 { 122 + label = suffix 123 + start = nextStart 124 + } else { 125 + label = suffix[:end] 126 + nextStart = start + end + 1 127 + start = nextStart 115 128 } 116 - labelBytes := []byte(domain_name[start:end]) 129 + 130 + labelBytes := []byte(label) 117 131 118 - if len(labelBytes) == 0 { 119 - continue 120 - } 121 132 if len(labelBytes) > 63 { 133 + // XXX: maybe should return an error 122 134 labelBytes = labelBytes[:63] 123 135 } 124 136