Commit Graph

118 Commits

Author SHA1 Message Date
cloudhead 09a284f09c
node: Make fetch timeout configurable
When a fetch is user-requested, a timeout can be supplied that is passed
down to the worker.

When a fetch is service-requested, a default timeout is used.
2023-09-01 12:13:45 +02:00
cloudhead 593f576ab4
node: Fix flaky limitter test
Ensures the addresses are different.
2023-08-09 17:07:21 +02:00
cloudhead fae518bca2
node: Improve `rad node connect` feedback
Only return once the connection is established or failed.

It's still not perfect, as several failure scenarios are not handled,
but it's an improvement.
2023-08-09 12:49:15 +02:00
cloudhead fb4a4e0079
node: Implement token-bucket rate limitter
Limit gossip messages and inbound connections.
For now, we don't limit git fetches.
2023-08-09 12:41:21 +02:00
cloudhead 260b1a428c
node: Move `address` field out of `State`
We move the session address to the top-level struct, since it's needed
in a bunch of places. This change is required for the rate-limiting
code that is coming next.
2023-08-09 12:41:21 +02:00
Fintan Halpenny dfa7ba1df5
radicle: type safe tracking config
The tracking database can be opened in read-only or read-write
mode. Knowing which is being used is significant in concurrent
scenarios, e.g. it's safer to have a read-only handle on multiple
threads.

Provide static type information by signifying what kind of database
handle is being worked with, read or read-write.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-07-14 16:52:42 +02:00
Alexis Sellier eb701be033
node: Make node aliases required
This is a fairly substantial change, which adds a new configuration file
to the user's `$RAD_HOME` that includes node configuration, including
the alias, and also makes node aliases required.

When running `rad auth`, the user is now prompted for an alias, which
defaults to `$USER`.

When running `rad self`, the alias is now shown.

If the user runs radicle without a config file, the defaults are loaded,
and `$USER` is used as the alias.
2023-07-11 18:08:59 +02:00
xphoniex ff81b1a6ed
node: Use `str::trim_end_matches` for stripping '\0' in alias
Signed-off-by: xphoniex <dj.2dixx@gmail.com>
2023-07-10 16:36:15 +02:00
Alexis Sellier 1a1e63d998
node: Implement `sessions` command
Returns session information through the control socket.

We also update `rad node status` to display sessions.
2023-07-04 00:26:31 +02:00
Alexis Sellier 5502676aa7
Fixes and improvements to alias handling
* Return the correct alias from a node announcement, stripping '\0'
  bytes.
* Accept `AliasStore` types as references and as owned.
* Store a `null` in the database if the alias received is empty.
2023-06-13 11:09:42 +02:00
Alexis Sellier ff7338de17
node: Always send node announcement on handshake
Previously, we only sent the announcement when there were external
addresses. But it contains other information like the node alias,
therefore we always send it.

Since the proof-of-work can be expensive to compute everytime, we add
the ability to load the local node announcement from the file system.

We also change the proof-of-work parameters so that they are relaxed
when running in debug mode, instead of when running tests.

Finally, we remove the boolean validation of the PoW. Instead, we store
the work per-node, in the database, to be used in the future in case of
DoS attacks or network congestion.
2023-06-07 11:39:23 +02:00
xphoniex 35ce6663c1
node: Add `--alias` option to node
Signed-off-by: xphoniex <dj.2dixx@gmail.com>
2023-05-10 17:03:42 +02:00
Alexis Sellier 1d9ee81b6d
node: Rename `reactor` module to `io`
The name was always confusing and didn't mean much in the contetx of the
service.
2023-05-08 19:31:20 +02:00
Alexis Sellier ca0abc4356
node: Keep track of connection attempts
When attempting to connect to a peer, and when succeeding, write the timestamp
to the database.

This will allow us to better select addresses and not retry peers to
soon.
2023-05-05 17:23:52 +02:00
Alexis Sellier df25e9a2a5
radicle: Fix unverified `Remote::new` constructor
We were allowing remotes to be constructed via a function that didn't
check its inputs.

This is now fixed by moving the public key into the `SignedRefs` struct.
2023-04-26 10:57:26 +02:00
Alexis Sellier 045d201916
node: Fix log pluralization 2023-04-25 12:47:36 +02:00
Alexis Sellier 671c169244
node: Implement `rad sync` command
This command announces refs to peers and waits for them to be
in sync.

Adds a subscribe method to `Handle` so that we can get the events
from the seed to allow us to confirm that the configured seeds fetched
from us.
2023-04-24 11:39:37 +02:00
Alexis Sellier 26ee6d26dc
node: Reduce log messages when sending messages 2023-04-20 16:32:41 +02:00
Alexis Sellier 9120db4ddb
node: Reduce log verbosity when receiving messages 2023-04-20 16:32:41 +02:00
Alexis Sellier bb07e25571
node: Emit event when refs are synced
This will help us give the user feedback when he pushes.
2023-04-17 16:18:34 +02:00
Alexis Sellier 8c92282578
node: Fix some error messages
A "block" policy doesn't necessarily mean an active block.
2023-04-14 13:55:22 +02:00
Alexis Sellier f4257eb953
node: Add setting for limiting fetch concurrency
Can be passed via `--limit-fetch-concurrency <num>`.
2023-04-14 13:15:52 +02:00
Alexis Sellier 89b9eb53b7
node: Implement protocol multiplexing
To improve the reliability and flexibility of the protocol, we introduce
multiplexing over peer connections. This involves a new `Frame` type
that carries a stream-id and payload.

