Optimize the RR reading further
remove len(strings) from the code. 16% increase in speed. Getting about 35K RR/s
This commit is contained in:
parent
f3eacbb9fb
commit
ed61734c89
34
defaults.go
34
defaults.go
|
@ -197,26 +197,29 @@ func (dns *Msg) IsEdns0() (ok bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDomainName checks if s is a valid domainname, it returns
|
// IsDomainName checks if s is a valid domainname, it returns
|
||||||
// the number of labels and true, when a domain name is valid. When false
|
// the number of labels, total length and true, when a domain name is valid.
|
||||||
// the returned labelcount isn't specified.
|
// When false the returned labelcount and length is 0 and 0.
|
||||||
func IsDomainName(s string) (uint8, bool) { // copied from net package.
|
func IsDomainName(s string) (uint8, uint8, bool) { // copied from net package.
|
||||||
// See RFC 1035, RFC 3696.
|
// See RFC 1035, RFC 3696.
|
||||||
if len(s) == 0 {
|
l := len(s)
|
||||||
return 0, false
|
if l == 0 || l > 255 {
|
||||||
|
return 0, 0, false
|
||||||
}
|
}
|
||||||
if len(s) > 255 { // Not true...?
|
// Simplify checking loop: make the name end in a dot
|
||||||
return 0, false
|
// Don't call Fqdn() to save another len(s)
|
||||||
}
|
if s[l-1] != '.' {
|
||||||
s = Fqdn(s) // simplify checking loop: make name end in dot
|
s += "."
|
||||||
|
l++
|
||||||
|
}
|
||||||
last := byte('.')
|
last := byte('.')
|
||||||
ok := false // ok once we've seen a letter
|
ok := false // ok once we've seen a letter
|
||||||
partlen := 0
|
partlen := 0
|
||||||
labels := uint8(0)
|
labels := uint8(0)
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < l; i++ {
|
||||||
c := s[i]
|
c := s[i]
|
||||||
switch {
|
switch {
|
||||||
default:
|
default:
|
||||||
return 0, false
|
return 0, uint8(l), false
|
||||||
case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_' || c == '*':
|
case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_' || c == '*':
|
||||||
ok = true
|
ok = true
|
||||||
partlen++
|
partlen++
|
||||||
|
@ -228,28 +231,27 @@ func IsDomainName(s string) (uint8, bool) { // copied from net package.
|
||||||
case c == '-':
|
case c == '-':
|
||||||
// byte before dash cannot be dot
|
// byte before dash cannot be dot
|
||||||
if last == '.' {
|
if last == '.' {
|
||||||
return 0, false
|
return 0, uint8(l), false
|
||||||
}
|
}
|
||||||
partlen++
|
partlen++
|
||||||
case c == '.':
|
case c == '.':
|
||||||
// byte before dot cannot be dot, dash
|
// byte before dot cannot be dot, dash
|
||||||
if last == '.' || last == '-' {
|
if last == '.' || last == '-' {
|
||||||
return 0, false
|
return 0, uint8(l), false
|
||||||
}
|
}
|
||||||
if last == '\\' { // Ok, escaped dot.
|
if last == '\\' { // Ok, escaped dot.
|
||||||
partlen++
|
partlen++
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if partlen > 63 || partlen == 0 {
|
if partlen > 63 || partlen == 0 {
|
||||||
return 0, false
|
return 0, uint8(l), false
|
||||||
}
|
}
|
||||||
partlen = 0
|
partlen = 0
|
||||||
labels++
|
labels++
|
||||||
}
|
}
|
||||||
last = c
|
last = c
|
||||||
}
|
}
|
||||||
|
return labels, uint8(l), ok
|
||||||
return labels, ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsFqdn checks if a domain name is fully qualified
|
// IsFqdn checks if a domain name is fully qualified
|
||||||
|
|
|
@ -201,7 +201,7 @@ func (s *RR_RRSIG) Sign(k PrivateKey, rrset []RR) error {
|
||||||
s.OrigTtl = rrset[0].Header().Ttl
|
s.OrigTtl = rrset[0].Header().Ttl
|
||||||
s.TypeCovered = rrset[0].Header().Rrtype
|
s.TypeCovered = rrset[0].Header().Rrtype
|
||||||
s.TypeCovered = rrset[0].Header().Rrtype
|
s.TypeCovered = rrset[0].Header().Rrtype
|
||||||
s.Labels, _ = IsDomainName(rrset[0].Header().Name)
|
s.Labels, _, _ = IsDomainName(rrset[0].Header().Name)
|
||||||
// ...
|
// ...
|
||||||
if strings.HasPrefix(rrset[0].Header().Name, "*") {
|
if strings.HasPrefix(rrset[0].Header().Name, "*") {
|
||||||
s.Labels-- // wildcard, remove from label count
|
s.Labels-- // wildcard, remove from label count
|
||||||
|
|
|
@ -7,15 +7,14 @@
|
||||||
# explain
|
# explain
|
||||||
.,CH,TXT,QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,1,0,0,0,DO,65535,NSID
|
.,CH,TXT,QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,1,0,0,0,DO,65535,NSID
|
||||||
# explain
|
# explain
|
||||||
.,IN,TXT,QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,1,0,0,0,DO,128,NSID
|
|
||||||
.,IN,TXT,QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,1,0,0,0,DO,127,NSID
|
.,IN,TXT,QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,1,0,0,0,DO,127,NSID
|
||||||
# explain
|
# explain
|
||||||
.,CH,TXT,UPDATE,NOERROR,qr,AA,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid
|
.,CH,TXT,UPDATE,NOERROR,qr,AA,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid
|
||||||
.,CH,TXT,UPDATE,BADTRUNC,qr,AA,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid
|
.,CH,TXT,UPDATE,BADTRUNC,qr,AA,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid
|
||||||
# explain
|
# explain
|
||||||
.,IN,TXT,IQUERY,NOERROR,qr,AA,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid
|
.,IN,TXT,IQUERY,NOERROR,qr,AA,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid
|
||||||
.,IN,TXT,QUERY,NOERROR,qr,AA,tc,RD,ra,ad,cd,z,1,0,0,0,DO,128,nsid
|
.,IN,TXT,QUERY,NOERROR,qr,AA,tc,RD,ra,ad,cd,z,1,0,0,0,DO,768,nsid
|
||||||
.,IN,TXT,QUERY,NOERROR,qr,AA,tc,RD,ra,ad,cd,z,1,0,0,0,DO,128,nsid
|
.,IN,TXT,QUERY,NOERROR,qr,AA,tc,RD,ra,ad,cd,z,1,0,0,0,DO,801,nsid
|
||||||
# explain
|
# explain
|
||||||
.,IN,TXT,STATUS,NOERROR,qr,AA,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid
|
.,IN,TXT,STATUS,NOERROR,qr,AA,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid
|
||||||
# explain
|
# explain
|
||||||
|
|
23
zscan.go
23
zscan.go
|
@ -161,11 +161,12 @@ func parseZone(r io.Reader, f string, t chan Token, include int) {
|
||||||
st = _EXPECT_OWNER_DIR
|
st = _EXPECT_OWNER_DIR
|
||||||
case _OWNER:
|
case _OWNER:
|
||||||
h.Name = l.token
|
h.Name = l.token
|
||||||
if _, ok := IsDomainName(l.token); !ok {
|
_, ld, ok := IsDomainName(l.token)
|
||||||
|
if !ok {
|
||||||
t <- Token{Error: &ParseError{f, "bad owner name", l}}
|
t <- Token{Error: &ParseError{f, "bad owner name", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !IsFqdn(h.Name) {
|
if h.Name[ld-1] != '.' {
|
||||||
h.Name += origin
|
h.Name += origin
|
||||||
}
|
}
|
||||||
st = _EXPECT_OWNER_BL
|
st = _EXPECT_OWNER_BL
|
||||||
|
@ -378,8 +379,10 @@ func zlexer(s scanner.Scanner, c chan lex) {
|
||||||
c <- l
|
c <- l
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch x := s.TokenText(); x {
|
// Each token we get is one byte, so we switch on that x[0]. This
|
||||||
case " ", "\t":
|
// avoids a len(x) that Go otherwise will perform when comparing strings.
|
||||||
|
switch x := s.TokenText(); x[0] {
|
||||||
|
case ' ', '\t':
|
||||||
escape = false
|
escape = false
|
||||||
if commt {
|
if commt {
|
||||||
break
|
break
|
||||||
|
@ -424,7 +427,7 @@ func zlexer(s scanner.Scanner, c chan lex) {
|
||||||
}
|
}
|
||||||
owner = false
|
owner = false
|
||||||
space = true
|
space = true
|
||||||
case ";":
|
case ';':
|
||||||
if escape {
|
if escape {
|
||||||
escape = false
|
escape = false
|
||||||
str[stri] = ';'
|
str[stri] = ';'
|
||||||
|
@ -438,7 +441,7 @@ func zlexer(s scanner.Scanner, c chan lex) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
commt = true
|
commt = true
|
||||||
case "\n":
|
case '\n':
|
||||||
// Hmmm, escape newline
|
// Hmmm, escape newline
|
||||||
escape = false
|
escape = false
|
||||||
if commt {
|
if commt {
|
||||||
|
@ -485,7 +488,7 @@ func zlexer(s scanner.Scanner, c chan lex) {
|
||||||
commt = false
|
commt = false
|
||||||
rrtype = false
|
rrtype = false
|
||||||
owner = true
|
owner = true
|
||||||
case "\\":
|
case '\\':
|
||||||
if commt {
|
if commt {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -498,7 +501,7 @@ func zlexer(s scanner.Scanner, c chan lex) {
|
||||||
str[stri] = '\\'
|
str[stri] = '\\'
|
||||||
stri++
|
stri++
|
||||||
escape = true
|
escape = true
|
||||||
case "\"":
|
case '"':
|
||||||
if commt {
|
if commt {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -510,7 +513,7 @@ func zlexer(s scanner.Scanner, c chan lex) {
|
||||||
}
|
}
|
||||||
// str += "\"" don't add quoted quotes
|
// str += "\"" don't add quoted quotes
|
||||||
quote = !quote
|
quote = !quote
|
||||||
case "(":
|
case '(':
|
||||||
if commt {
|
if commt {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -521,7 +524,7 @@ func zlexer(s scanner.Scanner, c chan lex) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
brace++
|
brace++
|
||||||
case ")":
|
case ')':
|
||||||
if commt {
|
if commt {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
40
zscan_rr.go
40
zscan_rr.go
|
@ -123,10 +123,11 @@ func setNS(h RR_Header, c chan lex, o, f string) (RR, *ParseError) {
|
||||||
|
|
||||||
l := <-c
|
l := <-c
|
||||||
rr.Ns = l.token
|
rr.Ns = l.token
|
||||||
if _, ok := IsDomainName(l.token); !ok {
|
_, ld, ok := IsDomainName(l.token)
|
||||||
|
if !ok {
|
||||||
return nil, &ParseError{f, "bad NS Ns", l}
|
return nil, &ParseError{f, "bad NS Ns", l}
|
||||||
}
|
}
|
||||||
if !IsFqdn(rr.Ns) {
|
if rr.Ns[ld-1]!= '.' {
|
||||||
rr.Ns += o
|
rr.Ns += o
|
||||||
}
|
}
|
||||||
return rr, nil
|
return rr, nil
|
||||||
|
@ -145,10 +146,11 @@ func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError) {
|
||||||
<-c // _BLANK
|
<-c // _BLANK
|
||||||
l = <-c // _STRING
|
l = <-c // _STRING
|
||||||
rr.Mx = l.token
|
rr.Mx = l.token
|
||||||
if _, ok := IsDomainName(l.token); !ok {
|
_, ld, ok := IsDomainName(l.token)
|
||||||
|
if !ok {
|
||||||
return nil, &ParseError{f, "bad MX Mx", l}
|
return nil, &ParseError{f, "bad MX Mx", l}
|
||||||
}
|
}
|
||||||
if !IsFqdn(rr.Mx) {
|
if rr.Mx[ld-1] != '.' {
|
||||||
rr.Mx += o
|
rr.Mx += o
|
||||||
}
|
}
|
||||||
return rr, nil
|
return rr, nil
|
||||||
|
@ -160,10 +162,11 @@ func setCNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError) {
|
||||||
|
|
||||||
l := <-c
|
l := <-c
|
||||||
rr.Cname = l.token
|
rr.Cname = l.token
|
||||||
if _, ok := IsDomainName(l.token); !ok {
|
_, ld, ok := IsDomainName(l.token)
|
||||||
|
if !ok {
|
||||||
return nil, &ParseError{f, "bad CNAME", l}
|
return nil, &ParseError{f, "bad CNAME", l}
|
||||||
}
|
}
|
||||||
if !IsFqdn(rr.Cname) {
|
if rr.Cname[ld-1] != '.' {
|
||||||
rr.Cname += o
|
rr.Cname += o
|
||||||
}
|
}
|
||||||
return rr, nil
|
return rr, nil
|
||||||
|
@ -176,19 +179,21 @@ func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError) {
|
||||||
l := <-c
|
l := <-c
|
||||||
rr.Ns = l.token
|
rr.Ns = l.token
|
||||||
<-c // _BLANK
|
<-c // _BLANK
|
||||||
if _, ok := IsDomainName(l.token); !ok {
|
_, ld, ok := IsDomainName(l.token)
|
||||||
|
if !ok {
|
||||||
return nil, &ParseError{f, "bad SOA mname", l}
|
return nil, &ParseError{f, "bad SOA mname", l}
|
||||||
}
|
}
|
||||||
if !IsFqdn(rr.Ns) {
|
if rr.Ns[ld-1] != '.' {
|
||||||
rr.Ns += o
|
rr.Ns += o
|
||||||
}
|
}
|
||||||
|
|
||||||
l = <-c
|
l = <-c
|
||||||
rr.Mbox = l.token
|
rr.Mbox = l.token
|
||||||
if _, ok := IsDomainName(l.token); !ok {
|
_, ld, ok = IsDomainName(l.token)
|
||||||
|
if !ok {
|
||||||
return nil, &ParseError{f, "bad SOA rname", l}
|
return nil, &ParseError{f, "bad SOA rname", l}
|
||||||
}
|
}
|
||||||
if !IsFqdn(rr.Mbox) {
|
if rr.Mbox[ld-1]!='.' {
|
||||||
rr.Mbox += o
|
rr.Mbox += o
|
||||||
}
|
}
|
||||||
<-c // _BLANK
|
<-c // _BLANK
|
||||||
|
@ -274,10 +279,11 @@ func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError) {
|
||||||
<-c // _BLANK
|
<-c // _BLANK
|
||||||
l = <-c
|
l = <-c
|
||||||
rr.SignerName = l.token
|
rr.SignerName = l.token
|
||||||
if _, ok := IsDomainName(l.token); !ok {
|
_, ld, ok := IsDomainName(l.token)
|
||||||
|
if !ok {
|
||||||
return nil, &ParseError{f, "bad RRSIG signername", l}
|
return nil, &ParseError{f, "bad RRSIG signername", l}
|
||||||
}
|
}
|
||||||
if !IsFqdn(rr.SignerName) {
|
if rr.SignerName[ld-1] != '.' {
|
||||||
rr.SignerName += o
|
rr.SignerName += o
|
||||||
}
|
}
|
||||||
// Get the remaining data until we see a NEWLINE
|
// Get the remaining data until we see a NEWLINE
|
||||||
|
@ -304,10 +310,11 @@ func setNSEC(h RR_Header, c chan lex, o, f string) (RR, *ParseError) {
|
||||||
|
|
||||||
l := <-c
|
l := <-c
|
||||||
rr.NextDomain = l.token
|
rr.NextDomain = l.token
|
||||||
if _, ok := IsDomainName(l.token); !ok {
|
_, ld, ok := IsDomainName(l.token)
|
||||||
|
if !ok {
|
||||||
return nil, &ParseError{f, "bad NSEC nextdomain", l}
|
return nil, &ParseError{f, "bad NSEC nextdomain", l}
|
||||||
}
|
}
|
||||||
if !IsFqdn(rr.NextDomain) {
|
if rr.NextDomain[ld-1] != '.' {
|
||||||
rr.NextDomain += o
|
rr.NextDomain += o
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,10 +371,11 @@ func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError) {
|
||||||
l = <-c
|
l = <-c
|
||||||
rr.HashLength = uint8(len(l.token))
|
rr.HashLength = uint8(len(l.token))
|
||||||
rr.NextDomain = l.token
|
rr.NextDomain = l.token
|
||||||
if _, ok := IsDomainName(l.token); !ok {
|
_, ld, ok := IsDomainName(l.token)
|
||||||
|
if !ok {
|
||||||
return nil, &ParseError{f, "bad NSEC nextdomain", l}
|
return nil, &ParseError{f, "bad NSEC nextdomain", l}
|
||||||
}
|
}
|
||||||
if !IsFqdn(rr.NextDomain) {
|
if rr.NextDomain[ld-1] != '.' {
|
||||||
rr.NextDomain += o
|
rr.NextDomain += o
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue