mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 11:15:07 +03:00 
			
		
		
		
	start of iterative dht searches
This commit is contained in:
		
							parent
							
								
									dc841c550b
								
							
						
					
					
						commit
						ecf7e490d7
					
				
					 6 changed files with 101 additions and 11 deletions
				
			
		| 
						 | 
					@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue