mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-26 07:11:40 +00:00
start of iterative dht searches
This commit is contained in:
parent
dc841c550b
commit
ecf7e490d7
@ -583,9 +583,9 @@ func (a *admin) getResponse_dot() []byte {
|
|||||||
infos[info.key] = info
|
infos[info.key] = info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addInfo(dht, "fillcolor=\"#ffffff\" style=filled", "Known in DHT") // white
|
addInfo(dht, "fillcolor=\"#ffffff\" style=filled", "Known in DHT") // white
|
||||||
addInfo(sessions, "fillcolor=\"#acf3fd\" style=filled", "Open session") // blue
|
addInfo(sessions, "fillcolor=\"#acf3fd\" style=filled", "Open session") // blue
|
||||||
addInfo(peers, "fillcolor=\"#ffffb5\" style=filled", "Connected peer") // yellow
|
addInfo(peers, "fillcolor=\"#ffffb5\" style=filled", "Connected peer") // yellow
|
||||||
addInfo(append([]admin_nodeInfo(nil), *self), "fillcolor=\"#a5ff8a\" style=filled", "This node") // green
|
addInfo(append([]admin_nodeInfo(nil), *self), "fillcolor=\"#a5ff8a\" style=filled", "This node") // green
|
||||||
// Get coords as a slice of strings, FIXME? this looks very fragile
|
// Get coords as a slice of strings, FIXME? this looks very fragile
|
||||||
coordSlice := func(coords string) []string {
|
coordSlice := func(coords string) []string {
|
||||||
|
@ -172,7 +172,7 @@ func (c *Core) GetAddress() *net.IP {
|
|||||||
func (c *Core) GetSubnet() *net.IPNet {
|
func (c *Core) GetSubnet() *net.IPNet {
|
||||||
subnet := address_subnetForNodeID(c.GetNodeID())[:]
|
subnet := address_subnetForNodeID(c.GetNodeID())[:]
|
||||||
subnet = append(subnet, 0, 0, 0, 0, 0, 0, 0, 0)
|
subnet = append(subnet, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||||
return &net.IPNet{ IP: subnet, Mask: net.CIDRMask(64, 128) }
|
return &net.IPNet{IP: subnet, Mask: net.CIDRMask(64, 128)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the output logger of the Yggdrasil node after startup. This may be
|
// Sets the output logger of the Yggdrasil node after startup. This may be
|
||||||
|
@ -106,6 +106,7 @@ func (t *dht) handleReq(req *dhtReq) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *dht) handleRes(res *dhtRes) {
|
func (t *dht) handleRes(res *dhtRes) {
|
||||||
|
t.core.searches.handleDHTRes(res)
|
||||||
reqs, isIn := t.reqs[res.key]
|
reqs, isIn := t.reqs[res.key]
|
||||||
if !isIn {
|
if !isIn {
|
||||||
return
|
return
|
||||||
|
@ -8,5 +8,5 @@ import "log"
|
|||||||
// Starts the function profiler. This is only supported when built with
|
// Starts the function profiler. This is only supported when built with
|
||||||
// '-tags build'.
|
// '-tags build'.
|
||||||
func StartProfiler(_ *log.Logger) error {
|
func StartProfiler(_ *log.Logger) error {
|
||||||
return errors.New("Release builds do not support -pprof, build using '-tags debug'")
|
return errors.New("Release builds do not support -pprof, build using '-tags debug'")
|
||||||
}
|
}
|
||||||
|
@ -128,12 +128,12 @@ func (r *router) sendPacket(bs []byte) {
|
|||||||
}
|
}
|
||||||
sinfo, isIn := r.core.searches.searches[*nodeID]
|
sinfo, isIn := r.core.searches.searches[*nodeID]
|
||||||
if !isIn {
|
if !isIn {
|
||||||
sinfo = r.core.searches.createSearch(nodeID, mask)
|
sinfo = r.core.searches.newIterSearch(nodeID, mask)
|
||||||
}
|
}
|
||||||
if packet != nil {
|
if packet != nil {
|
||||||
sinfo.packet = packet
|
sinfo.packet = packet
|
||||||
}
|
}
|
||||||
r.core.searches.sendSearch(sinfo)
|
r.core.searches.continueSearch(sinfo)
|
||||||
}
|
}
|
||||||
var sinfo *sessionInfo
|
var sinfo *sessionInfo
|
||||||
var isIn bool
|
var isIn bool
|
||||||
|
@ -16,15 +16,17 @@ package yggdrasil
|
|||||||
// The iterative parallel lookups from kad can skip over some DHT blackholes
|
// The iterative parallel lookups from kad can skip over some DHT blackholes
|
||||||
// This hides bugs, which I don't want to do right now
|
// This hides bugs, which I don't want to do right now
|
||||||
|
|
||||||
|
import "sort"
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
//import "fmt"
|
//import "fmt"
|
||||||
|
|
||||||
type searchInfo struct {
|
type searchInfo struct {
|
||||||
dest *NodeID
|
dest *NodeID
|
||||||
mask *NodeID
|
mask *NodeID
|
||||||
time time.Time
|
time time.Time
|
||||||
packet []byte
|
packet []byte
|
||||||
|
toVisit []*dhtInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
type searches struct {
|
type searches struct {
|
||||||
@ -55,6 +57,93 @@ func (s *searches) createSearch(dest *NodeID, mask *NodeID) *searchInfo {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
func (s *searches) handleDHTRes(res *dhtRes) {
|
||||||
|
if s.checkDHTRes(res) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.addToSearch(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *searches) addToSearch(res *dhtRes) {
|
||||||
|
// TODO
|
||||||
|
sinfo, isIn := s.searches[res.dest]
|
||||||
|
if !isIn {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
from := dhtInfo{key: res.key, coords: res.coords}
|
||||||
|
for _, info := range res.infos {
|
||||||
|
if dht_firstCloserThanThird(info.getNodeID(), &res.dest, from.getNodeID()) {
|
||||||
|
sinfo.toVisit = append(sinfo.toVisit, info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.SliceStable(sinfo.toVisit, func(i, j int) bool {
|
||||||
|
return dht_firstCloserThanThird(sinfo.toVisit[i].getNodeID(), &res.dest, sinfo.toVisit[j].getNodeID())
|
||||||
|
})
|
||||||
|
s.doSearchStep(sinfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *searches) doSearchStep(sinfo *searchInfo) {
|
||||||
|
if len(sinfo.toVisit) == 0 || time.Since(sinfo.time) > 6*time.Second {
|
||||||
|
// Dead end or timeout, do cleanup
|
||||||
|
delete(s.searches, *sinfo.dest)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
// Send to the next search target
|
||||||
|
var next *dhtInfo
|
||||||
|
next, sinfo.toVisit = sinfo.toVisit[0], sinfo.toVisit[1:]
|
||||||
|
s.core.dht.ping(next, sinfo.dest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *searches) continueSearch(sinfo *searchInfo) {
|
||||||
|
if time.Since(sinfo.time) < time.Second {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sinfo.time = time.Now()
|
||||||
|
s.doSearchStep(sinfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *searches) newIterSearch(dest *NodeID, mask *NodeID) *searchInfo {
|
||||||
|
sinfo := s.createSearch(dest, mask)
|
||||||
|
sinfo.toVisit = s.core.dht.lookup(dest, false)
|
||||||
|
return sinfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *searches) checkDHTRes(res *dhtRes) bool {
|
||||||
|
info, isIn := s.searches[res.dest]
|
||||||
|
if !isIn {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
them := getNodeID(&res.key)
|
||||||
|
var destMasked NodeID
|
||||||
|
var themMasked NodeID
|
||||||
|
for idx := 0; idx < NodeIDLen; idx++ {
|
||||||
|
destMasked[idx] = info.dest[idx] & info.mask[idx]
|
||||||
|
themMasked[idx] = them[idx] & info.mask[idx]
|
||||||
|
}
|
||||||
|
if themMasked != destMasked {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// They match, so create a session and send a sessionRequest
|
||||||
|
sinfo, isIn := s.core.sessions.getByTheirPerm(&res.key)
|
||||||
|
if !isIn {
|
||||||
|
sinfo = s.core.sessions.createSession(&res.key)
|
||||||
|
_, isIn := s.core.sessions.getByTheirPerm(&res.key)
|
||||||
|
if !isIn {
|
||||||
|
panic("This should never happen")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// FIXME (!) replay attacks could mess with coords? Give it a handle (tstamp)?
|
||||||
|
sinfo.coords = res.coords
|
||||||
|
sinfo.packet = info.packet
|
||||||
|
s.core.sessions.ping(sinfo)
|
||||||
|
// Cleanup
|
||||||
|
delete(s.searches, res.dest)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
type searchReq struct {
|
type searchReq struct {
|
||||||
key boxPubKey // Who I am
|
key boxPubKey // Who I am
|
||||||
coords []byte // Where I am
|
coords []byte // Where I am
|
||||||
|
Loading…
Reference in New Issue
Block a user