Peer-to-peer communications library for Rust based on QUIC protocol

Overview

qp2p

Crate Documentation
Documentation
MaidSafe website SAFE Dev Forum SAFE Network Forum

Overview

This library provides an API to simplify common tasks when creating P2P networks, including:

  • Establishing encrypted, uni- and bidirectional connections (using QUIC with TLS 1.3).
  • Connection pooling, for reusing already opened connections.
  • Fault-tolerance, including retries and racing connections against sets of peers.
  • Configuring UPnP and validating external connectivity.
  • Sending discrete messages (using QUIC streams as 'framing').

Features

QUIC

There are several informative posts describing both QUIC and TLS 1.3:

These are highly recommended to be able to better understand this library, in particular the Cloudflare blog posts (10 minute read).

Encryption of connections

QUIC provides connection security via the use of TLS 1.3. Currently, self-signed certificates are used to encrypt connections, but this provides no authentication.

In future, we would like to support authentication via certificate authorities and pre-agreed certificates. This should satisfy the requirements of many P2P networks, whether they trust any clearnet certificate authority (which may be a centralised attack source) or whether they pass the identity management up to a different layer to validate identities and simply use qp2p as a secured network in terms of encrypted connections.

Connection pooling

Although QUIC connections are relatively cheap to establish (e.g. compared to TCP connections), there is still some overhead. To minimise this overhead, all opened connections are pooled and reused based on their target socket address.

Fault tolerance

All operations are retried using an exponential back-off strategy (with jitter), configurable by how long to keep retrying for. This can help ensure continuity over flaky connections.

Note: This means that all messages sent with this library will have 'at least once' delivery – ideally message handling should be idempotent, or else deduplication will have to be performed on receipt.

Additionally, APIs are available to connect to any peer from a list of peers. Connections are established concurrently, and the first to succeed is kept, while the rest are discarded. This allows connecting to any of a set of equivalent peers, finding a still-reachable peer in a set of previously known peers, etc.

UPnP

qp2p has build-in support for the Internet Gateway Device Protocol (IGD). This enables automatic setup of port-forwarding for peers behind some NAT-enabled routers, including many home and small office routers. This serves to lower the barrier to accessing P2P networks as a peer.

When UPnP is unavailable, manual port-forwarding may be necessary to establish incoming connectivity.

Messaging

QUIC is a streaming protocol, without an explicit model for discrete messages. However, QUIC connections can multiplex an arbitrary number of streams, which are cheap to construct and dispose of. This library uses streams as a message framing mechanism, sending or receiving a single message per stream.

QUIC supports both unidirectional and bidirectional streams, and both are exposed through this library.

  • Unidirectional streams should typically be preferred for peer-to-peer communication. This requires peers to have external connectivity, which is generally better for fault tolerance (e.g. contact sharing, reconnection).

  • Bidirectional streams should be preferred for client-server communication. This does not require external connectivity, so clients can still communicate from behind firewalls/gateways (such as household routers).

License

