1package magna
2
3import (
4 "encoding/binary"
5 "strings"
6)
7
8// decode_domain decodes a domain name from a buffer starting at offset.
9// It returns the domain name along with the offset and error.
10func decode_domain(buf []byte, offset int) (string, int, error) {
11 labels := make([]string, 0)
12 seen_offsets := make(map[int]struct{})
13 has_jumped := false
14 prev_offset := 0
15
16 var length uint8
17 var label []byte
18 var sec byte
19 var err error
20 for {
21 length, offset, err = getU8(buf, offset)
22 if err != nil {
23 return "", len(buf), err
24 }
25
26 if length == 0 {
27 break
28 }
29
30 if length&0xC0 == 0xC0 {
31 sec, offset, err = getU8(buf, offset)
32 if err != nil {
33 return "", len(buf), err
34 }
35
36 if !has_jumped {
37 prev_offset = offset
38 has_jumped = true
39 }
40
41 if _, found := seen_offsets[offset]; found {
42 return "", len(buf), &DomainCompressionError{}
43 }
44
45 seen_offsets[offset] = struct{}{}
46 offset = int(sec)
47 } else {
48 if length > 63 {
49 return "", len(buf), &InvalidLabelError{Length: int(length)}
50 }
51
52 label, offset, err = getSlice(buf, offset, int(length))
53 if err != nil {
54 return "", len(buf), err
55 }
56
57 labels = append(labels, string(label))
58 }
59 }
60
61 if has_jumped {
62 offset = prev_offset
63 }
64
65 return strings.Join(labels, "."), offset, nil
66}
67
68// encode_domain returns the bytes of the input bytes appened with the encoded domain name.
69func encode_domain(bytes []byte, domain_name string, offsets *map[string]uint8) []byte {
70 pos := uint8(len(bytes))
71
72 labels := strings.Split(domain_name, ".")
73 for i, label := range labels {
74 remaining_labels := strings.Join(labels[i:], ".")
75
76 if offset, found := (*offsets)[remaining_labels]; found {
77 pointer := 0xC000 | uint16(offset)
78 bytes = binary.BigEndian.AppendUint16(bytes, pointer)
79
80 return bytes
81 }
82
83 bytes = append(bytes, uint8(len(label)))
84 bytes = append(bytes, []byte(label)...)
85
86 (*offsets)[remaining_labels] = pos
87 pos += 1 + uint8(len(label))
88 }
89
90 bytes = append(bytes, 0)
91 return bytes
92}