Skip to content

Instantly share code, notes, and snippets.

@upperwal
Last active December 22, 2023 07:18
Show Gist options
  • Save upperwal/38cd0c98e4a6b34c061db0ff26def9b9 to your computer and use it in GitHub Desktop.
Save upperwal/38cd0c98e4a6b34c061db0ff26def9b9 to your computer and use it in GitHub Desktop.
package main

import (
	"bufio"
	"context"
	"fmt"
	"time"
	"os"

	"github.com/libp2p/go-libp2p"
	"github.com/libp2p/go-libp2p-kad-dht"
	"github.com/libp2p/go-libp2p-net"
	"github.com/ipfs/go-datastore"
	"github.com/ipfs/go-ipfs-addr"
	"github.com/libp2p/go-libp2p-peerstore"
	"github.com/ipfs/go-cid"
	"github.com/multiformats/go-multihash"
	"github.com/multiformats/go-multiaddr"
	"github.com/libp2p/go-libp2p-crypto"
)

func handleStream(s net.Stream) {
	fmt.Println("Got a new stream!")


	rw := bufio.NewReadWriter(bufio.NewReader(s), bufio.NewWriter(s))

	go readData(rw)
	go writeData(rw)
	// stream 's' will stay open until you close it (or the other side closes it).
}

func readData(rw *bufio.ReadWriter) {
	for {
		str, _ := rw.ReadString('\n')

		if str == "" {
			return
		}
		if str != "\n" {
			// Green console colour: 	\x1b[32m
			// Reset console colour: 	\x1b[0m
			fmt.Printf("\x1b[32m%s\x1b[0m> ", str)
		}

	}
}

func writeData(rw *bufio.ReadWriter) {
	stdReader := bufio.NewReader(os.Stdin)

	for {
		fmt.Print("> ")
		sendData, err := stdReader.ReadString('\n')

		if err != nil {
			panic(err)
		}

		rw.WriteString(fmt.Sprintf("%s\n", sendData))
		rw.Flush()
	}

}

func main() {
	ctx := context.Background()

	prvKey, _, err := crypto.GenerateKeyPair(crypto.RSA, 2048)

	if err != nil {
		panic(err)
	}

	sourceMultiAddr, _ := multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/0.0.0.0/tcp/0"))
	host, err := libp2p.New (
		ctx,
		libp2p.ListenAddrs(sourceMultiAddr),
		libp2p.Identity(prvKey),
	)
	if err != nil {
		panic(err)
	}

	fmt.Println(host)

	host.SetStreamHandler("abhishek/1.0.0", handleStream)

	fmt.Println("This host: ", host.Addrs())

	dht := dht.NewDHTClient(ctx, host, datastore.NewMapDatastore())


	bootstrapPeers := []string{
		"/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
		"/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",
		"/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64",
		"/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",
		"/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd",
	}

	for _, addr := range bootstrapPeers {
		iaddr, _ := ipfsaddr.ParseString(addr)

		peerinfo, _ := peerstore.InfoFromP2pAddr(iaddr.Multiaddr())

		if err := host.Connect(ctx, *peerinfo); err != nil {
			panic(err)
		} else {
			fmt.Println("Connection established: ", *peerinfo)
		}
	}

	c, _ := cid.NewPrefixV1(cid.Raw, multihash.SHA2_256).Sum([]byte("meet me here"))

	fmt.Println("announcing ourselves...")
	tctx, _ := context.WithTimeout(ctx, time.Second*10)
	if err := dht.Provide(tctx, c, true); err != nil {
		panic(err)
	}

	// Now, look for others who have announced
	fmt.Println("searching for other peers...")
	tctx, _ = context.WithTimeout(ctx, time.Second*10)
	peers, err := dht.FindProviders(tctx, c)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Found %d peers!\n", len(peers))

	for _, p := range peers {
		fmt.Println("Peer: ", p)
	}

	for _, p := range peers {
		if p.ID == host.ID() {
			// No sense connecting to ourselves
			continue
		}

		tctx, _ := context.WithTimeout(ctx, time.Second*5)
		if err := host.Connect(tctx, p); err != nil {
			//fmt.Println("failed to connect to peer: ", err)
		} else {
			s, err := host.NewStream(context.Background(), p.ID, "abhishek/1.0.0")
			if err != nil {
				fmt.Println(err)
			} else {
				rw := bufio.NewReadWriter(bufio.NewReader(s), bufio.NewWriter(s))
				go writeData(rw)
				go readData(rw)
			}
			fmt.Println("Connected to: ", p)
		}
	}

	select{}

}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment