-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
305 additions
and
153 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
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 |
---|---|---|
|
@@ -26,14 +26,14 @@ to each other. For this to work a few challenges have to be solved: | |
- How do the nodes know and find each other? In a client-server communication, the client established the connection to | ||
the server, and the server is known by some pre-defined ip address (or addresses). In a P2P mesh network how to know | ||
the ip address of the client? Potentially, the client is roaming which means its ip address can change over time. | ||
**In libp2p this is solved by mDNS, DHT/Kademlia, and more**. | ||
**In libp2p this is solved by mDNS, DHT/Kademlia, and more**. | ||
|
||
- How can a node directly connect to another node? In client-server communication, the client initiates a connection to | ||
the server. This is an outbound connection. However, in a P2P connection, a node connects directly to another node, | ||
which is an inbound connection. Inbound connections are not always possible. Think of security (the router rejects | ||
inbound connection attempts), but also think of NAT devices (what is the correct ip address? A node might know a | ||
different ip address of itself than the outside world is able to connect to) **In libp2p this is solved by autonat, | ||
holepunching, relay-service, and more**. | ||
different ip address of itself than the outside world is able to connect to) **In libp2p this is solved by autonat, | ||
holepunching, relay-service, and more**. | ||
|
||
- Which wire protocol to use? In a client-server network the used protocol is obvious: the server dictates the protocol | ||
to be used, or else it rejects the connection. A server can easily support the current protocol version while also | ||
|
@@ -49,44 +49,44 @@ See for an in-depth description of libp2p, please see: https://libp2p.io/ | |
## Features | ||
|
||
- Multiformats. See my other repo: https://github.com/erwin-kok/multiformat | ||
- [X] multiaddr | ||
- [X] multibase | ||
- [X] multicodec | ||
- [X] multihash | ||
- [X] multistream-select | ||
|
||
- Crypto | ||
- [X] ED25519 | ||
- [X] ECDSA | ||
- [X] SECp256k1 | ||
- [X] RSA | ||
- [X] multiaddr | ||
- [X] multibase | ||
- [X] multicodec | ||
- [X] multihash | ||
- [X] multistream-select | ||
|
||
- Crypto | ||
- [X] ED25519 | ||
- [X] ECDSA | ||
- [X] SECp256k1 | ||
- [X] RSA | ||
|
||
- Transports | ||
- [X] Tcp | ||
- [ ] Quic (planned) | ||
- [X] Tcp | ||
- [ ] Quic (planned) | ||
|
||
- Muxers | ||
- [X] Mplex | ||
- [ ] Yamux (planned) | ||
- [ ] Quic (planned) | ||
- [X] Mplex | ||
- [ ] Yamux (planned) | ||
- [ ] Quic (planned) | ||
|
||
- Security | ||
- [X] Noise | ||
- [ ] Tls (planned) | ||
- [ ] Quic (planned) | ||
- [X] Noise | ||
- [ ] Tls (planned) | ||
- [ ] Quic (planned) | ||
|
||
- Protocols | ||
- [ ] Identify (planned) | ||
- [ ] Ping (planned) | ||
- [ ] DHT/Kademlia (planned) | ||
- [ ] pubsub (planned) | ||
- [ ] Identify (planned) | ||
- [ ] Ping (planned) | ||
- [ ] DHT/Kademlia (planned) | ||
- [ ] pubsub (planned) | ||
|
||
- Peer discovery | ||
- [ ] mDNS (planned) | ||
- [ ] DHT/Kademlia (planned) | ||
- [ ] mDNS (planned) | ||
- [ ] DHT/Kademlia (planned) | ||
|
||
- Datastore | ||
- [X] RocksDB | ||
- [X] RocksDB | ||
|
||
## Getting started | ||
|
||
|
@@ -104,78 +104,79 @@ dependencies { | |
} | ||
``` | ||
|
||
`libp2p-core` is mandatory, other dependencies are optional depending on your needs. For example, if you need tcp | ||
`libp2p-core` is mandatory, other dependencies are optional depending on your needs. For example, if you need tcp | ||
transport, include `libp2p-transport-tcp`, or if you want the mplex muxer include `libp2p-muxer-plex`. | ||
|
||
In your code, first create a host: | ||
|
||
```kotlin | ||
val hostBuilder = host { | ||
identity(localIdentity) | ||
muxers { | ||
mplex() | ||
} | ||
securityTransport { | ||
noise() | ||
} | ||
transports { | ||
tcp() | ||
} | ||
peerstore { | ||
gcInterval = 1.hours | ||
keyStore { | ||
password = "APasswordThatIsAtLeast20CharactersLong" | ||
dek { | ||
salt = "W/SC6fnZfBIWdeAD3l+ClLpQtfICEtn+KYTUhfKq6d7l" | ||
} | ||
} | ||
} | ||
swarm { | ||
dialTimeout = 10.minutes | ||
listenAddresses { | ||
multiAddress("/ip4/0.0.0.0/tcp/10333") | ||
} | ||
identity(localIdentity) | ||
muxers { | ||
mplex() | ||
} | ||
securityTransport { | ||
noise() | ||
} | ||
transports { | ||
tcp() | ||
} | ||
peerstore { | ||
gcInterval = 1.hours | ||
keyStore { | ||
password = "APasswordThatIsAtLeast20CharactersLong" | ||
dek { | ||
salt = "W/SC6fnZfBIWdeAD3l+ClLpQtfICEtn+KYTUhfKq6d7l" | ||
} | ||
datastore(datastore) | ||
} | ||
} | ||
swarm { | ||
dialTimeout = 10.minutes | ||
listenAddresses { | ||
multiAddress("/ip4/0.0.0.0/tcp/10333") | ||
} | ||
} | ||
datastore(datastore) | ||
} | ||
|
||
val host = hostBuilder.build(scope) | ||
.getOrElse { | ||
logger.error { "The following errors occurred while creating the host: ${errorMessage(it)}" } | ||
return@runBlocking | ||
} | ||
val host = hostBuilder.build(scope) | ||
.getOrElse { | ||
logger.error { "The following errors occurred while creating the host: ${errorMessage(it)}" } | ||
return@runBlocking | ||
} | ||
``` | ||
|
||
The layout is hopefully clear: for example, the code above will use `tcp` as a transport, `noise` for security and | ||
The layout is hopefully clear: for example, the code above will use `tcp` as a transport, `noise` for security and | ||
`mplex` as a muxer. | ||
|
||
Then you can add a handler: | ||
|
||
```kotlin | ||
host.setStreamHandler(ProtocolId.of("/chat/1.0.0")) { | ||
chatHandler(it) | ||
} | ||
chatHandler(it) | ||
} | ||
``` | ||
This means that if a peer connects and requests the `/chat/1.0.0` protocol, the corresponding handler will be called. | ||
|
||
This means that if a peer connects and requests the `/chat/1.0.0` protocol, the corresponding handler will be called. | ||
|
||
To call a peer and open a new stream, use the following code: | ||
|
||
```kotlin | ||
val stream = host.newStream(aPeerId, ProtocolId.of("/chat/1.0.0")) | ||
.getOrElse { | ||
logger.error { "Could not open chat stream with peer: ${errorMessage(it)}" } | ||
return@runBlocking | ||
} | ||
chatHandler(stream) | ||
.getOrElse { | ||
logger.error { "Could not open chat stream with peer: ${errorMessage(it)}" } | ||
return@runBlocking | ||
} | ||
chatHandler(stream) | ||
``` | ||
|
||
This tries to connect to peer `aPeerId` and tries to open a new stream for protocol `/chat/1.0.0`. If it fails, it | ||
This tries to connect to peer `aPeerId` and tries to open a new stream for protocol `/chat/1.0.0`. If it fails, it | ||
returns if it succeeds it progresses to the chatHandler. | ||
|
||
See also the example application in `app`. | ||
See also the example application in `examples/chat`. | ||
|
||
To use this sample app, start the application. It will create a new random LocalIdentity (key-pair) and logs the adres | ||
on which it listens on the output: | ||
To use this sample application, start the application. It will create a new random LocalIdentity (key-pair) and logs the | ||
adres on which it listens on the output: | ||
|
||
```shell | ||
[main] o.e.l.a.ApplicationKt$main$1: Local addresses the Host listens on: /ip4/0.0.0.0/tcp/10333/p2p/12D3KooWDfaEJxpmjbFLb9wUakCd6Lo6LRntaV3drb4EaYZRtYuY | ||
|
@@ -188,11 +189,11 @@ by using: | |
./chat -d /ip4/0.0.0.0/tcp/10333/p2p/12D3KooWDfaEJxpmjbFLb9wUakCd6Lo6LRntaV3drb4EaYZRtYuY | ||
``` | ||
|
||
On both sides it should mention that a connection is established. | ||
On both sides it should mention that a connection is established. | ||
|
||
## Contact | ||
|
||
If you want to contact me, please write an e-mail to: [erwin[email protected]](mailto:erwin-kok@gmx.com) | ||
If you want to contact me, please write an e-mail to: "erwin (DOT) kok (AT) protonmail (DOT) com" | ||
|
||
## Acknowledgements | ||
|
||
|
File renamed without changes.
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
File renamed without changes.
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
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
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
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
Oops, something went wrong.