func (s *Server) Announce(infoHash [20]byte, port int, impliedPort bool) (*Announce, error) {
	startAddrs, err := s.traversalStartingNodes()
	if err != nil {
		return nil, err
	}
	a := &Announce{
		Peers:               make(chan PeersValues, 100),
		values:              make(chan PeersValues),
		triedAddrs:          newBloomFilterForTraversal(),
		server:              s,
		infoHash:            int160FromByteArray(infoHash),
		announcePort:        port,
		announcePortImplied: impliedPort,
		contactRateLimiter:  make(chan struct{}, 10),
	}
	a.ctx, a.cancel = context.WithCancel(context.Background())
	a.stop = a.ctx.Done()
	a.nodesPendingContact.target = int160FromByteArray(infoHash)
	a.nodeContactorCond.L = &a.mu
	go a.rateUnlimiter()
	// Function ferries from values to Values until discovery is halted.
	go func() {
		defer close(a.Peers)
		for {
			select {
			case psv := <-a.values:
				select {
				case a.Peers <- psv:
				case <-a.stop:
					return
				}
			case <-a.stop:
				return
			}
		}
	}()
	for _, n := range startAddrs {
		a.pendContact(n)
	}
	a.maybeClose()
	go a.nodeContactor()
	return a, nil
}
func (s *Server) Announce(infoHash [20]byte, port int, impliedPort bool) (*Announce, error) {
	startAddrs, err := s.traversalStartingNodes()
	if err != nil {
		return nil, err
	}
	a := &Announce{
		Peers:               make(chan PeersValues, 100),
		values:              make(chan PeersValues),
		triedAddrs:          newBloomFilterForTraversal(),
		server:              s,
		infoHash:            int160FromByteArray(infoHash),
		announcePort:        port,
		announcePortImplied: impliedPort,
		contactRateLimiter:  make(chan struct{}, 10),
	}
	a.ctx, a.cancel = context.WithCancel(context.Background())
	a.stop = a.ctx.Done()
	a.nodesPendingContact.target = int160FromByteArray(infoHash)
	a.nodeContactorCond.L = &a.mu
	go a.rateUnlimiter()
	
	go func() {
		defer close(a.Peers)
		for {
			select {
			case psv := <-a.values:
				select {
				case a.Peers <- psv:
				case <-a.stop:
					return
				}
			case <-a.stop:
				return
			}
		}
	}()
	for _, n := range startAddrs {
		a.pendContact(n)
	}
	a.maybeClose()
	go a.nodeContactor()
	return a, nil
}
func ( s * Server ) Announce ( infoHash [ 20 ] byte , port int , impliedPort bool ) ( * Announce , error ) { startAddrs , err := s . traversalStartingNodes ( ) if err != nil { return nil , err } a := & Announce { Peers : make ( chan PeersValues , 100 ) , values : make ( chan PeersValues ) , triedAddrs : newBloomFilterForTraversal ( ) , server : s , infoHash : int160FromByteArray ( infoHash ) , announcePort : port , announcePortImplied : impliedPort , contactRateLimiter : make ( chan struct { } , 10 ) , } a . ctx , a . cancel = context . WithCancel ( context . Background ( ) ) a . stop = a . ctx . Done ( ) a . nodesPendingContact . target = int160FromByteArray ( infoHash ) a . nodeContactorCond . L = & a . mu go a . rateUnlimiter ( ) // Function ferries from values to Values until discovery is halted. go func ( ) { defer close ( a . Peers ) for { select { case psv := <- a . values : select { case a . Peers <- psv : case <- a . stop : return } case <- a . stop : return } } } ( ) for _ , n := range startAddrs { a . pendContact ( n ) } a . maybeClose ( ) go a . nodeContactor ( ) return a , nil }
// This is kind of the main thing you want to do with DHT. It traverses the
// graph toward nodes that store peers for the infohash, streaming them to the
// caller, and announcing the local node to each node if allowed and
// specified.
This is kind of the main thing you want to do with DHT . It traverses the graph toward nodes that store peers for the infohash streaming them to the caller and announcing the local node to each node if allowed and specified .