Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(upnp): add implementation based on IGD protocol #4156

Merged
merged 66 commits into from Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
bddebad
feat(protocols): Add initial UPnP protocol
jxs Jul 3, 2023
ba6ad5a
cargo clippy
jxs Jul 4, 2023
3638fd9
fix docs
jxs Jul 4, 2023
6671af3
review: address Thomas review
jxs Jul 4, 2023
7edc88b
review: address Thomas review
jxs Jul 5, 2023
5c59216
review: address Thomas review
jxs Jul 5, 2023
cb2dbbc
update copyright
jxs Jul 6, 2023
4172755
rename Provider trait to Gateway
jxs Jul 6, 2023
6fc4cfc
replace UnoderedFutures on the main behaviour
jxs Jul 6, 2023
0eb75da
update Cargo.toml formatting
jxs Jul 7, 2023
3f3f745
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Jul 7, 2023
7d679c8
revert Box<dyn Error> to String conversion.
jxs Jul 8, 2023
28e0fde
clippy
jxs Jul 8, 2023
bdb0818
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Jul 10, 2023
293133b
address Thomas and Max review
jxs Jul 10, 2023
a6b170f
convert Gateway back into Provider and make it a message interface
jxs Jul 11, 2023
96e3a44
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Jul 11, 2023
72eec83
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Jul 14, 2023
e24cc16
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Jul 24, 2023
b0f8f7a
refactor behaviour to reduce the amount of code
jxs Jul 25, 2023
4a90a78
update provider to handle tasks sequentially instead of concurrently
jxs Jul 25, 2023
f2207b6
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Jul 25, 2023
960a50e
switch to idg-next ,
jxs Jul 26, 2023
1874193
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Jul 27, 2023
92f5cea
add Changelog entries
jxs Jul 28, 2023
0b326bd
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Jul 28, 2023
5384ae6
update Cargo.lock
jxs Jul 28, 2023
7398842
fix docs
jxs Jul 28, 2023
e106ad9
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Jul 29, 2023
ac78e67
update multiaddr_to_socketaddr_protocol,
jxs Jul 29, 2023
13f3e74
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Jul 31, 2023
3843453
clippy
jxs Jul 31, 2023
27b2442
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Jul 31, 2023
5b3b905
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Jul 31, 2023
97129b6
downgrade time and pin to 0.3.23
jxs Jul 31, 2023
b1affdd
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Jul 31, 2023
2a0a757
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Aug 1, 2023
550c248
publicly export upnp::Event
jxs Aug 1, 2023
82cfe2a
add upnp-example
jxs Aug 1, 2023
b599faf
address Thomas review
jxs Aug 2, 2023
f3e0fe8
check if the Gateway's external addres is public
jxs Aug 2, 2023
50d6d4e
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Aug 2, 2023
d5c2e82
cargo clippy
jxs Aug 3, 2023
1a81c76
fix docs
jxs Aug 3, 2023
502ec30
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Aug 7, 2023
eb54f3a
address review
jxs Aug 7, 2023
3216093
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Aug 22, 2023
d631d3a
remove config
jxs Aug 26, 2023
fe3c94f
fix examples and feature flags
jxs Aug 26, 2023
98d00de
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Aug 26, 2023
ef6fd56
use SearchOptions::default
jxs Aug 26, 2023
e480e61
feature gate everything
jxs Aug 27, 2023
029eaf6
address review
jxs Aug 31, 2023
194c792
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Aug 31, 2023
e9b5cd6
do not do io on the behaviour,
jxs Sep 1, 2023
7c8c534
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Sep 4, 2023
e5cb61d
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Sep 5, 2023
316b524
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Sep 6, 2023
ebc4fdb
replace example with tokio
jxs Sep 6, 2023
98ba415
Merge branch 'master' of github.com:libp2p/rust-libp2p into add-upnp-…
jxs Sep 6, 2023
b642cd9
deprecate async-std support
jxs Sep 7, 2023
4c18dab
address review
jxs Sep 8, 2023
1de13e8
address missing remark on review
jxs Sep 8, 2023
4b68a48
add publish false to overcome cargo semver
jxs Sep 11, 2023
98108f7
Merge branch 'master' into add-upnp-protocol
jxs Sep 12, 2023
1a36609
Merge branch 'master' into add-upnp-protocol
mergify[bot] Sep 12, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -20,6 +20,7 @@
- [`libp2p-relay` CHANGELOG](protocols/relay/CHANGELOG.md)
- [`libp2p-request-response` CHANGELOG](protocols/request-response/CHANGELOG.md)
- [`libp2p-rendezvous` CHANGELOG](protocols/rendezvous/CHANGELOG.md)
- [`libp2p-upnp` CHANGELOG](protocols/upnp/CHANGELOG.md)

