Docs rework (#776)
This commit is contained in:
parent
fa5d102370
commit
eb78660702
|
@ -63,7 +63,7 @@ jobs:
|
||||||
git push origin gh-pages
|
git push origin gh-pages
|
||||||
|
|
||||||
update_site:
|
update_site:
|
||||||
if: github.ref == 'refs/heads/master'
|
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/docs'
|
||||||
name: 'Rebuild website'
|
name: 'Rebuild website'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
@ -74,8 +74,12 @@ jobs:
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
|
|
||||||
|
- uses: jiro4989/setup-nim-action@v1
|
||||||
|
with:
|
||||||
|
nim-version: 'stable'
|
||||||
|
|
||||||
- name: Generate website
|
- name: Generate website
|
||||||
run: pip install mkdocs-material && mkdocs build
|
run: pip install mkdocs-material && nimble website
|
||||||
|
|
||||||
- name: Clone the gh-pages branch
|
- name: Clone the gh-pages branch
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
|
@ -13,5 +13,6 @@ build/
|
||||||
.vscode/
|
.vscode/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
tests/pubsub/testgossipsub
|
tests/pubsub/testgossipsub
|
||||||
|
examples/*.md
|
||||||
nimble.develop
|
nimble.develop
|
||||||
nimble.paths
|
nimble.paths
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
|
|
||||||
Welcome to the nim-libp2p documentation!
|
Welcome to the nim-libp2p documentation!
|
||||||
|
|
||||||
Here, you'll find [tutorials](tutorial_1_connect.md) to help you get started, as well as [examples](directchat.nim) and
|
Here, you'll find [tutorials](tutorial_1_connect.md) to help you get started, as well as
|
||||||
the [full reference](https://status-im.github.io/nim-libp2p/master/libp2p.html).
|
the [full reference](https://status-im.github.io/nim-libp2p/master/libp2p.html).
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
|
## # Circuit Relay example
|
||||||
|
##
|
||||||
|
## Circuit Relay can be used when a node cannot reach another node
|
||||||
|
## directly, but can reach it through a another node (the Relay).
|
||||||
|
##
|
||||||
|
## That may happen because of NAT, Firewalls, or incompatible transports.
|
||||||
|
##
|
||||||
|
## More informations [here](https://docs.libp2p.io/concepts/circuit-relay/).
|
||||||
import chronos, stew/byteutils
|
import chronos, stew/byteutils
|
||||||
import ../libp2p,
|
import libp2p,
|
||||||
../libp2p/protocols/connectivity/relay/[relay, client]
|
libp2p/protocols/connectivity/relay/[relay, client]
|
||||||
|
|
||||||
# Helper to create a circuit relay node
|
# Helper to create a circuit relay node
|
||||||
proc createCircuitRelaySwitch(r: Relay): Switch =
|
proc createCircuitRelaySwitch(r: Relay): Switch =
|
||||||
|
|
|
@ -5,7 +5,7 @@ import
|
||||||
strformat, strutils,
|
strformat, strutils,
|
||||||
stew/byteutils,
|
stew/byteutils,
|
||||||
chronos,
|
chronos,
|
||||||
../libp2p
|
libp2p
|
||||||
|
|
||||||
const DefaultAddr = "/ip4/127.0.0.1/tcp/0"
|
const DefaultAddr = "/ip4/127.0.0.1/tcp/0"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import chronos # an efficient library for async
|
import chronos # an efficient library for async
|
||||||
import stew/byteutils # various utils
|
import stew/byteutils # various utils
|
||||||
import ../libp2p # when installed through nimble, just use `import libp2p`
|
import libp2p
|
||||||
|
|
||||||
##
|
##
|
||||||
# Create our custom protocol
|
# Create our custom protocol
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
# Simple ping tutorial
|
|
||||||
|
|
||||||
Hi all, welcome to the first nim-libp2p tutorial!
|
|
||||||
|
|
||||||
!!! tips ""
|
|
||||||
This tutorial is for everyone who is interested in building peer-to-peer applications. No Nim programming experience is needed.
|
|
||||||
|
|
||||||
To give you a quick overview, **Nim** is the programming language we are using and **nim-libp2p** is the Nim implementation of [libp2p](https://libp2p.io/), a modular library that enables the development of peer-to-peer network applications.
|
|
||||||
|
|
||||||
Hope you'll find it helpful in your journey of learning. Happy coding! ;)
|
|
||||||
|
|
||||||
## Before you start
|
|
||||||
The only prerequisite here is [Nim](https://nim-lang.org/), the programming language with a Python-like syntax and a performance similar to C. Detailed information can be found [here](https://nim-lang.org/docs/tut1.html).
|
|
||||||
|
|
||||||
Install Nim via their [official website](https://nim-lang.org/install.html).
|
|
||||||
Check Nim's installation via `nim --version` and its package manager Nimble via `nimble --version`.
|
|
||||||
|
|
||||||
You can now install the latest version of `nim-libp2p`:
|
|
||||||
```bash
|
|
||||||
nimble install libp2p@#master
|
|
||||||
```
|
|
||||||
|
|
||||||
## A simple ping application
|
|
||||||
We'll start by creating a simple application, which is starting two libp2p [switch](https://docs.libp2p.io/concepts/stream-multiplexing/#switch-swarm), and pinging each other using the [Ping](https://docs.libp2p.io/concepts/protocols/#ping) protocol.
|
|
||||||
|
|
||||||
!!! tips ""
|
|
||||||
You can extract the code from this tutorial by running `nim c -r tools/markdown_runner.nim examples/tutorial_1_connect.md` in the libp2p folder!
|
|
||||||
|
|
||||||
Let's create a `part1.nim`, and import our dependencies:
|
|
||||||
```nim
|
|
||||||
import chronos
|
|
||||||
|
|
||||||
import libp2p
|
|
||||||
import libp2p/protocols/ping
|
|
||||||
```
|
|
||||||
[chronos](https://github.com/status-im/nim-chronos) the asynchronous framework used by `nim-libp2p`
|
|
||||||
|
|
||||||
Next, we'll create an helper procedure to create our switches. A switch needs a bit of configuration, and it will be easier to do this configuration only once:
|
|
||||||
```nim
|
|
||||||
proc createSwitch(ma: MultiAddress, rng: ref HmacDrbgContext): Switch =
|
|
||||||
var switch = SwitchBuilder
|
|
||||||
.new()
|
|
||||||
.withRng(rng) # Give the application RNG
|
|
||||||
.withAddress(ma) # Our local address(es)
|
|
||||||
.withTcpTransport() # Use TCP as transport
|
|
||||||
.withMplex() # Use Mplex as muxer
|
|
||||||
.withNoise() # Use Noise as secure manager
|
|
||||||
.build()
|
|
||||||
|
|
||||||
return switch
|
|
||||||
```
|
|
||||||
This will create a switch using [Mplex](https://docs.libp2p.io/concepts/stream-multiplexing/) as a multiplexer, Noise to secure the communication, and TCP as an underlying transport.
|
|
||||||
|
|
||||||
You can of course tweak this, to use a different or multiple transport, or tweak the configuration of Mplex and Noise, but this is some sane defaults that we'll use going forward.
|
|
||||||
|
|
||||||
|
|
||||||
Let's now start to create our main procedure:
|
|
||||||
```nim
|
|
||||||
proc main() {.async, gcsafe.} =
|
|
||||||
let
|
|
||||||
rng = newRng()
|
|
||||||
localAddress = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
|
||||||
pingProtocol = Ping.new(rng=rng)
|
|
||||||
```
|
|
||||||
We created some variables that we'll need for the rest of the application: the global `rng` instance, our `localAddress`, and an instance of the `Ping` protocol.
|
|
||||||
The address is in the [MultiAddress](https://github.com/multiformats/multiaddr) format. The port `0` means "take any port available".
|
|
||||||
|
|
||||||
`tryGet` is procedure which is part of [nim-result](https://github.com/arnetheduck/nim-result/), that will throw an exception if the supplied MultiAddress is invalid.
|
|
||||||
|
|
||||||
We can now create our two switches:
|
|
||||||
```nim
|
|
||||||
let
|
|
||||||
switch1 = createSwitch(localAddress, rng)
|
|
||||||
switch2 = createSwitch(localAddress, rng)
|
|
||||||
|
|
||||||
switch1.mount(pingProtocol)
|
|
||||||
|
|
||||||
await switch1.start()
|
|
||||||
await switch2.start()
|
|
||||||
```
|
|
||||||
We've **mounted** the `pingProtocol` on our first switch. This means that the first switch will actually listen for any ping requests coming in, and handle them accordingly.
|
|
||||||
|
|
||||||
Now that we've started the nodes, they are listening for incoming peers.
|
|
||||||
We can find out which port was attributed, and the resulting local addresses, by using `switch1.peerInfo.addrs`.
|
|
||||||
|
|
||||||
We'll **dial** the first switch from the second one, by specifying it's **Peer ID**, it's **MultiAddress** and the **`Ping` protocol codec**:
|
|
||||||
```nim
|
|
||||||
let conn = await switch2.dial(switch1.peerInfo.peerId, switch1.peerInfo.addrs, PingCodec)
|
|
||||||
```
|
|
||||||
We now have a `Ping` connection setup between the second and the first switch, we can use it to actually ping the node:
|
|
||||||
```nim
|
|
||||||
# ping the other node and echo the ping duration
|
|
||||||
echo "ping: ", await pingProtocol.ping(conn)
|
|
||||||
|
|
||||||
# We must close the connection ourselves when we're done with it
|
|
||||||
await conn.close()
|
|
||||||
```
|
|
||||||
|
|
||||||
And that's it! Just a little bit of cleanup: shutting down the switches, waiting for them to stop, and we'll call our `main` procedure:
|
|
||||||
```nim
|
|
||||||
await allFutures(switch1.stop(), switch2.stop()) # close connections and shutdown all transports
|
|
||||||
|
|
||||||
waitFor(main())
|
|
||||||
```
|
|
||||||
|
|
||||||
You can now run this program using `nim c -r part1.nim`, and you should see the dialing sequence, ending with a ping output.
|
|
||||||
|
|
||||||
In the [next tutorial](tutorial_2_customproto.md), we'll look at how to create our own custom protocol.
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
## # Simple ping tutorial
|
||||||
|
##
|
||||||
|
## Hi all, welcome to the first nim-libp2p tutorial!
|
||||||
|
##
|
||||||
|
## !!! tips ""
|
||||||
|
## This tutorial is for everyone who is interested in building peer-to-peer applications. No Nim programming experience is needed.
|
||||||
|
##
|
||||||
|
## To give you a quick overview, **Nim** is the programming language we are using and **nim-libp2p** is the Nim implementation of [libp2p](https://libp2p.io/), a modular library that enables the development of peer-to-peer network applications.
|
||||||
|
##
|
||||||
|
## Hope you'll find it helpful in your journey of learning. Happy coding! ;)
|
||||||
|
##
|
||||||
|
## ## Before you start
|
||||||
|
## The only prerequisite here is [Nim](https://nim-lang.org/), the programming language with a Python-like syntax and a performance similar to C. Detailed information can be found [here](https://nim-lang.org/docs/tut1.html).
|
||||||
|
##
|
||||||
|
## Install Nim via their [official website](https://nim-lang.org/install.html).
|
||||||
|
## Check Nim's installation via `nim --version` and its package manager Nimble via `nimble --version`.
|
||||||
|
##
|
||||||
|
## You can now install the latest version of `nim-libp2p`:
|
||||||
|
## ```bash
|
||||||
|
## nimble install libp2p@#master
|
||||||
|
## ```
|
||||||
|
##
|
||||||
|
## ## A simple ping application
|
||||||
|
## We'll start by creating a simple application, which is starting two libp2p [switch](https://docs.libp2p.io/concepts/stream-multiplexing/#switch-swarm), and pinging each other using the [Ping](https://docs.libp2p.io/concepts/protocols/#ping) protocol.
|
||||||
|
##
|
||||||
|
## !!! tips ""
|
||||||
|
## You can find the source of this tutorial (and other tutorials) in the [libp2p/examples](https://github.com/status-im/nim-libp2p/tree/master/examples) folder!
|
||||||
|
##
|
||||||
|
## Let's create a `part1.nim`, and import our dependencies:
|
||||||
|
import chronos
|
||||||
|
|
||||||
|
import libp2p
|
||||||
|
import libp2p/protocols/ping
|
||||||
|
|
||||||
|
## [chronos](https://github.com/status-im/nim-chronos) the asynchronous framework used by `nim-libp2p`
|
||||||
|
##
|
||||||
|
## Next, we'll create an helper procedure to create our switches. A switch needs a bit of configuration, and it will be easier to do this configuration only once:
|
||||||
|
proc createSwitch(ma: MultiAddress, rng: ref HmacDrbgContext): Switch =
|
||||||
|
var switch = SwitchBuilder
|
||||||
|
.new()
|
||||||
|
.withRng(rng) # Give the application RNG
|
||||||
|
.withAddress(ma) # Our local address(es)
|
||||||
|
.withTcpTransport() # Use TCP as transport
|
||||||
|
.withMplex() # Use Mplex as muxer
|
||||||
|
.withNoise() # Use Noise as secure manager
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return switch
|
||||||
|
|
||||||
|
## This will create a switch using [Mplex](https://docs.libp2p.io/concepts/stream-multiplexing/) as a multiplexer, Noise to secure the communication, and TCP as an underlying transport.
|
||||||
|
##
|
||||||
|
## You can of course tweak this, to use a different or multiple transport, or tweak the configuration of Mplex and Noise, but this is some sane defaults that we'll use going forward.
|
||||||
|
##
|
||||||
|
##
|
||||||
|
## Let's now start to create our main procedure:
|
||||||
|
proc main() {.async, gcsafe.} =
|
||||||
|
let
|
||||||
|
rng = newRng()
|
||||||
|
localAddress = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
pingProtocol = Ping.new(rng=rng)
|
||||||
|
## We created some variables that we'll need for the rest of the application: the global `rng` instance, our `localAddress`, and an instance of the `Ping` protocol.
|
||||||
|
## The address is in the [MultiAddress](https://github.com/multiformats/multiaddr) format. The port `0` means "take any port available".
|
||||||
|
##
|
||||||
|
## `tryGet` is procedure which is part of [nim-result](https://github.com/arnetheduck/nim-result/), that will throw an exception if the supplied MultiAddress is invalid.
|
||||||
|
##
|
||||||
|
## We can now create our two switches:
|
||||||
|
let
|
||||||
|
switch1 = createSwitch(localAddress, rng)
|
||||||
|
switch2 = createSwitch(localAddress, rng)
|
||||||
|
|
||||||
|
switch1.mount(pingProtocol)
|
||||||
|
|
||||||
|
await switch1.start()
|
||||||
|
await switch2.start()
|
||||||
|
## We've **mounted** the `pingProtocol` on our first switch. This means that the first switch will actually listen for any ping requests coming in, and handle them accordingly.
|
||||||
|
##
|
||||||
|
## Now that we've started the nodes, they are listening for incoming peers.
|
||||||
|
## We can find out which port was attributed, and the resulting local addresses, by using `switch1.peerInfo.addrs`.
|
||||||
|
##
|
||||||
|
## We'll **dial** the first switch from the second one, by specifying it's **Peer ID**, it's **MultiAddress** and the **`Ping` protocol codec**:
|
||||||
|
let conn = await switch2.dial(switch1.peerInfo.peerId, switch1.peerInfo.addrs, PingCodec)
|
||||||
|
## We now have a `Ping` connection setup between the second and the first switch, we can use it to actually ping the node:
|
||||||
|
# ping the other node and echo the ping duration
|
||||||
|
echo "ping: ", await pingProtocol.ping(conn)
|
||||||
|
|
||||||
|
# We must close the connection ourselves when we're done with it
|
||||||
|
await conn.close()
|
||||||
|
## And that's it! Just a little bit of cleanup: shutting down the switches, waiting for them to stop, and we'll call our `main` procedure:
|
||||||
|
await allFutures(switch1.stop(), switch2.stop()) # close connections and shutdown all transports
|
||||||
|
|
||||||
|
waitFor(main())
|
||||||
|
|
||||||
|
## You can now run this program using `nim c -r part1.nim`, and you should see the dialing sequence, ending with a ping output.
|
||||||
|
##
|
||||||
|
## In the [next tutorial](tutorial_2_customproto.md), we'll look at how to create our own custom protocol.
|
|
@ -1,82 +0,0 @@
|
||||||
# Custom protocol in libp2p
|
|
||||||
|
|
||||||
In the [previous tutorial](tutorial_1_connect.md), we've looked at how to create a simple ping program using the `nim-libp2p`.
|
|
||||||
|
|
||||||
We'll now look at how to create a custom protocol inside the libp2p
|
|
||||||
|
|
||||||
Let's create a `part2.nim`, and import our dependencies:
|
|
||||||
```nim
|
|
||||||
import chronos
|
|
||||||
import stew/byteutils
|
|
||||||
|
|
||||||
import libp2p
|
|
||||||
```
|
|
||||||
This is similar to the first tutorial, except we don't need to import the `Ping` protocol.
|
|
||||||
|
|
||||||
Next, we'll declare our custom protocol
|
|
||||||
```nim
|
|
||||||
const TestCodec = "/test/proto/1.0.0"
|
|
||||||
|
|
||||||
type TestProto = ref object of LPProtocol
|
|
||||||
```
|
|
||||||
|
|
||||||
We've set a [protocol ID](https://docs.libp2p.io/concepts/protocols/#protocol-ids), and created a custom `LPProtocol`. In a more complex protocol, we could use this structure to store interesting variables.
|
|
||||||
|
|
||||||
A protocol generally has two part: and handling/server part, and a dialing/client part.
|
|
||||||
Theses two parts can be identical, but in our trivial protocol, the server will wait for a message from the client, and the client will send a message, so we have to handle the two cases separately.
|
|
||||||
|
|
||||||
Let's start with the server part:
|
|
||||||
```nim
|
|
||||||
proc new(T: typedesc[TestProto]): T =
|
|
||||||
# every incoming connections will in be handled in this closure
|
|
||||||
proc handle(conn: Connection, proto: string) {.async, gcsafe.} =
|
|
||||||
# Read up to 1024 bytes from this connection, and transform them into
|
|
||||||
# a string
|
|
||||||
echo "Got from remote - ", string.fromBytes(await conn.readLp(1024))
|
|
||||||
# We must close the connections ourselves when we're done with it
|
|
||||||
await conn.close()
|
|
||||||
|
|
||||||
return T(codecs: @[TestCodec], handler: handle)
|
|
||||||
```
|
|
||||||
This is a constructor for our `TestProto`, that will specify our `codecs` and a `handler`, which will be called for each incoming peer asking for this protocol.
|
|
||||||
In our handle, we simply read a message from the connection and `echo` it.
|
|
||||||
|
|
||||||
We can now create our client part:
|
|
||||||
```nim
|
|
||||||
proc hello(p: TestProto, conn: Connection) {.async.} =
|
|
||||||
await conn.writeLp("Hello p2p!")
|
|
||||||
```
|
|
||||||
Again, pretty straight-forward, we just send a message on the connection.
|
|
||||||
|
|
||||||
We can now create our main procedure:
|
|
||||||
```nim
|
|
||||||
proc main() {.async, gcsafe.} =
|
|
||||||
let
|
|
||||||
rng = newRng()
|
|
||||||
testProto = TestProto.new()
|
|
||||||
switch1 = newStandardSwitch(rng=rng)
|
|
||||||
switch2 = newStandardSwitch(rng=rng)
|
|
||||||
|
|
||||||
switch1.mount(testProto)
|
|
||||||
|
|
||||||
await switch1.start()
|
|
||||||
await switch2.start()
|
|
||||||
|
|
||||||
let conn = await switch2.dial(switch1.peerInfo.peerId, switch1.peerInfo.addrs, TestCodec)
|
|
||||||
|
|
||||||
await testProto.hello(conn)
|
|
||||||
|
|
||||||
# We must close the connection ourselves when we're done with it
|
|
||||||
await conn.close()
|
|
||||||
|
|
||||||
await allFutures(switch1.stop(), switch2.stop()) # close connections and shutdown all transports
|
|
||||||
```
|
|
||||||
|
|
||||||
This is very similar to the first tutorial's `main`, the only noteworthy difference is that we use `newStandardSwitch`, which is similar to the `createSwitch` of the first tutorial, but is bundled directly in libp2p
|
|
||||||
|
|
||||||
We can now wrap our program by calling our main proc:
|
|
||||||
```nim
|
|
||||||
waitFor(main())
|
|
||||||
```
|
|
||||||
|
|
||||||
And that's it!
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
## # Custom protocol in libp2p
|
||||||
|
##
|
||||||
|
## In the [previous tutorial](tutorial_1_connect.md), we've looked at how to create a simple ping program using the `nim-libp2p`.
|
||||||
|
##
|
||||||
|
## We'll now look at how to create a custom protocol inside the libp2p
|
||||||
|
##
|
||||||
|
## Let's create a `part2.nim`, and import our dependencies:
|
||||||
|
import chronos
|
||||||
|
import stew/byteutils
|
||||||
|
|
||||||
|
import libp2p
|
||||||
|
## This is similar to the first tutorial, except we don't need to import the `Ping` protocol.
|
||||||
|
##
|
||||||
|
## Next, we'll declare our custom protocol
|
||||||
|
const TestCodec = "/test/proto/1.0.0"
|
||||||
|
|
||||||
|
type TestProto = ref object of LPProtocol
|
||||||
|
|
||||||
|
## We've set a [protocol ID](https://docs.libp2p.io/concepts/protocols/#protocol-ids), and created a custom `LPProtocol`. In a more complex protocol, we could use this structure to store interesting variables.
|
||||||
|
##
|
||||||
|
## A protocol generally has two part: and handling/server part, and a dialing/client part.
|
||||||
|
## Theses two parts can be identical, but in our trivial protocol, the server will wait for a message from the client, and the client will send a message, so we have to handle the two cases separately.
|
||||||
|
##
|
||||||
|
## Let's start with the server part:
|
||||||
|
|
||||||
|
proc new(T: typedesc[TestProto]): T =
|
||||||
|
# every incoming connections will in be handled in this closure
|
||||||
|
proc handle(conn: Connection, proto: string) {.async, gcsafe.} =
|
||||||
|
# Read up to 1024 bytes from this connection, and transform them into
|
||||||
|
# a string
|
||||||
|
echo "Got from remote - ", string.fromBytes(await conn.readLp(1024))
|
||||||
|
# We must close the connections ourselves when we're done with it
|
||||||
|
await conn.close()
|
||||||
|
|
||||||
|
return T(codecs: @[TestCodec], handler: handle)
|
||||||
|
|
||||||
|
## This is a constructor for our `TestProto`, that will specify our `codecs` and a `handler`, which will be called for each incoming peer asking for this protocol.
|
||||||
|
## In our handle, we simply read a message from the connection and `echo` it.
|
||||||
|
##
|
||||||
|
## We can now create our client part:
|
||||||
|
proc hello(p: TestProto, conn: Connection) {.async.} =
|
||||||
|
await conn.writeLp("Hello p2p!")
|
||||||
|
|
||||||
|
## Again, pretty straight-forward, we just send a message on the connection.
|
||||||
|
##
|
||||||
|
## We can now create our main procedure:
|
||||||
|
proc main() {.async, gcsafe.} =
|
||||||
|
let
|
||||||
|
rng = newRng()
|
||||||
|
testProto = TestProto.new()
|
||||||
|
switch1 = newStandardSwitch(rng=rng)
|
||||||
|
switch2 = newStandardSwitch(rng=rng)
|
||||||
|
|
||||||
|
switch1.mount(testProto)
|
||||||
|
|
||||||
|
await switch1.start()
|
||||||
|
await switch2.start()
|
||||||
|
|
||||||
|
let conn = await switch2.dial(switch1.peerInfo.peerId, switch1.peerInfo.addrs, TestCodec)
|
||||||
|
|
||||||
|
await testProto.hello(conn)
|
||||||
|
|
||||||
|
# We must close the connection ourselves when we're done with it
|
||||||
|
await conn.close()
|
||||||
|
|
||||||
|
await allFutures(switch1.stop(), switch2.stop()) # close connections and shutdown all transports
|
||||||
|
|
||||||
|
## This is very similar to the first tutorial's `main`, the only noteworthy difference is that we use `newStandardSwitch`, which is similar to the `createSwitch` of the first tutorial, but is bundled directly in libp2p
|
||||||
|
##
|
||||||
|
## We can now wrap our program by calling our main proc:
|
||||||
|
waitFor(main())
|
||||||
|
|
||||||
|
## And that's it!
|
|
@ -32,16 +32,16 @@ proc runTest(filename: string, verify: bool = true, sign: bool = true,
|
||||||
rmFile "tests/" & filename.toExe
|
rmFile "tests/" & filename.toExe
|
||||||
|
|
||||||
proc buildSample(filename: string, run = false) =
|
proc buildSample(filename: string, run = false) =
|
||||||
var excstr = "nim c --opt:speed --threads:on -d:debug --verbosity:0 --hints:off "
|
var excstr = "nim c --opt:speed --threads:on -d:debug --verbosity:0 --hints:off -p:. "
|
||||||
excstr.add(" examples/" & filename)
|
excstr.add(" examples/" & filename)
|
||||||
exec excstr
|
exec excstr
|
||||||
if run:
|
if run:
|
||||||
exec "./examples/" & filename.toExe
|
exec "./examples/" & filename.toExe
|
||||||
rmFile "examples/" & filename.toExe
|
rmFile "examples/" & filename.toExe
|
||||||
|
|
||||||
proc buildTutorial(filename: string) =
|
proc tutorialToMd(filename: string) =
|
||||||
discard gorge "cat " & filename & " | nim c -r --hints:off tools/markdown_runner.nim | " &
|
let markdown = gorge "cat " & filename & " | nim c -r --verbosity:0 --hints:off tools/markdown_builder.nim "
|
||||||
" nim --verbosity:0 --hints:off c -"
|
writeFile(filename.replace(".nim", ".md"), markdown)
|
||||||
|
|
||||||
task testnative, "Runs libp2p native tests":
|
task testnative, "Runs libp2p native tests":
|
||||||
runTest("testnative")
|
runTest("testnative")
|
||||||
|
@ -86,12 +86,18 @@ task test_slim, "Runs the (slimmed down) test suite":
|
||||||
exec "nimble testfilter"
|
exec "nimble testfilter"
|
||||||
exec "nimble examples_build"
|
exec "nimble examples_build"
|
||||||
|
|
||||||
|
task website, "Build the website":
|
||||||
|
tutorialToMd("examples/tutorial_1_connect.nim")
|
||||||
|
tutorialToMd("examples/tutorial_2_customproto.nim")
|
||||||
|
tutorialToMd("examples/circuitrelay.nim")
|
||||||
|
exec "mkdocs build"
|
||||||
|
|
||||||
task examples_build, "Build the samples":
|
task examples_build, "Build the samples":
|
||||||
buildSample("directchat")
|
buildSample("directchat")
|
||||||
buildSample("helloworld", true)
|
buildSample("helloworld", true)
|
||||||
buildSample("circuitrelay", true)
|
buildSample("circuitrelay", true)
|
||||||
buildTutorial("examples/tutorial_1_connect.md")
|
buildSample("tutorial_1_connect", true)
|
||||||
buildTutorial("examples/tutorial_2_customproto.md")
|
buildSample("tutorial_2_customproto", true)
|
||||||
|
|
||||||
# pin system
|
# pin system
|
||||||
# while nimble lockfile
|
# while nimble lockfile
|
||||||
|
|
|
@ -3,7 +3,9 @@ site_name: nim-libp2p
|
||||||
repo_url: https://github.com/status-im/nim-libp2p
|
repo_url: https://github.com/status-im/nim-libp2p
|
||||||
repo_name: status-im/nim-libp2p
|
repo_name: status-im/nim-libp2p
|
||||||
site_url: https://status-im.github.io/nim-libp2p/docs
|
site_url: https://status-im.github.io/nim-libp2p/docs
|
||||||
edit_uri: edit/unstable/examples/
|
# Can't find a way to point the edit to the .nim instead
|
||||||
|
# of the .md
|
||||||
|
edit_uri: ''
|
||||||
|
|
||||||
docs_dir: examples
|
docs_dir: examples
|
||||||
|
|
||||||
|
@ -40,6 +42,7 @@ theme:
|
||||||
nav:
|
nav:
|
||||||
- Introduction: README.md
|
- Introduction: README.md
|
||||||
- Tutorials:
|
- Tutorials:
|
||||||
- 'Part I: Simple connection': tutorial_1_connect.md
|
- 'Simple connection': tutorial_1_connect.md
|
||||||
- 'Part II: Custom protocol': tutorial_2_customproto.md
|
- 'Create a custom protocol': tutorial_2_customproto.md
|
||||||
|
- 'Circuit Relay': circuitrelay.md
|
||||||
- Reference: '/nim-libp2p/master/libp2p.html'
|
- Reference: '/nim-libp2p/master/libp2p.html'
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import os, strutils
|
||||||
|
|
||||||
|
let contents =
|
||||||
|
if paramCount() > 0:
|
||||||
|
readFile(paramStr(1))
|
||||||
|
else:
|
||||||
|
stdin.readAll()
|
||||||
|
|
||||||
|
var code = ""
|
||||||
|
for line in contents.splitLines(true):
|
||||||
|
let
|
||||||
|
stripped = line.strip()
|
||||||
|
isMarkdown = stripped.startsWith("##")
|
||||||
|
|
||||||
|
if isMarkdown:
|
||||||
|
if code.strip.len > 0:
|
||||||
|
echo "```nim"
|
||||||
|
echo code.strip(leading = false)
|
||||||
|
echo "```"
|
||||||
|
code = ""
|
||||||
|
echo(if stripped.len > 3: stripped[3..^1]
|
||||||
|
else: "")
|
||||||
|
else:
|
||||||
|
code &= line
|
||||||
|
if code.strip.len > 0:
|
||||||
|
echo ""
|
||||||
|
echo "```nim"
|
||||||
|
echo code
|
||||||
|
echo "```"
|
Loading…
Reference in New Issue