In this folder, you can find a variety of examples to help you get started in using go-libp2p. Every example as a specific purpose and some of each incorporate a full tutorial that you can follow through, helping you expand your knowledge about libp2p and p2p networks in general.
Let us know if you find any issue or if you want to contribute and add a new tutorial, feel welcome to submit a pr, thank you!
## Examples and Tutorials
-[The libp2p 'host'](./libp2p-host)
-[Building an http proxy with libp2p](./http-proxy)
-[Protocol Multiplexing with multicodecs](./protocol-multiplexing-with-multicodecs)
-[An echo host](./echo)
-[Multicodecs with protobufs](./multipro)
-[P2P chat application](./chat)
\ No newline at end of file
The go-libp2p examples have moved to [go-libp2p-examples](https://github.com/libp2p/go-libp2p-examples).
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.
// 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.
This is an example that quickly shows how to use the `go-libp2p` stack, including Host/Basichost, Network/Swarm, Streams, Peerstores and Multiaddresses.
This example can be started in either listen mode, or dial mode.
In listen mode, it will sit and wait for incoming connections on the `/echo/1.0.0` protocol. Whenever it receives a stream, it will write the message `"Hello, world!"` over the stream and close it.
In dial mode, the node will start up, connect to the given address, open a stream to the target peer, and read a message on the protocol `/echo/1.0.0`.
## Build
From `go-libp2p` base folder:
```
> make deps
> go build ./examples/echo
```
## Usage
```
> ./echo -secio -l 10000
2017/03/15 14:11:32 I am /ip4/127.0.0.1/tcp/10000/ipfs/QmYo41GybvrXk8y8Xnm1P7pfA4YEXCpfnLyzgRPnNbG35e
2017/03/15 14:11:32 Now run "./echo -l 10001 -d /ip4/127.0.0.1/tcp/10000/ipfs/QmYo41GybvrXk8y8Xnm1P7pfA4YEXCpfnLyzgRPnNbG35e -secio" on a different terminal
2017/03/15 14:11:32 listening for connections
```
The listener libp2p host will print its `Multiaddress`, which indicates how it can be reached (ip4+tcp) and its randomly generated ID (`QmYo41Gyb...`)
Now, launch another node that talks to the listener:
The new node with send the message `"Hello, world!"` to the listener, which will in turn echo it over the stream and close it. The listener logs the message, and the sender logs the response.
## Details
The `makeBasicHost()` function creates a [go-libp2p-basichost](https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic) object. `basichost` objects wrap [go-libp2 swarms](https://godoc.org/github.com/libp2p/go-libp2p-swarm#Swarm) and should be used preferentially. A [go-libp2p-swarm Network](https://godoc.org/github.com/libp2p/go-libp2p-swarm#Network) is a `swarm` which complies to the [go-libp2p-net Network interface](https://godoc.org/github.com/libp2p/go-libp2p-net#Network) and takes care of maintaining streams, connections, multiplexing different protocols on them, handling incoming connections etc.
In order to create the swarm (and a `basichost`), the example needs:
- An [ipfs-procotol ID](https://godoc.org/github.com/libp2p/go-libp2p-peer#ID) like `QmNtX1cvrm2K6mQmMEaMxAuB4rTexhd87vpYVot4sEZzxc`. The example autogenerates a key pair on every run and uses an ID extracted from the public key (the hash of the public key). When using `-secio`, it uses the key pair to encrypt communications (otherwise, it leaves the connections unencrypted).
- A [Multiaddress](https://godoc.org/github.com/multiformats/go-multiaddr), which indicates how to reach this peer. There can be several of them (using different protocols or locations for example). Example: `/ip4/127.0.0.1/tcp/1234`.
- A [go-libp2p-peerstore](https://godoc.org/github.com/libp2p/go-libp2p-peerstore), which is used as a address book which matches node IDs to the multiaddresses through which they can be contacted. This peerstore gets autopopulated when manually opening a connection (with [`Connect()`](https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic#BasicHost.Connect). Alternatively, we can manually [`AddAddr()`](https://godoc.org/github.com/libp2p/go-libp2p-peerstore#AddrManager.AddAddr) as in the example.
A `basichost` can now open streams (bi-directional channel between to peers) using [NewStream](https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic#BasicHost.NewStream) and use them to send and receive data tagged with a `Protocol.ID` (a string). The host can also listen for incoming connections for a given
`Protocol` with [`SetStreamHandle()`](https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic#BasicHost.SetStreamHandler).
The example makes use of all of this to enable communication between a listener and a sender using protocol `/echo/1.0.0` (which could be any other thing).
In order to proxy an HTTP request, we create a local peer which listens on `localhost:9900`. HTTP requests performed to that address are tunneled via a libp2p stream to a remote peer, which then performs the HTTP requests and sends the response back to the local peer, which relays it to the user.
Note that this is a very simple approach to a proxy, and does not perform any header management, nor supports HTTPS. The `proxy.go` code is thoroughly commeted, detailing what is happening in every step.
## Build
From `go-libp2p` base folder:
```
> make deps
> go build ./examples/http-proxy
```
## Usage
First run the "remote" peer as follows. It will print a local peer address. If you would like to run this on a separate machine, please replace the IP accordingly:
// To construct a simple host with all the default settings, just use `New`
h,err:=libp2p.New(ctx)
iferr!=nil{
panic(err)
}
fmt.Printf("Hello World, my hosts ID is %s\n",h.ID())
```
If you want more control over the configuration, you can specify some options to the constructor. For a full list of all the configuration supported by the constructor see: [options.go](https://github.com/libp2p/go-libp2p/blob/master/options.go)
In this snippet we generate our own ID and specified on which address we want to listen:
fmt.Printf("Hello World, my second hosts ID is %s\n",h2.ID())
```
And thats it, you have a libp2p host and you're ready to start doing some awesome p2p networking!
In future guides we will go over ways to use hosts, configure them differently (hint: there are a huge number of ways to set these up), and interesting ways to apply this technology to various applications you might want to build.
To see this code all put together, take a look at [host.go](host.go).
# Protocol Multiplexing using rpc-style multicodecs, protobufs with libp2p
This examples shows how to use multicodecs (i.e. protobufs) to encode and transmit information between LibP2P hosts using LibP2P Streams.
Multicodecs present a common interface, making it very easy to swap the codec implementation if needed.
This example expects that you area already familiar with the [echo example](https://github.com/libp2p/go-libp2p/tree/master/examples/echo).
## Build
Install gx:
```sh
> go get -u github.com/whyrusleeping/gx
```
Run GX from the root libp2p source dir:
```sh
>gx install
```
Build libp2p:
```sh
> make deps
> make
```
Run from `multipro` directory
```sh
> go build
```
## Usage
```sh
> ./multipro
```
## Details
The example creates two LibP2P Hosts supporting 2 protocols: ping and echo.
Each protocol consists RPC-style requests and responses and each request and response is a typed protobufs message (and a go data object).
This is a different pattern then defining a whole p2p protocol as one protobuf message with lots of optional fields (as can be observed in various p2p-lib protocols using protobufs such as dht).
The example shows how to match async received responses with their requests. This is useful when processing a response requires access to the request data.
The idea is to use lib-p2p protocol multiplexing on a per-message basis.
### Features
1. 2 fully implemented protocols using an RPC-like request-response pattern - Ping and Echo
2. Scaffolding for quickly implementing new app-level versioned RPC-like protocols
3. Full authentication of incoming message data by author (who might not be the message's sender peer)
4. Base p2p format in protobufs with fields shared by all protocol messages
5. Full access to request data when processing a response.
// remove request from map as we have processed it here
delete(e.requests,data.MessageData.Id)
}else{
log.Println("Failed to locate request data boject for response")
return
}
ifreq.Message!=data.Message{
log.Fatalln("Expected echo to respond with request message")
}
log.Printf("%s: Received echo response from %s. Message id:%s. Message: %s.",s.Conn().LocalPeer(),s.Conn().RemotePeer(),data.MessageData.Id,data.Message)
e.done<-true
}
func(e*EchoProtocol)Echo(hosthost.Host)bool{
log.Printf("%s: Sending echo to: %s....",e.node.ID(),host.ID())