github.com/amazechain/amc@v0.1.3/internal/network/kad_dht.go (about)

     1  // Copyright 2022 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The AmazeChain library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package network
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"github.com/amazechain/amc/log"
    23  	"time"
    24  
    25  	kademliaDHT "github.com/libp2p/go-libp2p-kad-dht"
    26  	"github.com/libp2p/go-libp2p/core/peer"
    27  	discovery "github.com/libp2p/go-libp2p/p2p/discovery/routing"
    28  )
    29  
    30  type KadDHT struct {
    31  	*kademliaDHT.IpfsDHT
    32  
    33  	service *Service
    34  
    35  	routingDiscovery *discovery.RoutingDiscovery
    36  
    37  	ctx    context.Context
    38  	cancel context.CancelFunc
    39  }
    40  
    41  func NewKadDht(ctx context.Context, s *Service, isServer bool, bootstrappers ...peer.AddrInfo) (*KadDHT, error) {
    42  
    43  	c, cancel := context.WithCancel(ctx)
    44  	var mode kademliaDHT.ModeOpt
    45  	if isServer {
    46  		mode = kademliaDHT.ModeServer
    47  	} else {
    48  		mode = kademliaDHT.ModeClient
    49  	}
    50  
    51  	dht, err := kademliaDHT.New(c, s.host, kademliaDHT.Mode(mode), kademliaDHT.BootstrapPeers(bootstrappers...))
    52  
    53  	if err != nil {
    54  		log.Error("create dht failed", err)
    55  		cancel()
    56  		return nil, err
    57  	}
    58  
    59  	kDHT := &KadDHT{
    60  		IpfsDHT:          dht,
    61  		routingDiscovery: discovery.NewRoutingDiscovery(dht),
    62  		ctx:              c,
    63  		cancel:           cancel,
    64  		service:          s,
    65  	}
    66  
    67  	return kDHT, nil
    68  }
    69  
    70  func (k *KadDHT) Start() error {
    71  	err := k.Bootstrap(k.ctx)
    72  	if err != nil {
    73  		log.Error("setup bootstrap failed", err)
    74  		return err
    75  	}
    76  
    77  	//todo
    78  	//if err := k.discoverLocal(); err != nil {
    79  	//	log.Error("setup mdns discover failed", err)
    80  	//	return err
    81  	//}
    82  
    83  	k.routingDiscovery.Advertise(k.ctx, DiscoverProtocol)
    84  	go k.loopDiscoverRemote()
    85  
    86  	return nil
    87  }
    88  
    89  func (k *KadDHT) loopDiscoverRemote() {
    90  
    91  	ticker := time.NewTicker(10 * time.Second)
    92  	defer ticker.Stop()
    93  	for {
    94  		select {
    95  		case <-k.ctx.Done():
    96  			return
    97  		case <-ticker.C:
    98  			peerChan, err := k.routingDiscovery.FindPeers(k.ctx, DiscoverProtocol)
    99  			if err != nil {
   100  				log.Warn("find peers failed", err)
   101  			} else {
   102  				for p := range peerChan {
   103  					if p.ID != k.service.host.ID() {
   104  						log.Tracef("find peer %s", fmt.Sprintf("info: %s", p.String()))
   105  						k.service.HandlePeerFound(p)
   106  					}
   107  				}
   108  			}
   109  
   110  			ticker.Reset(60 * time.Second)
   111  		}
   112  	}
   113  }
   114  
   115  //func (k *KadDHT) findPeers() []peer.AddrInfo {
   116  	//peers, err := k.routingDiscovery.FindPeers(k.ctx, DiscoverProtocol)
   117  	//if err != nil {
   118  	//	return nil
   119  	//} else {
   120  	//	return peers
   121  	//}
   122  //}
   123  
   124  func (k *KadDHT) discoverLocal() error {
   125  
   126  	//m := mdns.NewMdnsService(k.service.host, "", k.service.HandlePeerFound)
   127  	//if err := m.Start(); err != nil {
   128  	//	log.Error("mdns start failed", err)
   129  	//	return err
   130  	//}
   131  	//
   132  	return nil
   133  }