Files
Reticulum-Go/pkg/resolver/resolver.go

86 lines
1.8 KiB
Go

package resolver
import (
"crypto/sha256"
"encoding/hex"
"errors"
"strings"
"sync"
"git.quad4.io/Networks/Reticulum-Go/pkg/identity"
)
const (
// Hash length conversion (bits to bytes)
BitsPerByte = 8
// Known destination data index
KnownDestIdentityIndex = 2
// Minimum name parts for hierarchical resolution
MinNameParts = 2
)
type Resolver struct {
cache map[string]*identity.Identity
cacheLock sync.RWMutex
}
func New() *Resolver {
return &Resolver{
cache: make(map[string]*identity.Identity),
}
}
func (r *Resolver) ResolveIdentity(fullName string) (*identity.Identity, error) {
if fullName == "" {
return nil, errors.New("empty identity name")
}
r.cacheLock.RLock()
if cachedIdentity, exists := r.cache[fullName]; exists {
r.cacheLock.RUnlock()
return cachedIdentity, nil
}
r.cacheLock.RUnlock()
// Hash the full name to create a deterministic identity
h := sha256.New()
h.Write([]byte(fullName))
nameHash := h.Sum(nil)[:identity.NAME_HASH_LENGTH/BitsPerByte]
hashStr := hex.EncodeToString(nameHash)
// Check if this identity is known
if knownData, exists := identity.GetKnownDestination(hashStr); exists {
if id, ok := knownData[KnownDestIdentityIndex].(*identity.Identity); ok {
r.cacheLock.Lock()
r.cache[fullName] = id
r.cacheLock.Unlock()
return id, nil
}
}
// Split name into parts for hierarchical resolution
parts := strings.Split(fullName, ".")
if len(parts) < MinNameParts {
return nil, errors.New("invalid identity name format")
}
// Create new identity if not found
id, err := identity.New()
if err != nil {
return nil, err
}
r.cacheLock.Lock()
r.cache[fullName] = id
r.cacheLock.Unlock()
return id, nil
}
func ResolveIdentity(fullName string) (*identity.Identity, error) {
r := New()
return r.ResolveIdentity(fullName)
}