package main import ( "context" "fmt" "os" "os/signal" "syscall" "github.com/libp2p/go-libp2p" kaddht "github.com/libp2p/go-libp2p-kad-dht" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/routing" "github.com/libp2p/go-libp2p/p2p/discovery/mdns" drouting "github.com/libp2p/go-libp2p/p2p/discovery/routing" dutil "github.com/libp2p/go-libp2p/p2p/discovery/util" "github.com/libp2p/go-libp2p/p2p/muxer/yamux" tls "github.com/libp2p/go-libp2p/p2p/security/tls" "github.com/libp2p/go-libp2p/p2p/transport/tcp" "github.com/libp2p/go-libp2p/p2p/transport/websocket" "github.com/multiformats/go-multiaddr" ) type discoveryNotifee struct { h host.Host ctx context.Context } func (m *discoveryNotifee) HandlePeerFound(pi peer.AddrInfo) { if m.h.Network().Connectedness(pi.ID) != network.Connected { fmt.Printf("Found %s!\n", pi.ID.ShortString()) m.h.Connect(m.ctx, pi) } } func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() transports := libp2p.ChainOptions( libp2p.Transport(tcp.NewTCPTransport), libp2p.Transport(websocket.New), ) muxers := libp2p.Muxer("/yamux/1.0.0", yamux.DefaultTransport) security := libp2p.Security(tls.ID, tls.New) listenAddrs := libp2p.ListenAddrStrings( "/ip4/0.0.0.0/tcp/0", "/ip4/0.0.0.0/tcp/0/ws", ) var dht *kaddht.IpfsDHT newDHT := func(h host.Host) (routing.PeerRouting, error) { var err error dht, err = kaddht.New(ctx, h) return dht, err } routing := libp2p.Routing(newDHT) host, err := libp2p.New( transports, listenAddrs, muxers, security, routing, ) if err != nil { panic(err) } // TODO: Replace our stream handler with a pubsub instance, and a handler // to field incoming messages on our topic. host.SetStreamHandler(chatProtocol, chatHandler) for _, addr := range host.Addrs() { fmt.Println("Listening on", addr) } targetAddr, err := multiaddr.NewMultiaddr("/ip4/127.0.0.1/tcp/63785/p2p/QmWjz6xb8v9K4KnYEwP5Yk75k5mMBCehzWFLCvvQpYxF3d") if err != nil { panic(err) } targetInfo, err := peer.AddrInfoFromP2pAddr(targetAddr) if err != nil { panic(err) } err = host.Connect(ctx, *targetInfo) if err != nil { fmt.Fprintf(os.Stderr, "connecting to bootstrap: %s", err) } else { fmt.Println("Connected to", targetInfo.ID) } notifee := &discoveryNotifee{h: host, ctx: ctx} mdns := mdns.NewMdnsService(host, "", notifee) if err := mdns.Start(); err != nil { panic(err) } err = dht.Bootstrap(ctx) if err != nil { panic(err) } routingDiscovery := drouting.NewRoutingDiscovery(dht) dutil.Advertise(ctx, routingDiscovery, string(chatProtocol)) peers, err := dutil.FindPeers(ctx, routingDiscovery, string(chatProtocol)) if err != nil { panic(err) } for _, peer := range peers { notifee.HandlePeerFound(peer) } donec := make(chan struct{}, 1) go chatInputLoop(ctx, host, donec) stop := make(chan os.Signal, 1) signal.Notify(stop, syscall.SIGINT) select { case <-stop: host.Close() os.Exit(0) case <-donec: host.Close() } }