2
0
mirror of https://github.com/namecoin/ncdns synced 2024-11-10 01:10:31 +00:00

refactoring

This commit is contained in:
Hugo Landau 2014-10-21 20:42:44 +01:00
parent b43778c158
commit 13d64f59a7
5 changed files with 94 additions and 75 deletions

View File

@ -8,6 +8,8 @@ import "encoding/hex"
import "fmt"
import "strings"
import "net"
import "github.com/hlandau/ncdns/namecoin"
import "github.com/hlandau/ncdns/ncerr"
type Backend interface {
// Lookup all resource records having a given fully-qualified owner name,
@ -25,7 +27,7 @@ type Backend interface {
type ncBackend struct {
s *Server
nc NamecoinConn
nc namecoin.NamecoinConn
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, ".")
if len(parts) < 2 {
if parts[0] != "bit" {
err = ErrNotInZone
err = ncerr.ErrNotInZone
return
}
@ -150,7 +152,7 @@ func (tx *Btx) determineDomain() (subname, basename, rootname string, err error)
}
}
err = ErrNotInZone
err = ncerr.ErrNotInZone
return
}
@ -165,7 +167,7 @@ func (tx *Btx) Do() (rrs []dns.RR, err error) {
if tx.rootname == "" {
// REFUSED
return nil, ErrNotInZone
return nil, ncerr.ErrNotInZone
}
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) {
rrs, err = tx.addAnswersUnderNCValue(d.ncv, tx.subname)
if err == ErrNoResults {
if err == ncerr.ErrNoResults {
err = nil
}
@ -315,14 +317,14 @@ func (tx *Btx) _findNCValue(ncv *ncValue, isubname, subname string, depth int,
if !ok {
sub, ok = ncv.Map["*"]
if !ok {
return nil, "", ErrNoSuchDomain
return nil, "", ncerr.ErrNoSuchDomain
}
}
return tx._findNCValue(sub, rest, head + "." + subname, depth+1, shortCircuitFunc)
}
if shortCircuitFunc != nil {
return nil, subname, ErrNoSuchDomain
return nil, subname, ncerr.ErrNoSuchDomain
}
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[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.
func (b *ncBackend) Lookup(qname string) (rrs []dns.RR, err error) {
btx := &Btx{}

View File

@ -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/hlandau/ncdns/ncerr"
import "encoding/json"
import "sync/atomic"
import "fmt"
//import "github.com/hlandau/degoutils/log"
// Used for generating IDs for JSON-RPC requests.
var idCounter int32 = 0
func newID() int32 {
@ -108,7 +112,7 @@ func (nc *NamecoinConn) Query(name string) (v string, err error) {
if r.Error != nil {
//log.Info("RPC error: ", r.Error)
if r.Error.Code == -4 {
return "", ErrNoSuchDomain
return "", ncerr.ErrNoSuchDomain
}
return "", r.Error
}

View File

@ -8,6 +8,7 @@ import "fmt"
import "strings"
import "sort"
import "github.com/hlandau/degoutils/config"
import "github.com/hlandau/ncdns/ncerr"
// A Go daemon to serve Namecoin domain records via DNS.
// 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
}
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 {
req *dns.Msg
res *dns.Msg
@ -224,9 +221,9 @@ func (s *Server) handle(rw dns.ResponseWriter, reqMsg *dns.Msg) {
err := tx.addAnswers()
if err != nil {
if err == ErrNoResults {
if err == ncerr.ErrNoResults {
tx.rcode = 0
} else if err == ErrNoSuchDomain {
} else if err == ncerr.ErrNoSuchDomain {
tx.rcode = dns.RcodeNameError
} else if tx.rcode == 0 {
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)
rrs, err = tx.s.b.Lookup(qname)
if err == nil && len(rrs) == 0 {
err = ErrNoResults
err = ncerr.ErrNoResults
}
return
}
@ -380,7 +377,7 @@ A:
if soa == nil {
// 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

35
ncerr/ncerr.go Normal file
View File

@ -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")

85
util.go
View File

@ -6,6 +6,18 @@ import "github.com/miekg/dns"
import "github.com/hlandau/degoutils/log"
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) {
parts := strings.Split(name, ".")
@ -18,32 +30,25 @@ func splitDomainHead(name string) (head string, rest string, err error) {
return
}
// unused
func splitDomainName(name string) (parts []string) {
if len(name) == 0 {
return
}
if name[len(name)-1] == '.' {
name = name[0:len(name)-1]
}
parts = strings.Split(name, ".")
return
// Determines if a transaction should be considered to have the given query type.
// Returns true iff the query type was qtype or ANY.
func (tx *Tx) istype(qtype uint16) bool {
return tx.qtype == qtype || tx.qtype == dns.TypeANY
}
func (tx *Tx) istype(x uint16) bool {
return tx.qtype == x || tx.qtype == dns.TypeANY
}
func stepName(n string) string {
if len(n) == 0 {
// This is used in NSEC3 hash generation. A hash like ...decafbad has one added
// 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.
//
// Takes a hash in base32hex form.
func stepName(hashB32Hex string) string {
if len(hashB32Hex) == 0 {
return ""
}
b, err := base32.HexEncoding.DecodeString(n)
log.Panice(err, n)
b, err := base32.HexEncoding.DecodeString(hashB32Hex)
log.Panice(err, hashB32Hex)
for i := len(b)-1; i>=0; i-- {
b[i] += 1
@ -55,8 +60,8 @@ func stepName(n string) string {
return base32.HexEncoding.EncodeToString(b)
}
// Returns true iff a type should be covered by a RRSIG.
func shouldSignType(t uint16, isAuthoritySection bool) bool {
//log.Info("shouldSignType ", t, " ", isAuthoritySection)
switch t {
case dns.TypeOPT:
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 {
opt := tx.req.IsEdns0()
if opt == nil {
@ -75,38 +81,18 @@ func (tx *Tx) useDNSSEC() bool {
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) {
if tx.rcode == 0 {
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 {
x := uint32(0)
for _, rr := range rra {
@ -118,6 +104,7 @@ func rraMaxTTL(rra []dns.RR) uint32 {
return x
}
// Used by signResponseSection.
func (tx *Tx) signRRs(rra []dns.RR, useKSK bool) (dns.RR, error) {
if len(rra) == 0 {
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
}
// Used by signResponse.
func (tx *Tx) signResponseSection(rra *[]dns.RR) error {
if len(*rra) == 0 {
return nil
@ -202,6 +190,8 @@ func (tx *Tx) signResponseSection(rra *[]dns.RR) error {
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 {
if !tx.useDNSSEC() {
return nil
@ -219,6 +209,7 @@ func (tx *Tx) signResponse() error {
return nil
}
// Used for sorting RRTYPE lists for encoding into type bit maps.
type uint16Slice []uint16
func (p uint16Slice) Len() int { return len(p) }
func (p uint16Slice) Less(i, j int) bool { return p[i] < p[j] }