Three stream types are made available:

1. Control
2. Gossip
3. Git

This change brings the following improvements:

* Removed need to queue fetch requests
* Removed need to queue gossip messages
* Removed need for `Fetch` and `FetchOk` messages
* Service doesn't need to know about inbound fetches
* Removed one round-trip for fetch negotiation
* Removed special `done` git packet
* Removed session logic and state around Git/Fetch protocols
* Removed code around upgrading/downgrading transport
* Worker in responder mode is able to process any number of fetches
* Connections support any number of concurrent fetches

We had to introduce a few extra things however to make it all work:

* A `VarInt` type for variable-length integers, since we want the frames
  to be lightweight.
* A custom "tunnel" implementation, since we couldn't use the existing
  one anymore.

Overall the change removes more complexity than it adds, while improving
the protocol along the way.
2023-04-10 14:41:55 +02:00
Fintan Halpenny c618c3e443
node: remove Namespaces::One
The One variant caused many paint points for fetching logic, where it
was not necessary. It was only constructed in one place, which could
be replaced by using the variant that holds a set of keys.

Remove the Namespaces::One variant and rename Namespaces::Many to
Namespaces::Trusted.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-03-31 12:23:32 +01:00
Fintan Halpenny adf6312a55
node: fetch trusted peers on clone
When a repository does not yet exist during a fetch, i.e. a clone,
then only delegates are being fetched.

Augment Namespaces::Many to hold the trusted and optional delegate peers
separately. Doing so allows the construction of the variant without
the repository existing, but tracking relationships existing.

This variant can then be used to build refspecs for both the trusted
peers and delegates when doing a cloning fetch.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-03-31 12:23:31 +01:00
Alexis Sellier fe8953ab8b
node: Don't penalize peer for protocol mismatch
Instead of returning a non-transient disconnect reason, return
a transient one, since protocol mismatches can happen.
2023-03-24 13:23:43 +01:00
Alexis Sellier d3f4189324
node: Fix reconnection logic
First, we make sure to always attempt reconnection to persistent peers,
no matter the reason.

Second, we don't re-attempt connections when an inbound peer
disconnects. This minimizes the chance of connections crossing.

Third, we clean up `session::Error`, and don't use it to signal a
missing session, since it doesn't really belong there.
2023-03-24 13:20:34 +01:00
Han Xu 241c41a632
node: Queue pending fetches in Session
Pending fetches are drained one at a time after the previous fetch is
completed.

Signed-off-by: Han Xu <keepsimple@gmail.com>
2023-03-22 08:46:27 +01:00
Alexis Sellier ed1120f3eb
node: Don't relay redundant gossip messages
This change ensures that on `Subscribe`, we only relay the latest
announcement of each node, per announcement category.

Previously, we would relay all announcement, while only the last one
was relevant.
2023-03-17 17:10:10 +01:00
xphoniex a49eec9892
node: Add eventing system to `Handler` and `Service`
Signed-off-by: xphoniex <dj.2dixx@gmail.com>
2023-03-16 22:26:57 +01:00
Alexis Sellier ebfd445034
node: Use correct scope when getting namespaces
We were using the default scope instead of the entry scope.
2023-03-16 15:38:05 +01:00
Alexis Sellier 5828b917f9
node: Fail fast when repository can't be read
It's not a good idea to have fallible operations run after `FetchOk`
is received, since there's no easy way to communicate the error
to the remote at that point. What would then happen is that the fetch
just "hangs", since nothing is there to cancel it.

Hence, we compute namespaces earlier in the process, and store the
namespaces in the session. If there is a failure, the fetch is
never initiated.
2023-03-15 16:22:43 +01:00
Alexis Sellier 40c58b45ed
node: Move `routing` to `radicle` crate 2023-03-15 12:59:49 +01:00
Alexis Sellier b558c742e6
node: Rename `repo_entries` to `repo_policies`
Do the same thing for `node_entries` etc.
2023-03-15 12:59:49 +01:00
Alexis Sellier cf8113765c
node: Move tracking store to `radicle` crate 2023-03-15 12:59:49 +01:00
Alexis Sellier cd12741bf2
node: Prevent redundant [re-]connections
It was possible to trigger multiple connection attempts to the same
peer, since we didn't track connection attempts that hadn't yet
returned to the service via `Service::attempted`.

