mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 11:15:07 +03:00 
			
		
		
		
	Make some API changes (currently broken)
This commit is contained in:
		
							parent
							
								
									a2966291b9
								
							
						
					
					
						commit
						37533f157d
					
				
					 4 changed files with 84 additions and 81 deletions
				
			
		| 
						 | 
				
			
			@ -17,6 +17,7 @@ import (
 | 
			
		|||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/config"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/util"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -243,31 +244,46 @@ func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log.
 | 
			
		|||
		}
 | 
			
		||||
	})
 | 
			
		||||
	a.AddHandler("dhtPing", []string{"box_pub_key", "coords", "[target]"}, func(in Info) (Info, error) {
 | 
			
		||||
		var reserr error
 | 
			
		||||
		var result yggdrasil.DHTRes
 | 
			
		||||
		if in["target"] == nil {
 | 
			
		||||
			in["target"] = "none"
 | 
			
		||||
		}
 | 
			
		||||
		result, err := a.core.DHTPing(in["box_pub_key"].(string), in["coords"].(string), in["target"].(string))
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			infos := make(map[string]map[string]string, len(result.Infos))
 | 
			
		||||
			for _, dinfo := range result.Infos {
 | 
			
		||||
				info := map[string]string{
 | 
			
		||||
					"box_pub_key": hex.EncodeToString(dinfo.PublicKey[:]),
 | 
			
		||||
					"coords":      fmt.Sprintf("%v", dinfo.Coords),
 | 
			
		||||
				}
 | 
			
		||||
				addr := net.IP(address.AddrForNodeID(crypto.GetNodeID(&dinfo.PublicKey))[:]).String()
 | 
			
		||||
				infos[addr] = info
 | 
			
		||||
		coords := util.DecodeCoordString(in["coords"].(string))
 | 
			
		||||
		var boxPubKey crypto.BoxPubKey
 | 
			
		||||
		if b, err := hex.DecodeString(in["box_pub_key"].(string)); err == nil {
 | 
			
		||||
			copy(boxPubKey[:], b[:])
 | 
			
		||||
			if n, err := hex.DecodeString(in["target"].(string)); err == nil {
 | 
			
		||||
				var targetNodeID crypto.NodeID
 | 
			
		||||
				copy(targetNodeID[:], n[:])
 | 
			
		||||
				result, reserr = a.core.DHTPing(boxPubKey, coords, &targetNodeID)
 | 
			
		||||
			} else {
 | 
			
		||||
				result, reserr = a.core.DHTPing(boxPubKey, coords, nil)
 | 
			
		||||
			}
 | 
			
		||||
			return Info{"nodes": infos}, nil
 | 
			
		||||
		} else {
 | 
			
		||||
			return Info{}, err
 | 
			
		||||
		}
 | 
			
		||||
		if reserr != nil {
 | 
			
		||||
			return Info{}, reserr
 | 
			
		||||
		}
 | 
			
		||||
		infos := make(map[string]map[string]string, len(result.Infos))
 | 
			
		||||
		for _, dinfo := range result.Infos {
 | 
			
		||||
			info := map[string]string{
 | 
			
		||||
				"box_pub_key": hex.EncodeToString(dinfo.PublicKey[:]),
 | 
			
		||||
				"coords":      fmt.Sprintf("%v", dinfo.Coords),
 | 
			
		||||
			}
 | 
			
		||||
			addr := net.IP(address.AddrForNodeID(crypto.GetNodeID(&dinfo.PublicKey))[:]).String()
 | 
			
		||||
			infos[addr] = info
 | 
			
		||||
		}
 | 
			
		||||
		return Info{"nodes": infos}, nil
 | 
			
		||||
	})
 | 
			
		||||
	a.AddHandler("getNodeInfo", []string{"[box_pub_key]", "[coords]", "[nocache]"}, func(in Info) (Info, error) {
 | 
			
		||||
		var nocache bool
 | 
			
		||||
		if in["nocache"] != nil {
 | 
			
		||||
			nocache = in["nocache"].(string) == "true"
 | 
			
		||||
		}
 | 
			
		||||
		var box_pub_key, coords string
 | 
			
		||||
		var box_pub_key string
 | 
			
		||||
		var coords []uint64
 | 
			
		||||
		if in["box_pub_key"] == nil && in["coords"] == nil {
 | 
			
		||||
			nodeinfo := a.core.MyNodeInfo()
 | 
			
		||||
			var jsoninfo interface{}
 | 
			
		||||
| 
						 | 
				
			
			@ -280,7 +296,7 @@ func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log.
 | 
			
		|||
			return Info{}, errors.New("Expecting both box_pub_key and coords")
 | 
			
		||||
		} else {
 | 
			
		||||
			box_pub_key = in["box_pub_key"].(string)
 | 
			
		||||
			coords = in["coords"].(string)
 | 
			
		||||
			coords = util.DecodeCoordString(in["coords"].(string))
 | 
			
		||||
		}
 | 
			
		||||
		result, err := a.core.GetNodeInfo(box_pub_key, coords, nocache)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,9 +2,13 @@ package util
 | 
			
		|||
 | 
			
		||||
// These are misc. utility functions that didn't really fit anywhere else
 | 
			
		||||
 | 
			
		||||
import "runtime"
 | 
			
		||||
import "sync"
 | 
			
		||||
import "time"
 | 
			
		||||
import (
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A wrapper around runtime.Gosched() so it doesn't need to be imported elsewhere.
 | 
			
		||||
func Yield() {
 | 
			
		||||
| 
						 | 
				
			
			@ -91,3 +95,16 @@ func Difference(a, b []string) []string {
 | 
			
		|||
	}
 | 
			
		||||
	return ab
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeCoordString decodes a string representing coordinates in [1 2 3] format
 | 
			
		||||
// and returns a []byte.
 | 
			
		||||
func DecodeCoordString(in string) (out []uint64) {
 | 
			
		||||
	s := strings.Trim(in, "[]")
 | 
			
		||||
	t := strings.Split(s, " ")
 | 
			
		||||
	for _, a := range t {
 | 
			
		||||
		if u, err := strconv.ParseUint(a, 0, 64); err == nil {
 | 
			
		||||
			out = append(out, u)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,8 +6,6 @@ import (
 | 
			
		|||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -46,14 +44,14 @@ type SwitchPeer struct {
 | 
			
		|||
// DHT searches.
 | 
			
		||||
type DHTEntry struct {
 | 
			
		||||
	PublicKey crypto.BoxPubKey
 | 
			
		||||
	Coords    []byte
 | 
			
		||||
	Coords    []uint64
 | 
			
		||||
	LastSeen  time.Duration
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DHTRes represents a DHT response, as returned by DHTPing.
 | 
			
		||||
type DHTRes struct {
 | 
			
		||||
	PublicKey crypto.BoxPubKey // key of the sender
 | 
			
		||||
	Coords    []byte           // coords of the sender
 | 
			
		||||
	Coords    []uint64         // coords of the sender
 | 
			
		||||
	Dest      crypto.NodeID    // the destination node ID
 | 
			
		||||
	Infos     []DHTEntry       // response
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -166,7 +164,7 @@ func (c *Core) GetDHT() []DHTEntry {
 | 
			
		|||
		})
 | 
			
		||||
		for _, v := range dhtentry {
 | 
			
		||||
			info := DHTEntry{
 | 
			
		||||
				Coords:   append([]byte{}, v.coords...),
 | 
			
		||||
				Coords:   append([]uint64{}, coordsBytestoUint64s(v.coords)...),
 | 
			
		||||
				LastSeen: now.Sub(v.recv),
 | 
			
		||||
			}
 | 
			
		||||
			copy(info.PublicKey[:], v.key[:])
 | 
			
		||||
| 
						 | 
				
			
			@ -346,30 +344,7 @@ func (c *Core) SetNodeInfo(nodeinfo interface{}, nodeinfoprivacy bool) {
 | 
			
		|||
// key and coordinates specified. The third parameter specifies whether a cached
 | 
			
		||||
// result is acceptable - this results in less traffic being generated than is
 | 
			
		||||
// necessary when, e.g. crawling the network.
 | 
			
		||||
func (c *Core) GetNodeInfo(keyString, coordString string, nocache bool) (NodeInfoPayload, error) {
 | 
			
		||||
	var key crypto.BoxPubKey
 | 
			
		||||
	if keyBytes, err := hex.DecodeString(keyString); err != nil {
 | 
			
		||||
		return NodeInfoPayload{}, err
 | 
			
		||||
	} else {
 | 
			
		||||
		copy(key[:], keyBytes)
 | 
			
		||||
	}
 | 
			
		||||
	if !nocache {
 | 
			
		||||
		if response, err := c.router.nodeinfo.getCachedNodeInfo(key); err == nil {
 | 
			
		||||
			return response, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	var coords []byte
 | 
			
		||||
	for _, cstr := range strings.Split(strings.Trim(coordString, "[]"), " ") {
 | 
			
		||||
		if cstr == "" {
 | 
			
		||||
			// Special case, happens if trimmed is the empty string, e.g. this is the root
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if u64, err := strconv.ParseUint(cstr, 10, 8); err != nil {
 | 
			
		||||
			return NodeInfoPayload{}, err
 | 
			
		||||
		} else {
 | 
			
		||||
			coords = append(coords, uint8(u64))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
func (c *Core) GetNodeInfo(key crypto.BoxPubKey, coords []byte, nocache bool) (NodeInfoPayload, error) {
 | 
			
		||||
	response := make(chan *NodeInfoPayload, 1)
 | 
			
		||||
	sendNodeInfoRequest := func() {
 | 
			
		||||
		c.router.nodeinfo.addCallback(key, func(nodeinfo *NodeInfoPayload) {
 | 
			
		||||
| 
						 | 
				
			
			@ -389,7 +364,7 @@ func (c *Core) GetNodeInfo(keyString, coordString string, nocache bool) (NodeInf
 | 
			
		|||
	for res := range response {
 | 
			
		||||
		return *res, nil
 | 
			
		||||
	}
 | 
			
		||||
	return NodeInfoPayload{}, fmt.Errorf("getNodeInfo timeout: %s", keyString)
 | 
			
		||||
	return NodeInfoPayload{}, fmt.Errorf("getNodeInfo timeout: %s", hex.EncodeToString(key[:]))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetSessionGatekeeper allows you to configure a handler function for deciding
 | 
			
		||||
| 
						 | 
				
			
			@ -477,64 +452,38 @@ func (c *Core) RemoveAllowedEncryptionPublicKey(bstr string) (err error) {
 | 
			
		|||
 | 
			
		||||
// DHTPing sends a DHT ping to the node with the provided key and coords,
 | 
			
		||||
// optionally looking up the specified target NodeID.
 | 
			
		||||
func (c *Core) DHTPing(keyString, coordString, targetString string) (DHTRes, error) {
 | 
			
		||||
	var key crypto.BoxPubKey
 | 
			
		||||
	if keyBytes, err := hex.DecodeString(keyString); err != nil {
 | 
			
		||||
		return DHTRes{}, err
 | 
			
		||||
	} else {
 | 
			
		||||
		copy(key[:], keyBytes)
 | 
			
		||||
	}
 | 
			
		||||
	var coords []byte
 | 
			
		||||
	for _, cstr := range strings.Split(strings.Trim(coordString, "[]"), " ") {
 | 
			
		||||
		if cstr == "" {
 | 
			
		||||
			// Special case, happens if trimmed is the empty string, e.g. this is the root
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if u64, err := strconv.ParseUint(cstr, 10, 8); err != nil {
 | 
			
		||||
			return DHTRes{}, err
 | 
			
		||||
		} else {
 | 
			
		||||
			coords = append(coords, uint8(u64))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
func (c *Core) DHTPing(key crypto.BoxPubKey, coords []uint64, target *crypto.NodeID) (DHTRes, error) {
 | 
			
		||||
	resCh := make(chan *dhtRes, 1)
 | 
			
		||||
	info := dhtInfo{
 | 
			
		||||
		key:    key,
 | 
			
		||||
		coords: coords,
 | 
			
		||||
		coords: coordsUint64stoBytes(coords),
 | 
			
		||||
	}
 | 
			
		||||
	target := *info.getNodeID()
 | 
			
		||||
	if targetString == "none" {
 | 
			
		||||
		// Leave the default target in place
 | 
			
		||||
	} else if targetBytes, err := hex.DecodeString(targetString); err != nil {
 | 
			
		||||
		return DHTRes{}, err
 | 
			
		||||
	} else if len(targetBytes) != len(target) {
 | 
			
		||||
		return DHTRes{}, errors.New("Incorrect target NodeID length")
 | 
			
		||||
	} else {
 | 
			
		||||
		var target crypto.NodeID
 | 
			
		||||
		copy(target[:], targetBytes)
 | 
			
		||||
	if target == nil {
 | 
			
		||||
		target = info.getNodeID()
 | 
			
		||||
	}
 | 
			
		||||
	rq := dhtReqKey{info.key, target}
 | 
			
		||||
	rq := dhtReqKey{info.key, *target}
 | 
			
		||||
	sendPing := func() {
 | 
			
		||||
		c.dht.addCallback(&rq, func(res *dhtRes) {
 | 
			
		||||
			resCh <- res
 | 
			
		||||
		})
 | 
			
		||||
		c.dht.ping(&info, &target)
 | 
			
		||||
		c.dht.ping(&info, &rq.dest)
 | 
			
		||||
	}
 | 
			
		||||
	c.router.doAdmin(sendPing)
 | 
			
		||||
	// TODO: do something better than the below...
 | 
			
		||||
	res := <-resCh
 | 
			
		||||
	if res != nil {
 | 
			
		||||
		r := DHTRes{
 | 
			
		||||
			Coords: append([]byte{}, res.Coords...),
 | 
			
		||||
			Coords: append([]uint64{}, coordsBytestoUint64s(res.Coords)...),
 | 
			
		||||
		}
 | 
			
		||||
		copy(r.PublicKey[:], res.Key[:])
 | 
			
		||||
		for _, i := range res.Infos {
 | 
			
		||||
			e := DHTEntry{
 | 
			
		||||
				Coords: append([]byte{}, i.coords...),
 | 
			
		||||
				Coords: append([]uint64{}, coordsBytestoUint64s(i.coords)...),
 | 
			
		||||
			}
 | 
			
		||||
			copy(e.PublicKey[:], i.key[:])
 | 
			
		||||
			r.Infos = append(r.Infos, e)
 | 
			
		||||
		}
 | 
			
		||||
		return r, nil
 | 
			
		||||
	}
 | 
			
		||||
	return DHTRes{}, fmt.Errorf("DHT ping timeout: %s", keyString)
 | 
			
		||||
	return DHTRes{}, fmt.Errorf("DHT ping timeout: %s", hex.EncodeToString(key[:]))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -137,6 +137,27 @@ type peerInfo struct {
 | 
			
		|||
// This is just a uint64 with a named type for clarity reasons.
 | 
			
		||||
type switchPort uint64
 | 
			
		||||
 | 
			
		||||
func coordsUint64stoBytes(in []uint64) (out []byte) {
 | 
			
		||||
	for _, coord := range in {
 | 
			
		||||
		c := wire_encode_uint64(coord)
 | 
			
		||||
		out = append(out, c...)
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func coordsBytestoUint64s(in []byte) (out []uint64) {
 | 
			
		||||
	offset := 0
 | 
			
		||||
	for {
 | 
			
		||||
		coord, length := wire_decode_uint64(in[offset:])
 | 
			
		||||
		if length == 0 {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		out = append(out, coord)
 | 
			
		||||
		offset += length
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This is the subset of the information about a peer needed to make routing decisions, and it stored separately in an atomically accessed table, which gets hammered in the "hot loop" of the routing logic (see: peer.handleTraffic in peers.go).
 | 
			
		||||
type tableElem struct {
 | 
			
		||||
	port    switchPort
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue