Files
sam3/resolver.go

87 lines
2.6 KiB
Go

package sam3
import (
"bufio"
"bytes"
"errors"
"fmt"
"strings"
"github.com/go-i2p/i2pkeys"
)
type SAMResolver struct {
*SAM
}
func NewSAMResolver(parent *SAM) (*SAMResolver, error) {
log.Debug("Creating new SAMResolver from existing SAM instance")
var s SAMResolver
s.SAM = parent
return &s, nil
}
func NewFullSAMResolver(address string) (*SAMResolver, error) {
log.WithField("address", address).Debug("Creating new full SAMResolver")
var s SAMResolver
var err error
s.SAM, err = NewSAM(address)
if err != nil {
log.WithError(err).Error("Failed to create new SAM instance")
return nil, err
}
return &s, nil
}
// Performs a lookup, probably this order: 1) routers known addresses, cached
// addresses, 3) by asking peers in the I2P network.
func (sam *SAMResolver) Resolve(name string) (i2pkeys.I2PAddr, error) {
log.WithField("name", name).Debug("Resolving name")
query := []byte(fmt.Sprintf("NAMING LOOKUP NAME=%s\n", name))
if _, err := sam.conn.Write(query); err != nil {
log.WithError(err).Error("Failed to write to SAM connection")
sam.Close()
return i2pkeys.I2PAddr(""), err
}
buf := make([]byte, 4096)
n, err := sam.conn.Read(buf)
if err != nil {
log.WithError(err).Error("Failed to read from SAM connection")
sam.Close()
return i2pkeys.I2PAddr(""), err
}
if n <= 13 || !strings.HasPrefix(string(buf[:n]), "NAMING REPLY ") {
log.Error("Failed to parse SAM response")
return i2pkeys.I2PAddr(""), errors.New("Failed to parse.")
}
s := bufio.NewScanner(bytes.NewReader(buf[13:n]))
s.Split(bufio.ScanWords)
for s.Scan() {
text := s.Text()
log.WithField("text", text).Debug("Parsing SAM response token")
// log.Println("SAM3", text)
if text == "RESULT=OK" {
continue
} else if text == "RESULT=INVALID_KEY" {
log.Error("Invalid key in resolver")
return i2pkeys.I2PAddr(""), fmt.Errorf("Invalid key - resolver")
} else if text == "RESULT=KEY_NOT_FOUND" {
log.WithField("name", name).Error("Unable to resolve name")
return i2pkeys.I2PAddr(""), fmt.Errorf("Unable to resolve %s", name)
} else if text == "NAME="+name {
continue
} else if strings.HasPrefix(text, "VALUE=") {
addr := i2pkeys.I2PAddr(text[6:])
log.WithField("addr", addr).Debug("Name resolved successfully")
return i2pkeys.I2PAddr(text[6:]), nil
} else if strings.HasPrefix(text, "MESSAGE=") {
log.WithField("message", text[8:]).Warn("Received message from SAM")
return i2pkeys.I2PAddr(""), fmt.Errorf("Received message from SAM: %s", text[8:])
} else {
continue
}
}
return i2pkeys.I2PAddr(""), fmt.Errorf("Unable to resolve %s", name)
}