Skip to content

Commit

Permalink
[fix]/debug
Browse files Browse the repository at this point in the history
[fix]/debug

Former-commit-id: 69c1aaa
  • Loading branch information
JackBekket authored Mar 14, 2019
2 parents c661f4e + ec02ee5 commit 27227c5
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
./go-examples
./rendezvous/chat
66 changes: 65 additions & 1 deletion README.md
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
```
24 changes: 24 additions & 0 deletions mDNS/flags.go
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
}
140 changes: 140 additions & 0 deletions mDNS/main.go
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
}
35 changes: 35 additions & 0 deletions mDNS/mdns.go
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
}
1 change: 0 additions & 1 deletion rendezvous/chat.REMOVED.git-id

This file was deleted.

0 comments on commit 27227c5

Please sign in to comment.