예제 #1
0
파일: router.go 프로젝트: h2so5/murcott
func (p *Router) getDirectSession(id utils.NodeID) *session {
	if id.Match(p.id) {
		return nil
	}
	p.sessionMutex.RLock()
	if s, ok := p.sessions[id]; ok {
		p.sessionMutex.RUnlock()
		return s
	}
	p.sessionMutex.RUnlock()

	var info *utils.NodeInfo
	p.dhtMutex.RLock()
	info = p.mainDht.GetNodeInfo(id)
	if info == nil {
		for _, d := range p.groupDht {
			info = d.GetNodeInfo(id)
			if info != nil {
				break
			}
		}
	}
	p.dhtMutex.RUnlock()

	if info == nil {
		return nil
	}

	addr, err := utp.ResolveAddr("utp", info.Addr.String())
	if err != nil {
		p.logger.Error("%v", err)
		return nil
	}

	conn, err := utp.DialUTPTimeout("utp", nil, addr, 100*time.Millisecond)
	if err != nil {
		p.logger.Error("%v %v", addr, err)
		return nil
	}

	s, err := newSesion(conn, p.key)
	if err != nil {
		conn.Close()
		p.logger.Error("%v", err)
		return nil
	} else {
		go p.readSession(s)
		p.addSession(s)
	}

	return s
}
예제 #2
0
파일: router.go 프로젝트: h2so5/murcott
func (p *Router) Join(group utils.NodeID) error {
	if p.getGroupDht(group) == nil {
		d := dht.NewDHT(10, p.ID(), group, p.listener.RawConn, p.logger)
		for _, n := range p.mainDht.LoadNodes(group.String()) {
			if !n.ID.Match(p.id) {
				d.Discover(n.Addr)
			}
		}
		p.dhtMutex.Lock()
		p.groupDht[group] = d
		p.dhtMutex.Unlock()
		p.mainDht.StoreNodes(group.String(), []utils.NodeInfo{
			utils.NodeInfo{ID: p.id, Addr: p.listener.Addr()},
		})
		return nil
	}
	return errors.New("already joined")
}
예제 #3
0
파일: router.go 프로젝트: h2so5/murcott
func (p *Router) getSessions(id utils.NodeID) []*session {
	var sessions []*session
	if bytes.Equal(id.NS[:], utils.GlobalNamespace[:]) {
		s := p.getDirectSession(id)
		if s != nil {
			sessions = append(sessions, s)
		}
	} else {
		if d, ok := p.groupDht[id]; ok {
			for _, n := range p.mainDht.LoadNodes(id.String()) {
				if !n.ID.Match(p.id) {
					d.Discover(n.Addr)
				}
			}
			for _, n := range d.FingerNodes() {
				s := p.getDirectSession(n.ID)
				if s != nil {
					sessions = append(sessions, s)
				}
			}
		}
	}
	return sessions
}
예제 #4
0
파일: dht.go 프로젝트: h2so5/murcott
func (p *DHT) FindNearestNode(findid utils.NodeID) []utils.NodeInfo {
	reqch := make(chan utils.NodeInfo, 100)
	endch := make(chan struct{}, 100)

	f := func(id utils.NodeID, command dhtRPCCommand) {
		defer func() { endch <- struct{}{} }()
		ret, err := p.sendAndWaitPacket(id, command)
		if err == nil {
			if _, ok := ret.command.Args["nodes"]; ok {
				var nodes []utils.NodeInfo
				ret.command.getArgs("nodes", &nodes)
				for _, n := range nodes {
					if n.ID.Digest.Cmp(p.id.Digest) != 0 {
						p.table.insert(n)
						reqch <- n
					}
				}
			}
		}
	}

	var res []utils.NodeInfo
	nodes := p.table.nearestNodes(findid)

	if len(nodes) == 0 {
		return res
	}

	for _, n := range nodes {
		reqch <- n
	}

	count := 0
	requested := make(map[utils.NodeID]utils.NodeInfo)

loop:
	for {
		select {
		case node := <-reqch:
			if _, ok := requested[node.ID]; !ok {
				requested[node.ID] = node
				c := p.newRPCCommand("find-node", map[string]interface{}{
					"id": string(findid.Bytes()),
				})
				go f(node.ID, c)
				count++
			}
		case <-endch:
			count--
			if count == 0 {
				break loop
			}
		}
	}

	for _, v := range requested {
		res = append(res, v)
	}

	sorter := utils.NodeInfoSorter{Nodes: res, ID: findid}
	sort.Sort(sorter)

	if len(sorter.Nodes) > p.k {
		return sorter.Nodes[:p.k]
	}
	return sorter.Nodes
}