refactoring

pull/18/head
Hugo Landau 10 years ago
parent b43778c158
commit 13d64f59a7

@ -8,6 +8,8 @@ import "encoding/hex"
import "fmt" import "fmt"
import "strings" import "strings"
import "net" import "net"
import "github.com/hlandau/ncdns/namecoin"
import "github.com/hlandau/ncdns/ncerr"
type Backend interface { type Backend interface {
// Lookup all resource records having a given fully-qualified owner name, // Lookup all resource records having a given fully-qualified owner name,
@ -25,7 +27,7 @@ type Backend interface {
type ncBackend struct { type ncBackend struct {
s *Server s *Server
nc NamecoinConn nc namecoin.NamecoinConn
cache lru.Cache // items are of type *Domain cache lru.Cache // items are of type *Domain
} }
@ -125,7 +127,7 @@ func (tx *Btx) determineDomain() (subname, basename, rootname string, err error)
parts := strings.Split(qname, ".") parts := strings.Split(qname, ".")
if len(parts) < 2 { if len(parts) < 2 {
if parts[0] != "bit" { if parts[0] != "bit" {
err = ErrNotInZone err = ncerr.ErrNotInZone
return return
} }
@ -150,7 +152,7 @@ func (tx *Btx) determineDomain() (subname, basename, rootname string, err error)
} }
} }
err = ErrNotInZone err = ncerr.ErrNotInZone
return return
} }
@ -165,7 +167,7 @@ func (tx *Btx) Do() (rrs []dns.RR, err error) {
if tx.rootname == "" { if tx.rootname == "" {
// REFUSED // REFUSED
return nil, ErrNotInZone return nil, ncerr.ErrNotInZone
} }
if tx.subname == "" && tx.basename == "" { if tx.subname == "" && tx.basename == "" {
@ -272,7 +274,7 @@ func (tx *Btx) doUserDomain() (rrs []dns.RR, err error) {
func (tx *Btx) doUnderDomain(d *Domain) (rrs []dns.RR, err error) { func (tx *Btx) doUnderDomain(d *Domain) (rrs []dns.RR, err error) {
rrs, err = tx.addAnswersUnderNCValue(d.ncv, tx.subname) rrs, err = tx.addAnswersUnderNCValue(d.ncv, tx.subname)
if err == ErrNoResults { if err == ncerr.ErrNoResults {
err = nil err = nil
} }
@ -315,14 +317,14 @@ func (tx *Btx) _findNCValue(ncv *ncValue, isubname, subname string, depth int,
if !ok { if !ok {
sub, ok = ncv.Map["*"] sub, ok = ncv.Map["*"]
if !ok { if !ok {
return nil, "", ErrNoSuchDomain return nil, "", ncerr.ErrNoSuchDomain
} }
} }
return tx._findNCValue(sub, rest, head + "." + subname, depth+1, shortCircuitFunc) return tx._findNCValue(sub, rest, head + "." + subname, depth+1, shortCircuitFunc)
} }
if shortCircuitFunc != nil { if shortCircuitFunc != nil {
return nil, subname, ErrNoSuchDomain return nil, subname, ncerr.ErrNoSuchDomain
} }
return ncv, subname, nil return ncv, subname, nil
@ -493,16 +495,6 @@ func (ncv *ncValue) GetDSs() (dss []dns.DS, err error) {
// f[b]("a", "b.c.d.e.f.g.zzz.bit") // f[b]("a", "b.c.d.e.f.g.zzz.bit")
// f[a]("", "a.b.c.d.e.f.g.zzz.bit") // f[a]("", "a.b.c.d.e.f.g.zzz.bit")
func absname(n string) string {
if n == "" {
return "."
}
if n[len(n)-1] != '.' {
return n + "."
}
return n
}
// Do low-level queries against an abstract zone file. // Do low-level queries against an abstract zone file.
func (b *ncBackend) Lookup(qname string) (rrs []dns.RR, err error) { func (b *ncBackend) Lookup(qname string) (rrs []dns.RR, err error) {
btx := &Btx{} btx := &Btx{}

@ -1,10 +1,14 @@
package main package namecoin
// btcjson had to be modified a bit to get correct error reporting.
import "github.com/hlandauf/btcjson" import "github.com/hlandauf/btcjson"
import "github.com/hlandau/ncdns/ncerr"
import "encoding/json" import "encoding/json"
import "sync/atomic" import "sync/atomic"
import "fmt" import "fmt"
//import "github.com/hlandau/degoutils/log"
// Used for generating IDs for JSON-RPC requests.
var idCounter int32 = 0 var idCounter int32 = 0
func newID() int32 { func newID() int32 {
@ -108,7 +112,7 @@ func (nc *NamecoinConn) Query(name string) (v string, err error) {
if r.Error != nil { if r.Error != nil {
//log.Info("RPC error: ", r.Error) //log.Info("RPC error: ", r.Error)
if r.Error.Code == -4 { if r.Error.Code == -4 {
return "", ErrNoSuchDomain return "", ncerr.ErrNoSuchDomain
} }
return "", r.Error return "", r.Error
} }

@ -8,6 +8,7 @@ import "fmt"
import "strings" import "strings"
import "sort" import "sort"
import "github.com/hlandau/degoutils/config" import "github.com/hlandau/degoutils/config"
import "github.com/hlandau/ncdns/ncerr"
// A Go daemon to serve Namecoin domain records via DNS. // A Go daemon to serve Namecoin domain records via DNS.
// This daemon is intended to be used in one of the following situations: // This daemon is intended to be used in one of the following situations:
@ -161,10 +162,6 @@ func (s *Server) runListener(net string) *dns.Server {
return ds return ds
} }
var ErrNoSuchDomain = rerrorf(dns.RcodeNameError, "no such domain")
var ErrNotInZone = rerrorf(dns.RcodeRefused, "domain not in zone")
var ErrNoResults = rerrorf(0, "no results")
type Tx struct { type Tx struct {
req *dns.Msg req *dns.Msg
res *dns.Msg res *dns.Msg
@ -224,9 +221,9 @@ func (s *Server) handle(rw dns.ResponseWriter, reqMsg *dns.Msg) {
err := tx.addAnswers() err := tx.addAnswers()
if err != nil { if err != nil {
if err == ErrNoResults { if err == ncerr.ErrNoResults {
tx.rcode = 0 tx.rcode = 0
} else if err == ErrNoSuchDomain { } else if err == ncerr.ErrNoSuchDomain {
tx.rcode = dns.RcodeNameError tx.rcode = dns.RcodeNameError
} else if tx.rcode == 0 { } else if tx.rcode == 0 {
log.Infoe(err, "Handler error, doing SERVFAIL") log.Infoe(err, "Handler error, doing SERVFAIL")
@ -248,7 +245,7 @@ func (tx *Tx) blookup(qname string) (rrs []dns.RR, err error) {
log.Info("blookup: ", qname) log.Info("blookup: ", qname)
rrs, err = tx.s.b.Lookup(qname) rrs, err = tx.s.b.Lookup(qname)
if err == nil && len(rrs) == 0 { if err == nil && len(rrs) == 0 {
err = ErrNoResults err = ncerr.ErrNoResults
} }
return return
} }
@ -380,7 +377,7 @@ A:
if soa == nil { if soa == nil {
// If we didn't even get a SOA at any point, we don't have any appropriate zone for this query. // If we didn't even get a SOA at any point, we don't have any appropriate zone for this query.
return ErrNotInZone return ncerr.ErrNotInZone
} }
tx.soa = soa tx.soa = soa

@ -0,0 +1,35 @@
package ncerr
import "github.com/miekg/dns"
import "fmt"
// An Error interface which allows an associated rcode to be queried.
type Error interface {
error
Rcode() int
}
type Rerr struct {
error
e error
rcode int
}
func (re *Rerr) Error() string {
return re.e.Error()
}
func (re *Rerr) Rcode() int {
return re.rcode
}
func rerrorf(rcode int, fmts string, args ...interface{}) Error {
re := &Rerr{}
re.e = fmt.Errorf(fmts, args...)
re.rcode = rcode
return re
}
// Standard errors.
var ErrNoSuchDomain = rerrorf(dns.RcodeNameError, "no such domain")
var ErrNotInZone = rerrorf(dns.RcodeRefused, "domain not in zone")
var ErrNoResults = rerrorf(0, "no results")

@ -6,6 +6,18 @@ import "github.com/miekg/dns"
import "github.com/hlandau/degoutils/log" import "github.com/hlandau/degoutils/log"
import "time" import "time"
// miekg/dns demands a superflous trailing dot, this makes sure it is correctly appended.
func absname(n string) string {
if n == "" {
return "."
}
if n[len(n)-1] != '.' {
return n + "."
}
return n
}
// Split a domain name a.b.c.d.e into parts a (the head) and b.c.d.e (the rest).
func splitDomainHead(name string) (head string, rest string, err error) { func splitDomainHead(name string) (head string, rest string, err error) {
parts := strings.Split(name, ".") parts := strings.Split(name, ".")
@ -18,32 +30,25 @@ func splitDomainHead(name string) (head string, rest string, err error) {
return return
} }
// unused // Determines if a transaction should be considered to have the given query type.
func splitDomainName(name string) (parts []string) { // Returns true iff the query type was qtype or ANY.
if len(name) == 0 { func (tx *Tx) istype(qtype uint16) bool {
return return tx.qtype == qtype || tx.qtype == dns.TypeANY
}
if name[len(name)-1] == '.' {
name = name[0:len(name)-1]
}
parts = strings.Split(name, ".")
return
} }
func (tx *Tx) istype(x uint16) bool { // This is used in NSEC3 hash generation. A hash like ...decafbad has one added
return tx.qtype == x || tx.qtype == dns.TypeANY // to it so that it becomes ...decafbae. This is needed because NSEC3's hashes
} // are inclusive-exclusive (i.e. "[,)"), and we want a hash that covers only the
// name specified.
func stepName(n string) string { //
if len(n) == 0 { // Takes a hash in base32hex form.
func stepName(hashB32Hex string) string {
if len(hashB32Hex) == 0 {
return "" return ""
} }
b, err := base32.HexEncoding.DecodeString(n) b, err := base32.HexEncoding.DecodeString(hashB32Hex)
log.Panice(err, n) log.Panice(err, hashB32Hex)
for i := len(b)-1; i>=0; i-- { for i := len(b)-1; i>=0; i-- {
b[i] += 1 b[i] += 1
@ -55,8 +60,8 @@ func stepName(n string) string {
return base32.HexEncoding.EncodeToString(b) return base32.HexEncoding.EncodeToString(b)
} }
// Returns true iff a type should be covered by a RRSIG.
func shouldSignType(t uint16, isAuthoritySection bool) bool { func shouldSignType(t uint16, isAuthoritySection bool) bool {
//log.Info("shouldSignType ", t, " ", isAuthoritySection)
switch t { switch t {
case dns.TypeOPT: case dns.TypeOPT:
return false return false
@ -67,6 +72,7 @@ func shouldSignType(t uint16, isAuthoritySection bool) bool {
} }
} }
// Returns true iff a client requested DNSSEC.
func (tx *Tx) useDNSSEC() bool { func (tx *Tx) useDNSSEC() bool {
opt := tx.req.IsEdns0() opt := tx.req.IsEdns0()
if opt == nil { if opt == nil {
@ -75,38 +81,18 @@ func (tx *Tx) useDNSSEC() bool {
return opt.Do() return opt.Do()
} }
// Sets an rcode for the response if there is no error rcode currently set for
// the response. The idea is to return the rcode corresponding to the first
// error which occurs.
func (tx *Tx) setRcode(x int) { func (tx *Tx) setRcode(x int) {
if tx.rcode == 0 { if tx.rcode == 0 {
tx.rcode = x tx.rcode = x
} }
} }
type Error interface {
error
Rcode() int
}
type Rerr struct {
error
e error
rcode int
}
func (re *Rerr) Error() string {
return re.e.Error()
}
func (re *Rerr) Rcode() int {
return re.rcode
}
func rerrorf(rcode int, fmts string, args ...interface{}) Error {
re := &Rerr{}
re.e = fmt.Errorf(fmts, args...)
re.rcode = rcode
return re
}
// Determines the maximum TTL for a slice of resource records.
// Returns 0 if the slice is empty.
func rraMaxTTL(rra []dns.RR) uint32 { func rraMaxTTL(rra []dns.RR) uint32 {
x := uint32(0) x := uint32(0)
for _, rr := range rra { for _, rr := range rra {
@ -118,6 +104,7 @@ func rraMaxTTL(rra []dns.RR) uint32 {
return x return x
} }
// Used by signResponseSection.
func (tx *Tx) signRRs(rra []dns.RR, useKSK bool) (dns.RR, error) { func (tx *Tx) signRRs(rra []dns.RR, useKSK bool) (dns.RR, error) {
if len(rra) == 0 { if len(rra) == 0 {
return nil, fmt.Errorf("no RRs to such") return nil, fmt.Errorf("no RRs to such")
@ -152,6 +139,7 @@ func (tx *Tx) signRRs(rra []dns.RR, useKSK bool) (dns.RR, error) {
return rrsig, nil return rrsig, nil
} }
// Used by signResponse.
func (tx *Tx) signResponseSection(rra *[]dns.RR) error { func (tx *Tx) signResponseSection(rra *[]dns.RR) error {
if len(*rra) == 0 { if len(*rra) == 0 {
return nil return nil
@ -202,6 +190,8 @@ func (tx *Tx) signResponseSection(rra *[]dns.RR) error {
return nil return nil
} }
// This is called to append RRSIGs to the response based on the current records in the Answer and
// Authority sections of the response. Records in the Additional section are not signed.
func (tx *Tx) signResponse() error { func (tx *Tx) signResponse() error {
if !tx.useDNSSEC() { if !tx.useDNSSEC() {
return nil return nil
@ -219,6 +209,7 @@ func (tx *Tx) signResponse() error {
return nil return nil
} }
// Used for sorting RRTYPE lists for encoding into type bit maps.
type uint16Slice []uint16 type uint16Slice []uint16
func (p uint16Slice) Len() int { return len(p) } func (p uint16Slice) Len() int { return len(p) }
func (p uint16Slice) Less(i, j int) bool { return p[i] < p[j] } func (p uint16Slice) Less(i, j int) bool { return p[i] < p[j] }

Loading…
Cancel
Save