Skip to content

Commit bcce1fb

Browse files
authored
feat: add pubsub browser peer discovery (#133)
* rust-peer: do not add externally observed maddrs Might fix #131 * feat: subscribe go peer to peer discovery topic * feat: add pubsub peer discovery to js peer * fix: build * fix: use peer:discovery event to hook to peer discovery events * fix: remove idb datastore no real reason to use it for now * feat: dial peers discovered through pubsub * chore: simplify code and move out fn * feat: autodial discovered with connection manager * chore: remove connection manager logs * refactor: simplify code further --------- Co-authored-by: Daniel N <[email protected]>
1 parent 2246b25 commit bcce1fb

File tree

10 files changed

+145
-113
lines changed

10 files changed

+145
-113
lines changed

go-peer/chatroom.go

+43-32
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ import (
1515
// ChatRoomBufSize is the number of incoming messages to buffer for each topic.
1616
const ChatRoomBufSize = 128
1717

18+
// Topic used to broadcast browser WebRTC addresses
19+
const PubSubDiscoveryTopic string = "universal-connectivity-browser-peer-discovery"
20+
21+
const ChatTopic string = "universal-connectivity"
22+
const ChatFileTopic string = "universal-connectivity-file"
23+
1824
// ChatRoom represents a subscription to a single PubSub topic. Messages
1925
// can be published to the topic with ChatRoom.Publish, and received
2026
// messages are pushed to the Messages channel.
@@ -23,13 +29,15 @@ type ChatRoom struct {
2329
Messages chan *ChatMessage
2430
SysMessages chan *ChatMessage
2531

26-
ctx context.Context
27-
h host.Host
28-
ps *pubsub.PubSub
29-
chatTopic *pubsub.Topic
30-
chatSub *pubsub.Subscription
31-
fileTopic *pubsub.Topic
32-
fileSub *pubsub.Subscription
32+
ctx context.Context
33+
h host.Host
34+
ps *pubsub.PubSub
35+
chatTopic *pubsub.Topic
36+
chatSub *pubsub.Subscription
37+
fileTopic *pubsub.Topic
38+
fileSub *pubsub.Subscription
39+
peerDiscoveryTopic *pubsub.Topic
40+
peerDiscoverySub *pubsub.Subscription
3341

3442
roomName string
3543
nick string
@@ -44,9 +52,9 @@ type ChatMessage struct {
4452

4553
// JoinChatRoom tries to subscribe to the PubSub topic for the room name, returning
4654
// a ChatRoom on success.
47-
func JoinChatRoom(ctx context.Context, h host.Host, ps *pubsub.PubSub, nickname string, roomName string) (*ChatRoom, error) {
55+
func JoinChatRoom(ctx context.Context, h host.Host, ps *pubsub.PubSub, nickname string) (*ChatRoom, error) {
4856
// join the pubsub chatTopic
49-
chatTopic, err := ps.Join(chatTopicName(roomName))
57+
chatTopic, err := ps.Join(ChatTopic)
5058
if err != nil {
5159
return nil, err
5260
}
@@ -58,7 +66,7 @@ func JoinChatRoom(ctx context.Context, h host.Host, ps *pubsub.PubSub, nickname
5866
}
5967

6068
// join the pubsub fileTopic
61-
fileTopic, err := ps.Join(fileTopicName(roomName))
69+
fileTopic, err := ps.Join(ChatFileTopic)
6270
if err != nil {
6371
return nil, err
6472
}
@@ -69,18 +77,31 @@ func JoinChatRoom(ctx context.Context, h host.Host, ps *pubsub.PubSub, nickname
6977
return nil, err
7078
}
7179

80+
// join the pubsub peer disovery topic
81+
peerDiscoveryTopic, err := ps.Join(PubSubDiscoveryTopic)
82+
if err != nil {
83+
return nil, err
84+
}
85+
86+
// and subscribe to it
87+
peerDiscoverySub, err := peerDiscoveryTopic.Subscribe()
88+
if err != nil {
89+
return nil, err
90+
}
91+
7292
cr := &ChatRoom{
73-
ctx: ctx,
74-
h: h,
75-
ps: ps,
76-
chatTopic: chatTopic,
77-
chatSub: chatSub,
78-
fileTopic: fileTopic,
79-
fileSub: fileSub,
80-
nick: nickname,
81-
roomName: roomName,
82-
Messages: make(chan *ChatMessage, ChatRoomBufSize),
83-
SysMessages: make(chan *ChatMessage, ChatRoomBufSize),
93+
ctx: ctx,
94+
h: h,
95+
ps: ps,
96+
chatTopic: chatTopic,
97+
chatSub: chatSub,
98+
fileTopic: fileTopic,
99+
fileSub: fileSub,
100+
peerDiscoveryTopic: peerDiscoveryTopic,
101+
peerDiscoverySub: peerDiscoverySub,
102+
nick: nickname,
103+
Messages: make(chan *ChatMessage, ChatRoomBufSize),
104+
SysMessages: make(chan *ChatMessage, ChatRoomBufSize),
84105
}
85106

86107
// start reading messages from the subscription in a loop
@@ -94,7 +115,7 @@ func (cr *ChatRoom) Publish(message string) error {
94115
}
95116

96117
func (cr *ChatRoom) ListPeers() []peer.ID {
97-
return cr.ps.ListPeers(chatTopicName(cr.roomName))
118+
return cr.ps.ListPeers(ChatTopic)
98119
}
99120

100121
// readLoop pulls messages from the pubsub chat/file topic and handles them.
@@ -187,13 +208,3 @@ func (cr *ChatRoom) requestFile(toPeer peer.ID, fileID []byte) ([]byte, error) {
187208

188209
return fileBody, nil
189210
}
190-
191-
// chatTopicName returns the name of the pubsub topic for the chat room.
192-
func chatTopicName(roomName string) string {
193-
return roomName
194-
}
195-
196-
// fileTopicName returns the name of the pubsub topic used for sending/recieving files in the chat room.
197-
func fileTopicName(roomName string) string {
198-
return fmt.Sprintf("%s-file", roomName)
199-
}

go-peer/main.go

+7-9
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,12 @@ func NewDHT(ctx context.Context, host host.Host, bootstrapPeers []multiaddr.Mult
7272
}
7373

7474
// Borrowed from https://medium.com/rahasak/libp2p-pubsub-peer-discovery-with-kademlia-dht-c8b131550ac7
75-
func Discover(ctx context.Context, h host.Host, dht *dht.IpfsDHT, rendezvous string) {
75+
// Only used by Go peer to find each other.
76+
// TODO: since this isn't implemented on the Rust or the JS side, can probably be removed
77+
func Discover(ctx context.Context, h host.Host, dht *dht.IpfsDHT) {
7678
routingDiscovery := routing.NewRoutingDiscovery(dht)
7779

78-
discovery.Advertise(ctx, routingDiscovery, rendezvous)
80+
discovery.Advertise(ctx, routingDiscovery, DiscoveryServiceTag)
7981

8082
ticker := time.NewTicker(time.Second * 10)
8183
defer ticker.Stop()
@@ -86,7 +88,7 @@ func Discover(ctx context.Context, h host.Host, dht *dht.IpfsDHT, rendezvous str
8688
return
8789
case <-ticker.C:
8890

89-
peers, err := discovery.FindPeers(ctx, routingDiscovery, rendezvous)
91+
peers, err := discovery.FindPeers(ctx, routingDiscovery, DiscoveryServiceTag)
9092
if err != nil {
9193
panic(err)
9294
}
@@ -115,7 +117,6 @@ func LogMsgf(f string, msg ...any) {
115117
func main() {
116118
// parse some flags to set our nickname and the room to join
117119
nickFlag := flag.String("nick", "", "nickname to use in chat. will be generated if empty")
118-
roomFlag := flag.String("room", "universal-connectivity", "name of chat room to join")
119120
idPath := flag.String("identity", "identity.key", "path to the private key (PeerID) file")
120121
certPath := flag.String("tls-cert-path", "", "path to the tls cert file (for websockets)")
121122
keyPath := flag.String("tls-key-path", "", "path to the tls key file (for websockets")
@@ -194,11 +195,8 @@ func main() {
194195
nick = defaultNick(h.ID())
195196
}
196197

197-
// join the room from the cli flag, or the flag default
198-
room := *roomFlag
199-
200198
// join the chat room
201-
cr, err := JoinChatRoom(ctx, h, ps, nick, room)
199+
cr, err := JoinChatRoom(ctx, h, ps, nick)
202200
if err != nil {
203201
panic(err)
204202
}
@@ -213,7 +211,7 @@ func main() {
213211
}
214212

215213
// setup peer discovery
216-
go Discover(ctx, h, dht, "universal-connectivity")
214+
go Discover(ctx, h, dht)
217215

218216
// setup local mDNS discovery
219217
if err := setupDiscovery(h); err != nil {

js-peer/package-lock.json

+32-18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js-peer/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
"@libp2p/identify": "^1.0.19",
2020
"@libp2p/interface-pubsub": "^4.0.1",
2121
"@libp2p/kad-dht": "^12.0.13",
22+
"@libp2p/pubsub-peer-discovery": "^10.0.2",
2223
"@libp2p/webrtc": "^4.0.28",
2324
"@libp2p/websockets": "^8.0.20",
2425
"@libp2p/webtransport": "^4.0.28",
2526
"@multiformats/multiaddr": "^12.2.1",
26-
"datastore-idb": "^2.1.9",
2727
"debug": "^4.3.4",
2828
"it-length-prefixed": "^9.0.4",
2929
"it-map": "^3.1.0",

js-peer/src/context/chat-ctx.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { createContext, useContext, useEffect, useState } from 'react';
22
import { useLibp2pContext } from './ctx';
33
import type { Message } from '@libp2p/interface'
4-
import { CHAT_FILE_TOPIC, CHAT_TOPIC, FILE_EXCHANGE_PROTOCOL } from '@/lib/constants'
4+
import { CHAT_FILE_TOPIC, CHAT_TOPIC, FILE_EXCHANGE_PROTOCOL, PUBSUB_PEER_DISCOVERY } from '@/lib/constants'
55
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
66
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
77
import { pipe } from 'it-pipe'
@@ -58,8 +58,11 @@ export const ChatProvider = ({ children }: any) => {
5858
chatFileMessageCB(evt, topic, data)
5959
break
6060
}
61+
case PUBSUB_PEER_DISCOVERY: {
62+
break
63+
}
6164
default: {
62-
throw new Error(`Unexpected gossipsub topic: ${topic}`)
65+
console.error(`Unexpected event %o on gossipsub topic: ${topic}`, evt)
6366
}
6467
}
6568
}

js-peer/src/context/peer-ctx.tsx

-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { PeerId } from '@libp2p/interface'
55

66
export interface PeerStats {
77
peerIds: PeerId[]
8-
connected: boolean
98
connections: Connection[]
109
latency: number
1110
}
@@ -17,7 +16,6 @@ export interface PeerContextInterface {
1716
export const peerContext = createContext<PeerContextInterface>({
1817
peerStats: {
1918
peerIds: [],
20-
connected: true,
2119
connections: [],
2220
latency: 0
2321
},
@@ -31,7 +29,6 @@ export const usePeerContext = () => {
3129
export const PeerProvider = ({ children }: { children: ReactNode }) => {
3230
const [peerStats, setPeerStats] = useState<PeerStats>({
3331
peerIds: [],
34-
connected: false,
3532
connections: [],
3633
latency: 0
3734
});

js-peer/src/lib/constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export const CHAT_TOPIC = "universal-connectivity"
22
export const CHAT_FILE_TOPIC = "universal-connectivity-file"
3+
export const PUBSUB_PEER_DISCOVERY = "universal-connectivity-browser-peer-discovery"
34
export const FILE_EXCHANGE_PROTOCOL = "/universal-connectivity-file/1"
45

56
export const CIRCUIT_RELAY_CODE = 290

0 commit comments

Comments
 (0)