With this change, we add an extra `Initial` state to sessions, so
that redundant connections are not attempted when one is already under
way.
2023-03-14 13:42:59 +01:00
Alexis Sellier 413238a1e0
node: Implement exponential back-off for reconnect
Instead of immediately attempting reconnection when a persistent
peer disconnects, wait some amount of time, increasing on every
attempt.
2023-03-13 17:43:49 +01:00
Alexis Sellier db38f2df76
node: Handle `FetchOk` never being received
It's possible for a peer to disconnect before responding with `FetchOk`.
In that case, we make sure to return to any pending fetch request with
an error.
2023-03-08 16:22:42 +01:00
Fintan Halpenny 1e8f5b2259
node: determine fetching namespace based on repo policy
To determine the correct Namespaces to use, the repo Policy and Scope
are consulted.

If the policy is Block then this is a failure state and is reported to
the other end.

Otherwise, if the policy is Track, then the scope is checked. For the
Trusted Scope then the Namespaces should consist of all tracked nodes
and delegates for the given repository. However, the repository might
not exist and so it is necessary for the whole repository to be
fetched.

For the All Scope, all Namespaces are fetched.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-03-08 11:33:41 +00:00
Fintan Halpenny e937cdd79a
node: improve fetch
The fetch implementation will potentially fetch the local operator's
remote, which is unnecessary and could result in deleted data.

Fix this by threading the local operator's public key and add an
ignore refspec to the fetch arguments, i.e.

    ^refs/namespaces/<local>/*

The implementation also strictly fetches all or one namespace. This is
improved upon by introducing a new variant for specifying a set of
namespaces.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-03-08 11:29:34 +00:00
Fintan Halpenny 546b402467
node: return full tracking policy
Instead of returning tuples for `repo_entry` and `node_entry`, return
the `Repo` and `Node` types, respectively.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-03-08 11:29:34 +00:00
Fintan Halpenny b82584617b
node: store Scope in tracking config
The tracking configuration has no way of consulting for a configured
scope.

This change allows the storing of this scope inside the tracking
`Config` -- currently unused.

The default Scope is chosen as Trusted, so that nodes do not
implicitly track any other node. If this behaviour is desired -- for
example, for seed nodes -- then All should be chosen.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-03-08 11:29:34 +00:00
Fintan Halpenny 5902236d0a
radicle: remove DelegatesOnly scope
The DelegatesOnly scope is very limited and causes more confusion than
it solves.

The Trusted scope subsumes DelegatesOnly since it implies delegates
along with any tracked nodes. This feels more natural to use and so
DelegatesOnly is removed -- leaving only Trusted and All.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-03-08 11:29:34 +00:00
Fintan Halpenny 39be7db1e9
radicle: make alias optional
Previously the alias field was simply a string which could possibly be
empty. Some checks were made to see if this string was empty.

Instead, make the logic more obvious by making the alias field
optional.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-03-08 11:29:34 +00:00
Fintan Halpenny e408b0d62c
node: use enum for fetch direction
A fetch is a client-server interaction and so there are two sides to
this interaction. These sides are generally referred to as receive --
the client side -- and upload -- the server side.

The `Fetch` type indicated whether it was doing a receive or upload by
using a field `initiated: bool`. However, this can be confusing when
you pair it with the `namespaces: Namespaces` field, since only the
receive side should be sending what refspecs it wants and the upload
side responds with those matching refspecs.

A better way to represent this is using an enum for which direction
the fetch is being considered, where the receive side contains the
Namespaces. To borrow from Noise, the variant names are 'Initiator'
for the client and 'Responder' for the server.

The resulting code then makes decisions based on what variant of the
enum was passed.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-03-08 10:12:54 +00:00
Alexis Sellier c3a5aced07
node: Handle case of crossing fetch requests
It is possible for a pair of nodes to concurrently ask each other
to fetch some repo. These "crossing" requests are problematic,
because the nodes end up waiting for each other to reply, and
the reply never comes.

With this change, the node pair agrees on proceeding with one of
the fetches, while canceling the other.
2023-03-07 16:22:22 +01:00
Fintan Halpenny 1f837c6572
node: implement tracking and routing
The routing function for Node was not implemented and there were no
functions for getting any tracking information.

This implements routing, tracked_repos, and tracked_nodes. To
accomplish this it was necessary to add associated types to the
Handler trait so that implementations could differ in the types they
use for returning this data, i.e. the control socket needs to use a
channel while the Node needs to return serializable data.

Currently, the Node uses a `Vec` but it would be more beneficial to
return an Iterator directly to ensure we are not always hitting the
heap.

To allow for the tracking types to be used across radicle-node (the
crate) and in radicle::node (the module), it was necessary to move
the types to the common place, i.e. radicle::node. At the same time,
new structs were added to make it easier to refer to tracked repos vs
tracked nodes.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-03-07 15:38:41 +01:00
Alexis Sellier 85df613682
cli: Implement automatic issue announcement 2023-03-07 08:40:20 +01:00
Fintan Halpenny c70dc71b18
node: improve seeds information
Previously, the seeds information would only consist of the connected
NodeIds.

Improve on this by adding any disconnected and fetching seeds as
well. A seed can either be disconnected, connected, or fetching --
where fetching implies connected.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2023-02-27 17:48:11 +01:00
Alexis Sellier 11da344e3a
node: Add `--tracking-policy` flag
Sets the default tracking policy.
2023-02-27 13:46:40 +01:00