This SAFE Network library is dual-licensed under the Modified BSD (LICENSE-BSD https://opensource.org/licenses/BSD-3-Clause) or the MIT license (LICENSE-MIT http://opensource.org/licenses/MIT) at your option.

Contributing

Want to contribute? Great πŸŽ‰

There are many ways to give back to the project, whether it be writing new code, fixing bugs, or just reporting errors. All forms of contributions are encouraged!

For instructions on how to contribute, see our Guide to contributing.

Comments
  • fix(p2p_node): 'polo' reply processing

    fix(p2p_node): 'polo' reply processing

    When trying to run the p2p_node example, I encountered a crash when polo is sent back to the peer:

    ---
    Listening on: 127.0.0.1:38616
    ---
    
    
    Received from 127.0.0.1:38091 --> b"marco"
    Error: 
       0: Connection was lost when trying to send a message
       1: The connection was closed by application (error code: 0, reason: )
    
    

    The client shows:

    Sending to 127.0.0.1:38616 --> b"marco"
    
    Done sending
    
    ---
    Listening on: 127.0.0.1:38091
    ---
    
    

    I was able to get it working with the following patch. I'm a beginner to this library, so please feel free to recommend a different way to tackle this! I was aiming for the simplest solution in this context.

    opened by m1cr0man 10
  • re-export tokio

    re-export tokio

    Describe the bug Currently, someone using this crate has to depend on it as well as on the tokio crate, this is bad because

    • A user should not have to depend on two crates in order to use one.
    • If a user depends on a different version than this crate tokio is duplicated, also if the version the user depends on is a breaking change of the one qp2p does, that could create problems since tokio is a runtime.

    To Reproduce

    1. depend on this crate (cargo add qp2p)
    2. run some code
    3. realize you can't use .await syntax
    4. depend on tokio (annoying)
    5. If versions are incompatible: code panics in a really weird way

    Expected behavior This crate re-exports tokio and that is the runtime you use

    Screenshots

    [dependencies]
    qp2p = "0.8.8"
    tokio = { version = "~0.2", features = ["rt-threaded", "macros"] }
    

    Desktop (please complete the following information where applicable):

    • quic-p2p: 0.8.8

    Additional context I'd be happy to create the pull request for this fix and all the documentation corrections. I'll also add the relevant tokio features to this crate and give them a tokio- prefix. In the end you should be able to use the crate like this:

    qp2p = { version = "0.9.0", features = ["tokio-rt-threaded"] }
    

    and use tokio like this:

    use qp2p::rt;
    
    #[rt::main]
    async fn main() {}
    

    or like this: (IMO less elegant but easier to adopt)

    use qp2p::tokio;
    
    #[tokio::main]
    async fn main() {}
    
    bug 
    opened by GilRtr 5
  • Error when compiling for 32-bit Linux

    Error when compiling for 32-bit Linux

    Describe the bug I get an error, when compiling for 32-bit Linux:

       Compiling qp2p v0.10.1
    error[E0308]: mismatched types
       --> /home/devel/.cargo/registry/src/github.com-1ecc6299db9ec823/qp2p-0.10.1/src/wire_msg.rs:156:45
        |
    156 |         let data_len = usize::from_be_bytes([0, 0, 0, 0, bytes[2], bytes[3], bytes[4], bytes[5]]);
        |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a fixed size of 4 elements, found one with 8 elements
    
    error: aborting due to previous error
    
    For more information about this error, try `rustc --explain E0308`.
    error: could not compile `qp2p`
    
    To learn more, run the command again with --verbose.
    warning: build failed, waiting for other jobs to finish...
    error: build failed
    cargo build --target=i686-unknown-linux-gnu  1171,25s user 83,79s system 143% cpu 14:35,91 total
    

    To Reproduce I was trying to compile a Rust FFI library. My lib.rs:

    use std::os::raw::c_char;
    use std::ffi::CString;
    use sn_api::Safe;
    
    // Based on this tutorial: https://dev.to/verkkokauppacom/creating-an-ffi-compatible-c-abi-library-in-rust-5dji
    
    fn xorurl_base() -> String {
        let mut safe = Safe::default();
        return safe.xorurl_base.to_string();
    }
    
    #[no_mangle]
    pub extern "C" fn c_xorurl_base() -> *mut c_char {
        let rust_string: String = xorurl_base();
    
        // Convert the String into a CString
        let c_string: CString = CString::new(rust_string).expect("Could not convert to CString");
    
        // Instead of returning the CString, we return a pointer for it.
        return c_string.into_raw();
    }
    

    Expected behavior I expect compilation without errors.

    • OS: Arch Linux
    • Shell: zsh
    • Rust: rustc 1.49.0 (e1884a8e3 2020-12-29)
    • quic-p2p crate version: 0.10.1
    bug 
    opened by loziniak 4
  • Add API to respond to bidirectional stream when getting next message from connection.

    Add API to respond to bidirectional stream when getting next message from connection.

    Hello,

    I was building bindings for qp2p for Elixir and came across a case where i needed to not only accept the next message from a bidirectional stream, but also reply to it. I couldn't figure out a way with the current API to do this without having some type of correlation prefix on the message.

    This PR adds a new method next_with_stream to ConnectionIncoming in order for users to respond to a bidirectional stream.

    If you can accomplish this without these changes in the current API or if you have suggestions, please let me know!

    opened by hansonkd 3
  • `max_idle_timeout` config setting

    `max_idle_timeout` config setting

    Not necessarily a bug, but I just wanted to make sure since I'm new in Rust. On line 218, function max_transport_config, file configs.rs. the code looks like this:

    let _ = config.max_idle_timeout(Some(idle_timeout)).ok();

    But max_idle_timeout's documentation, when it comes to Durations, states that it should look more like this:

    let _ = config.max_idle_timeout(Some(idle_timeout).try_into()?);

    With the change above Pycharm does not complain anymore for mismatched_types. As I said, not a bug, just looking to discuss this with someone that knows better.

    bug 
    opened by esmeraldaliaj 3
  • Remove bootstrap cache

    Remove bootstrap cache

    • dcaf370 fix: Add missing re-export for TransportErrorCode

      This is in the public interface, as a field of Close::Transport. Sadly this isn't detected by the unreachable_pub lint.

    • 33ca793 chore!: Remove unused Config::max_msg_size_allowed

      BREAKING CHANGE: Config::max_msg_size_allowed has been removed.

    • 10397e1 refactor: Sort error items in order of appearance

      This should help to keep this module navigable.

    • 958f09a refactor: Use a different struct for config internally

      The InternalConfig struct is a trimmed down version of Config, which ditches extraneous keys (that are used elsewhere) and removes Options (when there are default values).

      This does not affect on the public API.

    • b8461a6 refactor!: Remove random port fallback

      This is a bit 'too clever' for this library, and it's unlikely that this fallback was really being used (it would usually be left unspecified, so always be random).

      BREAKING CHANGE: This is a breaking behavioural change. It is now up to the caller if they want to retry with a different port.

    • e5fc09c refactor!: Move local address from config to QuicP2p::bootstrap

      Keeping the local address in config involved quite a lot of shenanigans to obtain a default value, and it doesn't provide much value. Typically users would look at Endpoint::local_addr, which is read from the underlying socket (by quinn).

      This does mean passing a local address when constructing an endpoint, but it's expected that users will have their own configuration structures, such that this won't be too disruptive.

      BREAKING CHANGE: Config::local_ip and Config::local_port have been removed. QuicP2p::bootstrap and QuicP2p::new_endpoint now require a local address to bind to. The Error::UnspecifiedLocalIp variant has been removed.

    • ad71740 refactor!: Remove BootstrapCache and hard-coded contacts

      This is another change intended to shed some cleverness from this library. It's likely that users will already be storing and maintaining a list of contacts, so rather than having to synchronise that with this library, we now just accept a list of contacts when bootstrap is called.

      BREAKING CHANGE: Config::hard_coded_contacts and Config::bootstrap_cache_dir have been removed. Additionally, QuicP2p::with_config no longer takes bootstrap_nodes – these should instead be passed to QuicP2p::bootstrap. Finally, the Error::InvalidPath and Error::UserHomeDir variants have been removed.

    • 9fc3eb0 refactor!: Make Config in QuicP2p::from_config non-optional

      Now that there are no shenanigans needed when setting up default Config, callers can just use Config::default().

      BREAKING CHANGE: QuicP2p::from_config now takes a Config argument, rather than Option<Config>. Config::default() (or Option::unwrap_or_default) should be used instead.

    • 34e2ed1 feat: Add Endpoint::connect_to_any

      This implements the 'bootstrap' process of contacting a set of nodes and returning the first one to which we successfully connect. QuicP2p::bootstrap is now implemented in terms of this function.

    • c837e9f doc: Update README

      The library has diverged somewhat from what was in the README. The new text tries to articulate the features you get over just using a QUIC library like quinn directly.

    • b36f31d chore: Remove redundant structopt annotation

      structopt uses kebab-ase by default.

    • c6fd90e refactor!: Use Duration in config and centralise defaults

      Rather than using names and documentation to specify the units for durations, we can use the Duration type which lets callers choose whatever works best for them. It also means we no longer have to convert to Duration internally, simplifying some code.

      Additionally, the default values for duration constants have been centralised under config, which has been made public so users can see them in documentation.

      BREAKING CHANGE: The duration fields in config have all changed:

      • idle_timeout_msec is renamed idle_timeout and is now an Option<Duration>.
      • keep_alive_interval_msec is renamed keep_alive_interval and is now an Option<Duration>.
      • upnp_lease_duration is now an Option<Duration>.
      • retry_duration_msec is renamed min_retry_duration and is now an Option<Duration>.
    • a2cc68c refactor: Move quinn config into InternalConfig

      This moves some responsbilities from QuicP2p to config.

    • cf29520 refactor: Move InternalConfig construction into config mod

      This further reduces the responsibilities of QuicP2p, and also reduces the 'spread' of config concerns.

    • 44ced5f refactor: Make SerialisableCertificate mod private

      This was only being used in tests::quinn, which can get what it needs from InternalConfig.

    • 5dea879 refactor: Merge peer_config into InternalConfig

      The peer_config mod contained helper functions for constructing the various bits of quinn configuration we need. Being config related, they fit just as well in the config module, further reducing the spread of 'config' concerns.

    • af418be refactor!: Delete SerializableCertificate

      This was not exposed, so the whole things can be replaced by a single function on InternalConfig.

      BREAKING CHANGE: The Error::Base64Decode variant has been removed.

    • a805a11 refactor!: Separate ConfigError from Error

      Currently, the only configuration-time errors are related to certificate generation. Since we currently generate self-signed certificates, the only failures that could happen would be due to bugs. As such, the ConfigError::CertificateGeneration variant doesn't attempt to capture all the info, rather just an opaque Error (though the backtrace and source chain will be preserved).

      This removes a number of variants from Error.

      BREAKING CHANGE: There are several breaking changes:

      • QuicP2p::from_config now returns Result<Self, ConfigError>.
      • The Error::CertificateParse variant has been removed.
      • The Error::CertificatePkParse variant has been removed.
      • The Error::CertificateGen variant has been removed.
      • The Error::Tls variant has been removed.
    • 237d23b chore!: Remove unused Error variants

      BREAKING CHANGE: The Error::DisconnectionNotification and Error::Configuration variants have been removed.

    • 8356d1e refactor!: Refactor WireMsg::read_from_stream to avoid logic error

      Previously we used TryFrom which we know will succeed thanks to our assertions, however we don't want to allow for the possibility of unexpected panics by using unwrap here.

      Since we have asserted the pointer size though, we can reasonably perform a lossy conversion with as, knowing that in fact nothing will be lost.

      BREAKING CHANGE: The Error::UnexpectedError variant has been removed.

    • 7c0dba6 refactor!: Rename Endpoint::socket_addr to public_addr

      This is a more appropriate name for the method.

      BREAKING CHANGE: Endpoint::socket_addr has been renamed to public_addr.

    • 9ea04db refactor!: Make ConnId::generate infallible

      This trait method originally allowed for an arbitrary Box<dyn Error>, likely to account for the possible serialization failure when using bincode::serialize in the impl for XorName. Whilst this allows for more exotic connection ID strategies, having to account for this error in all APIs that touch connection IDs is a bit of a pain.

      By rewriting the XorName impl to 'manually' extract the IP and port bytes, we can avoid any possibility of error and make the method infallible.

      BREAKING CHANGE: The ConnId::generate method now returns Self, and doesn't allow for errors. The Error::ConnectionIdGeneration variant has been removed.

    • aec6334 refactor!: Return Option from Endpoint::connect_to_any

      The Result returned by connect_to_any could only fail for two reasons:

      • An empty list of nodes was provided. Callers could know if that's the case and do their own validation, otherwise None is a perfectly reasonable result and consistent with other list operations (first, last, etc.).
      • Every peer failed to connect. In this case we would print the error, but only return a marker to the caller (Error::BootstrapFailed). This gives no extra information vs. None (especially since, as noted above, the caller can already distinguish this from an empty list of peers).

      QuicP2p::bootstrap still converts None to the corresponding error, so as to not break that API (though it should be removed soon).

      BREAKING CHANGE: Endpoint::connect_to_any now returns Option<SocketAddr> instead of Result<SocketAddr>.

    • 6bc1fb1 feat: Add Endpoint::new_client constructor

      This creates an Endpoint that can work as a client only (all the machinery for incoming transactions are dropped).

      Another difference from Endpoint::new is that this does none of the reachability checking, since this should not be necessary for client- only endpoints (though, the API for bidirectional streams is currently unusable). This massively reduces the possible errors, which have their own ClientError enum.

    • 9619472 refactor: Remove connection_deduplicator::Error

      This introduces a new (crate private) enum ConnectFailure which covers the three possible reasons a connect attempt might fail:

      • The connect parameters were invalid (quinn::ConnectError).
      • An I/O or protocol error occurred during connect (quinn::ConnectionError), which we expose as two variants in our API:
        • Error::ConnectionClosed indicating the connection was closed gracefully by ourselves, the application, or the protocol.
        • Error::ConnectionError for other possibilities (resets, timeouts, and transport errors).

      Ultimately, this allows us to ditch connection_deduplicator::Error in favour of ConnectFailure which can be used for other things in future.

      The separation of quinn::ConnectionError to Close and ConnectionError has also be factored into a private ConnectionCloseOrError enum.

    • 60dc1cd refactor: Remove Endpoint::create_new_connection

      This wasn't doing anything more than attempt_connection, so it can be removed.

    • 0d18404 refactor!: Merge 'connect' and 'close' errors with ConnectionError

      This introduces new variants to the ConnectionError enum to cover failures that may be encountered before establishing a connection (quinn::ConnectError) as well as closures (Close).

      This is useful for a couple of reasons:

      • Many of our APIs will transparently try to create connections before using them. Even when reducing the possible variants from these APIs, we would still need to account for these three possibilities (pre-connect error, connection error, and connection close).
      • It removes quinn::ConnectError from our public API, and better represents errors that should be impossible as bugs.
      • It replaces the crate-private ConnectFailure and simplifies some of the error conversion logic.

      BREAKING CHANGE: The Error::Connect and Error::ConnectionClosed variants have been removed. Several additional variants have been added to ConnectionError.

    • a80ba51 refactor!: Remove Error::UnknownStream variant

      This variant existed to handle errors returned by quinn when trying to set or get the stream's priority. The errors can occur because the stream objects are essentially indices into a map of underlying streams. Calling methods on the stream translates to a lookup into this map. Undelrying streams may close for various reasons independent of our handles for them (e.g. if the stream or connection closes).

      However, handling this situation as errors is not very useful. If we fail to set the priority of a stream because it doesn't exist, the effect of the priority would be unobservable. Any attempt to observe the effect (e.g. reading/writing to the stream) would lead to an error at that point, which is a far more convenient place to handle them.

      By ignoring errors when setting stream priority (and dropping the getter for priority, since there's no downstream use-case), we can remove the UnknownStream variant and reduce the range of possible errors from all functions that establish connections (which is many!).

      BREAKING CHANGE:

      • The Error::UnknownStream variant has been removed.
      • SendStream::set_priority is now infallible and returns ().
      • SendStream::priority has been removed.
    • f771972 refactor!: Make Endpoint::disconnect_from infallible

      This function can never return an error.

      BREAKING CHANGE: Endpoint::disconnect_from now returns ().

    • 95f59c0 fix: Make connection deduplicator handle cancellations

      When a connection attempt is made, ConnectionDeduplicator::query would return None for the first attempt, and any future attempts will await on the broadcast channel until the first caller calls ConnectionDeduplicator::complete. As such, subsequent callers would await forever if the first caller never called complete, e.g. because the enclosing task was cancelled, or due to a logic bug.

      This commit refactors ConnectionDeduplicator to store Weak references to the broadcast sender in the map, and query now returns the only strong reference. This way, if the caller that gets the strong reference is cancelled, the sender will drop and any queued callers will notice.

      This has the nice side effect of having to properly correlate the query and 'complete's, since the result of query is needed to complete.

    • df73eb3 refactor: Centralise connection pool interactions

      Endpoint had a few different methods for connecting, some of which would use the connection pool + deduplicator and some would not. It's not really clear when we wouldn't want to retry connection attempts, so this commit introduces a (private) get_or_connect_to function which always uses the pool and always retries. All functions that need a connection now use this.

      This has the nice side-effect of removing (most of) the need for Error::MissingConnection, since get_or_connect_to returns the established connection.

    • 98e98a6 refactor!: Use ConnectionError when possible

      This changes the public Endpoint methods connect_to and open_bidirectional_stream to use ConnectionError for errors. This reduces the scope of errors for callers to handle, and sets us up for further reductions with other methods.

      BREAKING CHANGE: Endpoint::connect_to and Endpoint::open_bidirectional_stream now use ConnectionError, rather than Error, for error results.

    • 4ea22d3 fix!: Fix WireMsg visibility

      This was marked pub and appeared in some APIs (SendStream::send, Error::UnexpectedMessageType) even though the type itself is unreachable (wire_msg mod is private and WireMsg is not re-exported).

      The type itself has been marked pub(crate), along with its associated functions, and functions that use it. The Error::UnexpectedMessageType variant has been changed to include a public newtype, which for users would behave like an opaque error. This assumes the intention was for the type not to be exposed.

      BREAKING CHANGE: SendStream::send is no longer public. Error::UnexpectedMessageType now contains a simple error struct.

    • bdf8dac feat!: Add SendError for send-specific errors

      The SendError covers only the error possibilities when sending a message, which makes it easier to handle by users. All APIs that simply connect and send messages (or just send messages) have been changed to return SendError.

      One method that could not easily be changed is try_send_message, since it returns a particular error variant when there is no matching connection in the pool. This may be changed separately.

      BREAKING CHANGE: The following APIs had their error type changed from Error to SendError:

      • SendStream::send_user_msg
      • SendStream::send
      • SendStream::finish
      • Endpoint::send_message

      Additionally, the StreamWrite and MaxLengthExceeded variants have been removed from Error, and a Send variant has been added.

    • fffa96f feat!: Add RecvNextError for receive-specific errors

      The RecvNextError (and RecvError) model the possible errors that can occur when receiving a message. RecvNextError is returned from RecvStream::next, and covers the additional possibility (over RecvError) of the received message not being a user message.

      This allowed the removal of several Error variants.

      BREAKING CHANGE: RecvStream::next now returns RecvNextError as the error type. The following Error variants have been removed:

      • Error::Serialisation (this is now fully covered by SendError and RecvError).
      • Error::InvalidMsgFlag (this case is now covered by RecvError::Serialization).
      • Error::StreamRead (this is now covered by RecvError).
      • Error::EmptyResponse (this case is now covered by RecvError::Serialization).
      • Error::UnexpectedMessageType (this case is now covered by `ReadNextError::UnexpectedMessageType).

      Finally, a Recv variant has been added to Error.

    • 6d2b523 refactor: Rename Endpoint::new to _new

      This is in preparation for adding a public new constructor.

    • de416c4 refactor: Switch test errors from anyhow to eyre

      We now use eyre, via color_eyre, for errors in tests. This should give us nicer output, and is consistent with the approach taken in other MaidSafe repositories.

    • 6e16a09 refactor!: Use SerializationError for too long messages

      This will allow merging the SendError and RecvError types.

      BREAKING CHANGE: The SendError::TooLong variant has been removed. The same condition (attempting to send a message longer than u32::MAX bytes) will now return SendError::Serialization.

    • 779afc0 refactor!: Treat unexpected messages as serialization errors

      The semantics of this are a bit questionable, but it allows us to remove the RecvNextError and UnexpectedMessageType types. Essentially, we treat the problem of receiving an unexpected message as if we've tried to deserialize the expected message, and found something else. This doesn't quite match the logic (we in fact do deserialize a message successfully), but is suitable for the API.

      BREAKING CHANGE: The RecvNextError and UnexpectedMessageType types have been removed. RecvError is used where RecvNextError was used previously.

    • efc4b56 refactor: Simplify igd::port_forward

      The new signature requires the caller to specify the external port separately from the local address, which is a better match for the actual port mapping functionality. This removes some unnecessary 'plumbing' for the return value.

    • f2ec696 refactor!: Use a separate type for IGD errors

      This removes all the Igd* variants from the Error enum. These would in fact never be exposed to users, since IGD errors are always caught and logged. As such, the new IgdError enum is crate-private.

      BREAKING CHANGE: The IgdAddPort, IgdRenewPort, IgdSearch, and IgdNotSupported variants have been removed from Error. These variants would never have been returned, but may be referenced in matches against Error values.

    • 86bc285 feat: Add public Endpoint::new constructor

      This can be used to construct new peer endpoints, which is positioned as the 'default' by naming the method simply new.

      This roughly follows the logic of the crate private new that it replaces (renamed to _new, to be removed in future), with some differences:

      • Errors that occur when establishing the public address or port forwarding are returned to the user. As a library, it's been deemed preferable that callers handle this and retry, with the relevant configuration altered, if desired.

      • Configured external IP/port are now combined with the steps to query our public address from a peer. This is intended to simplify the logic around public address handling – there's now a single sequence of steps:

        1. Start with public_addr = local_addr.
        2. If we bootstrapped to a peer, get our visible_addr from them.
        3. If we configured a specific external_ip, override that in public_addr.
          1. Otherwise, if we have a visible_addr, override the IP in public_addr.
        4. If we configured a specific external_port, override that in public_addr.
          1. Otherwise, if we have a visible_addr, override the port in public_addr.

        Still not exactly "simple", but easier to follow.

      • If we bootstrapped to a peer, we always test reachability of our determined public_addr. There's no reason not to do this – even if the endpoint is local-only, it verifies the expectation of the caller that the given contacts can reach us (which will work if they are also local).

    • 6a379c9 refactor!: Remove QuicP2p

      Now that Endpoint has public constructors, there's no need for the QuicP2p interface. This also removes a decent chunk of code from Endpoint itself.

      This leaves behind some redundant Error variants, but the intention is to remove that whole type soon.

      BREAKING CHANGE: The QuicP2p type has been removed. Use Endpoint::new or Endpoint::new_client instead. The BootstrapFailure, EmptyBootstrapNodesList, Io, Endpoint, NoEchoServerEndpointDefined, EchoServiceFailure, CannotAssignPort, IncorrectPublicAddress, and UnresolvedPublicIp Error variants have been removed.

    • 7102f59 refactor!: Remove Result alias

      Now that there are several public error types, a single Result alias doesn't really make sense. This also makes it easier to find and remove Error references.

      BREAKING CHANGE: The Result alias has been removed. It can be replaced by std::result::Result<T, qp2p::Error>.

    • 0f603c8 refactor!: Return RpcError from Endpoint::is_reachable

      The is_reachable method performs an endpoint echo operation against a given peer address. RpcError covers all the possible errors that can occur during this operation, and no more.

      BREAKING CHANGE: Endpoint::is_reachable now returns Result<(), RpcError>, rather than Result<(), Error>.

    • 08a38ed refactor!: Return SendError in Endpoint::try_send_message

      Rather than returning an Error::MissingConnection if the connection is not in the pool, this now returns Err(None). If the connection is in the pool, but there's an error sending the message, this will return Err(Some(error)). It remains to be seen how usable this will be for callers, but it avoid introducing another type for this single case and is a reasonable model.

      BREAKING CHANGE: Endpoint::try_send_message now returns Result<(), Option<SendError>> rather than Result<(), Error>. The Error::MissingConnection variant has been removed.

    • 22f5259 refactor!: Remove Error

      This was no longer used in any public APIs. The one internal use was to unify error when reading from streams in connections. This has been replaced by a private enum for that specific purpose.

      BREAKING CHANGE: The Error type has been removed.

    • 5492287 refactor!: Remove Endpoint::bootstrap_nodes

      This is no longer used.

      BREAKING CHANGE: The Endpoint::bootstrap_nodes method has been removed since it is no longer set.

    • 9f6cbbd fix: Don't use connection pool in Endpoint::is_reachable

      The point of this function is to test if a given address can be connected to. If we use the connection pool, we may use a connection that they established, giving us a false positive.

    • 7bd640f refactor: Deduplicate endpoint building logic

      This is an internal-only refactor to deduplicate the code for building an endpoint, between the new and new_client constructors.

    opened by connec 3
  • [WIP] Upgrade tokio to v1

    [WIP] Upgrade tokio to v1

    • [ ] Waiting on a release from quinn now that https://github.com/quinn-rs/quinn/pull/873 has been merged: https://github.com/quinn-rs/quinn/issues/856
    • [ ] Use the same version of tokio that quinn does
    opened by nashley 3
  • Release a 0.7.1 on crates.io with an updated readme which links to the new crates.io package

    Release a 0.7.1 on crates.io with an updated readme which links to the new crates.io package

    For users of an older version it's difficult to see that the package is continued under a different name. Therefore I would propose to release a 0.7.1 on crates.io with a readme which links to the new package.

    bug 
    opened by caemor 3
  • `echo_service` test is failing CI

    `echo_service` test is failing CI

    See https://github.com/maidsafe/quic-p2p/pull/107/checks?check_run_id=677634467#step:8:533

    Extract from logs

      18: std::panic::catch_unwind
                 at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd\src\libstd\panic.rs:394
      19: test::run_test_in_process
                 at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd\/src\libtest\lib.rs:542
      20: test::run_test::run_test_inner::{{closure}}
                 at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd\/src\libtest\lib.rs:451
    note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
    
    
    failures:
        tests::echo_service
    
    test result: FAILED. 21 passed; 1 failed; 2 ignored; 0 measured; 0 filtered out
    
    error: test failed, to rerun pass '-p quic-p2p --lib'
    ##[error]The process 'C:\Rust\.cargo\bin\cargo.exe' failed with exit code 101
    
    bug 
    opened by S-Coyle 3
  • Clarify Readme and fix SerialisableCertificate

    Clarify Readme and fix SerialisableCertificate

    Tried to fix and clarify my additionally added issues from #95.

    • Removed SerialisableCertificate from Public Interface and adapted other stuff around this change
    • Clarified Readme that currently only 3rd option is implemented, but others will follow
    opened by caemor 3
  • Better retries

    Better retries

    • bf2c26e refactor!: rename Config::retry_config to default_retry_config

      The plan is to introduce additional APIs to allow retries to be configured in all places that we perform retries. As such, the configured retry config will always behave as a default, and changing the name makes this clear.

    • 027dc51 refactor: improve retry APIs

      This is an attempt to allow callers to maintain a 'retry context' throughout their own code and calls to qp2p. For example, it may be desired to retry an operation for 60s, regardless of where the failure occurs. Without a change such as this, callers would have to wrap their entire operation in a top level retry, and it becomes difficult to reason about where retries may occur and for how long.

      The APIs introduced here allow callers to supply an implementation of backoff::backoff::Backoff, which will be used to drive retries. That alone is insufficient to allow a 'retry context' to be maintained, but the included qp2p::backoff::BackoffRef utility struct allows a mutable reference to a backoff::backoff::Backoff to be passed.

    opened by connec 2
  • RUSTSEC-2021-0139: ansi_term is Unmaintained

    RUSTSEC-2021-0139: ansi_term is Unmaintained

    ansi_term is Unmaintained

    | Details | | | ------------------- | ---------------------------------------------- | | Status | unmaintained | | Package | ansi_term | | Version | 0.12.1 | | URL | https://github.com/ogham/rust-ansi-term/issues/72 | | Date | 2021-08-18 |

    The maintainer has adviced this crate is deprecated and will not receive any maintenance.

    The crate does not seem to have much dependencies and may or may not be ok to use as-is.

    Last release seems to have been three years ago.

    Possible Alternative(s)

    The below list has not been vetted in any way and may or may not contain alternatives;

    See advisory page for additional details.

    opened by github-actions[bot] 0
  • RUSTSEC-2022-0048: xml-rs is Unmaintained

    RUSTSEC-2022-0048: xml-rs is Unmaintained

    xml-rs is Unmaintained

    | Details | | | ------------------- | ---------------------------------------------- | | Status | unmaintained | | Package | xml-rs | | Version | 0.8.4 | | URL | https://github.com/netvl/xml-rs/issues | | Date | 2022-01-26 |

    xml-rs is a XML parser has open issues around parsing including integer overflows / panics that may or may not be an issue with untrusted data.

    Together with these open issues with Unmaintained status xml-rs may or may not be suited to parse untrusted data.

    Alternatives

    See advisory page for additional details.

    opened by github-actions[bot] 0
  • When UPnP is unavailable

    When UPnP is unavailable

    In response to:

    When UPnP is unavailable, manual port-forwarding may be necessary to establish incoming connectivity.

    Is there an example of how to route traffic between two peers over a third-party β€œrelay” peer? Using qp2p.

    Something like TURN...

    enhancement 
    opened by cong-or 1
Releases(v0.34.2)
Owner
MaidSafe
MaidSafe
QUIC proxy that allows to use QUIC to connect to an SSH server without needing to patch the client or the server.

quicssh-rs ?? quicssh-rs is a QUIC proxy that allows to use QUIC to connect to an SSH server without needing to patch the client or the server. quicss

Jun Ouyang 18 May 5, 2023
IDP2P is a peer-to-peer identity protocol which enables a controller to create, manage and share its own proofs as well as did documents

IDP2P Experimental, inspired by ipfs, did:peer and keri Background See also (related topics): Decentralized Identifiers (DIDs) Verifiable Credentials

null 5 Oct 31, 2022
Core library for Lightning Network peer-to-peer nostr platform

Mostro server This document explains how Mostro works. Overview Due to the growing need to be able to operate with Bitcoin without giving up personal

Mostro 16 Jan 4, 2023
An end-to-end encrypted, anonymous IP-hiding, decentralized, audio/video/file sharing/offline messaging multi-device platform built for both communications and application security and performance.

An end-to-end encrypted, anonymous IP-hiding, decentralized, audio/video/file sharing/offline messaging multi-device platform built for both communications and application security and performance.

null 2 Apr 27, 2022
πŸ₯§ Savoury implementation of the QUIC transport protocol and HTTP/3

quiche is an implementation of the QUIC transport protocol and HTTP/3 as specified by the IETF. It provides a low level API for processing QUIC packet

Cloudflare 7.1k Jan 8, 2023
Painless peer-to-peer WebRTC networking for rust wasm

Matchbox Painless peer-to-peer WebRTC networking for rust wasm applications. The goal of the Matchbox project is to enable udp-like, unordered, unreli

Johan Klokkhammer Helsing 363 Jan 5, 2023
Easy-to-use wrapper for WebRTC DataChannels peer-to-peer connections written in Rust and compiling to WASM.

Easy-to-use wrapper for WebRTC DataChannels peer-to-peer connections written in Rust and compiling to WASM.

null 58 Dec 11, 2022
Simple Peer-to-Peer Exchange

Near Cetificate Devoloper - Demo Simple Peer-to-Peer Exchange On NEAR How it works? See how p2p exchange work here. Exploring The Code The contract co

null 3 Dec 20, 2021
Peer-to-peer overlay routing

Rust_Pinecone This is a port of the peer-to-peer overlay routing mechanism Pinecone and aims to be interoperable with it, although it isn't yet becaus

null 3 Aug 2, 2022
Mateversum is a peer-to-peer WebXR metaverse project.

Mateversum ?? Mateversum (pronounced: MAH-tay-ver-sum) is a peer-to-peer WebXR metaverse project. The idea is that you'd be able to connect to a netwo

Ashley 23 Dec 21, 2022
Quick Peer-To-Peer UDP file transfer

qft QFT is a small application for Quick (and really reliable) Peer-To-Peer UDP file transfer. If a friend sent you here... ...look at the "Releases"

Daniel H. 99 Jan 7, 2023
Futures-based QUIC implementation in Rust

Pure-rust QUIC protocol implementation Quinn is a pure-rust, future-based implementation of the QUIC transport protocol undergoing standardization by

null 2.6k Jan 8, 2023
A high-performance, lightweight, and cross-platform QUIC library

TQUIC English | δΈ­ζ–‡ TQUIC is a high-performance, lightweight, and cross-platform library for the IETF QUIC protocol. Advantages High performance: TQUIC

Tencent 11 Oct 27, 2023
neqo β€” an Implementation of QUIC written in Rust

Neqo, an Implementation of QUIC written in Rust To run test HTTP/3 programs (neqo-client and neqo-server): cargo build ./target/debug/neqo-server [::]

Mozilla 1.6k Jan 7, 2023
An experimental HTTP server in Rust that supports HTTP/1.1, HTTP/2, and HTTP/3 over QUIC.

?? H123 An experimental HTTP server in Rust that supports HTTP/1.1, HTTP/2, and HTTP/3 over QUIC. Warning This is an experimental project and not inte

Naoki Ikeguchi 7 Dec 15, 2022
TCP is so widely used, however QUIC may have a better performance.

TCP is so widely used, however QUIC may have a better performance. For softwares which use protocols built on TCP, this program helps them take FULL advantage of QUIC.

zephyr 15 Jun 10, 2022
MQTT over QUIC

MQuicTT ?? This is a pre-alpha project, tread carefully ?? A rustlang utility/library for MQTT over QUIC. QUIC allows us to send data over multiple co

null 29 Dec 16, 2022
A minimalistic encryption protocol for rust async streams/packets, based on noise protocol and snow.

Snowstorm A minimalistic encryption protocol for rust async streams / packets, based on noise protocol and snow. Quickstart Snowstorm allows you to se

Black Binary 19 Nov 22, 2022
BitTorrent peer ID registry/parser/(soon) encoder for Rust

BitTorrent peer ID registry/parser/(soon) encoder By convention, BitTorrent clients identify themselves and their versions in peer IDs they send to tr

TORRENTDYNE 3 Oct 16, 2023