Use an interface method for unpacking records (#884)
* Use an interface method for unpacking records * Eliminate err var declaration from unpack functions * Remove pointless r.Data assignment in PrivateRR.unpack
This commit is contained in:
parent
17dcb39074
commit
57b81e0614
21
dns.go
21
dns.go
|
@ -43,6 +43,12 @@ type RR interface {
|
||||||
|
|
||||||
// pack packs an RR into wire format.
|
// pack packs an RR into wire format.
|
||||||
pack(msg []byte, off int, compression compressionMap, compress bool) (headerEnd int, off1 int, err error)
|
pack(msg []byte, off int, compression compressionMap, compress bool) (headerEnd int, off1 int, err error)
|
||||||
|
|
||||||
|
// unpack unpacks an RR from wire format.
|
||||||
|
//
|
||||||
|
// This will only be called on a new and empty RR type with only the header populated. It
|
||||||
|
// will only be called if the record's RDATA is non-empty.
|
||||||
|
unpack(msg []byte, off int) (off1 int, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RR_Header is the header all DNS resource records share.
|
// RR_Header is the header all DNS resource records share.
|
||||||
|
@ -81,6 +87,10 @@ func (h *RR_Header) len(off int, compression map[string]struct{}) int {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *RR_Header) unpack(msg []byte, off int) (int, error) {
|
||||||
|
panic("dns: internal error: unpack should never be called on RR_Header")
|
||||||
|
}
|
||||||
|
|
||||||
// ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597.
|
// ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597.
|
||||||
func (rr *RFC3597) ToRFC3597(r RR) error {
|
func (rr *RFC3597) ToRFC3597(r RR) error {
|
||||||
buf := make([]byte, Len(r)*2)
|
buf := make([]byte, Len(r)*2)
|
||||||
|
@ -90,14 +100,17 @@ func (rr *RFC3597) ToRFC3597(r RR) error {
|
||||||
}
|
}
|
||||||
buf = buf[:off]
|
buf = buf[:off]
|
||||||
|
|
||||||
hdr := *r.Header()
|
*rr = RFC3597{Hdr: *r.Header()}
|
||||||
hdr.Rdlength = uint16(off - headerEnd)
|
rr.Hdr.Rdlength = uint16(off - headerEnd)
|
||||||
|
|
||||||
rfc3597, _, err := unpackRFC3597(hdr, buf, headerEnd)
|
if noRdata(rr.Hdr) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = rr.unpack(buf, headerEnd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
*rr = *rfc3597.(*RFC3597)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
21
msg.go
21
msg.go
|
@ -661,17 +661,28 @@ func UnpackRR(msg []byte, off int) (rr RR, off1 int, err error) {
|
||||||
// UnpackRRWithHeader unpacks the record type specific payload given an existing
|
// UnpackRRWithHeader unpacks the record type specific payload given an existing
|
||||||
// RR_Header.
|
// RR_Header.
|
||||||
func UnpackRRWithHeader(h RR_Header, msg []byte, off int) (rr RR, off1 int, err error) {
|
func UnpackRRWithHeader(h RR_Header, msg []byte, off int) (rr RR, off1 int, err error) {
|
||||||
|
if newFn, ok := TypeToRR[h.Rrtype]; ok {
|
||||||
|
rr = newFn()
|
||||||
|
*rr.Header() = h
|
||||||
|
} else {
|
||||||
|
rr = &RFC3597{Hdr: h}
|
||||||
|
}
|
||||||
|
|
||||||
|
if noRdata(h) {
|
||||||
|
return rr, off, nil
|
||||||
|
}
|
||||||
|
|
||||||
end := off + int(h.Rdlength)
|
end := off + int(h.Rdlength)
|
||||||
|
|
||||||
if fn, known := typeToUnpack[h.Rrtype]; !known {
|
off, err = rr.unpack(msg, off)
|
||||||
rr, off, err = unpackRFC3597(h, msg, off)
|
if err != nil {
|
||||||
} else {
|
return nil, end, err
|
||||||
rr, off, err = fn(h, msg, off)
|
|
||||||
}
|
}
|
||||||
if off != end {
|
if off != end {
|
||||||
return &h, end, &Error{err: "bad rdlength"}
|
return &h, end, &Error{err: "bad rdlength"}
|
||||||
}
|
}
|
||||||
return rr, off, err
|
|
||||||
|
return rr, off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// unpackRRslice unpacks msg[off:] into an []RR.
|
// unpackRRslice unpacks msg[off:] into an []RR.
|
||||||
|
|
|
@ -184,15 +184,8 @@ if rr.%s != "-" {
|
||||||
o := scope.Lookup(name)
|
o := scope.Lookup(name)
|
||||||
st, _ := getTypeStruct(o.Type(), scope)
|
st, _ := getTypeStruct(o.Type(), scope)
|
||||||
|
|
||||||
fmt.Fprintf(b, "func unpack%s(h RR_Header, msg []byte, off int) (RR, int, error) {\n", name)
|
fmt.Fprintf(b, "func (rr *%s) unpack(msg []byte, off int) (off1 int, err error) {\n", name)
|
||||||
fmt.Fprintf(b, "rr := new(%s)\n", name)
|
fmt.Fprint(b, `rdStart := off
|
||||||
fmt.Fprint(b, "rr.Hdr = h\n")
|
|
||||||
fmt.Fprint(b, `if noRdata(h) {
|
|
||||||
return rr, off, nil
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
_ = err
|
|
||||||
rdStart := off
|
|
||||||
_ = rdStart
|
_ = rdStart
|
||||||
|
|
||||||
`)
|
`)
|
||||||
|
@ -200,7 +193,7 @@ _ = rdStart
|
||||||
o := func(s string) {
|
o := func(s string) {
|
||||||
fmt.Fprintf(b, s, st.Field(i).Name())
|
fmt.Fprintf(b, s, st.Field(i).Name())
|
||||||
fmt.Fprint(b, `if err != nil {
|
fmt.Fprint(b, `if err != nil {
|
||||||
return rr, off, err
|
return off, err
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
@ -220,7 +213,7 @@ return rr, off, err
|
||||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||||
}
|
}
|
||||||
fmt.Fprint(b, `if err != nil {
|
fmt.Fprint(b, `if err != nil {
|
||||||
return rr, off, err
|
return off, err
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
continue
|
continue
|
||||||
|
@ -288,22 +281,13 @@ return rr, off, err
|
||||||
// If we've hit len(msg) we return without error.
|
// If we've hit len(msg) we return without error.
|
||||||
if i < st.NumFields()-1 {
|
if i < st.NumFields()-1 {
|
||||||
fmt.Fprintf(b, `if off == len(msg) {
|
fmt.Fprintf(b, `if off == len(msg) {
|
||||||
return rr, off, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Fprintf(b, "return rr, off, nil }\n\n")
|
fmt.Fprintf(b, "return off, nil }\n\n")
|
||||||
}
|
}
|
||||||
// Generate typeToUnpack map
|
|
||||||
fmt.Fprintln(b, "var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){")
|
|
||||||
for _, name := range namedTypes {
|
|
||||||
if name == "RFC3597" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(b, "Type%s: unpack%s,\n", name, name)
|
|
||||||
}
|
|
||||||
fmt.Fprintln(b, "}\n")
|
|
||||||
|
|
||||||
// gofmt
|
// gofmt
|
||||||
res, err := format.Source(b.Bytes())
|
res, err := format.Source(b.Bytes())
|
||||||
|
|
28
privaterr.go
28
privaterr.go
|
@ -83,6 +83,16 @@ func (r *PrivateRR) pack(msg []byte, off int, compression compressionMap, compre
|
||||||
return headerEnd, off, nil
|
return headerEnd, off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *PrivateRR) unpack(msg []byte, off int) (int, error) {
|
||||||
|
off1, err := r.Data.Unpack(msg[off:])
|
||||||
|
off += off1
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
|
||||||
// PrivateHandle registers a private resource record type. It requires
|
// PrivateHandle registers a private resource record type. It requires
|
||||||
// string and numeric representation of private RR type and generator function as argument.
|
// string and numeric representation of private RR type and generator function as argument.
|
||||||
func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
|
func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
|
||||||
|
@ -92,23 +102,6 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata)
|
||||||
TypeToString[rtype] = rtypestr
|
TypeToString[rtype] = rtypestr
|
||||||
StringToType[rtypestr] = rtype
|
StringToType[rtypestr] = rtype
|
||||||
|
|
||||||
typeToUnpack[rtype] = func(h RR_Header, msg []byte, off int) (RR, int, error) {
|
|
||||||
if noRdata(h) {
|
|
||||||
return &h, off, nil
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
|
|
||||||
rr := mkPrivateRR(h.Rrtype)
|
|
||||||
rr.Hdr = h
|
|
||||||
|
|
||||||
off1, err := rr.Data.Unpack(msg[off:])
|
|
||||||
off += off1
|
|
||||||
if err != nil {
|
|
||||||
return rr, off, err
|
|
||||||
}
|
|
||||||
return rr, off, err
|
|
||||||
}
|
|
||||||
|
|
||||||
setPrivateRR := func(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) {
|
setPrivateRR := func(h RR_Header, c *zlexer, o, f string) (RR, *ParseError) {
|
||||||
rr := mkPrivateRR(h.Rrtype)
|
rr := mkPrivateRR(h.Rrtype)
|
||||||
rr.Hdr = h
|
rr.Hdr = h
|
||||||
|
@ -146,6 +139,5 @@ func PrivateHandleRemove(rtype uint16) {
|
||||||
delete(TypeToString, rtype)
|
delete(TypeToString, rtype)
|
||||||
delete(typeToparserFunc, rtype)
|
delete(typeToparserFunc, rtype)
|
||||||
delete(StringToType, rtypestr)
|
delete(StringToType, rtypestr)
|
||||||
delete(typeToUnpack, rtype)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue