Skip to content
This repository has been archived by the owner on Mar 9, 2022. It is now read-only.

feat: Swarm.RelayService (circuit v2) #146

Merged
merged 10 commits into from
Nov 13, 2021
Merged

feat: Swarm.RelayService (circuit v2) #146

merged 10 commits into from
Nov 13, 2021

Conversation

marten-seemann
Copy link
Member

@marten-seemann marten-seemann commented Oct 17, 2021

@vyzo
Copy link
Contributor

vyzo commented Oct 17, 2021

Yeah, let's have the struct wholesale. Can we use the actual type directly?

swarm.go Outdated Show resolved Hide resolved
@marten-seemann marten-seemann force-pushed the circuit-v2 branch 2 times, most recently from 1338050 to 6487ed0 Compare October 17, 2021 14:43
@marten-seemann
Copy link
Member Author

Yeah, let's have the struct wholesale. Can we use the actual type directly?

Two problems:

  • we need to embed the RelayLimit in the Resources struct. That's easy.
  • we need to find a solution for the time.Duration, otherwise users will have to enter durations in nanoseconds

Do we have any good solution for dealing with JSON marshaling of time.Durations?

@vyzo
Copy link
Contributor

vyzo commented Oct 17, 2021 via email

@marten-seemann
Copy link
Member Author

perhaps we can define a json marshaller for the limit struct?

The RelayLimit is not a problem. We can just embed it in the struct, and we'll be fine (we lose the ability to compare to nil, but we can just add a IsZero method).
The problem here is the time.Duration. If we want a custom marshaller for that, we have define our own Duration type, something like in https://stackoverflow.com/questions/48050945/how-to-unmarshal-json-into-durations.

@marten-seemann
Copy link
Member Author

The problem here is the time.Duration. If we want a custom marshaller for that, we have define our own Duration type, something like in https://stackoverflow.com/questions/48050945/how-to-unmarshal-json-into-durations.

Actually, we don't, we could do something like this: https://penkovski.com/post/go-unmarshal-custom-types/. Still wondering if it wouldn't be easier to just define a new config struct here...

@vyzo
Copy link
Contributor

vyzo commented Oct 17, 2021 via email

@aschmahmann
Copy link
Contributor

aschmahmann commented Oct 17, 2021

we need to find a solution for the time.Duration, otherwise users will have to enter durations in nanoseconds

This seems to already be done in

type Duration time.Duration
and used by
Interval Duration `json:",omitempty"`

We also have some older examples like

RepublishPeriod string
RecordLifetime string
that are parsed manually in go-ipfs and could probably be switched over.

Side note: When this PR is ready for review/merging please tag me or one of the other go-ipfs stewards.

@marten-seemann
Copy link
Member Author

we need to find a solution for the time.Duration, otherwise users will have to enter durations in nanoseconds

This seems to already be done in

type Duration time.Duration

and used by

Interval Duration `json:",omitempty"`

That's awesome! That's exactly what I was looking for!

@marten-seemann
Copy link
Member Author

How do we usually deal with default values. Currently, this is what ends up in the JSON:

{
  "AddrFilters": null,
  "DisableBandwidthMetrics": false,
  "DisableNatPortMap": false,
  "DisableRelayService": false,
  "RelayServiceOpts": {
    "Limit": {
      "Duration": "0s",
      "Data": 0
    },
    "ReservationTTL": "0s",
    "MaxReservations": 0,
    "MaxCircuits": 0,
    "BufferSize": 0,
    "MaxReservationsPerPeer": 0,
    "MaxReservationsPerIP": 0,
    "MaxReservationsPerASN": 0
  },
  "EnableAutoRelay": false,
  "Transports": {
    "Network": {},
    "Security": {},
    "Multiplexers": {}
  },
  "ConnMgr": {
    "Type": "basic",
    "LowWater": 600,
    "HighWater": 900,
    "GracePeriod": "20s"
  }
}

Is it ok to have all 0s there and use our default values (as defined in the circuit v2 implementation) if the user doesn't configure anything other?

@aschmahmann
Copy link
Contributor

How do we usually deal with default values

Usually is a strong word here 😄. There have been multiple approaches taken in the past and IMO it'd be nice to move towards a config file that's basically empty unless the user has made explicit modifications since it'll let us change the defaults within the client and the user will benefit from the changes without needing to mess with their config files or force us to make awkward decisions in a repo migration (e.g. did they set the value to X because they wanted to or because it was the default, how might they feel about us changing it to Y?).

Is it ok to have all 0s there and use our default values (as defined in the circuit v2 implementation) if the user doesn't configure anything other?

It can be ok, and we've done it in the past as long as we document the default values. For example, https://github.com/ipfs/go-ipfs/blob/master/docs/config.md#autonatthrottleinterval.

However, a better approach is probably to use some of our types here like https://github.com/ipfs/go-ipfs/blob/master/docs/config.md#optionalinteger so we can use JSON's sentinel values rather than defining them ourselves (e.g. "zero seems like a safe sentinel here, but not there" kinds of problems). If this doesn't cover a value then we can create or modifying one of the existing types.

We can also use "omit empty" on some of the structs if we think they're too gross/bothersome to expose to the user although it's use is situational since it's still at least a little nice to have an exposure point to users about a config option that isn't only in the doc.

Copy link
Contributor

@vyzo vyzo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. We should probably note the defaults in the documentation.

@BigLep BigLep linked an issue Oct 19, 2021 that may be closed by this pull request
@aschmahmann
Copy link
Contributor

Before merging this could we get a PR to go-ipfs that integrates the options and the modifies https://github.com/ipfs/go-ipfs/blob/master/docs/config.md?

Really these repos should be combined, so it's basically part of the same PR here.

@marten-seemann
Copy link
Member Author

Before merging this could we get a PR to go-ipfs that integrates the options and the modifies https://github.com/ipfs/go-ipfs/blob/master/docs/config.md?

Here's the PR that updates the docs, and uses the values read from the config to configure libp2p: ipfs/kubo#8522

swarm.go Outdated Show resolved Hide resolved
swarm.go Outdated Show resolved Hide resolved
lidel added a commit that referenced this pull request Oct 26, 2021
This enables us to swap defaults in go-ipfs without touching the config
file generated during `ipfs init`

#146 (comment)
#146 (comment)
@lidel lidel changed the title remove EnableRelayHop option, add an option to disable circuit v2 feat: replace EnableRelayHop with Swarm.RelayService (circuit v2) Oct 26, 2021
Copy link
Member

@lidel lidel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied the changes from the review so far (ipfs/kubo@8821d8b) and tested how it behaves with ipfs init and ipfs config in ipfs/kubo#8522

Remaining work here (I'll continue poking tomorrow):

marten-seemann pushed a commit that referenced this pull request Oct 27, 2021
This enables us to swap defaults in go-ipfs without touching the config
file generated during `ipfs init`

#146 (comment)
#146 (comment)
@marten-seemann
Copy link
Member Author

Rebased.

Note that we still need to change the OptionalInteger to deal with pointers, and then change all occurrences of OptionalInteger in the RelayService struct to pointers. I'll leave this to a later PR.

func (p OptionalInteger) WithDefault(defaultValue int64) (value int64) {
if p.value == nil {
func (p *OptionalInteger) WithDefault(defaultValue int64) (value int64) {
if p == nil || p.value == nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems redundant. I'd define the type as type OptionalInteger *int64.

Copy link
Member

@lidel lidel Oct 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be my lack of go skills, but I was unable to make that work with pointer type and have WithDefault that pass this omitempty unmarshal test. Go does not seem to allow methods on pointer types, I was getting invalid receiver type errors.

The nil check here feels safer than introducing some creative hackery with unsafe.Pointer.
Lmk if there is a simple way I don't see (otherwise will merge as-is, and we can refine this in the future).

@lidel lidel self-assigned this Oct 28, 2021
@lidel lidel changed the title feat: replace EnableRelayHop with Swarm.RelayService (circuit v2) feat: Swarm.RelayService (circuit v2) Oct 28, 2021
adds Internal.Libp2pForceReachability
needed for sharness tests in ipfs/kubo#8522

Co-authored-by: Marcin Rataj <lidel@lidel.org>
Copy link
Member

@lidel lidel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM.

  • Rebased this PR so it includes recent improvements around Optional.. fields
  • Switched WIP: update go-libp2p to v0.16.0 kubo#8522 to the latest revision here, so Libp2pForceReachability can be wired up for use in tests.

@marten-seemann when you are back, lmk if you plan to change anything config-wise here. If not, I'd like to squash and merge this and prep for the new go-ipfs-config release.

internal.go Show resolved Hide resolved
@marten-seemann
Copy link
Member Author

I'm going to merge this PR. We need more options for configuring static relays and to enable hole punching, but that's independent of (although dependent on) this change.

@marten-seemann marten-seemann merged commit a1583a3 into master Nov 13, 2021
@marten-seemann marten-seemann deleted the circuit-v2 branch November 13, 2021 11:07
@aschmahmann aschmahmann mentioned this pull request Dec 1, 2021
80 tasks
laurentsenta pushed a commit to laurentsenta/kubo that referenced this pull request Feb 25, 2022
* remove the EnableRelayHop option in the SwarmConfig

* add an option to disable the limited relay

* make the relay service resources configurable

* refactor: use custom types

This enables us to swap defaults in go-ipfs without touching the config
file generated during `ipfs init`

ipfs/go-ipfs-config#146 (comment)
ipfs/go-ipfs-config#146 (comment)

* use OptionalDuration in RelayService configuration

* fix: *OptionalInteger with omitempty

This removes null values from the config

* fix: Flag does not need to be a pointer

* refactor: flatten RelayService limits

this simplifies consumer code and removes nil footgun

* docs: clarify different relay types

* feat: flag for ForceReachability mode in libp2p (ipfs#150)

adds Internal.Libp2pForceReachability
needed for sharness tests in ipfs#8522

Co-authored-by: Marcin Rataj <lidel@lidel.org>

Co-authored-by: Marcin Rataj <lidel@lidel.org>
laurentsenta pushed a commit to laurentsenta/kubo that referenced this pull request Feb 25, 2022
* remove the EnableRelayHop option in the SwarmConfig

* add an option to disable the limited relay

* make the relay service resources configurable

* refactor: use custom types

This enables us to swap defaults in go-ipfs without touching the config
file generated during `ipfs init`

ipfs/go-ipfs-config#146 (comment)
ipfs/go-ipfs-config#146 (comment)

* use OptionalDuration in RelayService configuration

* fix: *OptionalInteger with omitempty

This removes null values from the config

* fix: Flag does not need to be a pointer

* refactor: flatten RelayService limits

this simplifies consumer code and removes nil footgun

* docs: clarify different relay types

* feat: flag for ForceReachability mode in libp2p (ipfs#150)

adds Internal.Libp2pForceReachability
needed for sharness tests in ipfs#8522

Co-authored-by: Marcin Rataj <lidel@lidel.org>

Co-authored-by: Marcin Rataj <lidel@lidel.org>
laurentsenta pushed a commit to laurentsenta/kubo that referenced this pull request Mar 4, 2022
* remove the EnableRelayHop option in the SwarmConfig

* add an option to disable the limited relay

* make the relay service resources configurable

* refactor: use custom types

This enables us to swap defaults in go-ipfs without touching the config
file generated during `ipfs init`

ipfs/go-ipfs-config#146 (comment)
ipfs/go-ipfs-config#146 (comment)

* use OptionalDuration in RelayService configuration

* fix: *OptionalInteger with omitempty

This removes null values from the config

* fix: Flag does not need to be a pointer

* refactor: flatten RelayService limits

this simplifies consumer code and removes nil footgun

* docs: clarify different relay types

* feat: flag for ForceReachability mode in libp2p (ipfs#150)

adds Internal.Libp2pForceReachability
needed for sharness tests in ipfs#8522

Co-authored-by: Marcin Rataj <lidel@lidel.org>

Co-authored-by: Marcin Rataj <lidel@lidel.org>
laurentsenta pushed a commit to laurentsenta/kubo that referenced this pull request Mar 4, 2022
* remove the EnableRelayHop option in the SwarmConfig

* add an option to disable the limited relay

* make the relay service resources configurable

* refactor: use custom types

This enables us to swap defaults in go-ipfs without touching the config
file generated during `ipfs init`

ipfs/go-ipfs-config#146 (comment)
ipfs/go-ipfs-config#146 (comment)

* use OptionalDuration in RelayService configuration

* fix: *OptionalInteger with omitempty

This removes null values from the config

* fix: Flag does not need to be a pointer

* refactor: flatten RelayService limits

this simplifies consumer code and removes nil footgun

* docs: clarify different relay types

* feat: flag for ForceReachability mode in libp2p (ipfs#150)

adds Internal.Libp2pForceReachability
needed for sharness tests in ipfs#8522

Co-authored-by: Marcin Rataj <lidel@lidel.org>

Co-authored-by: Marcin Rataj <lidel@lidel.org>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
No open projects
Archived in project
Development

Successfully merging this pull request may close these issues.

libp2p v2 relay functionality is on by default and configurable
5 participants