mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-30 03:11:37 +00:00
commit
f046249ac6
BIN
src/.DS_Store
vendored
Normal file
BIN
src/.DS_Store
vendored
Normal file
Binary file not shown.
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/util"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
|
"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -78,11 +79,6 @@ func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log.
|
|||||||
}
|
}
|
||||||
return Info{"list": handlers}, nil
|
return Info{"list": handlers}, nil
|
||||||
})
|
})
|
||||||
/*
|
|
||||||
a.AddHandler("dot", []string{}, func(in Info) (Info, error) {
|
|
||||||
return Info{"dot": string(a.getResponse_dot())}, nil
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
a.AddHandler("getSelf", []string{}, func(in Info) (Info, error) {
|
a.AddHandler("getSelf", []string{}, func(in Info) (Info, error) {
|
||||||
ip := c.Address().String()
|
ip := c.Address().String()
|
||||||
subnet := c.Subnet()
|
subnet := c.Subnet()
|
||||||
@ -110,7 +106,7 @@ func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log.
|
|||||||
"bytes_recvd": p.BytesRecvd,
|
"bytes_recvd": p.BytesRecvd,
|
||||||
"proto": p.Protocol,
|
"proto": p.Protocol,
|
||||||
"endpoint": p.Endpoint,
|
"endpoint": p.Endpoint,
|
||||||
"box_pub_key": p.PublicKey,
|
"box_pub_key": hex.EncodeToString(p.PublicKey[:]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Info{"peers": peers}, nil
|
return Info{"peers": peers}, nil
|
||||||
@ -128,7 +124,7 @@ func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log.
|
|||||||
"bytes_recvd": s.BytesRecvd,
|
"bytes_recvd": s.BytesRecvd,
|
||||||
"proto": s.Protocol,
|
"proto": s.Protocol,
|
||||||
"endpoint": s.Endpoint,
|
"endpoint": s.Endpoint,
|
||||||
"box_pub_key": s.PublicKey,
|
"box_pub_key": hex.EncodeToString(s.PublicKey[:]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Info{"switchpeers": switchpeers}, nil
|
return Info{"switchpeers": switchpeers}, nil
|
||||||
@ -147,7 +143,7 @@ func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log.
|
|||||||
dht[so] = Info{
|
dht[so] = Info{
|
||||||
"coords": fmt.Sprintf("%v", d.Coords),
|
"coords": fmt.Sprintf("%v", d.Coords),
|
||||||
"last_seen": d.LastSeen.Seconds(),
|
"last_seen": d.LastSeen.Seconds(),
|
||||||
"box_pub_key": d.PublicKey,
|
"box_pub_key": hex.EncodeToString(d.PublicKey[:]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Info{"dht": dht}, nil
|
return Info{"dht": dht}, nil
|
||||||
@ -164,7 +160,7 @@ func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log.
|
|||||||
"mtu": s.MTU,
|
"mtu": s.MTU,
|
||||||
"uptime": s.Uptime.Seconds(),
|
"uptime": s.Uptime.Seconds(),
|
||||||
"was_mtu_fixed": s.WasMTUFixed,
|
"was_mtu_fixed": s.WasMTUFixed,
|
||||||
"box_pub_key": s.PublicKey,
|
"box_pub_key": hex.EncodeToString(s.PublicKey[:]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Info{"sessions": sessions}, nil
|
return Info{"sessions": sessions}, nil
|
||||||
@ -243,11 +239,28 @@ 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) {
|
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 {
|
if in["target"] == nil {
|
||||||
in["target"] = "none"
|
in["target"] = "none"
|
||||||
}
|
}
|
||||||
result, err := a.core.DHTPing(in["box_pub_key"].(string), in["coords"].(string), in["target"].(string))
|
coords := util.DecodeCoordString(in["coords"].(string))
|
||||||
if err == nil {
|
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)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Info{}, err
|
||||||
|
}
|
||||||
|
if reserr != nil {
|
||||||
|
return Info{}, reserr
|
||||||
|
}
|
||||||
infos := make(map[string]map[string]string, len(result.Infos))
|
infos := make(map[string]map[string]string, len(result.Infos))
|
||||||
for _, dinfo := range result.Infos {
|
for _, dinfo := range result.Infos {
|
||||||
info := map[string]string{
|
info := map[string]string{
|
||||||
@ -258,16 +271,14 @@ func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log.
|
|||||||
infos[addr] = info
|
infos[addr] = info
|
||||||
}
|
}
|
||||||
return Info{"nodes": infos}, nil
|
return Info{"nodes": infos}, nil
|
||||||
} else {
|
|
||||||
return Info{}, err
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
a.AddHandler("getNodeInfo", []string{"[box_pub_key]", "[coords]", "[nocache]"}, func(in Info) (Info, error) {
|
a.AddHandler("getNodeInfo", []string{"[box_pub_key]", "[coords]", "[nocache]"}, func(in Info) (Info, error) {
|
||||||
var nocache bool
|
var nocache bool
|
||||||
if in["nocache"] != nil {
|
if in["nocache"] != nil {
|
||||||
nocache = in["nocache"].(string) == "true"
|
nocache = in["nocache"].(string) == "true"
|
||||||
}
|
}
|
||||||
var box_pub_key, coords string
|
var boxPubKey crypto.BoxPubKey
|
||||||
|
var coords []uint64
|
||||||
if in["box_pub_key"] == nil && in["coords"] == nil {
|
if in["box_pub_key"] == nil && in["coords"] == nil {
|
||||||
nodeinfo := a.core.MyNodeInfo()
|
nodeinfo := a.core.MyNodeInfo()
|
||||||
var jsoninfo interface{}
|
var jsoninfo interface{}
|
||||||
@ -279,10 +290,14 @@ func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log.
|
|||||||
} else if in["box_pub_key"] == nil || in["coords"] == nil {
|
} else if in["box_pub_key"] == nil || in["coords"] == nil {
|
||||||
return Info{}, errors.New("Expecting both box_pub_key and coords")
|
return Info{}, errors.New("Expecting both box_pub_key and coords")
|
||||||
} else {
|
} else {
|
||||||
box_pub_key = in["box_pub_key"].(string)
|
if b, err := hex.DecodeString(in["box_pub_key"].(string)); err == nil {
|
||||||
coords = in["coords"].(string)
|
copy(boxPubKey[:], b[:])
|
||||||
|
} else {
|
||||||
|
return Info{}, err
|
||||||
}
|
}
|
||||||
result, err := a.core.GetNodeInfo(box_pub_key, coords, nocache)
|
coords = util.DecodeCoordString(in["coords"].(string))
|
||||||
|
}
|
||||||
|
result, err := a.core.GetNodeInfo(boxPubKey, coords, nocache)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
var m map[string]interface{}
|
var m map[string]interface{}
|
||||||
if err = json.Unmarshal(result, &m); err == nil {
|
if err = json.Unmarshal(result, &m); err == nil {
|
||||||
@ -472,133 +487,3 @@ func (a *AdminSocket) handleRequest(conn net.Conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getResponse_dot returns a response for a graphviz dot formatted
|
|
||||||
// representation of the known parts of the network. This is color-coded and
|
|
||||||
// labeled, and includes the self node, switch peers, nodes known to the DHT,
|
|
||||||
// and nodes with open sessions. The graph is structured as a tree with directed
|
|
||||||
// links leading away from the root.
|
|
||||||
/*
|
|
||||||
func (a *AdminSocket) getResponse_dot() []byte {
|
|
||||||
//self := a.getData_getSelf()
|
|
||||||
peers := a.core.GetSwitchPeers()
|
|
||||||
dht := a.core.GetDHT()
|
|
||||||
sessions := a.core.GetSessions()
|
|
||||||
// Start building a tree from all known nodes
|
|
||||||
type nodeInfo struct {
|
|
||||||
name string
|
|
||||||
key string
|
|
||||||
parent string
|
|
||||||
port uint64
|
|
||||||
options string
|
|
||||||
}
|
|
||||||
infos := make(map[string]nodeInfo)
|
|
||||||
// Get coords as a slice of strings, FIXME? this looks very fragile
|
|
||||||
coordSlice := func(coords string) []string {
|
|
||||||
tmp := strings.Replace(coords, "[", "", -1)
|
|
||||||
tmp = strings.Replace(tmp, "]", "", -1)
|
|
||||||
return strings.Split(tmp, " ")
|
|
||||||
}
|
|
||||||
// First fill the tree with all known nodes, no parents
|
|
||||||
addInfo := func(nodes []admin_nodeInfo, options string, tag string) {
|
|
||||||
for _, node := range nodes {
|
|
||||||
n := node.asMap()
|
|
||||||
info := nodeInfo{
|
|
||||||
key: n["coords"].(string),
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
if len(tag) > 0 {
|
|
||||||
info.name = fmt.Sprintf("%s\n%s", n["ip"].(string), tag)
|
|
||||||
} else {
|
|
||||||
info.name = n["ip"].(string)
|
|
||||||
}
|
|
||||||
coordsSplit := coordSlice(info.key)
|
|
||||||
if len(coordsSplit) != 0 {
|
|
||||||
portStr := coordsSplit[len(coordsSplit)-1]
|
|
||||||
portUint, err := strconv.ParseUint(portStr, 10, 64)
|
|
||||||
if err == nil {
|
|
||||||
info.port = portUint
|
|
||||||
}
|
|
||||||
}
|
|
||||||
infos[info.key] = info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addInfo(dht, "fillcolor=\"#ffffff\" style=filled fontname=\"sans serif\"", "Known in DHT") // white
|
|
||||||
addInfo(sessions, "fillcolor=\"#acf3fd\" style=filled fontname=\"sans serif\"", "Open session") // blue
|
|
||||||
addInfo(peers, "fillcolor=\"#ffffb5\" style=filled fontname=\"sans serif\"", "Connected peer") // yellow
|
|
||||||
addInfo(append([]admin_nodeInfo(nil), *self), "fillcolor=\"#a5ff8a\" style=filled fontname=\"sans serif\"", "This node") // green
|
|
||||||
// Now go through and create placeholders for any missing nodes
|
|
||||||
for _, info := range infos {
|
|
||||||
// This is ugly string manipulation
|
|
||||||
coordsSplit := coordSlice(info.key)
|
|
||||||
for idx := range coordsSplit {
|
|
||||||
key := fmt.Sprintf("[%v]", strings.Join(coordsSplit[:idx], " "))
|
|
||||||
newInfo, isIn := infos[key]
|
|
||||||
if isIn {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
newInfo.name = "?"
|
|
||||||
newInfo.key = key
|
|
||||||
newInfo.options = "fontname=\"sans serif\" style=dashed color=\"#999999\" fontcolor=\"#999999\""
|
|
||||||
|
|
||||||
coordsSplit := coordSlice(newInfo.key)
|
|
||||||
if len(coordsSplit) != 0 {
|
|
||||||
portStr := coordsSplit[len(coordsSplit)-1]
|
|
||||||
portUint, err := strconv.ParseUint(portStr, 10, 64)
|
|
||||||
if err == nil {
|
|
||||||
newInfo.port = portUint
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
infos[key] = newInfo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Now go through and attach parents
|
|
||||||
for _, info := range infos {
|
|
||||||
pSplit := coordSlice(info.key)
|
|
||||||
if len(pSplit) > 0 {
|
|
||||||
pSplit = pSplit[:len(pSplit)-1]
|
|
||||||
}
|
|
||||||
info.parent = fmt.Sprintf("[%v]", strings.Join(pSplit, " "))
|
|
||||||
infos[info.key] = info
|
|
||||||
}
|
|
||||||
// Finally, get a sorted list of keys, which we use to organize the output
|
|
||||||
var keys []string
|
|
||||||
for _, info := range infos {
|
|
||||||
keys = append(keys, info.key)
|
|
||||||
}
|
|
||||||
// sort
|
|
||||||
sort.SliceStable(keys, func(i, j int) bool {
|
|
||||||
return keys[i] < keys[j]
|
|
||||||
})
|
|
||||||
sort.SliceStable(keys, func(i, j int) bool {
|
|
||||||
return infos[keys[i]].port < infos[keys[j]].port
|
|
||||||
})
|
|
||||||
// Now print it all out
|
|
||||||
var out []byte
|
|
||||||
put := func(s string) {
|
|
||||||
out = append(out, []byte(s)...)
|
|
||||||
}
|
|
||||||
put("digraph {\n")
|
|
||||||
// First set the labels
|
|
||||||
for _, key := range keys {
|
|
||||||
info := infos[key]
|
|
||||||
put(fmt.Sprintf("\"%v\" [ label = \"%v\" %v ];\n", info.key, info.name, info.options))
|
|
||||||
}
|
|
||||||
// Then print the tree structure
|
|
||||||
for _, key := range keys {
|
|
||||||
info := infos[key]
|
|
||||||
if info.key == info.parent {
|
|
||||||
continue
|
|
||||||
} // happens for the root, skip it
|
|
||||||
port := fmt.Sprint(info.port)
|
|
||||||
style := "fontname=\"sans serif\""
|
|
||||||
if infos[info.parent].name == "?" || infos[info.key].name == "?" {
|
|
||||||
style = "fontname=\"sans serif\" style=dashed color=\"#999999\" fontcolor=\"#999999\""
|
|
||||||
}
|
|
||||||
put(fmt.Sprintf(" \"%+v\" -> \"%+v\" [ label = \"%v\" %s ];\n", info.parent, info.key, port, style))
|
|
||||||
}
|
|
||||||
put("}\n")
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
@ -2,9 +2,13 @@ package util
|
|||||||
|
|
||||||
// These are misc. utility functions that didn't really fit anywhere else
|
// These are misc. utility functions that didn't really fit anywhere else
|
||||||
|
|
||||||
import "runtime"
|
import (
|
||||||
import "sync"
|
"runtime"
|
||||||
import "time"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// A wrapper around runtime.Gosched() so it doesn't need to be imported elsewhere.
|
// A wrapper around runtime.Gosched() so it doesn't need to be imported elsewhere.
|
||||||
func Yield() {
|
func Yield() {
|
||||||
@ -91,3 +95,16 @@ func Difference(a, b []string) []string {
|
|||||||
}
|
}
|
||||||
return ab
|
return ab
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeCoordString decodes a string representing coordinates in [1 2 3] format
|
||||||
|
// and returns a []uint64.
|
||||||
|
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"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -34,7 +32,7 @@ type Peer struct {
|
|||||||
// to a given node.
|
// to a given node.
|
||||||
type SwitchPeer struct {
|
type SwitchPeer struct {
|
||||||
PublicKey crypto.BoxPubKey
|
PublicKey crypto.BoxPubKey
|
||||||
Coords []byte
|
Coords []uint64
|
||||||
BytesSent uint64
|
BytesSent uint64
|
||||||
BytesRecvd uint64
|
BytesRecvd uint64
|
||||||
Port uint64
|
Port uint64
|
||||||
@ -46,14 +44,14 @@ type SwitchPeer struct {
|
|||||||
// DHT searches.
|
// DHT searches.
|
||||||
type DHTEntry struct {
|
type DHTEntry struct {
|
||||||
PublicKey crypto.BoxPubKey
|
PublicKey crypto.BoxPubKey
|
||||||
Coords []byte
|
Coords []uint64
|
||||||
LastSeen time.Duration
|
LastSeen time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// DHTRes represents a DHT response, as returned by DHTPing.
|
// DHTRes represents a DHT response, as returned by DHTPing.
|
||||||
type DHTRes struct {
|
type DHTRes struct {
|
||||||
PublicKey crypto.BoxPubKey // key of the sender
|
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
|
Dest crypto.NodeID // the destination node ID
|
||||||
Infos []DHTEntry // response
|
Infos []DHTEntry // response
|
||||||
}
|
}
|
||||||
@ -85,7 +83,7 @@ type SwitchQueue struct {
|
|||||||
// Session represents an open session with another node.
|
// Session represents an open session with another node.
|
||||||
type Session struct {
|
type Session struct {
|
||||||
PublicKey crypto.BoxPubKey
|
PublicKey crypto.BoxPubKey
|
||||||
Coords []byte
|
Coords []uint64
|
||||||
BytesSent uint64
|
BytesSent uint64
|
||||||
BytesRecvd uint64
|
BytesRecvd uint64
|
||||||
MTU uint16
|
MTU uint16
|
||||||
@ -138,7 +136,7 @@ func (c *Core) GetSwitchPeers() []SwitchPeer {
|
|||||||
}
|
}
|
||||||
coords := elem.locator.getCoords()
|
coords := elem.locator.getCoords()
|
||||||
info := SwitchPeer{
|
info := SwitchPeer{
|
||||||
Coords: append([]byte{}, coords...),
|
Coords: append([]uint64{}, wire_coordsBytestoUint64s(coords)...),
|
||||||
BytesSent: atomic.LoadUint64(&peer.bytesSent),
|
BytesSent: atomic.LoadUint64(&peer.bytesSent),
|
||||||
BytesRecvd: atomic.LoadUint64(&peer.bytesRecvd),
|
BytesRecvd: atomic.LoadUint64(&peer.bytesRecvd),
|
||||||
Port: uint64(elem.port),
|
Port: uint64(elem.port),
|
||||||
@ -166,7 +164,7 @@ func (c *Core) GetDHT() []DHTEntry {
|
|||||||
})
|
})
|
||||||
for _, v := range dhtentry {
|
for _, v := range dhtentry {
|
||||||
info := DHTEntry{
|
info := DHTEntry{
|
||||||
Coords: append([]byte{}, v.coords...),
|
Coords: append([]uint64{}, wire_coordsBytestoUint64s(v.coords)...),
|
||||||
LastSeen: now.Sub(v.recv),
|
LastSeen: now.Sub(v.recv),
|
||||||
}
|
}
|
||||||
copy(info.PublicKey[:], v.key[:])
|
copy(info.PublicKey[:], v.key[:])
|
||||||
@ -214,7 +212,7 @@ func (c *Core) GetSessions() []Session {
|
|||||||
var session Session
|
var session Session
|
||||||
workerFunc := func() {
|
workerFunc := func() {
|
||||||
session = Session{
|
session = Session{
|
||||||
Coords: append([]byte{}, sinfo.coords...),
|
Coords: append([]uint64{}, wire_coordsBytestoUint64s(sinfo.coords)...),
|
||||||
MTU: sinfo.getMTU(),
|
MTU: sinfo.getMTU(),
|
||||||
BytesSent: sinfo.bytesSent,
|
BytesSent: sinfo.bytesSent,
|
||||||
BytesRecvd: sinfo.bytesRecvd,
|
BytesRecvd: sinfo.bytesRecvd,
|
||||||
@ -311,9 +309,9 @@ func (c *Core) EncryptionPublicKey() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Coords returns the current coordinates of the node.
|
// Coords returns the current coordinates of the node.
|
||||||
func (c *Core) Coords() []byte {
|
func (c *Core) Coords() []uint64 {
|
||||||
table := c.switchTable.table.Load().(lookupTable)
|
table := c.switchTable.table.Load().(lookupTable)
|
||||||
return table.self.getCoords()
|
return wire_coordsBytestoUint64s(table.self.getCoords())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Address gets the IPv6 address of the Yggdrasil node. This is always a /128
|
// Address gets the IPv6 address of the Yggdrasil node. This is always a /128
|
||||||
@ -336,8 +334,8 @@ func (c *Core) MyNodeInfo() NodeInfoPayload {
|
|||||||
return c.router.nodeinfo.getNodeInfo()
|
return c.router.nodeinfo.getNodeInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNodeInfo the lcal nodeinfo. Note that nodeinfo can be any value or struct,
|
// SetNodeInfo sets the local nodeinfo. Note that nodeinfo can be any value or
|
||||||
// it will be serialised into JSON automatically.
|
// struct, it will be serialised into JSON automatically.
|
||||||
func (c *Core) SetNodeInfo(nodeinfo interface{}, nodeinfoprivacy bool) {
|
func (c *Core) SetNodeInfo(nodeinfo interface{}, nodeinfoprivacy bool) {
|
||||||
c.router.nodeinfo.setNodeInfo(nodeinfo, nodeinfoprivacy)
|
c.router.nodeinfo.setNodeInfo(nodeinfo, nodeinfoprivacy)
|
||||||
}
|
}
|
||||||
@ -346,30 +344,7 @@ func (c *Core) SetNodeInfo(nodeinfo interface{}, nodeinfoprivacy bool) {
|
|||||||
// key and coordinates specified. The third parameter specifies whether a cached
|
// key and coordinates specified. The third parameter specifies whether a cached
|
||||||
// result is acceptable - this results in less traffic being generated than is
|
// result is acceptable - this results in less traffic being generated than is
|
||||||
// necessary when, e.g. crawling the network.
|
// necessary when, e.g. crawling the network.
|
||||||
func (c *Core) GetNodeInfo(keyString, coordString string, nocache bool) (NodeInfoPayload, error) {
|
func (c *Core) GetNodeInfo(key crypto.BoxPubKey, coords []uint64, 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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response := make(chan *NodeInfoPayload, 1)
|
response := make(chan *NodeInfoPayload, 1)
|
||||||
sendNodeInfoRequest := func() {
|
sendNodeInfoRequest := func() {
|
||||||
c.router.nodeinfo.addCallback(key, func(nodeinfo *NodeInfoPayload) {
|
c.router.nodeinfo.addCallback(key, func(nodeinfo *NodeInfoPayload) {
|
||||||
@ -379,7 +354,7 @@ func (c *Core) GetNodeInfo(keyString, coordString string, nocache bool) (NodeInf
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
c.router.nodeinfo.sendNodeInfo(key, coords, false)
|
c.router.nodeinfo.sendNodeInfo(key, wire_coordsUint64stoBytes(coords), false)
|
||||||
}
|
}
|
||||||
c.router.doAdmin(sendNodeInfoRequest)
|
c.router.doAdmin(sendNodeInfoRequest)
|
||||||
go func() {
|
go func() {
|
||||||
@ -389,7 +364,7 @@ func (c *Core) GetNodeInfo(keyString, coordString string, nocache bool) (NodeInf
|
|||||||
for res := range response {
|
for res := range response {
|
||||||
return *res, nil
|
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
|
// 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,
|
// DHTPing sends a DHT ping to the node with the provided key and coords,
|
||||||
// optionally looking up the specified target NodeID.
|
// optionally looking up the specified target NodeID.
|
||||||
func (c *Core) DHTPing(keyString, coordString, targetString string) (DHTRes, error) {
|
func (c *Core) DHTPing(key crypto.BoxPubKey, coords []uint64, target *crypto.NodeID) (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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resCh := make(chan *dhtRes, 1)
|
resCh := make(chan *dhtRes, 1)
|
||||||
info := dhtInfo{
|
info := dhtInfo{
|
||||||
key: key,
|
key: key,
|
||||||
coords: coords,
|
coords: wire_coordsUint64stoBytes(coords),
|
||||||
}
|
}
|
||||||
target := *info.getNodeID()
|
if target == nil {
|
||||||
if targetString == "none" {
|
target = info.getNodeID()
|
||||||
// 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)
|
|
||||||
}
|
}
|
||||||
rq := dhtReqKey{info.key, target}
|
rq := dhtReqKey{info.key, *target}
|
||||||
sendPing := func() {
|
sendPing := func() {
|
||||||
c.dht.addCallback(&rq, func(res *dhtRes) {
|
c.dht.addCallback(&rq, func(res *dhtRes) {
|
||||||
resCh <- res
|
resCh <- res
|
||||||
})
|
})
|
||||||
c.dht.ping(&info, &target)
|
c.dht.ping(&info, &rq.dest)
|
||||||
}
|
}
|
||||||
c.router.doAdmin(sendPing)
|
c.router.doAdmin(sendPing)
|
||||||
// TODO: do something better than the below...
|
// TODO: do something better than the below...
|
||||||
res := <-resCh
|
res := <-resCh
|
||||||
if res != nil {
|
if res != nil {
|
||||||
r := DHTRes{
|
r := DHTRes{
|
||||||
Coords: append([]byte{}, res.Coords...),
|
Coords: append([]uint64{}, wire_coordsBytestoUint64s(res.Coords)...),
|
||||||
}
|
}
|
||||||
copy(r.PublicKey[:], res.Key[:])
|
copy(r.PublicKey[:], res.Key[:])
|
||||||
for _, i := range res.Infos {
|
for _, i := range res.Infos {
|
||||||
e := DHTEntry{
|
e := DHTEntry{
|
||||||
Coords: append([]byte{}, i.coords...),
|
Coords: append([]uint64{}, wire_coordsBytestoUint64s(i.coords)...),
|
||||||
}
|
}
|
||||||
copy(e.PublicKey[:], i.key[:])
|
copy(e.PublicKey[:], i.key[:])
|
||||||
r.Infos = append(r.Infos, e)
|
r.Infos = append(r.Infos, e)
|
||||||
}
|
}
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
return DHTRes{}, fmt.Errorf("DHT ping timeout: %s", keyString)
|
return DHTRes{}, fmt.Errorf("DHT ping timeout: %s", hex.EncodeToString(key[:]))
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,29 @@ func wire_decode_coords(packet []byte) ([]byte, int) {
|
|||||||
return packet[coordBegin:coordEnd], coordEnd
|
return packet[coordBegin:coordEnd], coordEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Converts a []uint64 set of coords to a []byte set of coords.
|
||||||
|
func wire_coordsUint64stoBytes(in []uint64) (out []byte) {
|
||||||
|
for _, coord := range in {
|
||||||
|
c := wire_encode_uint64(coord)
|
||||||
|
out = append(out, c...)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a []byte set of coords to a []uint64 set of coords.
|
||||||
|
func wire_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
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Encodes a swtichMsg into its wire format.
|
// Encodes a swtichMsg into its wire format.
|
||||||
|
Loading…
Reference in New Issue
Block a user