gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet-go] branch master updated: MS2-RC2: Handle CNAME records with cu


From: gnunet
Subject: [gnunet-go] branch master updated: MS2-RC2: Handle CNAME records with custom block handler.
Date: Wed, 18 Dec 2019 22:22:44 +0100

This is an automated email from the git hooks/post-receive script.

bernd-fix pushed a commit to branch master
in repository gnunet-go.

The following commit(s) were added to refs/heads/master by this push:
     new 65f1f9c  MS2-RC2: Handle CNAME records with custom block handler.
65f1f9c is described below

commit 65f1f9c357307b92a7ee3fc1327f34eb24135667
Author: Bernd Fix <address@hidden>
AuthorDate: Wed Dec 18 22:18:28 2019 +0100

    MS2-RC2: Handle CNAME records with custom block handler.
---
 src/gnunet/service/gns/block_handler.go | 172 +++++++++++++++++++++-----------
 src/gnunet/service/gns/dns.go           |  49 ++++-----
 src/gnunet/service/gns/module.go        | 125 ++++++++++++++++-------
 src/gnunet/util/misc.go                 |  33 ++++++
 4 files changed, 255 insertions(+), 124 deletions(-)

diff --git a/src/gnunet/service/gns/block_handler.go 
b/src/gnunet/service/gns/block_handler.go
index 860b4a7..bf65e95 100644
--- a/src/gnunet/service/gns/block_handler.go
+++ b/src/gnunet/service/gns/block_handler.go
@@ -6,6 +6,7 @@ import (
 
        "gnunet/enums"
        "gnunet/message"
+       "gnunet/util"
 
        "github.com/bfix/gospel/crypto/ed25519"
        "github.com/bfix/gospel/logger"
@@ -16,17 +17,22 @@ type HdlrInst func(*message.GNSResourceRecord, []string) 
(BlockHandler, error)
 
 // Error codes
 var (
-       ErrInvalidRecordMix = fmt.Errorf("Invalid mix of RR types in block")
-       ErrBlockHandler     = fmt.Errorf("Internal block handler failure")
+       ErrInvalidRecordType = fmt.Errorf("Invalid resource record type")
+       ErrInvalidRecordBody = fmt.Errorf("Invalid resource record body")
+       ErrInvalidPKEY       = fmt.Errorf("Invalid PKEY resource record")
+       ErrInvalidCNAME      = fmt.Errorf("Invalid CNAME resource record")
+       ErrInvalidRecordMix  = fmt.Errorf("Invalid mix of RR types in block")
+       ErrBlockHandler      = fmt.Errorf("Internal block handler failure")
 )
 
 // Mapping of RR types to BlockHandler instanciation functions
 var (
        customHandler = map[int]HdlrInst{
-               enums.GNS_TYPE_PKEY:    NewPkeyHandler,
-               enums.GNS_TYPE_GNS2DNS: NewGns2DnsHandler,
-               enums.GNS_TYPE_BOX:     NewBoxHandler,
-               enums.GNS_TYPE_LEHO:    NewLehoHandler,
+               enums.GNS_TYPE_PKEY:      NewPkeyHandler,
+               enums.GNS_TYPE_GNS2DNS:   NewGns2DnsHandler,
+               enums.GNS_TYPE_BOX:       NewBoxHandler,
+               enums.GNS_TYPE_LEHO:      NewLehoHandler,
+               enums.GNS_TYPE_DNS_CNAME: NewCnameHandler,
        }
 )
 
@@ -39,17 +45,17 @@ var (
 
 // BlockHandler interface.
 type BlockHandler interface {
-       // AddRecord inserts a RR into the BlockHandler for (later) processing.
-       // The handler can inspect the remaining labels in a path if required.
-       // It returns an error if a record is not accepted by the block handler.
+       // AddRecord inserts an associated RR into the BlockHandler for (later)
+       // processing. The handler can inspect the remaining labels in a path
+       // if required. The method returns an error if a record is not accepted
+       // by the block handler (RR not of required type).
        AddRecord(rr *message.GNSResourceRecord, labels []string) error
 
-       // TypeAction returns a flag indicating how a resource record of a
-       // given type is to be treated by a custom block handler:
-       //   = -1: Record is not allowed
-       //   =  0: Record is allowed but will be ignored
-       //   =  1: Record is allowed and will be processed
-       TypeAction(t int) int
+       // Coexist checks if a custom block handler can co-exist with other
+       // resource records in the same block. 'cm' maps the resource type
+       // to an integer count (how many records of a type are present in the
+       // GNS block).
+       Coexist(cm util.CounterMap) bool
 
        // Records returns a list of RR of the given types associated with
        // the custom handler
@@ -69,7 +75,8 @@ type BlockHandler interface {
 
 // BlockHandlerList is a list of block handlers instantiated.
 type BlockHandlerList struct {
-       list map[int]BlockHandler // list of handler instances
+       list   map[int]BlockHandler // list of handler instances
+       counts util.CounterMap      // count number of RRs by type
 }
 
 // NewBlockHandlerList instantiates an a list of active block handlers
@@ -77,24 +84,21 @@ type BlockHandlerList struct {
 func NewBlockHandlerList(records []*message.GNSResourceRecord, labels 
[]string) (*BlockHandlerList, error) {
        // initialize block handler list
        hl := &BlockHandlerList{
-               list: make(map[int]BlockHandler),
+               list:   make(map[int]BlockHandler),
+               counts: make(util.CounterMap),
        }
-       // build a list of record types that are handled by a custom handler.
-       rrList := NewRRTypeList(
-               enums.GNS_TYPE_PKEY,
-               enums.GNS_TYPE_GNS2DNS,
-               enums.GNS_TYPE_BOX,
-               enums.GNS_TYPE_LEHO)
 
        // Traverse record list and build list of handler instances
        for _, rec := range records {
-               // check for custom handler type
+               // update counter map
                rrType := int(rec.Type)
-               if rrList.HasType(rrType) {
+               hl.counts.Add(rrType)
+
+               // check for custom handler type
+               if creat, ok := customHandler[rrType]; ok {
                        // check if a handler for given type already exists
                        var (
                                hdlr BlockHandler
-                               ok   bool
                                err  error
                        )
                        if hdlr, ok = hl.list[rrType]; ok {
@@ -105,23 +109,22 @@ func NewBlockHandlerList(records 
[]*message.GNSResourceRecord, labels []string)
                                continue
                        }
                        // create a new handler instance
-                       switch rrType {
-                       case enums.GNS_TYPE_PKEY:
-                               hdlr, err = NewPkeyHandler(rec, labels)
-                       case enums.GNS_TYPE_GNS2DNS:
-                               hdlr, err = NewGns2DnsHandler(rec, labels)
-                       case enums.GNS_TYPE_BOX:
-                               hdlr, err = NewBoxHandler(rec, labels)
-                       case enums.GNS_TYPE_LEHO:
-                               hdlr, err = NewLehoHandler(rec, labels)
-                       }
-                       if err != nil {
+                       if hdlr, err = creat(rec, labels); err != nil {
                                return nil, err
                        }
                        // store handler in list
                        hl.list[rrType] = hdlr
                }
        }
+
+       // Check if all registered handlers in list can co-exist with
+       // all the other records of varying type
+       for _, hdlr := range hl.list {
+               if !hdlr.Coexist(hl.counts) {
+                       return nil, ErrInvalidRecordMix
+               }
+       }
+       // return assembled handler list
        return hl, nil
 }
 
@@ -179,14 +182,11 @@ func (h *PkeyHandler) AddRecord(rec 
*message.GNSResourceRecord, labels []string)
        return nil
 }
 
-// TypeAction return a flag indicating how a resource record of a given type
+// Coexist return a flag indicating how a resource record of a given type
 // is to be treated (see BlockHandler interface)
-func (h *PkeyHandler) TypeAction(t int) int {
-       // no other resource record type is not allowed
-       if t == enums.GNS_TYPE_PKEY {
-               return 1
-       }
-       return -1
+func (h *PkeyHandler) Coexist(cm util.CounterMap) bool {
+       // only one type (GNS_TYPE_PKEY) is present
+       return len(cm) == 1 && cm.Num(enums.GNS_TYPE_PKEY) == 1
 }
 
 // Records returns a list of RR of the given type associated with this handler
@@ -252,11 +252,11 @@ func (h *Gns2DnsHandler) AddRecord(rec 
*message.GNSResourceRecord, labels []stri
        return nil
 }
 
-// TypeAction return a flag indicating how a resource record of a given type
+// Coexist return a flag indicating how a resource record of a given type
 // is to be treated (see BlockHandler interface)
-func (h *Gns2DnsHandler) TypeAction(t int) int {
-       // anything goes...
-       return 1
+func (h *Gns2DnsHandler) Coexist(cm util.CounterMap) bool {
+       // only one type (GNS_TYPE_GNS2DNS) is present
+       return len(cm) == 1 && cm.Num(enums.GNS_TYPE_GNS2DNS) > 0
 }
 
 // Records returns a list of RR of the given type associated with this handler
@@ -317,11 +317,11 @@ func (h *BoxHandler) AddRecord(rec 
*message.GNSResourceRecord, labels []string)
        return nil
 }
 
-// TypeAction return a flag indicating how a resource record of a given type
+// Coexist return a flag indicating how a resource record of a given type
 // is to be treated (see BlockHandler interface)
-func (h *BoxHandler) TypeAction(t int) int {
+func (h *BoxHandler) Coexist(cm util.CounterMap) bool {
        // anything goes...
-       return 1
+       return true
 }
 
 // Records returns a list of RR of the given type associated with this handler
@@ -376,16 +376,17 @@ func (h *LehoHandler) AddRecord(rec 
*message.GNSResourceRecord, labels []string)
        return nil
 }
 
-// TypeAction return a flag indicating how a resource record of a given type
+// Coexist return a flag indicating how a resource record of a given type
 // is to be treated (see BlockHandler interface)
-func (h *LehoHandler) TypeAction(t int) int {
-       // only A and AAAA records allowed beside LEHO
-       switch t {
-       case enums.GNS_TYPE_LEHO, enums.GNS_TYPE_DNS_A, enums.GNS_TYPE_DNS_AAAA:
-               return 1
-       default:
-               return -1
+func (h *LehoHandler) Coexist(cm util.CounterMap) bool {
+       // requires exactly one A/AAAA record alongside single LEHO
+       if len(cm) != 2 {
+               return false
        }
+       if cm.Num(enums.GNS_TYPE_LEHO) != 1 {
+               return false
+       }
+       return cm.Num(enums.GNS_TYPE_DNS_A) == 1 || 
cm.Num(enums.GNS_TYPE_DNS_AAAA) == 1
 }
 
 // Records returns a list of RR of the given type associated with this handler
@@ -396,3 +397,56 @@ func (h *LehoHandler) Records(kind RRTypeList) 
*GNSRecordSet {
        }
        return rs
 }
+
+//----------------------------------------------------------------------
+// CNAME handler
+//----------------------------------------------------------------------
+
+// CnameHandler implementing the BlockHandler interface
+type CnameHandler struct {
+       name string
+       rec  *message.GNSResourceRecord
+}
+
+// NewCnameHandler returns a new BlockHandler instance
+func NewCnameHandler(rec *message.GNSResourceRecord, labels []string) 
(BlockHandler, error) {
+       if int(rec.Type) != enums.GNS_TYPE_DNS_CNAME {
+               return nil, ErrInvalidRecordType
+       }
+       h := &CnameHandler{
+               name: "",
+       }
+       if err := h.AddRecord(rec, labels); err != nil {
+               return nil, err
+       }
+       return h, nil
+}
+
+// AddRecord inserts a CNAME record into the handler.
+func (h *CnameHandler) AddRecord(rec *message.GNSResourceRecord, labels 
[]string) error {
+       if int(rec.Type) != enums.GNS_TYPE_DNS_CNAME {
+               return ErrInvalidRecordType
+       }
+       if h.rec != nil {
+               return ErrInvalidCNAME
+       }
+       _, h.name = DNSNameFromBytes(rec.Data, 0)
+       h.rec = rec
+       return nil
+}
+
+// Coexist return a flag indicating how a resource record of a given type
+// is to be treated (see BlockHandler interface)
+func (h *CnameHandler) Coexist(cm util.CounterMap) bool {
+       // anything goes
+       return true
+}
+
+// Records returns a list of RR of the given type associated with this handler
+func (h *CnameHandler) Records(kind RRTypeList) *GNSRecordSet {
+       rs := NewGNSRecordSet()
+       if kind.HasType(enums.GNS_TYPE_DNS_CNAME) {
+               rs.AddRecord(h.rec)
+       }
+       return rs
+}
diff --git a/src/gnunet/service/gns/dns.go b/src/gnunet/service/gns/dns.go
index fe138b0..18e2b78 100644
--- a/src/gnunet/service/gns/dns.go
+++ b/src/gnunet/service/gns/dns.go
@@ -45,9 +45,11 @@ func DNSNameFromBytes(b []byte, offset int) (int, string) {
        return pos + 1, str
 }
 
-// queryDNS resolves a name on a given nameserver and delivers all matching
-// resource record (of type 'kind') to the result channel.
-func queryDNS(id int, name string, server net.IP, kind RRTypeList, res chan 
*GNSRecordSet) {
+func QueryDNS(id int, name string, server net.IP, kind RRTypeList) 
*GNSRecordSet {
+       // get default nameserver if not defined.
+       if server == nil {
+               server = net.IPv4(8, 8, 8, 8)
+       }
        logger.Printf(logger.DBG, "[dns][%d] Starting query for '%s' on 
'%s'...\n", id, name, server.String())
 
        // assemble query
@@ -80,14 +82,13 @@ func queryDNS(id int, name string, server net.IP, kind 
RRTypeList, res chan *GNS
                                continue
                        }
                        logger.Printf(logger.ERROR, "[dns][%d] Error: %s\n", 
id, errMsg)
-                       res <- nil
+                       return nil
                }
                // process results
                logger.Printf(logger.WARN, "[dns][%d] Response from DNS server 
received (%d/5).\n", id, retry+1)
                if in == nil {
                        logger.Printf(logger.ERROR, "[dns][%d] No results\n", 
id)
-                       res <- nil
-                       return
+                       return nil
                }
                set := NewGNSRecordSet()
                for _, record := range in.Answer {
@@ -118,12 +119,11 @@ func queryDNS(id int, name string, server net.IP, kind 
RRTypeList, res chan *GNS
                                set.AddRecord(rr)
                        }
                }
-               logger.Printf(logger.WARN, "[dns][%d] %d resource records 
extracted from response (%d/5).\n", id, set.Count, retry+1)
-               res <- set
-               return
+               logger.Printf(logger.INFO, "[dns][%d] %d resource records 
extracted from response (%d/5).\n", id, set.Count, retry+1)
+               return set
        }
        logger.Printf(logger.WARN, "[dns][%d] Resolution failed -- giving 
up...\n", id)
-       res <- nil
+       return nil
 }
 
 // ResolveDNS resolves a name in DNS. Multiple DNS servers are queried in
@@ -135,29 +135,16 @@ func (gns *GNSModule) ResolveDNS(name string, servers 
[]string, kind RRTypeList,
        // start DNS queries concurrently
        res := make(chan *GNSRecordSet)
        running := 0
-       for idx, srv := range servers {
+       for _, srv := range servers {
                // check if srv is an IPv4/IPv6 address
                addr := net.ParseIP(srv)
                logger.Printf(logger.DBG, "ParseIP('%s', len=%d) --> %v\n", 
srv, len(srv), addr)
                if addr == nil {
+                       // no, it is a name... try to resolve an IP address 
from the name
                        query := NewRRTypeList(enums.GNS_TYPE_DNS_A, 
enums.GNS_TYPE_DNS_AAAA)
-                       // no; resolve server name in GNS
-                       if strings.HasSuffix(srv, ".+") {
-                               // resolve server name relative to current zone
-                               zone := util.EncodeBinaryToString(pkey.Bytes())
-                               srv = strings.TrimSuffix(srv, ".+")
-                               set, err = gns.Resolve(srv, pkey, query, 
enums.GNS_LO_DEFAULT)
-                               if err != nil {
-                                       logger.Printf(logger.ERROR, "[dns] 
Can't resolve NS server '%s' in '%s'\n", srv, zone)
-                                       continue
-                               }
-                       } else {
-                               // resolve absolute GNS name (name MUST end in 
a PKEY)
-                               set, err = gns.Resolve(srv, nil, query, 
enums.GNS_LO_DEFAULT)
-                               if err != nil {
-                                       logger.Printf(logger.ERROR, "[dns] 
Can't resolve NS server '%s'\n", srv)
-                                       continue
-                               }
+                       if set, err = gns.ResolveUnknown(srv, pkey, query); err 
!= nil {
+                               logger.Printf(logger.ERROR, "[dns] Can't 
resolve NS server '%s': %s\n", srv, err.Error())
+                               continue
                        }
                        // traverse resource records for 'A' and 'AAAA' records.
                rec_loop:
@@ -173,12 +160,14 @@ func (gns *GNSModule) ResolveDNS(name string, servers 
[]string, kind RRTypeList,
                        }
                        // check if we have an IP address available
                        if addr == nil {
-                               logger.Printf(logger.WARN, "[dns] No IP address 
for nameserver in GNS")
+                               logger.Printf(logger.WARN, "[dns] No IP address 
for nameserver '%s'\n", srv)
                                continue
                        }
                }
                // query DNS concurrently
-               go queryDNS(idx, name, addr, kind, res)
+               go func() {
+                       res <- QueryDNS(util.NextID(), name, addr, kind)
+               }()
                running++
        }
        // check if we started some queries at all.
diff --git a/src/gnunet/service/gns/module.go b/src/gnunet/service/gns/module.go
index 3e7bd18..6732e08 100644
--- a/src/gnunet/service/gns/module.go
+++ b/src/gnunet/service/gns/module.go
@@ -20,10 +20,7 @@ import (
 
 // Error codes
 var (
-       ErrUnknownTLD        = fmt.Errorf("Unknown TLD in name")
-       ErrInvalidRecordType = fmt.Errorf("Invalid resource record type")
-       ErrInvalidRecordBody = fmt.Errorf("Invalid resource record body")
-       ErrInvalidPKEY       = fmt.Errorf("Invalid PKEY resource record")
+       ErrUnknownTLD = fmt.Errorf("Unknown TLD in name")
 )
 
 //----------------------------------------------------------------------
@@ -83,7 +80,7 @@ func NewQuery(pkey *ed25519.PublicKey, label string) *Query {
 //          (d) if rec is CNAME record:
 //                  if no remaining labels:
 //                      if requested types include CNAME -> (5)
-//                      if
+//                      -> Resolve(CNAME)
 //      resolution failed: name not completely processed and no zone available
 //
 //  (5) return records: it is the responsibility of the caller to assemble
@@ -119,30 +116,23 @@ func (gns *GNSModule) Resolve(path string, pkey 
*ed25519.PublicKey, kind RRTypeL
 
 // Resolve a fully qualified GNS absolute name (with multiple labels).
 func (gns *GNSModule) ResolveAbsolute(labels []string, kind RRTypeList, mode 
int) (set *GNSRecordSet, err error) {
-       // get the root zone key for the TLD
-       var (
-               pkey *ed25519.PublicKey
-               data []byte
-       )
-       for {
-               // (1) check if TLD is a public key string
-               if len(labels[0]) == 52 {
-                       if data, err = util.DecodeStringToBinary(labels[0], 
32); err == nil {
-                               if pkey = ed25519.NewPublicKeyFromBytes(data); 
pkey != nil {
-                                       break
-                               }
-                       }
-               }
+       // get the zone key for the TLD
+       // (1) check if TLD is a PKEY
+       pkey := gns.GetZoneKey(labels[0])
+       if pkey == nil {
                // (2) check if TLD is in our local config
-               if pkey = config.Cfg.GNS.GetRootZoneKey(labels[0]); pkey != nil 
{
-                       break
-               }
+               pkey = config.Cfg.GNS.GetRootZoneKey(labels[0])
+       }
+       if pkey == nil {
                // (3) check if TLD is one of our identities
-               if pkey, err = gns.GetLocalZone(labels[0]); err == nil {
-                       break
+               pkey, err = gns.GetLocalZone(labels[0])
+       }
+       if pkey == nil {
+               if err == nil {
+                       err = ErrUnknownTLD
                }
                // (4) we can't resolve this TLD
-               return nil, ErrUnknownTLD
+               return
        }
        // continue with resolution relative to a zone.
        return gns.ResolveRelative(labels[1:], pkey, kind, mode)
@@ -156,7 +146,6 @@ func (gns *GNSModule) ResolveRelative(labels []string, pkey 
*ed25519.PublicKey,
                records []*message.GNSResourceRecord // final resource records 
from resolution
                hdlrs   *BlockHandlerList            // list of block handlers 
in final step
        )
-name_loop:
        for ; len(labels) > 0; labels = labels[1:] {
                logger.Printf(logger.DBG, "[gns] ResolveRelative '%s' in 
'%s'\n", labels[0], util.EncodeBinaryToString(pkey.Bytes()))
 
@@ -192,16 +181,24 @@ name_loop:
                if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_PKEY); hdlr != nil {
                        // (1) PKEY record:
                        inst := hdlr.(*PkeyHandler)
-                       // if labels are pending, set new zone and continue 
resolution
-                       if len(labels) > 1 {
-                               pkey = inst.pkey
-                               continue name_loop
+                       // if labels are pending, set new zone and continue 
resolution;
+                       // otherwise resolve "@" label for the zone if no PKEY 
record
+                       // was requested.
+                       pkey = inst.pkey
+                       if len(labels) == 1 && 
!kind.HasType(enums.GNS_TYPE_PKEY) {
+                               labels = append(labels, "@")
                        }
                } else if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_GNS2DNS); 
hdlr != nil {
-                       // (2) GNS2DNS records: delegate resolution to DNS
+                       // (2) GNS2DNS records
                        inst := hdlr.(*Gns2DnsHandler)
-                       // we need to handle delegation to DNS: returns a list 
of found
-                       // resource records in DNS (filter by 'kind')
+                       // if we are at the end of the path and the requested 
type
+                       // includes GNS_TYPE_GNS2DNS, the GNS2DNS records are 
returned...
+                       if len(labels) == 1 && 
kind.HasType(enums.GNS_TYPE_GNS2DNS) {
+                               records = inst.recs
+                               break
+                       }
+                       // ... otherwise we need to handle delegation to DNS: 
returns a
+                       // list of found resource records in DNS (filter by 
'kind')
                        lbls := 
strings.Join(util.ReverseStringList(labels[1:]), ".")
                        if len(lbls) > 0 {
                                lbls += "."
@@ -213,15 +210,30 @@ name_loop:
                        }
                        // we are done with resolution; pass on records to 
caller
                        records = set.Records
-                       break name_loop
+                       break
                } else if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_BOX); hdlr != 
nil {
                        // (3) BOX records:
                        inst := hdlr.(*BoxHandler)
                        new_records := inst.Records(kind).Records
                        if len(new_records) > 0 {
                                records = new_records
-                               break name_loop
+                               break
+                       }
+               } else if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_DNS_CNAME); 
hdlr != nil {
+                       // (4) CNAME records:
+                       inst := hdlr.(*CnameHandler)
+                       // if we are at the end of the path and the requested 
type
+                       // includes GNS_TYPE_DNS_CNAME, the records are 
returned...
+                       if len(labels) == 1 && 
kind.HasType(enums.GNS_TYPE_DNS_CNAME) {
+                               break
                        }
+                       if set, err = gns.ResolveUnknown(inst.name, pkey, 
kind); err != nil {
+                               logger.Println(logger.ERROR, "[gns] CNAME 
resolution failed.")
+                               return
+                       }
+                       // we are done with resolution; pass on records to 
caller
+                       records = set.Records
+                       break
                }
        }
        // Assemble resulting resource record set by filtering for requested 
types.
@@ -237,6 +249,49 @@ name_loop:
        return
 }
 
+// ResolveUnknown resolves a name either in GNS (if applicable) or DNS:
+// If the name is a relative GNS path (ending in ".+"), it is resolved in GNS
+// relative to the zone PKEY. If the name is an absolute GNS name (ending in
+// a PKEY TLD), it is also resolved with GNS. All other names are resolved
+// via DNS queries.
+func (gns *GNSModule) ResolveUnknown(name string, pkey *ed25519.PublicKey, 
kind RRTypeList) (set *GNSRecordSet, err error) {
+       // relative GNS-based server name?
+       if strings.HasSuffix(name, ".+") {
+               // resolve server name relative to current zone
+               name = strings.TrimSuffix(name, ".+")
+               if set, err = gns.Resolve(name, pkey, kind, 
enums.GNS_LO_DEFAULT); err != nil {
+                       return
+               }
+       } else {
+               // check for absolute GNS name (with PKEY as TLD)
+               if zk := gns.GetZoneKey(name); zk != nil {
+                       // resolve absolute GNS name (name ends in a PKEY)
+                       if set, err = gns.Resolve(util.StripPathRight(name), 
zk, kind, enums.GNS_LO_DEFAULT); err != nil {
+                               return
+                       }
+               } else {
+                       // resolve the server name via DNS
+                       if set = QueryDNS(util.NextID(), name, nil, kind); set 
== nil {
+                               err = ErrNoDNSResults
+                       }
+               }
+       }
+       return
+}
+
+// GetZoneKey returns the PKEY (or nil) from an absolute GNS path.
+func (gns *GNSModule) GetZoneKey(path string) *ed25519.PublicKey {
+       labels := util.ReverseStringList(strings.Split(path, "."))
+       if len(labels[0]) == 52 {
+               if data, err := util.DecodeStringToBinary(labels[0], 32); err 
== nil {
+                       if pkey := ed25519.NewPublicKeyFromBytes(data); pkey != 
nil {
+                               return pkey
+                       }
+               }
+       }
+       return nil
+}
+
 // Lookup name in GNS.
 func (gns *GNSModule) Lookup(pkey *ed25519.PublicKey, label string, remote 
bool) (block *GNSBlock, err error) {
 
diff --git a/src/gnunet/util/misc.go b/src/gnunet/util/misc.go
new file mode 100644
index 0000000..6a8a4a3
--- /dev/null
+++ b/src/gnunet/util/misc.go
@@ -0,0 +1,33 @@
+package util
+
+import (
+       "strings"
+)
+
+type CounterMap map[interface{}]int
+
+func (cm CounterMap) Add(i interface{}) int {
+       count, ok := cm[i]
+       if !ok {
+               count = 1
+       } else {
+               count++
+       }
+       cm[i] = count
+       return count
+}
+
+func (cm CounterMap) Num(i interface{}) int {
+       count, ok := cm[i]
+       if !ok {
+               count = 0
+       }
+       return count
+}
+
+func StripPathRight(s string) string {
+       if idx := strings.LastIndex(s, "."); idx != -1 {
+               return s[:idx]
+       }
+       return s
+}

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]