commit d05a4d5f688dbd09900ceccdcc5f8109dd0671c2
Author: Cassandra Heart <cassandra@quilibrium.com>
Date: Wed Jun 12 00:50:16 2024 -0500
merge
commit db57ff1f191f9dedc87ca77da1c71244dd2325bd
Merge: 7b43494 2e3279a
Author: Cassandra Heart <cassandra@quilibrium.com>
Date: Wed Jun 12 00:49:32 2024 -0500
Merge branch 'v1.4.19' into not-release
commit 7b43494246e28152b46710c8c9821429d4231f7e
Author: Cassandra Heart <cassandra@quilibrium.com>
Date: Wed Jun 12 00:49:13 2024 -0500
pull from release site
commit 2e3279ac930ac630d9ca2b26cf4f3232abe79823
Author: Cassandra Heart <cassandra@quilibrium.com>
Date: Sat Jun 8 06:31:02 2024 -0500
remove binaries
commit 2768a8778b3860c5736352c8aa950e3496a46e56
Author: Cassandra Heart <cassandra@quilibrium.com>
Date: Sat Jun 8 06:24:44 2024 -0500
signatory #8 added
commit 6a944628575ccadd17c9f9f4a11a49c032fa0c1d
Author: Cassandra Heart <cassandra@quilibrium.com>
Date: Sat Jun 8 06:08:26 2024 -0500
signatory #6 added
commit b401fb65e5ddbe0340fe85aab1182d6120a4e161
Author: Cassandra Heart <cassandra@quilibrium.com>
Date: Sat Jun 8 05:39:03 2024 -0500
signatory #3 added
commit e5700913c0f6246fb607bcd3e219c257cb4a80e9
Author: Cassandra Heart <cassandra@quilibrium.com>
Date: Sat Jun 8 05:31:24 2024 -0500
signatory #15 added
commit 9b1da6c03e517135bfcd59226f900adab42f3687
Author: Cassandra Heart <cassandra@quilibrium.com>
Date: Sat Jun 8 05:23:02 2024 -0500
signatories #4 and #16 added
commit 9c97d1bbc399a070ac21b35ed9b1af127fa4c7ea
Author: Cassandra Heart <cassandra@quilibrium.com>
Date: Sat Jun 8 04:59:27 2024 -0500
signatories #1 and #2 added
commit 905e3f78a8121eade1c331ae910ed25dd534f27a
Author: Cassandra Heart <cassandra@quilibrium.com>
Date: Sat Jun 8 04:40:32 2024 -0500
build, binaries, signatory #13
commit ebfb57bc29d9ed1fb25d0dd100e38709354b3d84
Author: Cassandra Heart <cassandra@quilibrium.com>
Date: Sat Jun 8 03:38:53 2024 -0500
tests pass, let's go
commit 5d4612c6c624c3dc18f9a5657936034ac9d9d8dd
Author: Cassandra Heart <cassandra@quilibrium.com>
Date: Fri Jun 7 03:53:15 2024 -0500
update version info + readme
commit 6b0dd69e930d01b98acb8d7b56bb5d572e1a4324
Merge: 090d630 859221b
Author: Cassie Heart <cassandra@quilibrium.com>
Date: Fri Jun 7 08:25:16 2024 +0000
Merge branch 'feat-data-worker-direct-config' into 'v1.4.19'
feat: support detached configuration mode for data workers
See merge request quilibrium/ceremonyclient!7
commit 859221b179ab2631fa474be2494259afaaa6bd51
Author: Cassandra Heart <cassandra@quilibrium.com>
Date: Fri Jun 7 03:24:22 2024 -0500
feat: support detached configuration mode for data workers
commit 090d6301d44a2aa88886120783cd5a6e537aa6d1
Merge: 62db30c d1cae94
Author: Cassie Heart <cassandra@quilibrium.com>
Date: Fri Jun 7 06:25:43 2024 +0000
Merge branch 'feat-go-1-22' into 'v1.4.19'
feat: go 1.22 support
See merge request quilibrium/ceremonyclient!6
commit d1cae942165f4871f8051e266722c0ca717780cb
Author: Cassie Heart <cassandra@quilibrium.com>
Date: Fri Jun 7 06:25:43 2024 +0000
feat: go 1.22 support
commit 62db30c54f9258c92113c6664ce817670a339083
Merge: 0cbc0d0 f36cea3
Author: Cassie Heart <cassandra@quilibrium.com>
Date: Fri Jun 7 03:52:17 2024 +0000
Merge branch 'rust-vdf' into 'v1.4.19'
Switch to Rust VDF
See merge request quilibrium/ceremonyclient!2
commit f36cea323bfe5e56f519f59f9a0cce35f0f8b6ab
Author: Agost Biro <agostbiro@gmail.com>
Date: Fri Jun 7 03:52:16 2024 +0000
Switch to Rust VDF
commit 0cbc0d0d319713e20ca7f48588c4153833e58429
Merge: 986e12c 0c48a83
Author: Cassie Heart <cassandra@quilibrium.com>
Date: Fri Jun 7 00:50:15 2024 +0000
Merge branch 'release_image' into 'v1.4.19'
create docker image based on release binaries
See merge request quilibrium/ceremonyclient!4
commit 0c48a83bb5751abf7c8c0ff188bfdc2130631e78
Author: Marius Scurtescu <marius.scurtescu@gmail.com>
Date: Fri Jun 7 00:50:15 2024 +0000
create docker image based on release binaries
commit 986e12c88bb2d2b412b59f7db1ae39f828304dbe
Merge:
|
||
|---|---|---|
| .. | ||
| .gitignore | ||
| chat-example.gif | ||
| chatroom.go | ||
| go.mod | ||
| go.sum | ||
| main.go | ||
| README.md | ||
| ui.go | ||
go-libp2p-pubsub chat example
This example project builds a chat room application using go-libp2p-pubsub. The app runs in the terminal, and uses a text UI to show messages from other peers:
The goal of this example is to demonstrate the basic usage of the PubSub API, without getting into
the details of configuration.
Running
Clone this repo, then cd into the examples/pubsub/chat directory:
git clone https://github.com/libp2p/go-libp2p
cd go-libp2p/examples/pubsub/chat
Now you can either run with go run, or build and run the binary:
go run .
# or, build and run separately
go build .
./chat
To set a nickname, use the -nick flag:
go run . -nick=zoidberg
You can join a specific chat room with the -room flag:
go run . -room=planet-express
It's usually more fun to chat with others, so open a new terminal and run the app again.
If you set a custom chat room name with the -room flag, make sure you use the same one
for both apps. Once the new instance starts, the two chat apps should discover each other
automatically using mDNS, and typing a message into one app will send it to any others that are open.
To quit, hit Ctrl-C, or type /quit into the input field.
Code Overview
In main.go, we create a new libp2p Host and then create a new PubSub service
using the GossipSub router:
func main() {
// (omitted) parse flags, etc...
// 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)
}
// (omitted) setup mDNS discovery...
}
We configure the host to use local mDNS discovery, so that we can find other peers to chat with on the local network. We also parse a few command line flags, so we can set a friendly nickname, or choose a chat room by name.
Once we have a Host with an attached PubSub service, we join a ChatRoom:
// still in the main func
cr, err := JoinChatRoom(ctx, ps, h.ID(), nick, room)
if err != nil {
panic(err)
}
ChatRoom is a custom struct defined in chatroom.go:
// ChatRoom represents a subscription to a single PubSub topic. Messages
// can be published to the topic with ChatRoom.Publish, and received
// messages are pushed to the Messages channel.
type ChatRoom struct {
// Messages is a channel of messages received from other peers in the chat room
Messages chan *ChatMessage
ctx context.Context
ps *pubsub.PubSub
topic *pubsub.Topic
sub *pubsub.Subscription
roomName string
self peer.ID
nick string
}
A ChatRoom subscribes to a PubSub Topic, and reads messages from the Subscription. We're sending our messages
wrapped inside of a ChatMessage struct:
type ChatMessage struct {
Message string
SenderID string
SenderNick string
}
This lets us attach friendly nicknames to the messages for display. A real app might want to make sure that nicks are unique, but we just let anyone claim whatever nick they want and send it along with their messages.
The ChatMessages are encoded to JSON and published to the PubSub topic, in the Data field of a pubsub.Message.
We could have used any encoding, as long as everyone in the topic agrees on the format, but JSON is simple and good
enough for our purposes.
To send messages, we have a Publish method, which wraps messages in ChatMessage structs, encodes them, and publishes
to the pubsub.Topic:
func (cr *ChatRoom) Publish(message string) error {
m := ChatMessage{
Message: message,
SenderID: cr.self.String(),
SenderNick: cr.nick,
}
msgBytes, err := json.Marshal(m)
if err != nil {
return err
}
return cr.topic.Publish(cr.ctx, msgBytes)
}
In the background, the ChatRoom runs a readLoop goroutine, which reads messages from the pubsub.Subscription,
decodes the ChatMessage JSON, and sends the ChatMessages on a channel:
func (cr *ChatRoom) readLoop() {
for {
msg, err := cr.sub.Next(cr.ctx)
if err != nil {
close(cr.Messages)
return
}
// only forward messages delivered by others
if msg.ReceivedFrom == cr.self {
continue
}
cm := new(ChatMessage)
err = json.Unmarshal(msg.Data, cm)
if err != nil {
continue
}
// send valid messages onto the Messages channel
cr.Messages <- cm
}
}
There's also a ListPeers method, which just wraps the method of the same name in the PubSub service:
func (cr *ChatRoom) ListPeers() []peer.ID {
return cr.ps.ListPeers(topicName(cr.roomName))
}
That's pretty much it for the ChatRoom!
Back in main.go, once we've created our ChatRoom, we pass it
to NewChatUI, which constructs a three panel text UI for entering and viewing chat messages, because UIs
are fun.
The ChatUI is defined in ui.go, and the interesting bit is in the handleEvents event loop
method:
func (ui *ChatUI) handleEvents() {
peerRefreshTicker := time.NewTicker(time.Second)
defer peerRefreshTicker.Stop()
for {
select {
case input := <-ui.inputCh:
// when the user types in a line, publish it to the chat room and print to the message window
err := ui.cr.Publish(input)
if err != nil {
printErr("publish error: %s", err)
}
ui.displaySelfMessage(input)
case m := <-ui.cr.Messages:
// when we receive a message from the chat room, print it to the message window
ui.displayChatMessage(m)
case <-peerRefreshTicker.C:
// refresh the list of peers in the chat room periodically
ui.refreshPeers()
case <-ui.cr.ctx.Done():
return
case <-ui.doneCh:
return
}
}
}
