-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
6 changed files
with
265 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
./go-examples | ||
./rendezvous/chat |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,65 @@ | ||
# p2chat | ||
# p2chat | ||
|
||
Examples of local chats on libp2p stack | ||
|
||
Both examples work with automatic peer discovery | ||
I've separated mdns from rendezvous point, so you can try both of methods as you wish | ||
|
||
|
||
|
||
## What's the main difference and how it could be implemented as MoonShard solution | ||
|
||
Simply words, both methods use DHT for peerdiscovery | ||
|
||
mDNS using micro-dns service, which means that routing node in the network should support | ||
this service. Most of modern routers should support it, but not everyone | ||
(i.g. mDNS will definetly not working at Moscow subways as we learned in fields testing) | ||
Also not sure mDNS will work from mobile ad-hoc points, but have not tested it this far | ||
|
||
Rendezvous point is better solution, and also should decrease battery consumption | ||
Also it should better connect local chats with cloud (remote) nodes. | ||
Rendezvous also great when thereare a lot of offline nodes behind NAT and it hard to connect with them | ||
|
||
Probably will switch to SONM solution, but as far we are fully accomplish with libp2p stack | ||
|
||
|
||
## How to build | ||
require go version >=1.11 , so make sure your `go version` is okay | ||
|
||
If it start yelling about go modules, try | ||
``` | ||
export GO111MODULE=on | ||
``` | ||
I've include it into Makefile, but not sure it will work correctly | ||
|
||
|
||
### How to build rendezvous | ||
From main repo run | ||
``` | ||
> make deps | ||
> cd ./rendezvous | ||
> go build -o chat | ||
``` | ||
### How to use rendezvous | ||
Use two different terminal windows to run | ||
``` | ||
./chat -listen /ip4/127.0.0.1/tcp/6666 | ||
./chat -listen /ip4/127.0.0.1/tcp/6668 | ||
``` | ||
Remember about NAT penetration! | ||
|
||
### How to build mDNS | ||
``` | ||
go get -v -d ./... | ||
go build | ||
``` | ||
|
||
### How to use mDNS | ||
|
||
Use two different terminal windows to run | ||
``` | ||
./mDNS -port 6666 | ||
./mDNS -port 6667 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
) | ||
|
||
type config struct { | ||
RendezvousString string | ||
ProtocolID string | ||
listenHost string | ||
listenPort int | ||
} | ||
|
||
func parseFlags() *config { | ||
c := &config{} | ||
|
||
flag.StringVar(&c.RendezvousString, "rendezvous", "meetme", "Unique string to identify group of nodes. Share this with your friends to let them connect with you") | ||
flag.StringVar(&c.listenHost, "host", "0.0.0.0", "The bootstrap node host listen address\n") | ||
flag.StringVar(&c.ProtocolID, "pid", "/chat/1.1.0", "Sets a protocol id for stream headers") | ||
flag.IntVar(&c.listenPort, "port", 4001, "node listen port") | ||
|
||
flag.Parse() | ||
return c | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"context" | ||
"crypto/rand" | ||
"flag" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/libp2p/go-libp2p" | ||
"github.com/libp2p/go-libp2p-crypto" | ||
inet "github.com/libp2p/go-libp2p-net" | ||
protocol "github.com/libp2p/go-libp2p-protocol" | ||
"github.com/multiformats/go-multiaddr" | ||
) | ||
|
||
func handleStream(stream inet.Stream) { | ||
fmt.Println("Got a new 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). | ||
} | ||
|
||
func readData(rw *bufio.ReadWriter) { | ||
for { | ||
str, err := rw.ReadString('\n') | ||
if err != nil { | ||
fmt.Println("Error reading from buffer") | ||
panic(err) | ||
} | ||
|
||
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 { | ||
fmt.Println("Error reading from stdin") | ||
panic(err) | ||
} | ||
|
||
_, err = rw.WriteString(fmt.Sprintf("%s\n", sendData)) | ||
if err != nil { | ||
fmt.Println("Error writing to buffer") | ||
panic(err) | ||
} | ||
err = rw.Flush() | ||
if err != nil { | ||
fmt.Println("Error flushing buffer") | ||
panic(err) | ||
} | ||
} | ||
} | ||
|
||
func main() { | ||
help := flag.Bool("help", false, "Display Help") | ||
cfg := parseFlags() | ||
|
||
if *help { | ||
fmt.Printf("Simple example for peer discovery using mDNS. mDNS is great when you have multiple peers in local LAN.") | ||
fmt.Printf("Usage: \n Run './chat-with-mdns'\nor Run './chat-with-mdns -host [host] -port [port] -rendezvous [string] -pid [proto ID]'\n") | ||
|
||
os.Exit(0) | ||
} | ||
|
||
fmt.Printf("[*] Listening on: %s with port: %d\n", cfg.listenHost, cfg.listenPort) | ||
|
||
ctx := context.Background() | ||
r := rand.Reader | ||
|
||
// Creates a new RSA key pair for this host. | ||
prvKey, _, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, r) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
// 0.0.0.0 will listen on any interface device. | ||
sourceMultiAddr, _ := multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/%s/tcp/%d", cfg.listenHost, cfg.listenPort)) | ||
|
||
// libp2p.New constructs a new libp2p Host. | ||
// Other options can be added here. | ||
host, err := libp2p.New( | ||
ctx, | ||
libp2p.ListenAddrs(sourceMultiAddr), | ||
libp2p.Identity(prvKey), | ||
) | ||
|
||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
// Set a function as stream handler. | ||
// This function is called when a peer initiates a connection and starts a stream with this peer. | ||
host.SetStreamHandler(protocol.ID(cfg.ProtocolID), handleStream) | ||
|
||
fmt.Printf("\n[*] Your Multiaddress Is: /ip4/%s/tcp/%v/p2p/%s\n", cfg.listenHost, cfg.listenPort, host.ID().Pretty()) | ||
|
||
peerChan := initMDNS(ctx, host, cfg.RendezvousString) | ||
|
||
peer := <-peerChan // will block untill we discover a peer | ||
fmt.Println("Found peer:", peer, ", connecting") | ||
|
||
if err := host.Connect(ctx, peer); err != nil { | ||
fmt.Println("Connection failed:", err) | ||
} | ||
|
||
// 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) | ||
} | ||
|
||
select {} //wait here | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
host "github.com/libp2p/go-libp2p-host" | ||
pstore "github.com/libp2p/go-libp2p-peerstore" | ||
"github.com/libp2p/go-libp2p/p2p/discovery" | ||
) | ||
|
||
type discoveryNotifee struct { | ||
PeerChan chan pstore.PeerInfo | ||
} | ||
|
||
//interface to be called when new peer is found | ||
func (n *discoveryNotifee) HandlePeerFound(pi pstore.PeerInfo) { | ||
n.PeerChan <- pi | ||
} | ||
|
||
//Initialize the MDNS service | ||
func initMDNS(ctx context.Context, peerhost host.Host, rendezvous string) chan pstore.PeerInfo { | ||
// An hour might be a long long period in practical applications. But this is fine for us | ||
ser, err := discovery.NewMdnsService(ctx, peerhost, time.Hour, rendezvous) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
//register with service so that we get notified about peer discovery | ||
n := &discoveryNotifee{} | ||
n.PeerChan = make(chan pstore.PeerInfo) | ||
|
||
ser.RegisterNotifee(n) | ||
return n.PeerChan | ||
} |
This file was deleted.
Oops, something went wrong.