ceremonyclient/go-libp2p/examples/pubsub/chat/main.go
2024-06-07 06:25:43 +00:00

110 lines
3.0 KiB
Go

package main
import (
"context"
"flag"
"fmt"
"os"
"time"
"github.com/libp2p/go-libp2p"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/p2p/discovery/mdns"
)
// DiscoveryInterval is how often we re-publish our mDNS records.
const DiscoveryInterval = time.Hour
// DiscoveryServiceTag is used in our mDNS advertisements to discover other chat peers.
const DiscoveryServiceTag = "pubsub-chat-example"
func main() {
// parse some flags to set our nickname and the room to join
nickFlag := flag.String("nick", "", "nickname to use in chat. will be generated if empty")
roomFlag := flag.String("room", "awesome-chat-room", "name of chat room to join")
flag.Parse()
ctx := context.Background()
// create a new libp2p Host that listens on a random TCP port
h, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0"))
if err != nil {
panic(err)
}
// create a new PubSub service using the GossipSub router
ps, err := pubsub.NewGossipSub(ctx, h)
if err != nil {
panic(err)
}
// setup local mDNS discovery
if err := setupDiscovery(h); err != nil {
panic(err)
}
// use the nickname from the cli flag, or a default if blank
nick := *nickFlag
if len(nick) == 0 {
nick = defaultNick(h.ID())
}
// join the room from the cli flag, or the flag default
room := *roomFlag
// join the chat room
cr, err := JoinChatRoom(ctx, ps, h.ID(), nick, room)
if err != nil {
panic(err)
}
// draw the UI
ui := NewChatUI(cr)
if err = ui.Run(); err != nil {
printErr("error running text UI: %s", err)
}
}
// printErr is like fmt.Printf, but writes to stderr.
func printErr(m string, args ...interface{}) {
fmt.Fprintf(os.Stderr, m, args...)
}
// defaultNick generates a nickname based on the $USER environment variable and
// the last 8 chars of a peer ID.
func defaultNick(p peer.ID) string {
return fmt.Sprintf("%s-%s", os.Getenv("USER"), shortID(p))
}
// shortID returns the last 8 chars of a base58-encoded peer id.
func shortID(p peer.ID) string {
pretty := p.String()
return pretty[len(pretty)-8:]
}
// discoveryNotifee gets notified when we find a new peer via mDNS discovery
type discoveryNotifee struct {
h host.Host
}
// HandlePeerFound connects to peers discovered via mDNS. Once they're connected,
// the PubSub system will automatically start interacting with them if they also
// support PubSub.
func (n *discoveryNotifee) HandlePeerFound(pi peer.AddrInfo) {
fmt.Printf("discovered new peer %s\n", pi.ID)
err := n.h.Connect(context.Background(), pi)
if err != nil {
fmt.Printf("error connecting to peer %s: %s\n", pi.ID, err)
}
}
// setupDiscovery creates an mDNS discovery service and attaches it to the libp2p Host.
// This lets us automatically discover peers on the same LAN and connect to them.
func setupDiscovery(h host.Host) error {
// setup mDNS discovery to find local peers
s := mdns.NewMdnsService(h, DiscoveryServiceTag, &discoveryNotifee{h: h})
return s.Start()
}