msg.Copy() makes a deep-copy of the msg object

There was a copy function that did shallow copies of the msg
object. Export it and make it support proper deep copying.
This commit is contained in:
Marek Majkowski 2014-01-10 08:49:45 -08:00
parent a627d88e3f
commit 2cfad667d7
3 changed files with 30 additions and 10 deletions

View File

@ -105,7 +105,7 @@ func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
return r, rtt, err
}
if shared {
return r.copy(), rtt, nil
return r.Copy(), rtt, nil
}
return r, rtt, nil
}

22
msg.go
View File

@ -1545,18 +1545,30 @@ func (dns *Msg) Len() int {
return l
}
func (dns *Msg) copy() *Msg {
// Create a deep-copy
func (dns *Msg) Copy() *Msg {
r1 := new(Msg)
r1.MsgHdr = dns.MsgHdr
r1.Compress = dns.Compress
r1.Question = make([]Question, len(dns.Question))
copy(r1.Question, dns.Question) // Question is an immutable value, ok to do a shallow-copy
r1.Answer = make([]RR, len(dns.Answer))
for i := 0; i < len(dns.Answer); i++ {
r1.Answer[i] = dns.Answer[i].copy()
}
r1.Ns = make([]RR, len(dns.Ns))
for i := 0; i < len(dns.Ns); i++ {
r1.Ns[i] = dns.Ns[i].copy()
}
r1.Extra = make([]RR, len(dns.Extra))
copy(r1.Question, dns.Question)
copy(r1.Answer, dns.Answer)
copy(r1.Ns, dns.Ns)
copy(r1.Extra, dns.Extra)
for i := 0; i < len(dns.Extra); i++ {
r1.Extra[i] = dns.Extra[i].copy()
}
return r1
}

View File

@ -165,6 +165,14 @@ const (
_LOC_EQUATOR = 1 << 31 // RFC 1876, Section 2.
)
// helper: duplicate net.IP structure (it's a []byte)
func dupIP(ip net.IP) net.IP {
var ip2 net.IP
ip2 = make([]byte, len(ip))
copy(ip2, ip)
return ip2
}
// DNS queries.
type Question struct {
Name string `dns:"cdomain-name"` // "cdomain-name" specifies encoding (and may be compressed)
@ -586,7 +594,7 @@ type A struct {
}
func (rr *A) Header() *RR_Header { return &rr.Hdr }
func (rr *A) copy() RR { return &A{*rr.Hdr.copyHeader(), rr.A} }
func (rr *A) copy() RR { return &A{*rr.Hdr.copyHeader(), dupIP(rr.A)} }
func (rr *A) len() int { return rr.Hdr.len() + net.IPv4len }
func (rr *A) String() string {
@ -602,7 +610,7 @@ type AAAA struct {
}
func (rr *AAAA) Header() *RR_Header { return &rr.Hdr }
func (rr *AAAA) copy() RR { return &AAAA{*rr.Hdr.copyHeader(), rr.AAAA} }
func (rr *AAAA) copy() RR { return &AAAA{*rr.Hdr.copyHeader(), dupIP(rr.AAAA)} }
func (rr *AAAA) len() int { return rr.Hdr.len() + net.IPv6len }
func (rr *AAAA) String() string {
@ -1264,7 +1272,7 @@ func (rr *WKS) len() int { return rr.Hdr.len() + net.IPv4len + 1 }
func (rr *WKS) copy() RR {
cp := make([]uint16, len(rr.BitMap), cap(rr.BitMap))
copy(cp, rr.BitMap)
return &WKS{*rr.Hdr.copyHeader(), rr.Address, rr.Protocol, cp}
return &WKS{*rr.Hdr.copyHeader(), dupIP(rr.Address), rr.Protocol, cp}
}
func (rr *WKS) String() (s string) {
@ -1303,7 +1311,7 @@ type L32 struct {
}
func (rr *L32) Header() *RR_Header { return &rr.Hdr }
func (rr *L32) copy() RR { return &L32{*rr.Hdr.copyHeader(), rr.Preference, rr.Locator32} }
func (rr *L32) copy() RR { return &L32{*rr.Hdr.copyHeader(), rr.Preference, dupIP(rr.Locator32)} }
func (rr *L32) len() int { return rr.Hdr.len() + net.IPv4len }
func (rr *L32) String() string {