func (msg *Message) SetResponseCode(code ResponseCode) {
	msg.Header.RCode = code
	if len(msg.packet) > 3 {
		if code == RCodeOK {
			msg.packet[3] &= 0xF0
		} else {
			msg.packet[3] |= (0x0F & byte(code))
		}
	}
}
SetResponseCode in message header and in packet.
package dns
import (
	"fmt"
	"log"
	"net"
	"strconv"
	"strings"
	"github.com/shuLhan/share/lib/ascii"
	libbytes "github.com/shuLhan/share/lib/bytes"
	"github.com/shuLhan/share/lib/debug"
	libnet "github.com/shuLhan/share/lib/net"
	"github.com/shuLhan/share/lib/reflect"
)
type Message struct {
	Header     SectionHeader
	Question   SectionQuestion
	Answer     []ResourceRecord
	Authority  []ResourceRecord
	Additional []ResourceRecord
	packet []byte
	off uint16
	dnameOff map[string]uint16
	dname    string
}
func NewMessage() *Message {
	return &Message{
		Header: SectionHeader{
			IsQuery: true,
			IsRD:    true,
			QDCount: 1,
		},
		Question: SectionQuestion{
			Type:  QueryTypeA,
			Class: QueryClassIN,
		},
		dnameOff: make(map[string]uint16),
	}
}
func NewMessageAddress(hname []byte, addresses [][]byte) (msg *Message) {
	if !libnet.IsHostnameValid(hname, false) {
		return nil
	}
	if len(addresses) == 0 {
		return nil
	}
	addr := addresses[0]
	qtype := GetQueryTypeFromAddress(addr)
	if qtype == 0 {
		return nil
	}
	hname = ascii.ToLower(hname)
	rr := ResourceRecord{
		Name:  string(hname),
		Type:  qtype,
		Class: QueryClassIN,
		TTL:   defaultTTL,
		Value: string(addr),
	}
	msg = &Message{
		Header: SectionHeader{
			IsAA:    true,
			QDCount: 1,
			ANCount: 1,
		},
		Question: SectionQuestion{
			Name:  string(hname),
			Type:  qtype,
			Class: QueryClassIN,
		},
		Answer: []ResourceRecord{rr},
	}
	for _, addr := range addresses[1:] {
		qtype = GetQueryTypeFromAddress(addr)
		if qtype == 0 {
			continue
		}
		if qtype != msg.Question.Type {
			continue
		}
		msg.Answer = append(msg.Answer, ResourceRecord{
			Name:  string(hname),
			Type:  qtype,
			Class: QueryClassIN,
			TTL:   defaultTTL,
			Value: string(addr),
		})
		msg.Header.ANCount++
	}
	_, err := msg.Pack()
	if err != nil {
		return nil
	}
	return msg
}
func NewMessageFromRR(rr *ResourceRecord) (msg *Message, err error) {
	msg = &Message{
		Header: SectionHeader{
			IsAA:    true,
			QDCount: 1,
			ANCount: 1,
		},
		Question: SectionQuestion{
			Name:  rr.Name,
			Type:  rr.Type,
			Class: rr.Class,
		},
		Answer: []ResourceRecord{*rr},
	}
	_, err = msg.Pack()
	if err != nil {
		return nil, err
	}
	return msg, nil
}
func (msg *Message) AddAnswer(rr *ResourceRecord) (err error) {
	switch rr.Type {
	case QueryTypeSOA, QueryTypePTR:
		if len(msg.Answer) > 0 {
			msg.Answer[0] = *rr
		} else {
			msg.Answer = append(msg.Answer, *rr)
		}
	default:
		msg.Answer = append(msg.Answer, *rr)
		msg.Header.ANCount++
	}
	_, err = msg.Pack()
	return err
}
func (msg *Message) FilterAnswers(t uint16) (answers []ResourceRecord) {
	for _, rr := range msg.Answer {
		if rr.Type == t {
			answers = append(answers, rr)
		}
	}
	return
}
func (msg *Message) compress() bool {
	off, ok := msg.dnameOff[msg.dname]
	if ok {
		msg.packet = append(msg.packet, maskPointer|byte(off>>8))
		msg.packet = append(msg.packet, byte(off))
		msg.off += 2
		return true
	}
	return false
}
func (msg *Message) packDomainName(dname []byte, doCompress bool) (n int) {
	var (
		ok bool
		d  int
	)
	dname = ascii.ToLower(dname)
	msg.dname = string(dname)
	if doCompress {
		ok = msg.compress()
		if ok {
			return 2
		}
	}
	count := byte(0)
	msg.packet = append(msg.packet, 0)
	msg.dnameOff[msg.dname] = msg.off
	for x := 0; x < len(dname); x++ {
		c := dname[x]
		if c == '\\' {
			x++
			if x == len(dname) {
				return n
			}
			c = dname[x]
			if ascii.IsDigit(c) {
				if x+2 >= len(dname) {
					return n
				}
				d, _ = strconv.Atoi(string(dname[x : x+3]))
				c = byte(d)
				if c >= 'A' && c <= 'Z' {
					c += 32
				}
				x += 2
			}
			msg.packet = append(msg.packet, c)
			count++
			continue
		}
		if c == '.' {
			if count == 0 {
				continue
			}
			msg.packet[msg.off] = count
			msg.dname = string(dname[x+1:])
			msg.off += uint16(count + 1)
			n += int(count + 1)
			if doCompress {
				ok = msg.compress()
				if ok {
					n += 2
					return n
				}
			}
			count = 0
			msg.packet = append(msg.packet, 0)
			msg.dnameOff[msg.dname] = msg.off
			if x+1 == len(dname) {
				return n
			}
			continue
		}
		msg.packet = append(msg.packet, c)
		count++
	}
	if count > 0 {
		msg.packet[msg.off] = count
		msg.off += uint16(count + 1)
		n += int(count + 1)
	}
	if len(dname) > 0 {
		msg.packet = append(msg.packet, 0)
		msg.off++
		n++
	}
	return n
}
func (msg *Message) packQuestion() {
	msg.packDomainName([]byte(msg.Question.Name), false)
	msg.packet = libbytes.AppendUint16(msg.packet, msg.Question.Type)
	msg.packet = libbytes.AppendUint16(msg.packet, msg.Question.Class)
	msg.off += 4
}
func (msg *Message) packRR(rr *ResourceRecord) {
	var (
		rrOPT *RDataOPT
	)
	if rr.Type == QueryTypeOPT {
		msg.packet = append(msg.packet, 0)
		rrOPT, _ = rr.Value.(*RDataOPT)
	} else {
		msg.packDomainName([]byte(rr.Name), true)
	}
	msg.packet = libbytes.AppendUint16(msg.packet, rr.Type)
	msg.packet = libbytes.AppendUint16(msg.packet, rr.Class)
	msg.off += 4
	if rr.Type == QueryTypeOPT {
		rr.TTL = 0
		rr.TTL = uint32(rrOPT.ExtRCode) << 24
		rr.TTL |= (uint32(rrOPT.Version) << 16)
		if rrOPT.DO {
			rr.TTL |= maskOPTDO
		}
	}
	rr.offTTL = uint(msg.off)
	msg.packet = libbytes.AppendUint32(msg.packet, rr.TTL)
	msg.off += 4
	msg.packRData(rr)
}
func (msg *Message) packRData(rr *ResourceRecord) {
	switch rr.Type {
	case QueryTypeA:
		msg.packA(rr)
	case QueryTypeNS:
		msg.packTextAsDomain(rr)
	case QueryTypeMD:
	case QueryTypeMF:
	case QueryTypeCNAME:
		msg.packTextAsDomain(rr)
	case QueryTypeSOA:
		msg.packSOA(rr)
	case QueryTypeMB:
		msg.packTextAsDomain(rr)
	case QueryTypeMG:
		msg.packTextAsDomain(rr)
	case QueryTypeMR:
		msg.packTextAsDomain(rr)
	case QueryTypeNULL:
		msg.packTextAsDomain(rr)
	case QueryTypeWKS:
		msg.packWKS(rr)
	case QueryTypePTR:
		msg.packTextAsDomain(rr)
	case QueryTypeHINFO:
		msg.packHINFO(rr)
	case QueryTypeMINFO:
		msg.packMINFO(rr)
	case QueryTypeMX:
		msg.packMX(rr)
	case QueryTypeTXT:
		msg.packTXT(rr)
	case QueryTypeSRV:
		msg.packSRV(rr)
	case QueryTypeAAAA:
		msg.packAAAA(rr)
	case QueryTypeOPT:
		msg.packOPT(rr)
	}
}
func (msg *Message) packA(rr *ResourceRecord) {
	msg.packet = libbytes.AppendUint16(msg.packet, rdataIPv4Size)
	msg.off += 2
	rrText, _ := rr.Value.(string)
	ip := net.ParseIP(rrText)
	if ip == nil {
		msg.packet = append(msg.packet, rrText[:rdataIPv4Size]...)
	} else {
		ipv4 := ip.To4()
		if ipv4 == nil {
			msg.packet = append(msg.packet, ip[:rdataIPv4Size]...)
		} else {
			msg.packet = append(msg.packet, ipv4...)
		}
	}
	msg.off += rdataIPv4Size
}
func (msg *Message) packTextAsDomain(rr *ResourceRecord) {
	msg.packet = libbytes.AppendUint16(msg.packet, 0)
	off := uint(msg.off)
	msg.off += 2
	rrText, _ := rr.Value.(string)
	n := msg.packDomainName([]byte(rrText), true)
	libbytes.WriteUint16(msg.packet, off, uint16(n))
}
func (msg *Message) packSOA(rr *ResourceRecord) {
	msg.packet = libbytes.AppendUint16(msg.packet, 0)
	off := uint(msg.off)
	msg.off += 2
	rrSOA, _ := rr.Value.(*RDataSOA)
	n := msg.packDomainName([]byte(rrSOA.MName), true)
	n += msg.packDomainName([]byte(rrSOA.RName), true)
	msg.packet = libbytes.AppendUint32(msg.packet, rrSOA.Serial)
	msg.packet = libbytes.AppendInt32(msg.packet, rrSOA.Refresh)
	msg.packet = libbytes.AppendInt32(msg.packet, rrSOA.Retry)
	msg.packet = libbytes.AppendInt32(msg.packet, rrSOA.Expire)
	msg.packet = libbytes.AppendUint32(msg.packet, rrSOA.Minimum)
	libbytes.WriteUint16(msg.packet, off, uint16(n+20))
	msg.off += uint16(n + 20)
}
func (msg *Message) packWKS(rr *ResourceRecord) {
	rrWKS, _ := rr.Value.(*RDataWKS)
	n := uint16(5 + len(rrWKS.BitMap))
	msg.packet = libbytes.AppendUint16(msg.packet, n)
	msg.off += 2
	msg.packet = append(msg.packet, rrWKS.Address[:4]...)
	msg.packet = append(msg.packet, rrWKS.Protocol)
	msg.packet = append(msg.packet, rrWKS.BitMap...)
	msg.off += n
}
func (msg *Message) packHINFO(rr *ResourceRecord) {
	rrHInfo, _ := rr.Value.(*RDataHINFO)
	n := len(rrHInfo.CPU)
	n += len(rrHInfo.OS)
	msg.packet = libbytes.AppendUint16(msg.packet, uint16(n))
	msg.off += 2
	msg.packet = append(msg.packet, rrHInfo.CPU...)
	msg.packet = append(msg.packet, rrHInfo.OS...)
	msg.off += uint16(n)
}
func (msg *Message) packMINFO(rr *ResourceRecord) {
	rrMInfo, _ := rr.Value.(*RDataMINFO)
	off := uint(msg.off)
	msg.packet = libbytes.AppendUint16(msg.packet, 0)
	msg.off += 2
	n := msg.packDomainName([]byte(rrMInfo.RMailBox), true)
	n += msg.packDomainName([]byte(rrMInfo.EmailBox), true)
	libbytes.WriteUint16(msg.packet, off, uint16(n))
}
func (msg *Message) packMX(rr *ResourceRecord) {
	rrMX, _ := rr.Value.(*RDataMX)
	off := uint(msg.off)
	msg.packet = libbytes.AppendUint16(msg.packet, 0)
	msg.off += 2
	msg.packet = libbytes.AppendInt16(msg.packet, rrMX.Preference)
	msg.off += 2
	n := msg.packDomainName([]byte(rrMX.Exchange), true)
	libbytes.WriteUint16(msg.packet, off, uint16(n+2))
}
func (msg *Message) packTXT(rr *ResourceRecord) {
	rrText, _ := rr.Value.(string)
	n := uint16(len(rrText))
	msg.packet = libbytes.AppendUint16(msg.packet, n+1)
	msg.off += 2
	msg.packet = append(msg.packet, byte(n))
	msg.packet = append(msg.packet, rrText...)
	msg.off += n
}
func (msg *Message) packSRV(rr *ResourceRecord) {
	rrSRV, _ := rr.Value.(*RDataSRV)
	off := uint(msg.off)
	msg.packet = libbytes.AppendUint16(msg.packet, 0)
	msg.off += 2
	msg.packet = libbytes.AppendUint16(msg.packet, rrSRV.Priority)
	msg.off += 2
	msg.packet = libbytes.AppendUint16(msg.packet, rrSRV.Weight)
	msg.off += 2
	msg.packet = libbytes.AppendUint16(msg.packet, rrSRV.Port)
	msg.off += 2
	n := msg.packDomainName([]byte(rrSRV.Target), false) + 6
	libbytes.WriteUint16(msg.packet, off, uint16(n))
}
func (msg *Message) packAAAA(rr *ResourceRecord) {
	rrText, _ := rr.Value.(string)
	msg.packet = libbytes.AppendUint16(msg.packet, rdataIPv6Size)
	msg.off += 2
	ip := net.ParseIP(rrText)
	if ip == nil {
		msg.packet = append(msg.packet, rrText[:rdataIPv6Size]...)
	} else {
		msg.packet = append(msg.packet, ip...)
	}
	msg.off += rdataIPv6Size
	msg.off += rdataIPv6Size
}
func (msg *Message) packOPT(rr *ResourceRecord) {
	rrOPT, _ := rr.Value.(*RDataOPT)
	off := uint(msg.off)
	msg.packet = libbytes.AppendUint16(msg.packet, 0)
	msg.off += 2
	if rrOPT.Length == 0 {
		return
	}
	msg.packet = libbytes.AppendUint16(msg.packet, rrOPT.Code)
	if rrOPT.Length < 512 {
		msg.packet = libbytes.AppendUint16(msg.packet, 512)
	} else {
		msg.packet = libbytes.AppendUint16(msg.packet, rrOPT.Length)
	}
	msg.packet = append(msg.packet, rrOPT.Data[:rrOPT.Length]...)
	n := 4 + rrOPT.Length
	libbytes.WriteUint16(msg.packet, off, n)
	msg.off += n
}
func (msg *Message) Reset() {
	msg.Header.Reset()
	msg.Question.Reset()
	msg.ResetRR()
	msg.packet = append(msg.packet[:0], make([]byte, maxUDPPacketSize)...)
	msg.dname = ""
	msg.off = 0
	msg.dnameOff = make(map[string]uint16)
}
func (msg *Message) ResetRR() {
	msg.Answer = nil
	msg.Authority = nil
	msg.Additional = nil
}
func (msg *Message) IsExpired() bool {
	for x := 0; x < len(msg.Answer); x++ {
		if msg.Answer[x].TTL == 0 {
			return true
		}
	}
	if len(msg.Answer) > 0 {
		return false
	}
	for x := 0; x < len(msg.Authority); x++ {
		if msg.Authority[x].TTL == 0 {
			return true
		}
	}
	return false
}
func (msg *Message) Pack() ([]byte, error) {
	msg.dnameOff = make(map[string]uint16)
	msg.packet = msg.packet[:0]
	msg.Header.ANCount = uint16(len(msg.Answer))
	msg.Header.NSCount = uint16(len(msg.Authority))
	msg.Header.ARCount = uint16(len(msg.Additional))
	header := msg.Header.pack()
	msg.packet = append(msg.packet, header...)
	msg.off = uint16(sectionHeaderSize)
	msg.packQuestion()
	if msg.Header.IsQuery {
		msg.dnameOff = nil
		return msg.packet, nil
	}
	for x := 0; x < len(msg.Answer); x++ {
		msg.packRR(&msg.Answer[x])
	}
	for x := 0; x < len(msg.Authority); x++ {
		msg.packRR(&msg.Authority[x])
	}
	for x := 0; x < len(msg.Additional); x++ {
		msg.packRR(&msg.Additional[x])
	}
	msg.dnameOff = nil
	return msg.packet, nil
}
func (msg *Message) RemoveAnswer(rr *ResourceRecord) (err error) {
	for x, an := range msg.Answer {
		fmt.Printf("RemoveAnswer: %s == %s?\n", an.Value, rr.Value)
		if !reflect.IsEqual(an.Value, rr.Value) {
			continue
		}
		copy(msg.Answer[x:], msg.Answer[x+1:])
		msg.Answer = msg.Answer[:len(msg.Answer)-1]
		msg.Header.ANCount--
		_, err = msg.Pack()
		break
	}
	return err
}
func (msg *Message) SetAuthorativeAnswer(isAA bool) {
	msg.Header.IsAA = isAA
	if len(msg.packet) > 2 {
		if isAA {
			msg.packet[2] |= headerIsAA
		} else {
			msg.packet[2] = (msg.packet[2] & 0xFB)
		}
	}
}
func (msg *Message) SetID(id uint16) {
	msg.Header.ID = id
	if len(msg.packet) > 2 {
		libbytes.WriteUint16(msg.packet, 0, id)
	}
}
func (msg *Message) SetQuery(isQuery bool) {
	msg.Header.IsQuery = isQuery
	if len(msg.packet) > 3 {
		if isQuery {
			msg.packet[2] &= 0x71
			msg.packet[3] &= 0x7F
		} else {
			msg.packet[2] |= headerIsResponse
		}
	}
}
func (msg *Message) SetRecursionDesired(isRD bool) {
	msg.Header.IsRD = isRD
	if len(msg.packet) > 2 {
		if isRD {
			msg.packet[2] |= headerIsRD
		} else {
			msg.packet[2] &= 0xFE
		}
	}
}