1package magna
2
3import (
4 "encoding/binary"
5 "fmt"
6)
7
8// Decode decodes the header from the bytes.
9func (h *Header) Decode(buf []byte, offset int) (int, error) {
10 var err error
11 h.ID, offset, err = getU16(buf, offset)
12 if err != nil {
13 return len(buf), fmt.Errorf("header decode: failed to read ID: %w", err)
14 }
15
16 flags, offset, err := getU16(buf, offset)
17 if err != nil {
18 return len(buf), fmt.Errorf("header decode: failed to read flags: %w", err)
19 }
20
21 h.QDCount, offset, err = getU16(buf, offset)
22 if err != nil {
23 return len(buf), fmt.Errorf("header decode: failed to read QDCount: %w", err)
24 }
25
26 h.ANCount, offset, err = getU16(buf, offset)
27 if err != nil {
28 return len(buf), fmt.Errorf("header decode: failed to read ANCount: %w", err)
29 }
30
31 h.NSCount, offset, err = getU16(buf, offset)
32 if err != nil {
33 return len(buf), fmt.Errorf("header decode: failed to read NSCount: %w", err)
34 }
35
36 h.ARCount, offset, err = getU16(buf, offset)
37 if err != nil {
38 return len(buf), fmt.Errorf("header decode: failed to read ARCount: %w", err)
39 }
40
41 h.QR = ((flags >> 15) & 0x01) == 1
42 h.OPCode = OPCode((flags >> 11) & 0x0F)
43 h.AA = ((flags >> 10) & 0x01) == 1
44 h.TC = ((flags >> 9) & 0x01) == 1
45 h.RD = ((flags >> 8) & 0x01) == 1
46 h.RA = ((flags >> 7) & 0x01) == 1
47 h.Z = uint8((flags >> 4) & 0x07)
48 h.RCode = RCode((flags & 0x0F))
49
50 return offset, nil
51}
52
53// Encode encodes the header packet to the byte representation.
54func (h *Header) Encode() []byte {
55 bytes := make([]byte, 0, 12)
56
57 bytes = binary.BigEndian.AppendUint16(bytes, h.ID)
58
59 var flags uint16
60 if h.QR {
61 flags |= 1 << 15
62 }
63
64 flags |= uint16(h.OPCode) << 11
65
66 if h.AA {
67 flags |= 1 << 10
68 }
69
70 if h.TC {
71 flags |= 1 << 9
72 }
73
74 if h.RD {
75 flags |= 1 << 8
76 }
77
78 if h.RA {
79 flags |= 1 << 7
80 }
81
82 flags |= uint16(h.Z) << 4
83 flags |= uint16(h.RCode)
84
85 bytes = binary.BigEndian.AppendUint16(bytes, flags)
86 bytes = binary.BigEndian.AppendUint16(bytes, h.QDCount)
87 bytes = binary.BigEndian.AppendUint16(bytes, h.ANCount)
88 bytes = binary.BigEndian.AppendUint16(bytes, h.NSCount)
89 bytes = binary.BigEndian.AppendUint16(bytes, h.ARCount)
90
91 return bytes
92}