## Transport Protocols & Upgrades

Expand Down
69 changes: 69 additions & 0 deletions Cargo.lock
jxs marked this conversation as resolved.
Show resolved Hide resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Expand Up @@ -13,6 +13,7 @@ members = [
"examples/ping-example",
"examples/relay-server",
"examples/rendezvous",
"examples/upnp",
"identity",
"interop-tests",
"misc/allow-block-list",
Expand Down Expand Up @@ -40,6 +41,7 @@ members = [
"protocols/relay",
"protocols/rendezvous",
"protocols/request-response",
"protocols/upnp",
"swarm",
"swarm-derive",
"swarm-test",
Expand Down Expand Up @@ -90,6 +92,7 @@ libp2p-pnet = { version = "0.23.0", path = "transports/pnet" }
libp2p-quic = { version = "0.9.2", path = "transports/quic" }
libp2p-relay = { version = "0.16.1", path = "protocols/relay" }
libp2p-rendezvous = { version = "0.13.0", path = "protocols/rendezvous" }
libp2p-upnp = { version = "0.1.0", path = "protocols/upnp" }
libp2p-request-response = { version = "0.25.1", path = "protocols/request-response" }
libp2p-server = { version = "0.12.3", path = "misc/server" }
libp2p-swarm = { version = "0.43.4", path = "swarm" }
Expand Down
11 changes: 11 additions & 0 deletions examples/upnp/Cargo.toml
@@ -0,0 +1,11 @@
[package]
name = "upnp-example"
version = "0.1.0"
edition = "2021"
publish = false
license = "MIT"

[dependencies]
tokio = { version = "1", features = [ "rt-multi-thread", "macros"] }
futures = "0.3.28"
libp2p = { path = "../../libp2p", features = ["tokio", "dns", "macros", "noise", "ping", "tcp", "websocket", "yamux", "upnp"] }
23 changes: 23 additions & 0 deletions examples/upnp/README.md
@@ -0,0 +1,23 @@
## Description

The upnp example showcases how to use the upnp network behaviour to externally open ports on the network gateway.


## Usage

To run the example, follow these steps:

1. In a terminal window, run the following command:

```sh
cargo run
```

2. This command will start the swarm and print the `NewExternalAddr` if the gateway supports `UPnP` or
`GatewayNotFound` if it doesn't.


## Conclusion

The upnp example demonstrates the usage of **libp2p** to externally open a port on the gateway if it
supports [`UPnP`](https://en.wikipedia.org/wiki/Universal_Plug_and_Play).
81 changes: 81 additions & 0 deletions examples/upnp/src/main.rs
@@ -0,0 +1,81 @@
// Copyright 2023 Protocol Labs.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#![doc = include_str!("../README.md")]

use futures::prelude::*;
use libp2p::core::upgrade::Version;
use libp2p::{
identity, noise,
swarm::{SwarmBuilder, SwarmEvent},
tcp, upnp, yamux, Multiaddr, PeerId, Transport,
};
use std::error::Error;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let local_key = identity::Keypair::generate_ed25519();
let local_peer_id = PeerId::from(local_key.public());
println!("Local peer id: {local_peer_id:?}");

let transport = tcp::tokio::Transport::default()
.upgrade(Version::V1Lazy)
.authenticate(noise::Config::new(&local_key)?)
.multiplex(yamux::Config::default())
.boxed();

let mut swarm = SwarmBuilder::with_tokio_executor(
transport,
upnp::tokio::Behaviour::default(),
local_peer_id,
)
.build();

// Tell the swarm to listen on all interfaces and a random, OS-assigned
// port.
swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;

// Dial the peer identified by the multi-address given as the second
// command-line argument, if any.
if let Some(addr) = std::env::args().nth(1) {
let remote: Multiaddr = addr.parse()?;
swarm.dial(remote)?;
println!("Dialed {addr}")
}

loop {
match swarm.select_next_some().await {
SwarmEvent::NewListenAddr { address, .. } => println!("Listening on {address:?}"),
SwarmEvent::Behaviour(upnp::Event::NewExternalAddr(addr)) => {
println!("New external address: {addr}");
}
SwarmEvent::Behaviour(upnp::Event::GatewayNotFound) => {
println!("Gateway does not support UPnP");
break;
}
SwarmEvent::Behaviour(upnp::Event::NonRoutableGateway) => {
println!("Gateway is not exposed directly to the public Internet, i.e. it itself has a private IP address.");
break;
}
_ => {}
}
}
Ok(())
}
4 changes: 4 additions & 0 deletions libp2p/CHANGELOG.md
Expand Up @@ -10,10 +10,14 @@
- Add `json` feature which exposes `request_response::json`.
See [PR 4188].

- Add support for UPnP via the IGD protocol.
See [PR 4156].

- Add `libp2p-memory-connection-limits` providing memory usage based connection limit configurations.
See [PR 4281].

[PR 4188]: https://github.com/libp2p/rust-libp2p/pull/4188
[PR 4156]: https://github.com/libp2p/rust-libp2p/pull/4156
[PR 4217]: https://github.com/libp2p/rust-libp2p/pull/4217
[PR 4281]: https://github.com/libp2p/rust-libp2p/pull/4281

Expand Down
5 changes: 4 additions & 1 deletion libp2p/Cargo.toml
Expand Up @@ -50,6 +50,7 @@ full = [
"websocket",
"webtransport-websys",
"yamux",
"upnp"
]

async-std = ["libp2p-swarm/async-std", "libp2p-mdns?/async-io", "libp2p-tcp?/async-io", "libp2p-dns?/async-std", "libp2p-quic?/async-std"]
Expand Down Expand Up @@ -82,14 +83,15 @@ secp256k1 = ["libp2p-identity/secp256k1"]
serde = ["libp2p-core/serde", "libp2p-kad?/serde", "libp2p-gossipsub?/serde"]
tcp = ["dep:libp2p-tcp"]
tls = ["dep:libp2p-tls"]
tokio = ["libp2p-swarm/tokio", "libp2p-mdns?/tokio", "libp2p-tcp?/tokio", "libp2p-dns?/tokio", "libp2p-quic?/tokio"]
tokio = ["libp2p-swarm/tokio", "libp2p-mdns?/tokio", "libp2p-tcp?/tokio", "libp2p-dns?/tokio", "libp2p-quic?/tokio", "libp2p-upnp?/tokio"]
uds = ["dep:libp2p-uds"]
wasm-bindgen = ["futures-timer/wasm-bindgen", "instant/wasm-bindgen", "getrandom/js", "libp2p-swarm/wasm-bindgen", "libp2p-gossipsub?/wasm-bindgen"]
wasm-ext = ["dep:libp2p-wasm-ext"]
wasm-ext-websocket = ["wasm-ext", "libp2p-wasm-ext?/websocket"]
websocket = ["dep:libp2p-websocket"]
webtransport-websys = ["dep:libp2p-webtransport-websys"]
yamux = ["dep:libp2p-yamux"]
upnp = ["dep:libp2p-upnp"]

[dependencies]
bytes = "1"
Expand Down Expand Up @@ -133,6 +135,7 @@ libp2p-quic = { workspace = true, optional = true }
libp2p-tcp = { workspace = true, optional = true }
libp2p-tls = { workspace = true, optional = true }
libp2p-uds = { workspace = true, optional = true }
libp2p-upnp = { workspace = true, optional = true }
libp2p-websocket = { workspace = true, optional = true }

[dev-dependencies]
Expand Down
4 changes: 4 additions & 0 deletions libp2p/src/lib.rs
Expand Up @@ -127,6 +127,10 @@ pub use libp2p_tls as tls;
#[cfg(not(target_arch = "wasm32"))]
#[doc(inline)]
pub use libp2p_uds as uds;
#[cfg(feature = "upnp")]
#[cfg(not(target_arch = "wasm32"))]
#[doc(inline)]
pub use libp2p_upnp as upnp;
#[cfg(feature = "wasm-ext")]
#[doc(inline)]
pub use libp2p_wasm_ext as wasm_ext;
Expand Down
3 changes: 3 additions & 0 deletions protocols/upnp/CHANGELOG.md
@@ -0,0 +1,3 @@
## 0.1.0 - unreleased

- Initial version
25 changes: 25 additions & 0 deletions protocols/upnp/Cargo.toml
@@ -0,0 +1,25 @@
[package]
name = "libp2p-upnp"
edition = "2021"
rust-version = "1.60.0"
description = "UPnP support for libp2p transports"
version = "0.1.0"
license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p"
keywords = ["peer-to-peer", "libp2p", "networking"]
categories = ["network-programming", "asynchronous"]
publish = false

thomaseizinger marked this conversation as resolved.
Show resolved Hide resolved
[dependencies]
futures = "0.3.28"
futures-timer = "3.0.2"
igd-next = "0.14.2"
libp2p-core = { workspace = true }
libp2p-swarm = { workspace = true }
log = "0.4.19"
void = "1.0.2"
tokio = { version = "1.29", default-features = false, features = ["rt"], optional = true }

[features]
tokio = ["igd-next/aio_tokio", "dep:tokio"]