ceremonyclient/go-libp2p/examples/chat-with-mdns/README.md
2024-06-07 06:25:43 +00:00

3.1 KiB

p2p chat app with libp2p [support peer discovery using mdns]

This program demonstrates a simple p2p chat application. You will learn how to discover a peer in the network (using mdns), connect to it and open a chat stream. This example is heavily influenced by (and shamelessly copied from) chat-with-rendezvous example

How to build this example?

go get -v -d ./...

go build

Usage

Use two different terminal windows to run

./chat-with-mdns -port 6666
./chat-with-mdns -port 6668

So how does it work?

  1. Configure a p2p host
ctx := context.Background()

// libp2p.New constructs a new libp2p Host.
// Other options can be added here.
host, err := libp2p.New()

libp2p.New is the constructor for libp2p node. It creates a host with given configuration.

  1. Set a default handler function for incoming connections.

This function is called on the local peer when a remote peer initiate a connection and starts a stream with the local peer.

// Set a function as stream handler.
host.SetStreamHandler("/chat/1.1.0", handleStream)

handleStream is executed for each new stream incoming to the local peer. stream is used to exchange data between local and remote peer. This example uses non blocking functions for reading and writing from this stream.

func handleStream(stream net.Stream) {

    // Create a buffer stream for non blocking read and write.
    rw := bufio.NewReadWriter(bufio.NewReader(stream), bufio.NewWriter(stream))

    go readData(rw)
    go writeData(rw)

    // 'stream' will stay open until you close it (or the other side closes it).
}
  1. Find peers nearby using mdns

New mdns discovery service in host.

notifee := &discoveryNotifee{PeerChan: make(chan peer.AddrInfo)}
ser, err := discovery.NewMdnsService(peerhost, rendezvous, notifee)

register Notifee interface with service so that we get notified about peer discovery

	ser.Start()
  1. Open streams to peers found.

Finally we open stream to the peers we found, as we find them

	peer := <-peerChan // will block until we discover a peer
	// this is used to avoid call `NewStream` from both side
	if peer.ID > host.ID() {
		// if other end peer id greater than us, don't connect to it, just wait for it to connect us
		fmt.Println("Found peer:", peer, " id is greater than us, wait for it to connect to us")
		continue
	}
	fmt.Println("Found peer:", peer, ", connecting")

	if err := host.Connect(ctx, peer); err != nil {
		fmt.Println("Connection failed:", err)
		continue
	}

	// open a stream, this stream will be handled by handleStream other end
	stream, err := host.NewStream(ctx, peer.ID, protocol.ID(cfg.ProtocolID))

	if err != nil {
		fmt.Println("Stream open failed", err)
	} else {
		rw := bufio.NewReadWriter(bufio.NewReader(stream), bufio.NewWriter(stream))

		go writeData(rw)
		go readData(rw)
		fmt.Println("Connected to:", peer)
	}

Authors

  1. Bineesh Lazar