This program demonstrates a simple p2p chat application. It can work between two peers if
1. Both have private IP address (same network).
2. At least one of them has a public IP address.
Assume if 'A' and 'B' are on different networks host 'A' may or may not have a public IP address but host 'B' has one.
Usage: Run `./chat -sp <SOURCE_PORT>` on host 'B' where <SOURCE_PORT> can be any port number. Now run `./chat -d <MULTIADDR_B>` on node 'A' [`<MULTIADDR_B>` is multiaddress of host 'B' which can be obtained from host 'B' console].
## Build
To build the example, first run `make deps` in the root directory.
```
> make deps
> go build ./examples/chat
```
## Usage
On node 'B'
```
> ./chat -sp 3001
Run ./chat -d /ip4/127.0.0.1/tcp/3001/ipfs/QmdXGaeGiVA745XorV1jr11RHxB9z4fqykm6xCUPX1aTJo
2018/02/27 01:21:32 Got a new stream!
> hi (received messages in green colour)
> hello (sent messages in white colour)
> no
```
On node 'A'. Replace 127.0.0.1 with <PUBLIC_IP> if node 'B' has one.
**NOTE: debug mode is enabled by default, debug mode will always generate same node id (on each node) on every execution. Disable debug using `--debug false` flag while running your executable.**
// stream 's' will stay open until you close it (or the other side closes it).
}
funcreadData(rw*bufio.ReadWriter){
for{
str,_:=rw.ReadString('\n')
ifstr==""{
return
}
ifstr!="\n"{
// Green console colour: \x1b[32m
// Reset console colour: \x1b[0m
fmt.Printf("\x1b[32m%s\x1b[0m> ",str)
}
}
}
funcwriteData(rw*bufio.ReadWriter){
stdReader:=bufio.NewReader(os.Stdin)
for{
fmt.Print("> ")
sendData,err:=stdReader.ReadString('\n')
iferr!=nil{
panic(err)
}
rw.WriteString(fmt.Sprintf("%s\n",sendData))
rw.Flush()
}
}
funcmain(){
sourcePort:=flag.Int("sp",0,"Source port number")
dest:=flag.String("d","","Dest MultiAddr String")
help:=flag.Bool("help",false,"Display Help")
debug:=flag.Bool("debug",true,"Debug generated same node id on every execution.")
flag.Parse()
if*help{
fmt.Printf("This program demonstrates a simple p2p chat application using libp2p\n\n")
fmt.Printf("Usage: Run './chat -sp <SOURCE_PORT>' where <SOURCE_PORT> can be any port number. Now run './chat -d <MULTIADDR>' where <MULTIADDR> is multiaddress of previous listener host.\n")
os.Exit(0)
}
// If debug is enabled used constant random source else cryptographic randomness.
varrio.Reader
if*debug{
// Constant random source. This will always generate the same host ID on multiple execution.
// NewHost constructs a new *BasicHost and activates it by attaching its
// stream and connection handlers to the given inet.Network (network).
// Other options like NATManager can also be added here.
// See docs: https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic#HostOpts
host:=basichost.New(network)
if*dest==""{
// Set a function as stream handler.
// This function is called when a peer initiate a connection and starts a stream with this peer.
// Only applicable on the receiving side.
host.SetStreamHandler("/chat/1.0.0",handleStream)
fmt.Printf("Run './chat -d /ip4/127.0.0.1/tcp/%d/ipfs/%s' on another console.\n You can replace 127.0.0.1 with public IP as well.\n",*sourcePort,host.ID().Pretty())
fmt.Printf("\nWaiting for incoming connection\n\n")
// Hang forever
<-make(chanstruct{})
}else{
// Add destination peer multiaddress in the peerstore.
// This will be used during connection and stream creation by libp2p.
peerID:=addAddrToPeerstore(host,*dest)
fmt.Println("This node's multiaddress: ")
// IP will be 0.0.0.0 (listen on any interface) and port will be 0 (choose one for me).
// Although this node will not listen for any connection. It will just initiate a connect with
// one of its peer and use that stream to communicate.