diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000000..1ba3fd8360
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,8 @@
+blank_issues_enabled: true
+contact_links:
+ - name: Technical Questions
+ url: https://github.com/libp2p/go-libp2p/discussions/new?category=q-a
+ about: Please ask technical questions in the go-libp2p Github Discusions forum.
+ - name: Community-wide libp2p Discussion
+ url: https://discuss.libp2p.io
+ about: Discussions and questions about the libp2p community.
diff --git a/.github/workflows/go-check.yml b/.github/workflows/go-check.yml
index c469d49133..09ee2fc9ce 100644
--- a/.github/workflows/go-check.yml
+++ b/.github/workflows/go-check.yml
@@ -16,3 +16,5 @@ concurrency:
jobs:
go-check:
uses: pl-strflt/uci/.github/workflows/go-check.yml@v0.0
+ with:
+ go-generate-ignore-protoc-version-comments: true
diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml
index 1907fa24c9..452137ac21 100644
--- a/.github/workflows/go-test.yml
+++ b/.github/workflows/go-test.yml
@@ -17,4 +17,4 @@ jobs:
go-test:
uses: libp2p/uci/.github/workflows/go-test.yml@v0.0
with:
- go-versions: '["1.20.x","1.21.x"]'
+ go-versions: '["1.21.x", "1.22.x"]'
diff --git a/.github/workflows/interop-test.yml b/.github/workflows/interop-test.yml
index 606f0fe0bf..f32055344c 100644
--- a/.github/workflows/interop-test.yml
+++ b/.github/workflows/interop-test.yml
@@ -19,14 +19,14 @@ on:
- 'test-plans/**'
jobs:
- run-multidim-interop:
- name: Run multidimensional interoperability tests
+ run-transport-interop:
+ name: Run transport interoperability tests
runs-on: ${{ fromJSON(vars['INTEROP_TEST_RUNNER_UBUNTU'] || '"ubuntu-22.04"') }}
steps:
- uses: actions/checkout@v3
- name: Build image
run: docker build -t go-libp2p-head -f test-plans/PingDockerfile .
- - uses: libp2p/test-plans/.github/actions/run-interop-ping-test@master
+ - uses: libp2p/test-plans/.github/actions/run-transport-interop-test@master
with:
test-filter: go-libp2p-head
extra-versions: ${{ github.workspace }}/test-plans/ping-version.json
diff --git a/README.md b/README.md
index 7a95a13705..960d89e4f8 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-
+
The Go implementation of the libp2p Networking Stack.
@@ -83,7 +83,7 @@ There's a few things you can do right now to help out:
## Supported Go Versions
We test against and support the two most recent major releases of Go. This is
-informed by Go's own [security policy](https://go.dev/security).
+informed by Go's own [security policy](https://go.dev/doc/security/policy).
# Notable Users
Some notable users of go-libp2p are:
diff --git a/config/config.go b/config/config.go
index 22e8688517..ff6fa765e3 100644
--- a/config/config.go
+++ b/config/config.go
@@ -27,6 +27,7 @@ import (
blankhost "github.com/libp2p/go-libp2p/p2p/host/blank"
"github.com/libp2p/go-libp2p/p2p/host/eventbus"
"github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem"
+ rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
routed "github.com/libp2p/go-libp2p/p2p/host/routed"
"github.com/libp2p/go-libp2p/p2p/net/swarm"
tptu "github.com/libp2p/go-libp2p/p2p/net/upgrader"
@@ -253,12 +254,13 @@ func (cfg *Config) addTransports() ([]fx.Option, error) {
}
fxopts = append(fxopts, fx.Provide(PrivKeyToStatelessResetKey))
+ fxopts = append(fxopts, fx.Provide(PrivKeyToTokenGeneratorKey))
if cfg.QUICReuse != nil {
fxopts = append(fxopts, cfg.QUICReuse...)
} else {
fxopts = append(fxopts,
- fx.Provide(func(key quic.StatelessResetKey, _ *swarm.Swarm, lifecycle fx.Lifecycle) (*quicreuse.ConnManager, error) {
- cm, err := quicreuse.NewConnManager(key)
+ fx.Provide(func(key quic.StatelessResetKey, tokenGenerator quic.TokenGeneratorKey, _ *swarm.Swarm, lifecycle fx.Lifecycle) (*quicreuse.ConnManager, error) {
+ cm, err := quicreuse.NewConnManager(key, tokenGenerator)
if err != nil {
return nil, err
}
@@ -326,6 +328,19 @@ func (cfg *Config) NewNode() (host.Host, error) {
if cfg.EnableAutoRelay && !cfg.Relay {
return nil, fmt.Errorf("cannot enable autorelay; relay is not enabled")
}
+ // If possible check that the resource manager conn limit is higher than the
+ // limit set in the conn manager.
+ if l, ok := cfg.ResourceManager.(connmgr.GetConnLimiter); ok {
+ err := cfg.ConnManager.CheckLimit(l)
+ if err != nil {
+ log.Warn(fmt.Sprintf("rcmgr limit conflicts with connmgr limit: %v", err))
+ }
+ }
+
+ if !cfg.DisableMetrics {
+ rcmgr.MustRegisterWith(cfg.PrometheusRegisterer)
+ }
+
fxopts := []fx.Option{
fx.Provide(func() event.Bus {
return eventbus.NewBus(eventbus.WithMetricsTracer(eventbus.NewMetricsTracer(eventbus.WithRegisterer(cfg.PrometheusRegisterer))))
@@ -348,7 +363,9 @@ func (cfg *Config) NewNode() (host.Host, error) {
// should probably fail if listening on *any* addr fails.
return sw.Listen(cfg.ListenAddrs...)
},
- OnStop: func(context.Context) error { return sw.Close() },
+ OnStop: func(context.Context) error {
+ return sw.Close()
+ },
})
return sw
}),
@@ -379,12 +396,15 @@ func (cfg *Config) NewNode() (host.Host, error) {
// Note: h.AddrsFactory may be changed by relayFinder, but non-relay version is
// used by AutoNAT below.
if cfg.EnableAutoRelay {
- mt := autorelay.WithMetricsTracer(autorelay.NewMetricsTracer(autorelay.WithRegisterer(cfg.PrometheusRegisterer)))
- mtOpts := []autorelay.Option{mt}
- autoRelayOpts := append(mtOpts, cfg.AutoRelayOpts...)
+ if !cfg.DisableMetrics {
+ mt := autorelay.WithMetricsTracer(
+ autorelay.NewMetricsTracer(autorelay.WithRegisterer(cfg.PrometheusRegisterer)))
+ mtOpts := []autorelay.Option{mt}
+ cfg.AutoRelayOpts = append(mtOpts, cfg.AutoRelayOpts...)
+ }
fxopts = append(fxopts,
fx.Invoke(func(h *bhost.BasicHost, lifecycle fx.Lifecycle) (*autorelay.AutoRelay, error) {
- ar, err := autorelay.NewAutoRelay(h, autoRelayOpts...)
+ ar, err := autorelay.NewAutoRelay(h, cfg.AutoRelayOpts...)
if err != nil {
return nil, err
}
diff --git a/config/quic_stateless_reset.go b/config/quic.go
similarity index 53%
rename from config/quic_stateless_reset.go
rename to config/quic.go
index a12be56f5b..66c40da97f 100644
--- a/config/quic_stateless_reset.go
+++ b/config/quic.go
@@ -11,7 +11,10 @@ import (
"github.com/quic-go/quic-go"
)
-const statelessResetKeyInfo = "libp2p quic stateless reset key"
+const (
+ statelessResetKeyInfo = "libp2p quic stateless reset key"
+ tokenGeneratorKeyInfo = "libp2p quic token generator key"
+)
func PrivKeyToStatelessResetKey(key crypto.PrivKey) (quic.StatelessResetKey, error) {
var statelessResetKey quic.StatelessResetKey
@@ -25,3 +28,16 @@ func PrivKeyToStatelessResetKey(key crypto.PrivKey) (quic.StatelessResetKey, err
}
return statelessResetKey, nil
}
+
+func PrivKeyToTokenGeneratorKey(key crypto.PrivKey) (quic.TokenGeneratorKey, error) {
+ var tokenKey quic.TokenGeneratorKey
+ keyBytes, err := key.Raw()
+ if err != nil {
+ return tokenKey, err
+ }
+ keyReader := hkdf.New(sha256.New, keyBytes, nil, []byte(tokenGeneratorKeyInfo))
+ if _, err := io.ReadFull(keyReader, tokenKey[:]); err != nil {
+ return tokenKey, err
+ }
+ return tokenKey, nil
+}
diff --git a/core/connmgr/manager.go b/core/connmgr/manager.go
index e0d6c52012..d756e4399f 100644
--- a/core/connmgr/manager.go
+++ b/core/connmgr/manager.go
@@ -74,6 +74,10 @@ type ConnManager interface {
// then it will return true if the peer is protected for any tag
IsProtected(id peer.ID, tag string) (protected bool)
+ // CheckLimit will return an error if the connection manager's internal
+ // connection limit exceeds the provided system limit.
+ CheckLimit(l GetConnLimiter) error
+
// Close closes the connection manager and stops background processes.
Close() error
}
@@ -89,3 +93,9 @@ type TagInfo struct {
// Conns maps connection ids (such as remote multiaddr) to their creation time.
Conns map[string]time.Time
}
+
+// GetConnLimiter provides access to a component's total connection limit.
+type GetConnLimiter interface {
+ // GetConnLimit returns the total connection limit of the implementing component.
+ GetConnLimit() int
+}
diff --git a/core/connmgr/null.go b/core/connmgr/null.go
index 25743f4ec7..735411712a 100644
--- a/core/connmgr/null.go
+++ b/core/connmgr/null.go
@@ -21,4 +21,5 @@ func (NullConnMgr) Notifee() network.Notifiee { return network.Gl
func (NullConnMgr) Protect(peer.ID, string) {}
func (NullConnMgr) Unprotect(peer.ID, string) bool { return false }
func (NullConnMgr) IsProtected(peer.ID, string) bool { return false }
+func (NullConnMgr) CheckLimit(l GetConnLimiter) error { return nil }
func (NullConnMgr) Close() error { return nil }
diff --git a/core/crypto/ecdsa.go b/core/crypto/ecdsa.go
index 8e392c9ed9..c890afe836 100644
--- a/core/crypto/ecdsa.go
+++ b/core/crypto/ecdsa.go
@@ -4,6 +4,7 @@ import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
+ "crypto/sha256"
"crypto/x509"
"encoding/asn1"
"errors"
@@ -12,7 +13,6 @@ import (
pb "github.com/libp2p/go-libp2p/core/crypto/pb"
"github.com/libp2p/go-libp2p/core/internal/catch"
- "github.com/libp2p/go-libp2p/internal/sha256"
)
// ECDSAPrivateKey is an implementation of an ECDSA private key
diff --git a/core/crypto/ecdsa_test.go b/core/crypto/ecdsa_test.go
index cc75d5740a..6e4720d7c2 100644
--- a/core/crypto/ecdsa_test.go
+++ b/core/crypto/ecdsa_test.go
@@ -25,7 +25,7 @@ func TestECDSABasicSignAndVerify(t *testing.T) {
}
if !ok {
- t.Fatal("signature didnt match")
+ t.Fatal("signature didn't match")
}
// change data
diff --git a/core/crypto/key.go b/core/crypto/key.go
index 3652c3cde0..6725188d75 100644
--- a/core/crypto/key.go
+++ b/core/crypto/key.go
@@ -4,12 +4,10 @@
package crypto
import (
- "crypto/elliptic"
"crypto/rand"
"crypto/subtle"
"encoding/base64"
"errors"
- "fmt"
"io"
"github.com/libp2p/go-libp2p/core/crypto/pb"
@@ -122,51 +120,6 @@ func GenerateKeyPairWithReader(typ, bits int, src io.Reader) (PrivKey, PubKey, e
}
}
-// GenerateEKeyPair returns an ephemeral public key and returns a function that will compute
-// the shared secret key. Used in the identify module.
-//
-// Focuses only on ECDH now, but can be made more general in the future.
-func GenerateEKeyPair(curveName string) ([]byte, GenSharedKey, error) {
- var curve elliptic.Curve
-
- switch curveName {
- case "P-256":
- curve = elliptic.P256()
- case "P-384":
- curve = elliptic.P384()
- case "P-521":
- curve = elliptic.P521()
- default:
- return nil, nil, fmt.Errorf("unknown curve name")
- }
-
- priv, x, y, err := elliptic.GenerateKey(curve, rand.Reader)
- if err != nil {
- return nil, nil, err
- }
-
- pubKey := elliptic.Marshal(curve, x, y)
-
- done := func(theirPub []byte) ([]byte, error) {
- // Verify and unpack node's public key.
- x, y := elliptic.Unmarshal(curve, theirPub)
- if x == nil {
- return nil, fmt.Errorf("malformed public key: %d %v", len(theirPub), theirPub)
- }
-
- if !curve.IsOnCurve(x, y) {
- return nil, errors.New("invalid public key")
- }
-
- // Generate shared secret.
- secret, _ := curve.ScalarMult(x, y, priv)
-
- return secret.Bytes(), nil
- }
-
- return pubKey, done, nil
-}
-
// UnmarshalPublicKey converts a protobuf serialized public key into its
// representative object
func UnmarshalPublicKey(data []byte) (PubKey, error) {
diff --git a/core/crypto/key_test.go b/core/crypto/key_test.go
index 44d8b16915..efd8ed5149 100644
--- a/core/crypto/key_test.go
+++ b/core/crypto/key_test.go
@@ -8,6 +8,7 @@ import (
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
+ "crypto/sha256"
"crypto/x509"
"fmt"
"reflect"
@@ -16,7 +17,6 @@ import (
. "github.com/libp2p/go-libp2p/core/crypto"
pb "github.com/libp2p/go-libp2p/core/crypto/pb"
"github.com/libp2p/go-libp2p/core/test"
- "github.com/libp2p/go-libp2p/internal/sha256"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
secp256k1ecdsa "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
@@ -291,15 +291,3 @@ func testKeyEquals(t *testing.T, k Key) {
t.Fatal("Keys should not equal.")
}
}
-
-func TestUnknownCurveErrors(t *testing.T) {
- _, _, err := GenerateEKeyPair("P-256")
- if err != nil {
- t.Fatal(err)
- }
-
- _, _, err = GenerateEKeyPair("error-please")
- if err == nil {
- t.Fatal("expected invalid key type to error")
- }
-}
diff --git a/core/crypto/rsa_go.go b/core/crypto/rsa_go.go
index c955cf8e05..845dae926a 100644
--- a/core/crypto/rsa_go.go
+++ b/core/crypto/rsa_go.go
@@ -4,13 +4,13 @@ import (
"crypto"
"crypto/rand"
"crypto/rsa"
+ "crypto/sha256"
"crypto/x509"
"errors"
"io"
pb "github.com/libp2p/go-libp2p/core/crypto/pb"
"github.com/libp2p/go-libp2p/core/internal/catch"
- "github.com/libp2p/go-libp2p/internal/sha256"
)
// RsaPrivateKey is a rsa private key
diff --git a/core/crypto/rsa_test.go b/core/crypto/rsa_test.go
index f4a7971a59..dbc88dda25 100644
--- a/core/crypto/rsa_test.go
+++ b/core/crypto/rsa_test.go
@@ -24,7 +24,7 @@ func TestRSABasicSignAndVerify(t *testing.T) {
}
if !ok {
- t.Fatal("signature didnt match")
+ t.Fatal("signature didn't match")
}
// change data
diff --git a/core/crypto/secp256k1.go b/core/crypto/secp256k1.go
index bcd68ac6da..99e7464bc5 100644
--- a/core/crypto/secp256k1.go
+++ b/core/crypto/secp256k1.go
@@ -1,6 +1,7 @@
package crypto
import (
+ "crypto/sha256"
"fmt"
"io"
@@ -9,7 +10,6 @@ import (
"github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
- "github.com/libp2p/go-libp2p/internal/sha256"
)
// Secp256k1PrivateKey is a Secp256k1 private key
diff --git a/core/crypto/secp256k1_test.go b/core/crypto/secp256k1_test.go
index 81f2f57884..67bbe470b9 100644
--- a/core/crypto/secp256k1_test.go
+++ b/core/crypto/secp256k1_test.go
@@ -24,7 +24,7 @@ func TestSecp256k1BasicSignAndVerify(t *testing.T) {
}
if !ok {
- t.Fatal("signature didnt match")
+ t.Fatal("signature didn't match")
}
// change data
diff --git a/core/network/context_test.go b/core/network/context_test.go
index b12def5ef6..65a865498d 100644
--- a/core/network/context_test.go
+++ b/core/network/context_test.go
@@ -47,13 +47,13 @@ func TestSimultaneousConnect(t *testing.T) {
ok, isClient, reason := GetSimultaneousConnect(serverCtx)
require.True(t, ok)
require.False(t, isClient)
- require.Equal(t, reason, "foobar")
+ require.Equal(t, "foobar", reason)
})
t.Run("for the client", func(t *testing.T) {
serverCtx := WithSimultaneousConnect(context.Background(), true, "foo")
ok, isClient, reason := GetSimultaneousConnect(serverCtx)
require.True(t, ok)
require.True(t, isClient)
- require.Equal(t, reason, "foo")
+ require.Equal(t, "foo", reason)
})
}
diff --git a/core/network/mocks/mock_conn_management_scope.go b/core/network/mocks/mock_conn_management_scope.go
index 5d847f91ff..d6538e17a3 100644
--- a/core/network/mocks/mock_conn_management_scope.go
+++ b/core/network/mocks/mock_conn_management_scope.go
@@ -1,5 +1,10 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/libp2p/go-libp2p/core/network (interfaces: ConnManagementScope)
+//
+// Generated by this command:
+//
+// mockgen -package mocknetwork -destination mock_conn_management_scope.go github.com/libp2p/go-libp2p/core/network ConnManagementScope
+//
// Package mocknetwork is a generated GoMock package.
package mocknetwork
@@ -7,9 +12,9 @@ package mocknetwork
import (
reflect "reflect"
- gomock "github.com/golang/mock/gomock"
network "github.com/libp2p/go-libp2p/core/network"
peer "github.com/libp2p/go-libp2p/core/peer"
+ gomock "go.uber.org/mock/gomock"
)
// MockConnManagementScope is a mock of ConnManagementScope interface.
@@ -83,7 +88,7 @@ func (m *MockConnManagementScope) ReleaseMemory(arg0 int) {
}
// ReleaseMemory indicates an expected call of ReleaseMemory.
-func (mr *MockConnManagementScopeMockRecorder) ReleaseMemory(arg0 interface{}) *gomock.Call {
+func (mr *MockConnManagementScopeMockRecorder) ReleaseMemory(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReleaseMemory", reflect.TypeOf((*MockConnManagementScope)(nil).ReleaseMemory), arg0)
}
@@ -97,7 +102,7 @@ func (m *MockConnManagementScope) ReserveMemory(arg0 int, arg1 byte) error {
}
// ReserveMemory indicates an expected call of ReserveMemory.
-func (mr *MockConnManagementScopeMockRecorder) ReserveMemory(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockConnManagementScopeMockRecorder) ReserveMemory(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReserveMemory", reflect.TypeOf((*MockConnManagementScope)(nil).ReserveMemory), arg0, arg1)
}
@@ -111,7 +116,7 @@ func (m *MockConnManagementScope) SetPeer(arg0 peer.ID) error {
}
// SetPeer indicates an expected call of SetPeer.
-func (mr *MockConnManagementScopeMockRecorder) SetPeer(arg0 interface{}) *gomock.Call {
+func (mr *MockConnManagementScopeMockRecorder) SetPeer(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetPeer", reflect.TypeOf((*MockConnManagementScope)(nil).SetPeer), arg0)
}
diff --git a/core/network/mocks/mock_peer_scope.go b/core/network/mocks/mock_peer_scope.go
index 1633839993..325a894c2c 100644
--- a/core/network/mocks/mock_peer_scope.go
+++ b/core/network/mocks/mock_peer_scope.go
@@ -1,5 +1,10 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/libp2p/go-libp2p/core/network (interfaces: PeerScope)
+//
+// Generated by this command:
+//
+// mockgen -package mocknetwork -destination mock_peer_scope.go github.com/libp2p/go-libp2p/core/network PeerScope
+//
// Package mocknetwork is a generated GoMock package.
package mocknetwork
@@ -7,9 +12,9 @@ package mocknetwork
import (
reflect "reflect"
- gomock "github.com/golang/mock/gomock"
network "github.com/libp2p/go-libp2p/core/network"
peer "github.com/libp2p/go-libp2p/core/peer"
+ gomock "go.uber.org/mock/gomock"
)
// MockPeerScope is a mock of PeerScope interface.
@@ -71,7 +76,7 @@ func (m *MockPeerScope) ReleaseMemory(arg0 int) {
}
// ReleaseMemory indicates an expected call of ReleaseMemory.
-func (mr *MockPeerScopeMockRecorder) ReleaseMemory(arg0 interface{}) *gomock.Call {
+func (mr *MockPeerScopeMockRecorder) ReleaseMemory(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReleaseMemory", reflect.TypeOf((*MockPeerScope)(nil).ReleaseMemory), arg0)
}
@@ -85,7 +90,7 @@ func (m *MockPeerScope) ReserveMemory(arg0 int, arg1 byte) error {
}
// ReserveMemory indicates an expected call of ReserveMemory.
-func (mr *MockPeerScopeMockRecorder) ReserveMemory(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockPeerScopeMockRecorder) ReserveMemory(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReserveMemory", reflect.TypeOf((*MockPeerScope)(nil).ReserveMemory), arg0, arg1)
}
diff --git a/core/network/mocks/mock_protocol_scope.go b/core/network/mocks/mock_protocol_scope.go
index 646eede623..80d29676b9 100644
--- a/core/network/mocks/mock_protocol_scope.go
+++ b/core/network/mocks/mock_protocol_scope.go
@@ -1,5 +1,10 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/libp2p/go-libp2p/core/network (interfaces: ProtocolScope)
+//
+// Generated by this command:
+//
+// mockgen -package mocknetwork -destination mock_protocol_scope.go github.com/libp2p/go-libp2p/core/network ProtocolScope
+//
// Package mocknetwork is a generated GoMock package.
package mocknetwork
@@ -7,9 +12,9 @@ package mocknetwork
import (
reflect "reflect"
- gomock "github.com/golang/mock/gomock"
network "github.com/libp2p/go-libp2p/core/network"
protocol "github.com/libp2p/go-libp2p/core/protocol"
+ gomock "go.uber.org/mock/gomock"
)
// MockProtocolScope is a mock of ProtocolScope interface.
@@ -71,7 +76,7 @@ func (m *MockProtocolScope) ReleaseMemory(arg0 int) {
}
// ReleaseMemory indicates an expected call of ReleaseMemory.
-func (mr *MockProtocolScopeMockRecorder) ReleaseMemory(arg0 interface{}) *gomock.Call {
+func (mr *MockProtocolScopeMockRecorder) ReleaseMemory(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReleaseMemory", reflect.TypeOf((*MockProtocolScope)(nil).ReleaseMemory), arg0)
}
@@ -85,7 +90,7 @@ func (m *MockProtocolScope) ReserveMemory(arg0 int, arg1 byte) error {
}
// ReserveMemory indicates an expected call of ReserveMemory.
-func (mr *MockProtocolScopeMockRecorder) ReserveMemory(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockProtocolScopeMockRecorder) ReserveMemory(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReserveMemory", reflect.TypeOf((*MockProtocolScope)(nil).ReserveMemory), arg0, arg1)
}
diff --git a/core/network/mocks/mock_resource_manager.go b/core/network/mocks/mock_resource_manager.go
index dbf6219c38..98e186e1ff 100644
--- a/core/network/mocks/mock_resource_manager.go
+++ b/core/network/mocks/mock_resource_manager.go
@@ -1,5 +1,10 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/libp2p/go-libp2p/core/network (interfaces: ResourceManager)
+//
+// Generated by this command:
+//
+// mockgen -package mocknetwork -destination mock_resource_manager.go github.com/libp2p/go-libp2p/core/network ResourceManager
+//
// Package mocknetwork is a generated GoMock package.
package mocknetwork
@@ -7,11 +12,11 @@ package mocknetwork
import (
reflect "reflect"
- gomock "github.com/golang/mock/gomock"
network "github.com/libp2p/go-libp2p/core/network"
peer "github.com/libp2p/go-libp2p/core/peer"
protocol "github.com/libp2p/go-libp2p/core/protocol"
multiaddr "github.com/multiformats/go-multiaddr"
+ gomock "go.uber.org/mock/gomock"
)
// MockResourceManager is a mock of ResourceManager interface.
@@ -61,7 +66,7 @@ func (m *MockResourceManager) OpenConnection(arg0 network.Direction, arg1 bool,
}
// OpenConnection indicates an expected call of OpenConnection.
-func (mr *MockResourceManagerMockRecorder) OpenConnection(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockResourceManagerMockRecorder) OpenConnection(arg0, arg1, arg2 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OpenConnection", reflect.TypeOf((*MockResourceManager)(nil).OpenConnection), arg0, arg1, arg2)
}
@@ -76,7 +81,7 @@ func (m *MockResourceManager) OpenStream(arg0 peer.ID, arg1 network.Direction) (
}
// OpenStream indicates an expected call of OpenStream.
-func (mr *MockResourceManagerMockRecorder) OpenStream(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockResourceManagerMockRecorder) OpenStream(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OpenStream", reflect.TypeOf((*MockResourceManager)(nil).OpenStream), arg0, arg1)
}
@@ -90,7 +95,7 @@ func (m *MockResourceManager) ViewPeer(arg0 peer.ID, arg1 func(network.PeerScope
}
// ViewPeer indicates an expected call of ViewPeer.
-func (mr *MockResourceManagerMockRecorder) ViewPeer(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockResourceManagerMockRecorder) ViewPeer(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ViewPeer", reflect.TypeOf((*MockResourceManager)(nil).ViewPeer), arg0, arg1)
}
@@ -104,7 +109,7 @@ func (m *MockResourceManager) ViewProtocol(arg0 protocol.ID, arg1 func(network.P
}
// ViewProtocol indicates an expected call of ViewProtocol.
-func (mr *MockResourceManagerMockRecorder) ViewProtocol(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockResourceManagerMockRecorder) ViewProtocol(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ViewProtocol", reflect.TypeOf((*MockResourceManager)(nil).ViewProtocol), arg0, arg1)
}
@@ -118,7 +123,7 @@ func (m *MockResourceManager) ViewService(arg0 string, arg1 func(network.Service
}
// ViewService indicates an expected call of ViewService.
-func (mr *MockResourceManagerMockRecorder) ViewService(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockResourceManagerMockRecorder) ViewService(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ViewService", reflect.TypeOf((*MockResourceManager)(nil).ViewService), arg0, arg1)
}
@@ -132,7 +137,7 @@ func (m *MockResourceManager) ViewSystem(arg0 func(network.ResourceScope) error)
}
// ViewSystem indicates an expected call of ViewSystem.
-func (mr *MockResourceManagerMockRecorder) ViewSystem(arg0 interface{}) *gomock.Call {
+func (mr *MockResourceManagerMockRecorder) ViewSystem(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ViewSystem", reflect.TypeOf((*MockResourceManager)(nil).ViewSystem), arg0)
}
@@ -146,7 +151,7 @@ func (m *MockResourceManager) ViewTransient(arg0 func(network.ResourceScope) err
}
// ViewTransient indicates an expected call of ViewTransient.
-func (mr *MockResourceManagerMockRecorder) ViewTransient(arg0 interface{}) *gomock.Call {
+func (mr *MockResourceManagerMockRecorder) ViewTransient(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ViewTransient", reflect.TypeOf((*MockResourceManager)(nil).ViewTransient), arg0)
}
diff --git a/core/network/mocks/mock_resource_scope_span.go b/core/network/mocks/mock_resource_scope_span.go
index ba9a4245db..5123ff8d75 100644
--- a/core/network/mocks/mock_resource_scope_span.go
+++ b/core/network/mocks/mock_resource_scope_span.go
@@ -1,5 +1,10 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/libp2p/go-libp2p/core/network (interfaces: ResourceScopeSpan)
+//
+// Generated by this command:
+//
+// mockgen -package mocknetwork -destination mock_resource_scope_span.go github.com/libp2p/go-libp2p/core/network ResourceScopeSpan
+//
// Package mocknetwork is a generated GoMock package.
package mocknetwork
@@ -7,8 +12,8 @@ package mocknetwork
import (
reflect "reflect"
- gomock "github.com/golang/mock/gomock"
network "github.com/libp2p/go-libp2p/core/network"
+ gomock "go.uber.org/mock/gomock"
)
// MockResourceScopeSpan is a mock of ResourceScopeSpan interface.
@@ -68,7 +73,7 @@ func (m *MockResourceScopeSpan) ReleaseMemory(arg0 int) {
}
// ReleaseMemory indicates an expected call of ReleaseMemory.
-func (mr *MockResourceScopeSpanMockRecorder) ReleaseMemory(arg0 interface{}) *gomock.Call {
+func (mr *MockResourceScopeSpanMockRecorder) ReleaseMemory(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReleaseMemory", reflect.TypeOf((*MockResourceScopeSpan)(nil).ReleaseMemory), arg0)
}
@@ -82,7 +87,7 @@ func (m *MockResourceScopeSpan) ReserveMemory(arg0 int, arg1 byte) error {
}
// ReserveMemory indicates an expected call of ReserveMemory.
-func (mr *MockResourceScopeSpanMockRecorder) ReserveMemory(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockResourceScopeSpanMockRecorder) ReserveMemory(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReserveMemory", reflect.TypeOf((*MockResourceScopeSpan)(nil).ReserveMemory), arg0, arg1)
}
diff --git a/core/network/mocks/mock_stream_management_scope.go b/core/network/mocks/mock_stream_management_scope.go
index 7dace90959..472eb7acb8 100644
--- a/core/network/mocks/mock_stream_management_scope.go
+++ b/core/network/mocks/mock_stream_management_scope.go
@@ -1,5 +1,10 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/libp2p/go-libp2p/core/network (interfaces: StreamManagementScope)
+//
+// Generated by this command:
+//
+// mockgen -package mocknetwork -destination mock_stream_management_scope.go github.com/libp2p/go-libp2p/core/network StreamManagementScope
+//
// Package mocknetwork is a generated GoMock package.
package mocknetwork
@@ -7,9 +12,9 @@ package mocknetwork
import (
reflect "reflect"
- gomock "github.com/golang/mock/gomock"
network "github.com/libp2p/go-libp2p/core/network"
protocol "github.com/libp2p/go-libp2p/core/protocol"
+ gomock "go.uber.org/mock/gomock"
)
// MockStreamManagementScope is a mock of StreamManagementScope interface.
@@ -97,7 +102,7 @@ func (m *MockStreamManagementScope) ReleaseMemory(arg0 int) {
}
// ReleaseMemory indicates an expected call of ReleaseMemory.
-func (mr *MockStreamManagementScopeMockRecorder) ReleaseMemory(arg0 interface{}) *gomock.Call {
+func (mr *MockStreamManagementScopeMockRecorder) ReleaseMemory(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReleaseMemory", reflect.TypeOf((*MockStreamManagementScope)(nil).ReleaseMemory), arg0)
}
@@ -111,7 +116,7 @@ func (m *MockStreamManagementScope) ReserveMemory(arg0 int, arg1 byte) error {
}
// ReserveMemory indicates an expected call of ReserveMemory.
-func (mr *MockStreamManagementScopeMockRecorder) ReserveMemory(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockStreamManagementScopeMockRecorder) ReserveMemory(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReserveMemory", reflect.TypeOf((*MockStreamManagementScope)(nil).ReserveMemory), arg0, arg1)
}
@@ -139,7 +144,7 @@ func (m *MockStreamManagementScope) SetProtocol(arg0 protocol.ID) error {
}
// SetProtocol indicates an expected call of SetProtocol.
-func (mr *MockStreamManagementScopeMockRecorder) SetProtocol(arg0 interface{}) *gomock.Call {
+func (mr *MockStreamManagementScopeMockRecorder) SetProtocol(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetProtocol", reflect.TypeOf((*MockStreamManagementScope)(nil).SetProtocol), arg0)
}
@@ -153,7 +158,7 @@ func (m *MockStreamManagementScope) SetService(arg0 string) error {
}
// SetService indicates an expected call of SetService.
-func (mr *MockStreamManagementScopeMockRecorder) SetService(arg0 interface{}) *gomock.Call {
+func (mr *MockStreamManagementScopeMockRecorder) SetService(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetService", reflect.TypeOf((*MockStreamManagementScope)(nil).SetService), arg0)
}
diff --git a/core/network/mocks/network.go b/core/network/mocks/network.go
index 6fe8e91736..73025bd288 100644
--- a/core/network/mocks/network.go
+++ b/core/network/mocks/network.go
@@ -1,8 +1,8 @@
package mocknetwork
-//go:generate sh -c "go run github.com/golang/mock/mockgen -package mocknetwork -destination mock_resource_manager.go github.com/libp2p/go-libp2p/core/network ResourceManager"
-//go:generate sh -c "go run github.com/golang/mock/mockgen -package mocknetwork -destination mock_conn_management_scope.go github.com/libp2p/go-libp2p/core/network ConnManagementScope"
-//go:generate sh -c "go run github.com/golang/mock/mockgen -package mocknetwork -destination mock_stream_management_scope.go github.com/libp2p/go-libp2p/core/network StreamManagementScope"
-//go:generate sh -c "go run github.com/golang/mock/mockgen -package mocknetwork -destination mock_peer_scope.go github.com/libp2p/go-libp2p/core/network PeerScope"
-//go:generate sh -c "go run github.com/golang/mock/mockgen -package mocknetwork -destination mock_protocol_scope.go github.com/libp2p/go-libp2p/core/network ProtocolScope"
-//go:generate sh -c "go run github.com/golang/mock/mockgen -package mocknetwork -destination mock_resource_scope_span.go github.com/libp2p/go-libp2p/core/network ResourceScopeSpan"
+//go:generate sh -c "go run go.uber.org/mock/mockgen -package mocknetwork -destination mock_resource_manager.go github.com/libp2p/go-libp2p/core/network ResourceManager"
+//go:generate sh -c "go run go.uber.org/mock/mockgen -package mocknetwork -destination mock_conn_management_scope.go github.com/libp2p/go-libp2p/core/network ConnManagementScope"
+//go:generate sh -c "go run go.uber.org/mock/mockgen -package mocknetwork -destination mock_stream_management_scope.go github.com/libp2p/go-libp2p/core/network StreamManagementScope"
+//go:generate sh -c "go run go.uber.org/mock/mockgen -package mocknetwork -destination mock_peer_scope.go github.com/libp2p/go-libp2p/core/network PeerScope"
+//go:generate sh -c "go run go.uber.org/mock/mockgen -package mocknetwork -destination mock_protocol_scope.go github.com/libp2p/go-libp2p/core/network ProtocolScope"
+//go:generate sh -c "go run go.uber.org/mock/mockgen -package mocknetwork -destination mock_resource_scope_span.go github.com/libp2p/go-libp2p/core/network ResourceScopeSpan"
diff --git a/core/peer/addrinfo.go b/core/peer/addrinfo.go
index fba4cfd0eb..de7dd4d989 100644
--- a/core/peer/addrinfo.go
+++ b/core/peer/addrinfo.go
@@ -86,7 +86,7 @@ func AddrInfoFromP2pAddr(m ma.Multiaddr) (*AddrInfo, error) {
// AddrInfoToP2pAddrs converts an AddrInfo to a list of Multiaddrs.
func AddrInfoToP2pAddrs(pi *AddrInfo) ([]ma.Multiaddr, error) {
- p2ppart, err := ma.NewComponent("p2p", Encode(pi.ID))
+ p2ppart, err := ma.NewComponent("p2p", pi.ID.String())
if err != nil {
return nil, err
}
@@ -102,7 +102,7 @@ func AddrInfoToP2pAddrs(pi *AddrInfo) ([]ma.Multiaddr, error) {
func (pi *AddrInfo) Loggable() map[string]interface{} {
return map[string]interface{}{
- "peerID": pi.ID.Pretty(),
+ "peerID": pi.ID.String(),
"addrs": pi.Addrs,
}
}
diff --git a/core/peer/addrinfo_test.go b/core/peer/addrinfo_test.go
index 9f18a8b603..3fd1556e6a 100644
--- a/core/peer/addrinfo_test.go
+++ b/core/peer/addrinfo_test.go
@@ -3,9 +3,9 @@ package peer_test
import (
"testing"
- ma "github.com/multiformats/go-multiaddr"
-
. "github.com/libp2p/go-libp2p/core/peer"
+
+ ma "github.com/multiformats/go-multiaddr"
)
var (
@@ -19,7 +19,7 @@ func init() {
if err != nil {
panic(err)
}
- maddrPeer = ma.StringCast("/p2p/" + Encode(testID))
+ maddrPeer = ma.StringCast("/p2p/" + testID.String())
maddrTpt = ma.StringCast("/ip4/127.0.0.1/tcp/1234")
maddrFull = maddrTpt.Encapsulate(maddrPeer)
}
@@ -115,7 +115,7 @@ func TestAddrInfosFromP2pAddrs(t *testing.T) {
t.Fatal(err)
}
for _, info := range infos {
- exaddrs, ok := expected[info.ID.Pretty()]
+ exaddrs, ok := expected[info.ID.String()]
if !ok {
t.Fatalf("didn't expect peer %s", info.ID)
}
@@ -129,7 +129,7 @@ func TestAddrInfosFromP2pAddrs(t *testing.T) {
t.Fatalf("expected %s, got %s", exaddrs[i], addr)
}
}
- delete(expected, info.ID.Pretty())
+ delete(expected, info.ID.String())
}
}
@@ -144,7 +144,7 @@ func TestAddrInfoJSON(t *testing.T) {
t.Fatal(err)
}
if addrInfo.ID != testID {
- t.Fatalf("expected ID to equal %s, got %s", testID.Pretty(), addrInfo.ID.Pretty())
+ t.Fatalf("expected ID to equal %s, got %s", testID, addrInfo.ID)
}
if len(addrInfo.Addrs) != 1 || !addrInfo.Addrs[0].Equal(maddrFull) {
t.Fatalf("expected addrs to match %v, got %v", maddrFull, addrInfo.Addrs)
diff --git a/core/peer/peer.go b/core/peer/peer.go
index f7f649f24d..b77fb684ec 100644
--- a/core/peer/peer.go
+++ b/core/peer/peer.go
@@ -41,12 +41,6 @@ const maxInlineKeyLength = 42
// hash output as a multihash. See IDFromPublicKey for details.
type ID string
-// Pretty returns a base58-encoded string representation of the ID.
-// Deprecated: use String() instead.
-func (id ID) Pretty() string {
- return id.String()
-}
-
// Loggable returns a pretty peer ID string in loggable JSON format.
func (id ID) Loggable() map[string]interface{} {
return map[string]interface{}{
@@ -145,16 +139,6 @@ func Decode(s string) (ID, error) {
return FromCid(c)
}
-// Encode encodes a peer ID as a string.
-//
-// At the moment, it base58 encodes the peer ID but, in the future, it will
-// switch to encoding it as a CID by default.
-//
-// Deprecated: use id.String instead.
-func Encode(id ID) string {
- return id.String()
-}
-
// FromCid converts a CID to a peer ID, if possible.
func FromCid(c cid.Cid) (ID, error) {
code := mc.Code(c.Type())
diff --git a/core/peer/peer_serde.go b/core/peer/peer_serde.go
index 5fd1cd50c9..3e2f71793e 100644
--- a/core/peer/peer_serde.go
+++ b/core/peer/peer_serde.go
@@ -45,7 +45,7 @@ func (id ID) Size() int {
}
func (id ID) MarshalJSON() ([]byte, error) {
- return json.Marshal(Encode(id))
+ return json.Marshal(id.String())
}
func (id *ID) UnmarshalJSON(data []byte) (err error) {
@@ -59,7 +59,7 @@ func (id *ID) UnmarshalJSON(data []byte) (err error) {
// MarshalText returns the text encoding of the ID.
func (id ID) MarshalText() ([]byte, error) {
- return []byte(Encode(id)), nil
+ return []byte(id.String()), nil
}
// UnmarshalText restores the ID from its text encoding.
diff --git a/core/routing/routing.go b/core/routing/routing.go
index e1d47451d6..b995b052b9 100644
--- a/core/routing/routing.go
+++ b/core/routing/routing.go
@@ -76,7 +76,7 @@ type Routing interface {
ValueStore
// Bootstrap allows callers to hint to the routing system to get into a
- // Boostrapped state and remain there. It is not a synchronous call.
+ // Bootstrapped state and remain there. It is not a synchronous call.
Bootstrap(context.Context) error
// TODO expose io.Closer or plain-old Close error
diff --git a/core/transport/transport.go b/core/transport/transport.go
index 89a9608d41..d56a3cff06 100644
--- a/core/transport/transport.go
+++ b/core/transport/transport.go
@@ -5,6 +5,7 @@ package transport
import (
"context"
"errors"
+ "fmt"
"net"
"github.com/libp2p/go-libp2p/core/network"
@@ -124,3 +125,47 @@ type Upgrader interface {
// Upgrade upgrades the multiaddr/net connection into a full libp2p-transport connection.
Upgrade(ctx context.Context, t Transport, maconn manet.Conn, dir network.Direction, p peer.ID, scope network.ConnManagementScope) (CapableConn, error)
}
+
+// DialUpdater provides updates on in progress dials.
+type DialUpdater interface {
+ // DialWithUpdates dials a remote peer and provides updates on the passed channel.
+ DialWithUpdates(context.Context, ma.Multiaddr, peer.ID, chan<- DialUpdate) (CapableConn, error)
+}
+
+// DialUpdateKind indicates the type of DialUpdate event.
+type DialUpdateKind int
+
+const (
+ // UpdateKindDialFailed indicates dial failed.
+ UpdateKindDialFailed DialUpdateKind = iota
+ // UpdateKindDialSuccessful indicates dial succeeded.
+ UpdateKindDialSuccessful
+ // UpdateKindHandshakeProgressed indicates successful completion of the TCP 3-way
+ // handshake
+ UpdateKindHandshakeProgressed
+)
+
+func (k DialUpdateKind) String() string {
+ switch k {
+ case UpdateKindDialFailed:
+ return "DialFailed"
+ case UpdateKindDialSuccessful:
+ return "DialSuccessful"
+ case UpdateKindHandshakeProgressed:
+ return "UpdateKindHandshakeProgressed"
+ default:
+ return fmt.Sprintf("DialUpdateKind", k)
+ }
+}
+
+// DialUpdate is used by DialUpdater to provide dial updates.
+type DialUpdate struct {
+ // Kind is the kind of update event.
+ Kind DialUpdateKind
+ // Addr is the peer's address.
+ Addr ma.Multiaddr
+ // Conn is the resulting connection on success.
+ Conn CapableConn
+ // Err is the reason for dial failure.
+ Err error
+}
diff --git a/dashboards/docker-compose.base.yml b/dashboards/docker-compose.base.yml
index 4c87d284ea..b46514af93 100644
--- a/dashboards/docker-compose.base.yml
+++ b/dashboards/docker-compose.base.yml
@@ -26,3 +26,4 @@ services:
- ./identify/identify.json:/var/lib/grafana/dashboards/identify.json
- ./relaysvc/relaysvc.json:/var/lib/grafana/dashboards/relaysvc.json
- ./swarm/swarm.json:/var/lib/grafana/dashboards/swarm.json
+ - ./resource-manager/resource-manager.json:/var/lib/grafana/dashboards/resource-manager.json
diff --git a/dashboards/swarm/swarm.json b/dashboards/swarm/swarm.json
index e5f2fe7ec7..d206de29c4 100644
--- a/dashboards/swarm/swarm.json
+++ b/dashboards/swarm/swarm.json
@@ -232,9 +232,7 @@
"options": {
"orientation": "auto",
"reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
+ "calcs": ["lastNotNull"],
"fields": "",
"values": false
},
@@ -1139,9 +1137,7 @@
},
"pieType": "pie",
"reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
+ "calcs": ["lastNotNull"],
"fields": "",
"values": false
},
@@ -1816,9 +1812,7 @@
},
"pieType": "pie",
"reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
+ "calcs": ["lastNotNull"],
"fields": "",
"values": false
},
@@ -2016,9 +2010,7 @@
},
"pieType": "pie",
"reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
+ "calcs": ["lastNotNull"],
"fields": "",
"values": false
},
@@ -2110,9 +2102,7 @@
},
"pieType": "pie",
"reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
+ "calcs": ["lastNotNull"],
"fields": "",
"values": false
},
@@ -2205,9 +2195,7 @@
},
"pieType": "pie",
"reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
+ "calcs": ["lastNotNull"],
"fields": "",
"values": false
},
@@ -2372,15 +2360,11 @@
"displayMode": "table",
"placement": "right",
"showLegend": true,
- "values": [
- "percent"
- ]
+ "values": ["percent"]
},
"pieType": "donut",
"reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
+ "calcs": ["lastNotNull"],
"fields": "",
"values": false
},
@@ -2652,9 +2636,7 @@
},
"pieType": "pie",
"reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
+ "calcs": ["lastNotNull"],
"fields": "",
"values": false
},
@@ -2798,22 +2780,16 @@
},
"id": 38,
"options": {
- "displayLabels": [
- "percent"
- ],
+ "displayLabels": ["percent"],
"legend": {
"displayMode": "table",
"placement": "right",
"showLegend": true,
- "values": [
- "percent"
- ]
+ "values": ["percent"]
},
"pieType": "donut",
"reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
+ "calcs": ["lastNotNull"],
"fields": "",
"values": false
},
@@ -3036,23 +3012,16 @@
},
"id": 42,
"options": {
- "displayLabels": [
- "percent",
- "name"
- ],
+ "displayLabels": ["percent", "name"],
"legend": {
"displayMode": "table",
"placement": "right",
"showLegend": true,
- "values": [
- "percent"
- ]
+ "values": ["percent"]
},
"pieType": "donut",
"reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
+ "calcs": ["lastNotNull"],
"fields": "",
"values": false
},
@@ -3296,9 +3265,7 @@
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
+ "calcs": ["lastNotNull"],
"fields": "",
"values": false
},
@@ -3360,9 +3327,7 @@
"options": {
"orientation": "vertical",
"reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
+ "calcs": ["lastNotNull"],
"fields": "",
"values": false
},
@@ -3395,6 +3360,16 @@
"tags": [],
"templating": {
"list": [
+ {
+ "hide": 0,
+ "label": "datasource",
+ "name": "DS_PROMETHEUS",
+ "options": [],
+ "query": "prometheus",
+ "refresh": 1,
+ "regex": "",
+ "type": "datasource"
+ },
{
"current": {},
"datasource": {
@@ -3412,7 +3387,6 @@
"refId": "StandardVariableQuery"
},
"refresh": 1,
- "regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
@@ -3429,4 +3403,4 @@
"uid": "a15PyhO4z",
"version": 4,
"weekStart": ""
-}
\ No newline at end of file
+}
diff --git a/defaults.go b/defaults.go
index d11302690c..8f7dc94671 100644
--- a/defaults.go
+++ b/defaults.go
@@ -27,8 +27,8 @@ import (
// Useful when you want to extend, but not replace, the supported transport
// security protocols.
var DefaultSecurity = ChainOptions(
- Security(noise.ID, noise.New),
Security(tls.ID, tls.New),
+ Security(noise.ID, noise.New),
)
// DefaultMuxers configures libp2p to use the stream connection multiplexers.
diff --git a/docs/flaky-tests.md b/docs/flaky-tests.md
index e65800ac4f..667dd77a0f 100644
--- a/docs/flaky-tests.md
+++ b/docs/flaky-tests.md
@@ -28,7 +28,7 @@ processes are vying for CPU time.
sudo cgset -r cpu.cfs_quota_us=10000 cpulimit
sudo cgset -r cpu.cfs_period_us=1000000 cpulimit
- # Run a shell with in our limited environemnt
+ # Run a shell with in our limited environment
sudo cgexec -g cpu:cpulimit bash
# In the shell, run the test
diff --git a/examples/README.md b/examples/README.md
index 7930ff7860..529122fe78 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -15,4 +15,4 @@ Let us know if you find any issue or if you want to contribute and add a new tut
- [P2P chat application with peer discovery using mdns](./chat-with-mdns)
- [A chapter based approach to building a libp2p application](./ipfs-camp-2019/) _Created for [IPFS Camp 2019](https://github.com/ipfs/camp/tree/master/CORE_AND_ELECTIVE_COURSES/CORE_COURSE_B)_
-For js-libp2p examples, check https://github.com/libp2p/js-libp2p/tree/master/examples
+For js-libp2p examples, check https://github.com/libp2p/js-libp2p-examples
diff --git a/examples/chat-with-mdns/README.md b/examples/chat-with-mdns/README.md
index 836fb7a7bb..8e467e696a 100644
--- a/examples/chat-with-mdns/README.md
+++ b/examples/chat-with-mdns/README.md
@@ -57,29 +57,37 @@ func handleStream(stream net.Stream) {
3. **Find peers nearby using mdns**
-Start [mdns discovery](https://godoc.org/github.com/libp2p/go-libp2p/p2p/discovery#NewMdnsService) service in host.
+New [mdns discovery](https://godoc.org/github.com/libp2p/go-libp2p/p2p/discovery#NewMdnsService) service in host.
```go
-ser, err := discovery.NewMdnsService(peerhost, rendezvous)
+notifee := &discoveryNotifee{PeerChan: make(chan peer.AddrInfo)}
+ser, err := discovery.NewMdnsService(peerhost, rendezvous, notifee)
```
register [Notifee interface](https://godoc.org/github.com/libp2p/go-libp2p/p2p/discovery#Notifee) with service so that we get notified about peer discovery
```go
- n := &discoveryNotifee{}
- ser.RegisterNotifee(n)
+ ser.Start()
```
+
4. **Open streams to peers found.**
Finally we open stream to the peers we found, as we find them
```go
peer := <-peerChan // will block until we discover a peer
+ // this is used to avoid call `NewStream` from both side
+ if peer.ID > host.ID() {
+ // if other end peer id greater than us, don't connect to it, just wait for it to connect us
+ fmt.Println("Found peer:", peer, " id is greater than us, wait for it to connect to us")
+ continue
+ }
fmt.Println("Found peer:", peer, ", connecting")
if err := host.Connect(ctx, peer); err != nil {
fmt.Println("Connection failed:", err)
+ continue
}
// open a stream, this stream will be handled by handleStream other end
diff --git a/examples/chat-with-mdns/main.go b/examples/chat-with-mdns/main.go
index 57b89c2583..55c36adf40 100644
--- a/examples/chat-with-mdns/main.go
+++ b/examples/chat-with-mdns/main.go
@@ -111,11 +111,16 @@ func main() {
// This function is called when a peer initiates a connection and starts a stream with this peer.
host.SetStreamHandler(protocol.ID(cfg.ProtocolID), handleStream)
- fmt.Printf("\n[*] Your Multiaddress Is: /ip4/%s/tcp/%v/p2p/%s\n", cfg.listenHost, cfg.listenPort, host.ID().Pretty())
+ fmt.Printf("\n[*] Your Multiaddress Is: /ip4/%s/tcp/%v/p2p/%s\n", cfg.listenHost, cfg.listenPort, host.ID())
peerChan := initMDNS(host, cfg.RendezvousString)
for { // allows multiple peers to join
peer := <-peerChan // will block until we discover a peer
+ if peer.ID > host.ID() {
+ // if other end peer id greater than us, don't connect to it, just wait for it to connect us
+ fmt.Println("Found peer:", peer, " id is greater than us, wait for it to connect to us")
+ continue
+ }
fmt.Println("Found peer:", peer, ", connecting")
if err := host.Connect(ctx, peer); err != nil {
diff --git a/examples/chat/chat.go b/examples/chat/chat.go
index cd1c2872ea..d89ea3cd85 100644
--- a/examples/chat/chat.go
+++ b/examples/chat/chat.go
@@ -187,7 +187,7 @@ func startPeer(ctx context.Context, h host.Host, streamHandler network.StreamHan
return
}
- log.Printf("Run './chat -d /ip4/127.0.0.1/tcp/%v/p2p/%s' on another console.\n", port, h.ID().Pretty())
+ log.Printf("Run './chat -d /ip4/127.0.0.1/tcp/%v/p2p/%s' on another console.\n", port, h.ID())
log.Println("You can replace 127.0.0.1 with public IP as well.")
log.Println("Waiting for incoming connection")
log.Println()
diff --git a/examples/chat/chat_test.go b/examples/chat/chat_test.go
index 1a1cea3c7e..4240b477c2 100644
--- a/examples/chat/chat_test.go
+++ b/examples/chat/chat_test.go
@@ -49,7 +49,7 @@ func TestMain(t *testing.T) {
cancel() // end the test
})
- dest := fmt.Sprintf("/ip4/127.0.0.1/tcp/%v/p2p/%s", port1, h1.ID().Pretty())
+ dest := fmt.Sprintf("/ip4/127.0.0.1/tcp/%v/p2p/%s", port1, h1.ID())
h2, err := makeHost(port2, rand.Reader)
if err != nil {
diff --git a/examples/echo/README.md b/examples/echo/README.md
index 380716001c..4c30609fa8 100644
--- a/examples/echo/README.md
+++ b/examples/echo/README.md
@@ -42,7 +42,7 @@ The `makeBasicHost()` function creates a [go-libp2p-basichost](https://godoc.org
In order to create the swarm (and a `basichost`), the example needs:
-- An [ipfs-procotol ID](https://godoc.org/github.com/libp2p/go-libp2p-peer#ID) like `QmNtX1cvrm2K6mQmMEaMxAuB4rTexhd87vpYVot4sEZzxc`. The example autogenerates a key pair on every run and uses an ID extracted from the public key (the hash of the public key). When using `-insecure`, it leaves the connection unencrypted (otherwise, it uses the key pair to encrypt communications).
+- An [ipfs-protocol ID](https://godoc.org/github.com/libp2p/go-libp2p-peer#ID) like `QmNtX1cvrm2K6mQmMEaMxAuB4rTexhd87vpYVot4sEZzxc`. The example autogenerates a key pair on every run and uses an ID extracted from the public key (the hash of the public key). When using `-insecure`, it leaves the connection unencrypted (otherwise, it uses the key pair to encrypt communications).
- A [Multiaddress](https://godoc.org/github.com/multiformats/go-multiaddr), which indicates how to reach this peer. There can be several of them (using different protocols or locations for example). Example: `/ip4/127.0.0.1/tcp/1234`.
- A [go-libp2p-peerstore](https://godoc.org/github.com/libp2p/go-libp2p-peerstore), which is used as an address book which matches node IDs to the multiaddresses through which they can be contacted. This peerstore gets autopopulated when manually opening a connection (with [`Connect()`](https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic#BasicHost.Connect). Alternatively, we can manually [`AddAddr()`](https://godoc.org/github.com/libp2p/go-libp2p-peerstore#AddrManager.AddAddr) as in the example.
diff --git a/examples/echo/main.go b/examples/echo/main.go
index 3bba896183..90c7248634 100644
--- a/examples/echo/main.go
+++ b/examples/echo/main.go
@@ -88,7 +88,7 @@ func makeBasicHost(listenPort int, insecure bool, randseed int64) (host.Host, er
func getHostAddress(ha host.Host) string {
// Build host multiaddress
- hostAddr, _ := ma.NewMultiaddr(fmt.Sprintf("/p2p/%s", ha.ID().Pretty()))
+ hostAddr, _ := ma.NewMultiaddr(fmt.Sprintf("/p2p/%s", ha.ID()))
// Now we can build a full multiaddress to reach this host
// by encapsulating both addresses:
@@ -125,18 +125,6 @@ func runSender(ctx context.Context, ha host.Host, targetPeer string) {
fullAddr := getHostAddress(ha)
log.Printf("I am %s\n", fullAddr)
- // Set a stream handler on host A. /echo/1.0.0 is
- // a user-defined protocol name.
- ha.SetStreamHandler("/echo/1.0.0", func(s network.Stream) {
- log.Println("sender received new stream")
- if err := doEcho(s); err != nil {
- log.Println(err)
- s.Reset()
- } else {
- s.Close()
- }
- })
-
// Turn the targetPeer into a multiaddr.
maddr, err := ma.NewMultiaddr(targetPeer)
if err != nil {
diff --git a/examples/go.mod b/examples/go.mod
index ae49341ebb..4c373b8cb6 100644
--- a/examples/go.mod
+++ b/examples/go.mod
@@ -7,10 +7,10 @@ require (
github.com/google/uuid v1.3.0
github.com/ipfs/go-datastore v0.6.0
github.com/ipfs/go-log/v2 v2.5.1
- github.com/libp2p/go-libp2p v0.31.0
- github.com/libp2p/go-libp2p-kad-dht v0.20.1-0.20230209220319-6c2045abad23
- github.com/multiformats/go-multiaddr v0.11.0
- github.com/prometheus/client_golang v1.14.0
+ github.com/libp2p/go-libp2p v0.32.0
+ github.com/libp2p/go-libp2p-kad-dht v0.25.1
+ github.com/multiformats/go-multiaddr v0.12.0
+ github.com/prometheus/client_golang v1.16.0
)
require (
@@ -25,34 +25,35 @@ require (
github.com/elastic/gosigar v0.14.2 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
+ github.com/go-logr/logr v1.2.4 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
- github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gopacket v1.1.19 // indirect
- github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect
+ github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
- github.com/huin/goupnp v1.2.0 // indirect
+ github.com/huin/goupnp v1.3.0 // indirect
+ github.com/ipfs/boxo v0.10.0 // indirect
github.com/ipfs/go-cid v0.4.1 // indirect
- github.com/ipfs/go-ipfs-util v0.0.2 // indirect
- github.com/ipfs/go-ipns v0.2.0 // indirect
github.com/ipfs/go-log v1.0.5 // indirect
- github.com/ipld/go-ipld-prime v0.16.0 // indirect
+ github.com/ipld/go-ipld-prime v0.20.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
- github.com/klauspost/compress v1.16.7 // indirect
+ github.com/klauspost/compress v1.17.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.1.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect
- github.com/libp2p/go-libp2p-kbucket v0.5.0 // indirect
+ github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect
github.com/libp2p/go-libp2p-record v0.2.0 // indirect
+ github.com/libp2p/go-libp2p-routing-helpers v0.7.2 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-nat v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect
@@ -60,9 +61,9 @@ require (
github.com/libp2p/go-yamux/v4 v4.0.1 // indirect
github.com/libp2p/zeroconf/v2 v2.2.0 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
- github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
- github.com/miekg/dns v1.1.55 // indirect
+ github.com/miekg/dns v1.1.56 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
@@ -74,37 +75,42 @@ require (
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
- github.com/multiformats/go-multistream v0.4.1 // indirect
+ github.com/multiformats/go-multistream v0.5.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
- github.com/onsi/ginkgo/v2 v2.11.0 // indirect
+ github.com/onsi/ginkgo/v2 v2.13.0 // indirect
github.com/opencontainers/runtime-spec v1.1.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/pkg/errors v0.9.1 // indirect
- github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e // indirect
+ github.com/polydawn/refmt v0.89.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
- github.com/prometheus/common v0.42.0 // indirect
- github.com/prometheus/procfs v0.9.0 // indirect
+ github.com/prometheus/common v0.44.0 // indirect
+ github.com/prometheus/procfs v0.11.1 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
- github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
- github.com/quic-go/quic-go v0.38.1 // indirect
- github.com/quic-go/webtransport-go v0.5.3 // indirect
+ github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
+ github.com/quic-go/quic-go v0.39.3 // indirect
+ github.com/quic-go/webtransport-go v0.6.0 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
go.opencensus.io v0.24.0 // indirect
- go.uber.org/dig v1.17.0 // indirect
- go.uber.org/fx v1.20.0 // indirect
+ go.opentelemetry.io/otel v1.16.0 // indirect
+ go.opentelemetry.io/otel/metric v1.16.0 // indirect
+ go.opentelemetry.io/otel/trace v1.16.0 // indirect
+ go.uber.org/dig v1.17.1 // indirect
+ go.uber.org/fx v1.20.1 // indirect
+ go.uber.org/mock v0.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.25.0 // indirect
- golang.org/x/crypto v0.12.0 // indirect
- golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
- golang.org/x/mod v0.12.0 // indirect
- golang.org/x/net v0.14.0 // indirect
- golang.org/x/sync v0.3.0 // indirect
- golang.org/x/sys v0.11.0 // indirect
- golang.org/x/text v0.12.0 // indirect
- golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
- google.golang.org/protobuf v1.30.0 // indirect
+ go.uber.org/zap v1.26.0 // indirect
+ golang.org/x/crypto v0.14.0 // indirect
+ golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
+ golang.org/x/mod v0.13.0 // indirect
+ golang.org/x/net v0.17.0 // indirect
+ golang.org/x/sync v0.4.0 // indirect
+ golang.org/x/sys v0.13.0 // indirect
+ golang.org/x/text v0.13.0 // indirect
+ golang.org/x/tools v0.14.0 // indirect
+ gonum.org/v1/gonum v0.13.0 // indirect
+ google.golang.org/protobuf v1.31.0 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
)
diff --git a/examples/go.sum b/examples/go.sum
index e77a14289c..9d370030ad 100644
--- a/examples/go.sum
+++ b/examples/go.sum
@@ -33,7 +33,6 @@ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -58,15 +57,19 @@ github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
-github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns=
-github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
+github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
+github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
+github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
@@ -76,13 +79,11 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
-github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -105,7 +106,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
@@ -113,16 +113,16 @@ github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo=
-github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
+github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0=
+github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
-github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
@@ -134,9 +134,10 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
-github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY=
-github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
-github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M=
+github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
+github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
+github.com/ipfs/boxo v0.10.0 h1:tdDAxq8jrsbRkYoF+5Rcqyeb91hgWe2hp7iLu7ORZLY=
+github.com/ipfs/boxo v0.10.0/go.mod h1:Fg+BnfxZ0RPzR0nOodzdIq3A7KgoWAOWsEIImrIQdBM=
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
@@ -144,16 +145,13 @@ github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8=
-github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ=
-github.com/ipfs/go-ipns v0.2.0 h1:BgmNtQhqOw5XEZ8RAfWEpK4DhqaYiuP6h71MhIp7xXU=
-github.com/ipfs/go-ipns v0.2.0/go.mod h1:3cLT2rbvgPZGkHJoPO1YMJeh6LtkxopCkKFcio/wE24=
github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
-github.com/ipld/go-ipld-prime v0.16.0 h1:RS5hhjB/mcpeEPJvfyj0qbOj/QL+/j05heZ0qa97dVo=
-github.com/ipld/go-ipld-prime v0.16.0/go.mod h1:axSCuOCBPqrH+gvXr2w9uAOulJqBPhHPT2PjoiiU1qA=
+github.com/ipld/go-ipld-prime v0.20.0 h1:Ud3VwE9ClxpO2LkCYP7vWPc0Fo+dYdYzgxUJZ3uRG4g=
+github.com/ipld/go-ipld-prime v0.20.0/go.mod h1:PzqZ/ZR981eKbgdr3y2DJYeD/8bgMawdGVlJDE8kK+M=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
@@ -169,39 +167,37 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
-github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
-github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
-github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
+github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
-github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c=
github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro=
-github.com/libp2p/go-libp2p v0.31.0 h1:LFShhP8F6xthWiBBq3euxbKjZsoRajVEyBS9snfHxYg=
-github.com/libp2p/go-libp2p v0.31.0/go.mod h1:W/FEK1c/t04PbRH3fA9i5oucu5YcgrG0JVoBWT1B7Eg=
+github.com/libp2p/go-libp2p v0.32.0 h1:86I4B7nBUPIyTgw3+5Ibq6K7DdKRCuZw8URCfPc1hQM=
+github.com/libp2p/go-libp2p v0.32.0/go.mod h1:hXXC3kXPlBZ1eu8Q2hptGrMB4mZ3048JUoS4EKaHW5c=
github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s=
github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w=
-github.com/libp2p/go-libp2p-kad-dht v0.20.1-0.20230209220319-6c2045abad23 h1:VGjUg3I0gLugtjZKI4kzvPiptmfYhWHK6YGBI4ZI2Cs=
-github.com/libp2p/go-libp2p-kad-dht v0.20.1-0.20230209220319-6c2045abad23/go.mod h1:ScWrKlutIaRETyELjPNXUO2TekuzLsE5nCBVuNR9l0g=
-github.com/libp2p/go-libp2p-kbucket v0.5.0 h1:g/7tVm8ACHDxH29BGrpsQlnNeu+6OF1A9bno/4/U1oA=
-github.com/libp2p/go-libp2p-kbucket v0.5.0/go.mod h1:zGzGCpQd78b5BNTDGHNDLaTt9aDK/A02xeZp9QeFC4U=
+github.com/libp2p/go-libp2p-kad-dht v0.25.1 h1:ofFNrf6MMEy4vi3R1VbJ7LOcTn3Csh0cDcaWHTxtWNA=
+github.com/libp2p/go-libp2p-kad-dht v0.25.1/go.mod h1:6za56ncRHYXX4Nc2vn8z7CZK0P4QiMcrn77acKLM2Oo=
+github.com/libp2p/go-libp2p-kbucket v0.6.3 h1:p507271wWzpy2f1XxPzCQG9NiN6R6lHL9GiSErbQQo0=
+github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEHetYSPXOaJnOiD8i0=
github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0=
github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk=
+github.com/libp2p/go-libp2p-routing-helpers v0.7.2 h1:xJMFyhQ3Iuqnk9Q2dYE1eUTzsah7NLw3Qs2zjUV78T0=
+github.com/libp2p/go-libp2p-routing-helpers v0.7.2/go.mod h1:cN4mJAD/7zfPKXBcs9ze31JGYAZgzdABEm+q/hkswb8=
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
@@ -220,16 +216,16 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
-github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
-github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
-github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
+github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
+github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
@@ -238,53 +234,42 @@ github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdn
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
-github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
-github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
-github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
-github.com/multiformats/go-multiaddr v0.11.0 h1:XqGyJ8ufbCE0HmTDwx2kPdsrQ36AGPZNZX6s6xfJH10=
-github.com/multiformats/go-multiaddr v0.11.0/go.mod h1:gWUm0QLR4thQ6+ZF6SXUw8YjtwQSPapICM+NmCkxHSM=
+github.com/multiformats/go-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE=
+github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8=
github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A=
github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
-github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
-github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ=
github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg=
github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k=
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
-github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
-github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
-github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84=
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
-github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo=
-github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q=
+github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE=
+github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA=
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
-github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
-github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
-github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
-github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
-github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
+github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
+github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
+github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -298,34 +283,33 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e h1:ZOcivgkkFRnjfoTcGsDq3UQYiBmekwLA+qg0OjyB/ls=
-github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o=
+github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4=
+github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
-github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
+github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
+github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
-github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
-github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
+github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
+github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
-github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
+github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
+github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
-github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=
-github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
-github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE=
-github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4=
-github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU=
-github.com/quic-go/webtransport-go v0.5.3/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU=
+github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
+github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
+github.com/quic-go/quic-go v0.39.3 h1:o3YB6t2SR+HU/pgwF29kJ6g4jJIJEwEZ8CKia1h1TKg=
+github.com/quic-go/quic-go v0.39.3/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q=
+github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY=
+github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc=
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
-github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
@@ -353,10 +337,10 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
-github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
-github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
+github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
+github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
+github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
@@ -375,11 +359,11 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
-github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0=
-github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a h1:G++j5e0OC488te356JvdhaM8YS6nMsjLAYF7JxCv07w=
-github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
+github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
+github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -388,15 +372,23 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
+go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s=
+go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
+go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
+go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
+go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs=
+go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
-go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI=
-go.uber.org/dig v1.17.0/go.mod h1:rTxpf7l5I0eBTlE6/9RL+lDybC7WFwY2QH55ZSjy1mU=
-go.uber.org/fx v1.20.0 h1:ZMC/pnRvhsthOZh9MZjMq5U8Or3mA9zBSPaLnzs3ihQ=
-go.uber.org/fx v1.20.0/go.mod h1:qCUj0btiR3/JnanEr1TYEePfSw6o/4qYJscgvzQ5Ub0=
+go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc=
+go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
+go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk=
+go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
+go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
+go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
@@ -404,8 +396,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
-go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
-go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
+go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
+go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -416,13 +408,12 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
-golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
-golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -434,8 +425,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
+golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -454,8 +445,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
-golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
-golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -469,8 +460,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -484,7 +475,6 @@ golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -492,16 +482,15 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
-golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
-golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -520,14 +509,15 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
-golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
+golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
+golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gonum.org/v1/gonum v0.13.0 h1:a0T3bh+7fhRyqeNbiC3qVHYmkiQgit3wnNan/2c0HMM=
+gonum.org/v1/gonum v0.13.0/go.mod h1:/WPYRckkfWrhWefxyYTfrTtQR0KH4iyHNuzxqXAKyAU=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
@@ -561,8 +551,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
-google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
@@ -573,7 +563,6 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
@@ -584,7 +573,6 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
-lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
diff --git a/examples/http-proxy/proxy.go b/examples/http-proxy/proxy.go
index 27d9597870..f96d4b8b00 100644
--- a/examples/http-proxy/proxy.go
+++ b/examples/http-proxy/proxy.go
@@ -144,7 +144,7 @@ func (p *ProxyService) Serve() {
// Streams are multiplexed over single connections so, unlike connections
// themselves, they are cheap to create and dispose of.
func (p *ProxyService) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- fmt.Printf("proxying request for %s to peer %s\n", r.URL, p.dest.Pretty())
+ fmt.Printf("proxying request for %s to peer %s\n", r.URL, p.dest)
// We need to send the request to the remote libp2p peer, so
// we open a stream to it
stream, err := p.host.NewStream(context.Background(), p.dest, Protocol)
diff --git a/examples/ipfs-camp-2019/go.mod b/examples/ipfs-camp-2019/go.mod
index 947afb0394..d4773430c5 100644
--- a/examples/ipfs-camp-2019/go.mod
+++ b/examples/ipfs-camp-2019/go.mod
@@ -4,10 +4,10 @@ go 1.20
require (
github.com/gogo/protobuf v1.3.2
- github.com/libp2p/go-libp2p v0.31.0
- github.com/libp2p/go-libp2p-kad-dht v0.21.0
- github.com/libp2p/go-libp2p-pubsub v0.9.0
- github.com/multiformats/go-multiaddr v0.11.0
+ github.com/libp2p/go-libp2p v0.32.0
+ github.com/libp2p/go-libp2p-kad-dht v0.25.1
+ github.com/libp2p/go-libp2p-pubsub v0.10.0
+ github.com/multiformats/go-multiaddr v0.12.0
)
require (
@@ -20,41 +20,41 @@ require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
- github.com/emirpasic/gods v1.18.1 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
+ github.com/go-logr/logr v1.2.4 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
- github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gopacket v1.1.19 // indirect
- github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect
+ github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
- github.com/huin/goupnp v1.2.0 // indirect
+ github.com/huin/goupnp v1.3.0 // indirect
+ github.com/ipfs/boxo v0.10.0 // indirect
github.com/ipfs/go-cid v0.4.1 // indirect
github.com/ipfs/go-datastore v0.6.0 // indirect
- github.com/ipfs/go-ipfs-util v0.0.2 // indirect
- github.com/ipfs/go-ipns v0.2.0 // indirect
github.com/ipfs/go-log v1.0.5 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect
- github.com/ipld/go-ipld-prime v0.16.0 // indirect
+ github.com/ipld/go-ipld-prime v0.20.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
- github.com/klauspost/compress v1.16.7 // indirect
+ github.com/klauspost/compress v1.17.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.1.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect
- github.com/libp2p/go-libp2p-kbucket v0.5.0 // indirect
+ github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect
github.com/libp2p/go-libp2p-record v0.2.0 // indirect
+ github.com/libp2p/go-libp2p-routing-helpers v0.7.2 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-nat v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect
@@ -62,9 +62,9 @@ require (
github.com/libp2p/go-yamux/v4 v4.0.1 // indirect
github.com/libp2p/zeroconf/v2 v2.2.0 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
- github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
- github.com/miekg/dns v1.1.55 // indirect
+ github.com/miekg/dns v1.1.56 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
@@ -76,38 +76,43 @@ require (
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
- github.com/multiformats/go-multistream v0.4.1 // indirect
+ github.com/multiformats/go-multistream v0.5.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
- github.com/onsi/ginkgo/v2 v2.11.0 // indirect
+ github.com/onsi/ginkgo/v2 v2.13.0 // indirect
github.com/opencontainers/runtime-spec v1.1.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/pkg/errors v0.9.1 // indirect
- github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e // indirect
- github.com/prometheus/client_golang v1.14.0 // indirect
+ github.com/polydawn/refmt v0.89.0 // indirect
+ github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
- github.com/prometheus/common v0.42.0 // indirect
- github.com/prometheus/procfs v0.9.0 // indirect
+ github.com/prometheus/common v0.44.0 // indirect
+ github.com/prometheus/procfs v0.11.1 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
- github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
- github.com/quic-go/quic-go v0.38.1 // indirect
- github.com/quic-go/webtransport-go v0.5.3 // indirect
+ github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
+ github.com/quic-go/quic-go v0.39.3 // indirect
+ github.com/quic-go/webtransport-go v0.6.0 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
go.opencensus.io v0.24.0 // indirect
- go.uber.org/dig v1.17.0 // indirect
- go.uber.org/fx v1.20.0 // indirect
+ go.opentelemetry.io/otel v1.16.0 // indirect
+ go.opentelemetry.io/otel/metric v1.16.0 // indirect
+ go.opentelemetry.io/otel/trace v1.16.0 // indirect
+ go.uber.org/dig v1.17.1 // indirect
+ go.uber.org/fx v1.20.1 // indirect
+ go.uber.org/mock v0.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.25.0 // indirect
- golang.org/x/crypto v0.12.0 // indirect
- golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
- golang.org/x/mod v0.12.0 // indirect
- golang.org/x/net v0.14.0 // indirect
- golang.org/x/sync v0.3.0 // indirect
- golang.org/x/sys v0.11.0 // indirect
- golang.org/x/text v0.12.0 // indirect
- golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
- google.golang.org/protobuf v1.30.0 // indirect
+ go.uber.org/zap v1.26.0 // indirect
+ golang.org/x/crypto v0.14.0 // indirect
+ golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
+ golang.org/x/mod v0.13.0 // indirect
+ golang.org/x/net v0.17.0 // indirect
+ golang.org/x/sync v0.4.0 // indirect
+ golang.org/x/sys v0.13.0 // indirect
+ golang.org/x/text v0.13.0 // indirect
+ golang.org/x/tools v0.14.0 // indirect
+ gonum.org/v1/gonum v0.13.0 // indirect
+ google.golang.org/protobuf v1.31.0 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
)
diff --git a/examples/ipfs-camp-2019/go.sum b/examples/ipfs-camp-2019/go.sum
index 75bd8d0664..2e33d32759 100644
--- a/examples/ipfs-camp-2019/go.sum
+++ b/examples/ipfs-camp-2019/go.sum
@@ -33,7 +33,6 @@ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -49,8 +48,6 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4=
github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
-github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
-github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@@ -60,15 +57,19 @@ github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
-github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns=
-github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
+github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
+github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
+github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
@@ -78,13 +79,11 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
-github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -107,7 +106,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
@@ -115,16 +113,16 @@ github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo=
-github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
+github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0=
+github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
-github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
@@ -138,9 +136,10 @@ github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+l
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
-github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY=
-github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
-github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M=
+github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
+github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
+github.com/ipfs/boxo v0.10.0 h1:tdDAxq8jrsbRkYoF+5Rcqyeb91hgWe2hp7iLu7ORZLY=
+github.com/ipfs/boxo v0.10.0/go.mod h1:Fg+BnfxZ0RPzR0nOodzdIq3A7KgoWAOWsEIImrIQdBM=
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
@@ -148,16 +147,13 @@ github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8=
-github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ=
-github.com/ipfs/go-ipns v0.2.0 h1:BgmNtQhqOw5XEZ8RAfWEpK4DhqaYiuP6h71MhIp7xXU=
-github.com/ipfs/go-ipns v0.2.0/go.mod h1:3cLT2rbvgPZGkHJoPO1YMJeh6LtkxopCkKFcio/wE24=
github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
-github.com/ipld/go-ipld-prime v0.16.0 h1:RS5hhjB/mcpeEPJvfyj0qbOj/QL+/j05heZ0qa97dVo=
-github.com/ipld/go-ipld-prime v0.16.0/go.mod h1:axSCuOCBPqrH+gvXr2w9uAOulJqBPhHPT2PjoiiU1qA=
+github.com/ipld/go-ipld-prime v0.20.0 h1:Ud3VwE9ClxpO2LkCYP7vWPc0Fo+dYdYzgxUJZ3uRG4g=
+github.com/ipld/go-ipld-prime v0.20.0/go.mod h1:PzqZ/ZR981eKbgdr3y2DJYeD/8bgMawdGVlJDE8kK+M=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
@@ -173,41 +169,39 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
-github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
-github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
-github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
+github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
-github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c=
github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro=
-github.com/libp2p/go-libp2p v0.31.0 h1:LFShhP8F6xthWiBBq3euxbKjZsoRajVEyBS9snfHxYg=
-github.com/libp2p/go-libp2p v0.31.0/go.mod h1:W/FEK1c/t04PbRH3fA9i5oucu5YcgrG0JVoBWT1B7Eg=
+github.com/libp2p/go-libp2p v0.32.0 h1:86I4B7nBUPIyTgw3+5Ibq6K7DdKRCuZw8URCfPc1hQM=
+github.com/libp2p/go-libp2p v0.32.0/go.mod h1:hXXC3kXPlBZ1eu8Q2hptGrMB4mZ3048JUoS4EKaHW5c=
github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s=
github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w=
-github.com/libp2p/go-libp2p-kad-dht v0.21.0 h1:J0Yd22VA+sk0CJRGMgtfHvLVIkZDyJ3AJGiljywIw5U=
-github.com/libp2p/go-libp2p-kad-dht v0.21.0/go.mod h1:Bhm9diAFmc6qcWAr084bHNL159srVZRKADdp96Qqd1I=
-github.com/libp2p/go-libp2p-kbucket v0.5.0 h1:g/7tVm8ACHDxH29BGrpsQlnNeu+6OF1A9bno/4/U1oA=
-github.com/libp2p/go-libp2p-kbucket v0.5.0/go.mod h1:zGzGCpQd78b5BNTDGHNDLaTt9aDK/A02xeZp9QeFC4U=
-github.com/libp2p/go-libp2p-pubsub v0.9.0 h1:mcLb4WzwhUG4OKb0rp1/bYMd/DYhvMyzJheQH3LMd1s=
-github.com/libp2p/go-libp2p-pubsub v0.9.0/go.mod h1:OEsj0Cc/BpkqikXRTrVspWU/Hx7bMZwHP+6vNMd+c7I=
+github.com/libp2p/go-libp2p-kad-dht v0.25.1 h1:ofFNrf6MMEy4vi3R1VbJ7LOcTn3Csh0cDcaWHTxtWNA=
+github.com/libp2p/go-libp2p-kad-dht v0.25.1/go.mod h1:6za56ncRHYXX4Nc2vn8z7CZK0P4QiMcrn77acKLM2Oo=
+github.com/libp2p/go-libp2p-kbucket v0.6.3 h1:p507271wWzpy2f1XxPzCQG9NiN6R6lHL9GiSErbQQo0=
+github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEHetYSPXOaJnOiD8i0=
+github.com/libp2p/go-libp2p-pubsub v0.10.0 h1:wS0S5FlISavMaAbxyQn3dxMOe2eegMfswM471RuHJwA=
+github.com/libp2p/go-libp2p-pubsub v0.10.0/go.mod h1:1OxbaT/pFRO5h+Dpze8hdHQ63R0ke55XTs6b6NwLLkw=
github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0=
github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk=
+github.com/libp2p/go-libp2p-routing-helpers v0.7.2 h1:xJMFyhQ3Iuqnk9Q2dYE1eUTzsah7NLw3Qs2zjUV78T0=
+github.com/libp2p/go-libp2p-routing-helpers v0.7.2/go.mod h1:cN4mJAD/7zfPKXBcs9ze31JGYAZgzdABEm+q/hkswb8=
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
@@ -226,16 +220,16 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
-github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
-github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
-github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
+github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
+github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
@@ -244,53 +238,42 @@ github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdn
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
-github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
-github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
-github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
-github.com/multiformats/go-multiaddr v0.11.0 h1:XqGyJ8ufbCE0HmTDwx2kPdsrQ36AGPZNZX6s6xfJH10=
-github.com/multiformats/go-multiaddr v0.11.0/go.mod h1:gWUm0QLR4thQ6+ZF6SXUw8YjtwQSPapICM+NmCkxHSM=
+github.com/multiformats/go-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE=
+github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8=
github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A=
github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
-github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
-github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ=
github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg=
github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k=
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
-github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
-github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
-github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84=
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
-github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo=
-github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q=
+github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE=
+github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA=
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
-github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
-github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
-github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
-github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
-github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
+github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
+github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
+github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -304,34 +287,33 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e h1:ZOcivgkkFRnjfoTcGsDq3UQYiBmekwLA+qg0OjyB/ls=
-github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o=
+github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4=
+github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
-github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
+github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
+github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
-github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
-github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
+github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
+github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
-github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
+github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
+github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
-github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=
-github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
-github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE=
-github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4=
-github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU=
-github.com/quic-go/webtransport-go v0.5.3/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU=
+github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
+github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
+github.com/quic-go/quic-go v0.39.3 h1:o3YB6t2SR+HU/pgwF29kJ6g4jJIJEwEZ8CKia1h1TKg=
+github.com/quic-go/quic-go v0.39.3/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q=
+github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY=
+github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc=
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
-github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
@@ -359,10 +341,10 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
-github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
-github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
+github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
+github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
+github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
@@ -381,11 +363,11 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
-github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0=
-github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a h1:G++j5e0OC488te356JvdhaM8YS6nMsjLAYF7JxCv07w=
-github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
+github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
+github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -394,15 +376,23 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
+go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s=
+go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
+go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
+go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
+go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs=
+go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
-go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI=
-go.uber.org/dig v1.17.0/go.mod h1:rTxpf7l5I0eBTlE6/9RL+lDybC7WFwY2QH55ZSjy1mU=
-go.uber.org/fx v1.20.0 h1:ZMC/pnRvhsthOZh9MZjMq5U8Or3mA9zBSPaLnzs3ihQ=
-go.uber.org/fx v1.20.0/go.mod h1:qCUj0btiR3/JnanEr1TYEePfSw6o/4qYJscgvzQ5Ub0=
+go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc=
+go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
+go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk=
+go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
+go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
+go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
@@ -410,8 +400,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
-go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
-go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
+go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
+go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -422,13 +412,12 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
-golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
-golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -440,8 +429,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
+golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -460,8 +449,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
-golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
-golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -475,8 +464,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -490,7 +479,6 @@ golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -498,16 +486,15 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
-golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
-golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -526,14 +513,15 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
-golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
+golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
+golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gonum.org/v1/gonum v0.13.0 h1:a0T3bh+7fhRyqeNbiC3qVHYmkiQgit3wnNan/2c0HMM=
+gonum.org/v1/gonum v0.13.0/go.mod h1:/WPYRckkfWrhWefxyYTfrTtQR0KH4iyHNuzxqXAKyAU=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
@@ -567,8 +555,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
-google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
@@ -579,7 +567,6 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
@@ -590,7 +577,6 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
-lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
diff --git a/examples/libp2p-host/README.md b/examples/libp2p-host/README.md
index e187f067cf..966ee0e1fd 100644
--- a/examples/libp2p-host/README.md
+++ b/examples/libp2p-host/README.md
@@ -84,7 +84,7 @@ defer h2.Close()
fmt.Printf("Hello World, my second hosts ID is %s\n", h2.ID())
```
-And thats it, you have a libp2p host and you're ready to start doing some awesome p2p networking!
+And that's it, you have a libp2p host and you're ready to start doing some awesome p2p networking!
In future guides we will go over ways to use hosts, configure them differently (hint: there are a huge number of ways to set these up), and interesting ways to apply this technology to various applications you might want to build.
diff --git a/examples/multipro/pb/p2p.pb.go b/examples/multipro/pb/p2p.pb.go
index a33d549749..2399383cd4 100644
--- a/examples/multipro/pb/p2p.pb.go
+++ b/examples/multipro/pb/p2p.pb.go
@@ -110,7 +110,7 @@ func (m *MessageData) GetSign() []byte {
return nil
}
-// a protocol define a set of reuqest and responses
+// A protocol defines a set of requests and responses.
type PingRequest struct {
MessageData *MessageData `protobuf:"bytes,1,opt,name=messageData" json:"messageData,omitempty"`
// method specific data
@@ -205,7 +205,7 @@ func (m *PingResponse) GetMessage() string {
return ""
}
-// a protocol define a set of reuqest and responses
+// A protocol defines a set of requests and responses
type EchoRequest struct {
MessageData *MessageData `protobuf:"bytes,1,opt,name=messageData" json:"messageData,omitempty"`
// method specific data
diff --git a/examples/multipro/pb/p2p.proto b/examples/multipro/pb/p2p.proto
index 5488f2a6f3..a360b24635 100644
--- a/examples/multipro/pb/p2p.proto
+++ b/examples/multipro/pb/p2p.proto
@@ -16,7 +16,7 @@ message MessageData {
//// ping protocol
-// a protocol define a set of reuqest and responses
+// A protocol defines a set of requests and responses.
message PingRequest {
MessageData messageData = 1;
@@ -36,7 +36,7 @@ message PingResponse {
//// echo protocol
-// a protocol define a set of reuqest and responses
+// A protocol defines a set of requests and responses.
message EchoRequest {
MessageData messageData = 1;
diff --git a/examples/pubsub/basic-chat-with-rendezvous/go.mod b/examples/pubsub/basic-chat-with-rendezvous/go.mod
index c775e76528..7f3c62a676 100644
--- a/examples/pubsub/basic-chat-with-rendezvous/go.mod
+++ b/examples/pubsub/basic-chat-with-rendezvous/go.mod
@@ -3,9 +3,9 @@ module github.com/libp2p/go-libp2p/examples/pubsub/chat
go 1.20
require (
- github.com/libp2p/go-libp2p v0.31.0
- github.com/libp2p/go-libp2p-kad-dht v0.21.0
- github.com/libp2p/go-libp2p-pubsub v0.9.0
+ github.com/libp2p/go-libp2p v0.32.0
+ github.com/libp2p/go-libp2p-kad-dht v0.25.1
+ github.com/libp2p/go-libp2p-pubsub v0.10.0
)
require (
@@ -18,95 +18,100 @@ require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
- github.com/emirpasic/gods v1.18.1 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
+ github.com/go-logr/logr v1.2.4 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
- github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gopacket v1.1.19 // indirect
- github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect
+ github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
- github.com/huin/goupnp v1.2.0 // indirect
+ github.com/huin/goupnp v1.3.0 // indirect
+ github.com/ipfs/boxo v0.10.0 // indirect
github.com/ipfs/go-cid v0.4.1 // indirect
github.com/ipfs/go-datastore v0.6.0 // indirect
- github.com/ipfs/go-ipfs-util v0.0.2 // indirect
- github.com/ipfs/go-ipns v0.2.0 // indirect
github.com/ipfs/go-log v1.0.5 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect
- github.com/ipld/go-ipld-prime v0.9.0 // indirect
+ github.com/ipld/go-ipld-prime v0.20.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
- github.com/klauspost/compress v1.16.7 // indirect
+ github.com/klauspost/compress v1.17.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.1.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect
- github.com/libp2p/go-libp2p-kbucket v0.5.0 // indirect
+ github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect
github.com/libp2p/go-libp2p-record v0.2.0 // indirect
+ github.com/libp2p/go-libp2p-routing-helpers v0.7.2 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-nat v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect
github.com/libp2p/go-reuseport v0.4.0 // indirect
github.com/libp2p/go-yamux/v4 v4.0.1 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
- github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
- github.com/miekg/dns v1.1.55 // indirect
+ github.com/miekg/dns v1.1.56 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
- github.com/multiformats/go-multiaddr v0.11.0 // indirect
+ github.com/multiformats/go-multiaddr v0.12.0 // indirect
github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
- github.com/multiformats/go-multistream v0.4.1 // indirect
+ github.com/multiformats/go-multistream v0.5.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
- github.com/onsi/ginkgo/v2 v2.11.0 // indirect
+ github.com/onsi/ginkgo/v2 v2.13.0 // indirect
github.com/opencontainers/runtime-spec v1.1.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/pkg/errors v0.9.1 // indirect
- github.com/polydawn/refmt v0.0.0-20190807091052-3d65705ee9f1 // indirect
- github.com/prometheus/client_golang v1.14.0 // indirect
+ github.com/polydawn/refmt v0.89.0 // indirect
+ github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
- github.com/prometheus/common v0.42.0 // indirect
- github.com/prometheus/procfs v0.9.0 // indirect
+ github.com/prometheus/common v0.44.0 // indirect
+ github.com/prometheus/procfs v0.11.1 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
- github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
- github.com/quic-go/quic-go v0.38.1 // indirect
- github.com/quic-go/webtransport-go v0.5.3 // indirect
+ github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
+ github.com/quic-go/quic-go v0.39.3 // indirect
+ github.com/quic-go/webtransport-go v0.6.0 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
go.opencensus.io v0.24.0 // indirect
- go.uber.org/dig v1.17.0 // indirect
- go.uber.org/fx v1.20.0 // indirect
+ go.opentelemetry.io/otel v1.16.0 // indirect
+ go.opentelemetry.io/otel/metric v1.16.0 // indirect
+ go.opentelemetry.io/otel/trace v1.16.0 // indirect
+ go.uber.org/dig v1.17.1 // indirect
+ go.uber.org/fx v1.20.1 // indirect
+ go.uber.org/mock v0.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.25.0 // indirect
- golang.org/x/crypto v0.12.0 // indirect
- golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
- golang.org/x/mod v0.12.0 // indirect
- golang.org/x/net v0.14.0 // indirect
- golang.org/x/sync v0.3.0 // indirect
- golang.org/x/sys v0.11.0 // indirect
- golang.org/x/text v0.12.0 // indirect
- golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
- google.golang.org/protobuf v1.30.0 // indirect
+ go.uber.org/zap v1.26.0 // indirect
+ golang.org/x/crypto v0.14.0 // indirect
+ golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
+ golang.org/x/mod v0.13.0 // indirect
+ golang.org/x/net v0.17.0 // indirect
+ golang.org/x/sync v0.4.0 // indirect
+ golang.org/x/sys v0.13.0 // indirect
+ golang.org/x/text v0.13.0 // indirect
+ golang.org/x/tools v0.14.0 // indirect
+ gonum.org/v1/gonum v0.13.0 // indirect
+ google.golang.org/protobuf v1.31.0 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
)
diff --git a/examples/pubsub/basic-chat-with-rendezvous/go.sum b/examples/pubsub/basic-chat-with-rendezvous/go.sum
index 4c673531e3..69289f6e8b 100644
--- a/examples/pubsub/basic-chat-with-rendezvous/go.sum
+++ b/examples/pubsub/basic-chat-with-rendezvous/go.sum
@@ -48,8 +48,6 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4=
github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
-github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
-github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@@ -59,14 +57,19 @@ github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
-github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
+github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
+github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
+github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
@@ -76,13 +79,11 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
-github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -104,7 +105,6 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
@@ -113,16 +113,16 @@ github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo=
-github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
+github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0=
+github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
-github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
@@ -136,9 +136,10 @@ github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+l
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
-github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY=
-github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
-github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M=
+github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
+github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
+github.com/ipfs/boxo v0.10.0 h1:tdDAxq8jrsbRkYoF+5Rcqyeb91hgWe2hp7iLu7ORZLY=
+github.com/ipfs/boxo v0.10.0/go.mod h1:Fg+BnfxZ0RPzR0nOodzdIq3A7KgoWAOWsEIImrIQdBM=
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
@@ -146,16 +147,13 @@ github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8=
-github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ=
-github.com/ipfs/go-ipns v0.2.0 h1:BgmNtQhqOw5XEZ8RAfWEpK4DhqaYiuP6h71MhIp7xXU=
-github.com/ipfs/go-ipns v0.2.0/go.mod h1:3cLT2rbvgPZGkHJoPO1YMJeh6LtkxopCkKFcio/wE24=
github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
-github.com/ipld/go-ipld-prime v0.9.0 h1:N2OjJMb+fhyFPwPnVvJcWU/NsumP8etal+d2v3G4eww=
-github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8=
+github.com/ipld/go-ipld-prime v0.20.0 h1:Ud3VwE9ClxpO2LkCYP7vWPc0Fo+dYdYzgxUJZ3uRG4g=
+github.com/ipld/go-ipld-prime v0.20.0/go.mod h1:PzqZ/ZR981eKbgdr3y2DJYeD/8bgMawdGVlJDE8kK+M=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
@@ -171,16 +169,15 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
-github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
-github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
+github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@@ -191,18 +188,20 @@ github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38y
github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro=
-github.com/libp2p/go-libp2p v0.31.0 h1:LFShhP8F6xthWiBBq3euxbKjZsoRajVEyBS9snfHxYg=
-github.com/libp2p/go-libp2p v0.31.0/go.mod h1:W/FEK1c/t04PbRH3fA9i5oucu5YcgrG0JVoBWT1B7Eg=
+github.com/libp2p/go-libp2p v0.32.0 h1:86I4B7nBUPIyTgw3+5Ibq6K7DdKRCuZw8URCfPc1hQM=
+github.com/libp2p/go-libp2p v0.32.0/go.mod h1:hXXC3kXPlBZ1eu8Q2hptGrMB4mZ3048JUoS4EKaHW5c=
github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s=
github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w=
-github.com/libp2p/go-libp2p-kad-dht v0.21.0 h1:J0Yd22VA+sk0CJRGMgtfHvLVIkZDyJ3AJGiljywIw5U=
-github.com/libp2p/go-libp2p-kad-dht v0.21.0/go.mod h1:Bhm9diAFmc6qcWAr084bHNL159srVZRKADdp96Qqd1I=
-github.com/libp2p/go-libp2p-kbucket v0.5.0 h1:g/7tVm8ACHDxH29BGrpsQlnNeu+6OF1A9bno/4/U1oA=
-github.com/libp2p/go-libp2p-kbucket v0.5.0/go.mod h1:zGzGCpQd78b5BNTDGHNDLaTt9aDK/A02xeZp9QeFC4U=
-github.com/libp2p/go-libp2p-pubsub v0.9.0 h1:mcLb4WzwhUG4OKb0rp1/bYMd/DYhvMyzJheQH3LMd1s=
-github.com/libp2p/go-libp2p-pubsub v0.9.0/go.mod h1:OEsj0Cc/BpkqikXRTrVspWU/Hx7bMZwHP+6vNMd+c7I=
+github.com/libp2p/go-libp2p-kad-dht v0.25.1 h1:ofFNrf6MMEy4vi3R1VbJ7LOcTn3Csh0cDcaWHTxtWNA=
+github.com/libp2p/go-libp2p-kad-dht v0.25.1/go.mod h1:6za56ncRHYXX4Nc2vn8z7CZK0P4QiMcrn77acKLM2Oo=
+github.com/libp2p/go-libp2p-kbucket v0.6.3 h1:p507271wWzpy2f1XxPzCQG9NiN6R6lHL9GiSErbQQo0=
+github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEHetYSPXOaJnOiD8i0=
+github.com/libp2p/go-libp2p-pubsub v0.10.0 h1:wS0S5FlISavMaAbxyQn3dxMOe2eegMfswM471RuHJwA=
+github.com/libp2p/go-libp2p-pubsub v0.10.0/go.mod h1:1OxbaT/pFRO5h+Dpze8hdHQ63R0ke55XTs6b6NwLLkw=
github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0=
github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk=
+github.com/libp2p/go-libp2p-routing-helpers v0.7.2 h1:xJMFyhQ3Iuqnk9Q2dYE1eUTzsah7NLw3Qs2zjUV78T0=
+github.com/libp2p/go-libp2p-routing-helpers v0.7.2/go.mod h1:cN4mJAD/7zfPKXBcs9ze31JGYAZgzdABEm+q/hkswb8=
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
@@ -219,15 +218,15 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
-github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
-github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
-github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
+github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
+github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
@@ -236,52 +235,42 @@ github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdn
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
-github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
-github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
-github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
-github.com/multiformats/go-multiaddr v0.11.0 h1:XqGyJ8ufbCE0HmTDwx2kPdsrQ36AGPZNZX6s6xfJH10=
-github.com/multiformats/go-multiaddr v0.11.0/go.mod h1:gWUm0QLR4thQ6+ZF6SXUw8YjtwQSPapICM+NmCkxHSM=
+github.com/multiformats/go-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE=
+github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8=
github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A=
github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
-github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg=
github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k=
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
-github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
-github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
-github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg=
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
-github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo=
-github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q=
+github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE=
+github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA=
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
-github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
-github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
-github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
-github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
-github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
+github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
+github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
+github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -295,32 +284,33 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/polydawn/refmt v0.0.0-20190807091052-3d65705ee9f1 h1:CskT+S6Ay54OwxBGB0R3Rsx4Muto6UnEYTyKJbyRIAI=
-github.com/polydawn/refmt v0.0.0-20190807091052-3d65705ee9f1/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o=
+github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4=
+github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
-github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
+github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
+github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
-github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
-github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
+github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
+github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
-github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
+github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
+github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
-github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=
-github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
-github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE=
-github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4=
-github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU=
-github.com/quic-go/webtransport-go v0.5.3/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU=
+github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
+github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
+github.com/quic-go/quic-go v0.39.3 h1:o3YB6t2SR+HU/pgwF29kJ6g4jJIJEwEZ8CKia1h1TKg=
+github.com/quic-go/quic-go v0.39.3/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q=
+github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY=
+github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc=
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
@@ -348,10 +338,10 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
-github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
-github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
+github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
+github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
+github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
@@ -370,10 +360,11 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
-github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a h1:G++j5e0OC488te356JvdhaM8YS6nMsjLAYF7JxCv07w=
-github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
+github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
+github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -382,15 +373,23 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
+go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s=
+go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
+go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
+go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
+go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs=
+go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
-go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI=
-go.uber.org/dig v1.17.0/go.mod h1:rTxpf7l5I0eBTlE6/9RL+lDybC7WFwY2QH55ZSjy1mU=
-go.uber.org/fx v1.20.0 h1:ZMC/pnRvhsthOZh9MZjMq5U8Or3mA9zBSPaLnzs3ihQ=
-go.uber.org/fx v1.20.0/go.mod h1:qCUj0btiR3/JnanEr1TYEePfSw6o/4qYJscgvzQ5Ub0=
+go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc=
+go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
+go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk=
+go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
+go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
+go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
@@ -398,8 +397,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
-go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
-go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
+go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
+go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -410,13 +409,12 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
-golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
-golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -428,8 +426,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
+golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -447,8 +445,8 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
-golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -462,8 +460,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -477,21 +475,19 @@ golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
-golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
-golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -510,14 +506,15 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
-golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
+golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
+golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gonum.org/v1/gonum v0.13.0 h1:a0T3bh+7fhRyqeNbiC3qVHYmkiQgit3wnNan/2c0HMM=
+gonum.org/v1/gonum v0.13.0/go.mod h1:/WPYRckkfWrhWefxyYTfrTtQR0KH4iyHNuzxqXAKyAU=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
@@ -551,8 +548,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
-google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
@@ -562,6 +559,7 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/examples/pubsub/basic-chat-with-rendezvous/main.go b/examples/pubsub/basic-chat-with-rendezvous/main.go
index 57729ed137..46d8ca093e 100644
--- a/examples/pubsub/basic-chat-with-rendezvous/main.go
+++ b/examples/pubsub/basic-chat-with-rendezvous/main.go
@@ -95,9 +95,9 @@ func discoverPeers(ctx context.Context, h host.Host) {
}
err := h.Connect(ctx, peer)
if err != nil {
- fmt.Println("Failed connecting to ", peer.ID.Pretty(), ", error:", err)
+ fmt.Printf("Failed connecting to %s, error: %s\n", peer.ID, err)
} else {
- fmt.Println("Connected to:", peer.ID.Pretty())
+ fmt.Println("Connected to:", peer.ID)
anyConnected = true
}
}
diff --git a/examples/pubsub/chat/README.md b/examples/pubsub/chat/README.md
index 2b99c1219f..a37af70543 100644
--- a/examples/pubsub/chat/README.md
+++ b/examples/pubsub/chat/README.md
@@ -132,7 +132,7 @@ to the `pubsub.Topic`:
func (cr *ChatRoom) Publish(message string) error {
m := ChatMessage{
Message: message,
- SenderID: cr.self.Pretty(),
+ SenderID: cr.self.String(),
SenderNick: cr.nick,
}
msgBytes, err := json.Marshal(m)
diff --git a/examples/pubsub/chat/chatroom.go b/examples/pubsub/chat/chatroom.go
index 452cc309e8..dc323d5018 100644
--- a/examples/pubsub/chat/chatroom.go
+++ b/examples/pubsub/chat/chatroom.go
@@ -71,7 +71,7 @@ func JoinChatRoom(ctx context.Context, ps *pubsub.PubSub, selfID peer.ID, nickna
func (cr *ChatRoom) Publish(message string) error {
m := ChatMessage{
Message: message,
- SenderID: cr.self.Pretty(),
+ SenderID: cr.self.String(),
SenderNick: cr.nick,
}
msgBytes, err := json.Marshal(m)
diff --git a/examples/pubsub/chat/go.mod b/examples/pubsub/chat/go.mod
index 25b7451c72..18de1a589e 100644
--- a/examples/pubsub/chat/go.mod
+++ b/examples/pubsub/chat/go.mod
@@ -4,8 +4,8 @@ go 1.20
require (
github.com/gdamore/tcell/v2 v2.5.2
- github.com/libp2p/go-libp2p v0.31.0
- github.com/libp2p/go-libp2p-pubsub v0.9.0
+ github.com/libp2p/go-libp2p v0.32.0
+ github.com/libp2p/go-libp2p-pubsub v0.10.0
github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8
)
@@ -19,26 +19,23 @@ require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
- github.com/emirpasic/gods v1.18.1 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/gdamore/encoding v1.0.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
- github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gopacket v1.1.19 // indirect
- github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect
+ github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
- github.com/huin/goupnp v1.2.0 // indirect
+ github.com/huin/goupnp v1.3.0 // indirect
github.com/ipfs/go-cid v0.4.1 // indirect
- github.com/ipfs/go-log v1.0.5 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
- github.com/klauspost/compress v1.16.7 // indirect
+ github.com/klauspost/compress v1.17.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
@@ -53,27 +50,26 @@ require (
github.com/libp2p/zeroconf/v2 v2.2.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
- github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
- github.com/miekg/dns v1.1.55 // indirect
+ github.com/miekg/dns v1.1.56 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
- github.com/multiformats/go-multiaddr v0.11.0 // indirect
+ github.com/multiformats/go-multiaddr v0.12.0 // indirect
github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
- github.com/multiformats/go-multistream v0.4.1 // indirect
+ github.com/multiformats/go-multistream v0.5.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
- github.com/onsi/ginkgo/v2 v2.11.0 // indirect
+ github.com/onsi/ginkgo/v2 v2.13.0 // indirect
github.com/opencontainers/runtime-spec v1.1.0 // indirect
- github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
@@ -81,25 +77,26 @@ require (
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
- github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
- github.com/quic-go/quic-go v0.38.1 // indirect
- github.com/quic-go/webtransport-go v0.5.3 // indirect
+ github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
+ github.com/quic-go/quic-go v0.39.3 // indirect
+ github.com/quic-go/webtransport-go v0.6.0 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
- go.uber.org/dig v1.17.0 // indirect
- go.uber.org/fx v1.20.0 // indirect
+ go.uber.org/dig v1.17.1 // indirect
+ go.uber.org/fx v1.20.1 // indirect
+ go.uber.org/mock v0.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.25.0 // indirect
- golang.org/x/crypto v0.12.0 // indirect
- golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
- golang.org/x/mod v0.12.0 // indirect
- golang.org/x/net v0.14.0 // indirect
- golang.org/x/sync v0.3.0 // indirect
- golang.org/x/sys v0.11.0 // indirect
- golang.org/x/term v0.11.0 // indirect
- golang.org/x/text v0.12.0 // indirect
- golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
+ go.uber.org/zap v1.26.0 // indirect
+ golang.org/x/crypto v0.14.0 // indirect
+ golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
+ golang.org/x/mod v0.13.0 // indirect
+ golang.org/x/net v0.17.0 // indirect
+ golang.org/x/sync v0.4.0 // indirect
+ golang.org/x/sys v0.13.0 // indirect
+ golang.org/x/term v0.13.0 // indirect
+ golang.org/x/text v0.13.0 // indirect
+ golang.org/x/tools v0.14.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
)
diff --git a/examples/pubsub/chat/go.sum b/examples/pubsub/chat/go.sum
index 525b606a93..a347d5219e 100644
--- a/examples/pubsub/chat/go.sum
+++ b/examples/pubsub/chat/go.sum
@@ -46,8 +46,6 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4=
github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
-github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
-github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
@@ -77,8 +75,6 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
-github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
@@ -95,9 +91,8 @@ github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo=
-github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
-github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0=
+github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -107,15 +102,12 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
-github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY=
-github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
+github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
+github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
-github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
-github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
-github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
@@ -128,8 +120,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
-github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
+github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
@@ -147,12 +139,12 @@ github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38y
github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro=
-github.com/libp2p/go-libp2p v0.31.0 h1:LFShhP8F6xthWiBBq3euxbKjZsoRajVEyBS9snfHxYg=
-github.com/libp2p/go-libp2p v0.31.0/go.mod h1:W/FEK1c/t04PbRH3fA9i5oucu5YcgrG0JVoBWT1B7Eg=
+github.com/libp2p/go-libp2p v0.32.0 h1:86I4B7nBUPIyTgw3+5Ibq6K7DdKRCuZw8URCfPc1hQM=
+github.com/libp2p/go-libp2p v0.32.0/go.mod h1:hXXC3kXPlBZ1eu8Q2hptGrMB4mZ3048JUoS4EKaHW5c=
github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s=
github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w=
-github.com/libp2p/go-libp2p-pubsub v0.9.0 h1:mcLb4WzwhUG4OKb0rp1/bYMd/DYhvMyzJheQH3LMd1s=
-github.com/libp2p/go-libp2p-pubsub v0.9.0/go.mod h1:OEsj0Cc/BpkqikXRTrVspWU/Hx7bMZwHP+6vNMd+c7I=
+github.com/libp2p/go-libp2p-pubsub v0.10.0 h1:wS0S5FlISavMaAbxyQn3dxMOe2eegMfswM471RuHJwA=
+github.com/libp2p/go-libp2p-pubsub v0.10.0/go.mod h1:1OxbaT/pFRO5h+Dpze8hdHQ63R0ke55XTs6b6NwLLkw=
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
@@ -173,8 +165,8 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
-github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@@ -183,8 +175,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfr
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
-github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
-github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
+github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
+github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
@@ -206,8 +198,8 @@ github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
-github.com/multiformats/go-multiaddr v0.11.0 h1:XqGyJ8ufbCE0HmTDwx2kPdsrQ36AGPZNZX6s6xfJH10=
-github.com/multiformats/go-multiaddr v0.11.0/go.mod h1:gWUm0QLR4thQ6+ZF6SXUw8YjtwQSPapICM+NmCkxHSM=
+github.com/multiformats/go-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE=
+github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8=
github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A=
github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
@@ -219,21 +211,19 @@ github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI1
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
-github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo=
-github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q=
+github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE=
+github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA=
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
-github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
-github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
-github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
+github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
+github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
+github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
-github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
@@ -256,19 +246,18 @@ github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJf
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
-github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=
-github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
-github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE=
-github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4=
-github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU=
-github.com/quic-go/webtransport-go v0.5.3/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU=
+github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
+github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
+github.com/quic-go/quic-go v0.39.3 h1:o3YB6t2SR+HU/pgwF29kJ6g4jJIJEwEZ8CKia1h1TKg=
+github.com/quic-go/quic-go v0.39.3/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q=
+github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY=
+github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc=
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8 h1:xe+mmCnDN82KhC010l3NfYlA8ZbOuzbXAzSYBa6wbMc=
github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8/go.mod h1:WIfMkQNY+oq/mWwtsjOYHIZBuwthioY2srOmljJkTnk=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
-github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
@@ -315,52 +304,48 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
-go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
-go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI=
-go.uber.org/dig v1.17.0/go.mod h1:rTxpf7l5I0eBTlE6/9RL+lDybC7WFwY2QH55ZSjy1mU=
-go.uber.org/fx v1.20.0 h1:ZMC/pnRvhsthOZh9MZjMq5U8Or3mA9zBSPaLnzs3ihQ=
-go.uber.org/fx v1.20.0/go.mod h1:qCUj0btiR3/JnanEr1TYEePfSw6o/4qYJscgvzQ5Ub0=
+go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc=
+go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
+go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk=
+go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
-go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
+go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
+go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
-go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
-go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
-go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
-go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
+go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
+go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
-golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
-golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
+golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -378,8 +363,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
-golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
-golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -393,8 +378,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -417,20 +402,20 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220318055525-2edf467146b5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
-golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
-golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
+golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
+golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
-golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -440,17 +425,13 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
-golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
+golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
+golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -479,7 +460,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -491,7 +471,6 @@ grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJd
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
diff --git a/examples/pubsub/chat/main.go b/examples/pubsub/chat/main.go
index 45a103d03d..593e41e245 100644
--- a/examples/pubsub/chat/main.go
+++ b/examples/pubsub/chat/main.go
@@ -80,7 +80,7 @@ func defaultNick(p peer.ID) string {
// shortID returns the last 8 chars of a base58-encoded peer id.
func shortID(p peer.ID) string {
- pretty := p.Pretty()
+ pretty := p.String()
return pretty[len(pretty)-8:]
}
@@ -93,10 +93,10 @@ type discoveryNotifee struct {
// the PubSub system will automatically start interacting with them if they also
// support PubSub.
func (n *discoveryNotifee) HandlePeerFound(pi peer.AddrInfo) {
- fmt.Printf("discovered new peer %s\n", pi.ID.Pretty())
+ fmt.Printf("discovered new peer %s\n", pi.ID)
err := n.h.Connect(context.Background(), pi)
if err != nil {
- fmt.Printf("error connecting to peer %s: %s\n", pi.ID.Pretty(), err)
+ fmt.Printf("error connecting to peer %s: %s\n", pi.ID, err)
}
}
diff --git a/examples/relay/main.go b/examples/relay/main.go
index e8fa8b7ba0..7e16b1b19d 100644
--- a/examples/relay/main.go
+++ b/examples/relay/main.go
@@ -27,7 +27,7 @@ func run() {
unreachable1, err := libp2p.New(
libp2p.NoListenAddrs,
// Usually EnableRelay() is not required as it is enabled by default
- // but NoListenAddrs overrides this, so we're adding it in explictly again.
+ // but NoListenAddrs overrides this, so we're adding it in explicitly again.
libp2p.EnableRelay(),
)
if err != nil {
diff --git a/examples/routed-echo/main.go b/examples/routed-echo/main.go
index 2f40549b51..342661b619 100644
--- a/examples/routed-echo/main.go
+++ b/examples/routed-echo/main.go
@@ -83,7 +83,7 @@ func makeRoutedHost(listenPort int, randseed int64, bootstrapPeers []peer.AddrIn
}
// Build host multiaddress
- hostAddr, _ := ma.NewMultiaddr(fmt.Sprintf("/ipfs/%s", routedHost.ID().Pretty()))
+ hostAddr, _ := ma.NewMultiaddr(fmt.Sprintf("/ipfs/%s", routedHost.ID()))
// Now we can build a full multiaddress to reach this host
// by encapsulating both addresses:
@@ -94,7 +94,7 @@ func makeRoutedHost(listenPort int, randseed int64, bootstrapPeers []peer.AddrIn
log.Println(addr.Encapsulate(hostAddr))
}
- log.Printf("Now run \"./routed-echo -l %d -d %s%s\" on a different terminal\n", listenPort+1, routedHost.ID().Pretty(), globalFlag)
+ log.Printf("Now run \"./routed-echo -l %d -d %s%s\" on a different terminal\n", listenPort+1, routedHost.ID(), globalFlag)
return routedHost, nil
}
diff --git a/go.mod b/go.mod
index da172c0581..1ba2f7ac34 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module github.com/libp2p/go-libp2p
-go 1.20
+go 1.21
retract v0.26.1 // Tag was applied incorrectly due to a bug in the release workflow.
@@ -8,10 +8,9 @@ require (
github.com/benbjohnson/clock v1.3.5
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0
- github.com/flynn/noise v1.0.0
- github.com/golang/mock v1.6.0
+ github.com/flynn/noise v1.1.0
github.com/google/gopacket v1.1.19
- github.com/gorilla/websocket v1.5.0
+ github.com/gorilla/websocket v1.5.1
github.com/hashicorp/golang-lru/arc/v2 v2.0.5
github.com/hashicorp/golang-lru/v2 v2.0.5
github.com/ipfs/go-cid v0.4.1
@@ -20,10 +19,10 @@ require (
github.com/ipfs/go-ds-leveldb v0.5.0
github.com/ipfs/go-log/v2 v2.5.1
github.com/jbenet/go-temp-err-catcher v0.1.0
- github.com/klauspost/compress v1.16.7
+ github.com/klauspost/compress v1.17.6
github.com/libp2p/go-buffer-pool v0.1.0
github.com/libp2p/go-flow-metrics v0.1.0
- github.com/libp2p/go-libp2p-asn-util v0.3.0
+ github.com/libp2p/go-libp2p-asn-util v0.4.1
github.com/libp2p/go-libp2p-testing v0.12.0
github.com/libp2p/go-msgio v0.3.0
github.com/libp2p/go-nat v0.2.0
@@ -33,32 +32,37 @@ require (
github.com/libp2p/zeroconf/v2 v2.2.0
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b
- github.com/minio/sha256-simd v1.0.1
github.com/mr-tron/base58 v1.2.0
github.com/multiformats/go-base32 v0.1.0
- github.com/multiformats/go-multiaddr v0.11.0
+ github.com/multiformats/go-multiaddr v0.12.2
github.com/multiformats/go-multiaddr-dns v0.3.1
github.com/multiformats/go-multiaddr-fmt v0.1.0
github.com/multiformats/go-multibase v0.2.0
github.com/multiformats/go-multicodec v0.9.0
github.com/multiformats/go-multihash v0.2.3
- github.com/multiformats/go-multistream v0.4.1
+ github.com/multiformats/go-multistream v0.5.0
github.com/multiformats/go-varint v0.0.7
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58
- github.com/prometheus/client_golang v1.14.0
- github.com/prometheus/client_model v0.4.0
- github.com/quic-go/quic-go v0.38.1
- github.com/quic-go/webtransport-go v0.5.3
+ github.com/pion/datachannel v1.5.5
+ github.com/pion/ice/v2 v2.3.11
+ github.com/pion/logging v0.2.2
+ github.com/pion/stun v0.6.1
+ github.com/pion/webrtc/v3 v3.2.23
+ github.com/prometheus/client_golang v1.18.0
+ github.com/prometheus/client_model v0.6.0
+ github.com/quic-go/quic-go v0.41.0
+ github.com/quic-go/webtransport-go v0.6.0
github.com/raulk/go-watchdog v1.3.0
github.com/stretchr/testify v1.8.4
- go.uber.org/fx v1.20.0
- go.uber.org/goleak v1.2.0
- golang.org/x/crypto v0.12.0
- golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
- golang.org/x/sync v0.3.0
- golang.org/x/sys v0.11.0
- golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846
- google.golang.org/protobuf v1.30.0
+ go.uber.org/fx v1.20.1
+ go.uber.org/goleak v1.3.0
+ go.uber.org/mock v0.4.0
+ golang.org/x/crypto v0.19.0
+ golang.org/x/exp v0.0.0-20240213143201-ec583247a57a
+ golang.org/x/sync v0.6.0
+ golang.org/x/sys v0.17.0
+ golang.org/x/tools v0.18.0
+ google.golang.org/protobuf v1.32.0
)
require (
@@ -81,37 +85,45 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
- github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect
- github.com/google/uuid v1.3.0 // indirect
- github.com/huin/goupnp v1.2.0 // indirect
+ github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect
+ github.com/google/uuid v1.4.0 // indirect
+ github.com/huin/goupnp v1.3.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
- github.com/klauspost/cpuid/v2 v2.2.5 // indirect
+ github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
- github.com/libp2p/go-cidranger v1.1.0 // indirect
- github.com/mattn/go-isatty v0.0.19 // indirect
- github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
- github.com/miekg/dns v1.1.55 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/miekg/dns v1.1.58 // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
+ github.com/minio/sha256-simd v1.0.1 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
- github.com/onsi/ginkgo v1.16.5 // indirect
- github.com/onsi/ginkgo/v2 v2.11.0 // indirect
- github.com/opencontainers/runtime-spec v1.1.0 // indirect
+ github.com/onsi/ginkgo/v2 v2.15.0 // indirect
+ github.com/opencontainers/runtime-spec v1.2.0 // indirect
+ github.com/pion/dtls/v2 v2.2.8 // indirect
+ github.com/pion/interceptor v0.1.25 // indirect
+ github.com/pion/mdns v0.0.9 // indirect
+ github.com/pion/randutil v0.1.0 // indirect
+ github.com/pion/rtcp v1.2.13 // indirect
+ github.com/pion/rtp v1.8.3 // indirect
+ github.com/pion/sctp v1.8.9 // indirect
+ github.com/pion/sdp/v3 v3.0.6 // indirect
+ github.com/pion/srtp/v2 v2.0.18 // indirect
+ github.com/pion/transport/v2 v2.2.4 // indirect
+ github.com/pion/turn/v2 v2.1.4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/prometheus/common v0.37.0 // indirect
- github.com/prometheus/procfs v0.8.0 // indirect
+ github.com/prometheus/common v0.47.0 // indirect
+ github.com/prometheus/procfs v0.12.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
- github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
- go.uber.org/dig v1.17.0 // indirect
+ go.uber.org/dig v1.17.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.25.0 // indirect
- golang.org/x/mod v0.12.0 // indirect
- golang.org/x/net v0.14.0 // indirect
- golang.org/x/text v0.12.0 // indirect
+ go.uber.org/zap v1.27.0 // indirect
+ golang.org/x/mod v0.15.0 // indirect
+ golang.org/x/net v0.21.0 // indirect
+ golang.org/x/text v0.14.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
)
diff --git a/go.sum b/go.sum
index 8e84048fc9..0137afb78e 100644
--- a/go.sum
+++ b/go.sum
@@ -2,38 +2,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
-cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
-cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
-cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
-cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
-cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
-cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
-cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
-cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
-cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
-cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
-cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
-cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
-cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
-cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
-cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
-cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
-cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
-cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
-cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
-cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
-cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
-cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
-cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
-cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
-cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
-cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
-cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
-cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
-cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
-cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
-dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
@@ -41,14 +10,8 @@ git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGy
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M=
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
-github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
@@ -56,24 +19,16 @@ github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZx
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
-github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
-github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
-github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
-github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
-github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
@@ -93,6 +48,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU=
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
+github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8=
@@ -109,13 +65,9 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4=
github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
-github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
-github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
-github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
-github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
+github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=
+github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@@ -125,19 +77,8 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
-github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
-github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
-github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
-github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
-github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
-github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
-github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
-github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
+github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
@@ -150,33 +91,17 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
-github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
-github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
-github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
-github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
-github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
-github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
@@ -184,58 +109,42 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
-github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
-github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo=
-github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
+github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo=
+github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
-github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
+github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
-github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
-github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
-github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
-github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
+github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
-github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru/arc/v2 v2.0.5 h1:l2zaLDubNhW4XO3LnliVj0GXO3+/CGNJAg1dcN2Fpfw=
github.com/hashicorp/golang-lru/arc/v2 v2.0.5/go.mod h1:ny6zBSQZi2JxIeYcv7kt2sH2PXJtirBN7RDhRpxPkxU=
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY=
-github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
-github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
+github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
@@ -260,43 +169,33 @@ github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPw
github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o=
github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
-github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
-github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
-github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
-github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
-github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
-github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
-github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
+github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
+github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
+github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
-github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
-github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c=
-github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro=
-github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s=
-github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w=
+github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
+github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg=
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
@@ -317,16 +216,14 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
-github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
-github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
-github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
-github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
+github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
+github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
@@ -339,11 +236,8 @@ github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dz
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
@@ -353,8 +247,8 @@ github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
-github.com/multiformats/go-multiaddr v0.11.0 h1:XqGyJ8ufbCE0HmTDwx2kPdsrQ36AGPZNZX6s6xfJH10=
-github.com/multiformats/go-multiaddr v0.11.0/go.mod h1:gWUm0QLR4thQ6+ZF6SXUw8YjtwQSPapICM+NmCkxHSM=
+github.com/multiformats/go-multiaddr v0.12.2 h1:9G9sTY/wCYajKa9lyfWPmpZAwe6oV+Wb1zcmMS1HG24=
+github.com/multiformats/go-multiaddr v0.12.2/go.mod h1:GKyaTYjZRdcUhyOetrxTk9z0cW+jA/YrnqTOvKgi44M=
github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A=
github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
@@ -366,13 +260,11 @@ github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI1
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
-github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo=
-github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q=
+github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE=
+github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA=
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
-github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
@@ -381,69 +273,102 @@ github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
-github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
-github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
+github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
+github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
-github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
+github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
+github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
+github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
-github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
+github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
-github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8=
+github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0=
+github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
+github.com/pion/dtls/v2 v2.2.8 h1:BUroldfiIbV9jSnC6cKOMnyiORRWrWWpV11JUyEu5OA=
+github.com/pion/dtls/v2 v2.2.8/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
+github.com/pion/ice/v2 v2.3.11 h1:rZjVmUwyT55cmN8ySMpL7rsS8KYsJERsrxJLLxpKhdw=
+github.com/pion/ice/v2 v2.3.11/go.mod h1:hPcLC3kxMa+JGRzMHqQzjoSj3xtE9F+eoncmXLlCL4E=
+github.com/pion/interceptor v0.1.25 h1:pwY9r7P6ToQ3+IF0bajN0xmk/fNw/suTgaTdlwTDmhc=
+github.com/pion/interceptor v0.1.25/go.mod h1:wkbPYAak5zKsfpVDYMtEfWEy8D4zL+rpxCxPImLOg3Y=
+github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
+github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
+github.com/pion/mdns v0.0.8/go.mod h1:hYE72WX8WDveIhg7fmXgMKivD3Puklk0Ymzog0lSyaI=
+github.com/pion/mdns v0.0.9 h1:7Ue5KZsqq8EuqStnpPWV33vYYEH0+skdDN5L7EiEsI4=
+github.com/pion/mdns v0.0.9/go.mod h1:2JA5exfxwzXiCihmxpTKgFUpiQws2MnipoPK09vecIc=
+github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
+github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
+github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I=
+github.com/pion/rtcp v1.2.12/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4=
+github.com/pion/rtcp v1.2.13 h1:+EQijuisKwm/8VBs8nWllr0bIndR7Lf7cZG200mpbNo=
+github.com/pion/rtcp v1.2.13/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4=
+github.com/pion/rtp v1.8.2/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
+github.com/pion/rtp v1.8.3 h1:VEHxqzSVQxCkKDSHro5/4IUUG1ea+MFdqR2R3xSpNU8=
+github.com/pion/rtp v1.8.3/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
+github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0=
+github.com/pion/sctp v1.8.8/go.mod h1:igF9nZBrjh5AtmKc7U30jXltsFHicFCXSmWA2GWRaWs=
+github.com/pion/sctp v1.8.9 h1:TP5ZVxV5J7rz7uZmbyvnUvsn7EJ2x/5q9uhsTtXbI3g=
+github.com/pion/sctp v1.8.9/go.mod h1:cMLT45jqw3+jiJCrtHVwfQLnfR0MGZ4rgOJwUOIqLkI=
+github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw=
+github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw=
+github.com/pion/srtp/v2 v2.0.18 h1:vKpAXfawO9RtTRKZJbG4y0v1b11NZxQnxRl85kGuUlo=
+github.com/pion/srtp/v2 v2.0.18/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA=
+github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
+github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
+github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40=
+github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI=
+github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
+github.com/pion/transport/v2 v2.2.2/go.mod h1:OJg3ojoBJopjEeECq2yJdXH9YVrUJ1uQ++NjXLOUorc=
+github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
+github.com/pion/transport/v2 v2.2.4 h1:41JJK6DZQYSeVLxILA2+F4ZkKb4Xd/tFJZRFZQ9QAlo=
+github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
+github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM=
+github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0=
+github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
+github.com/pion/turn/v2 v2.1.4 h1:2xn8rduI5W6sCZQkEnIUDAkrBQNl2eYIBCHMZ3QMmP8=
+github.com/pion/turn/v2 v2.1.4/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
+github.com/pion/webrtc/v3 v3.2.23 h1:GbqEuxBbVLFhXk0GwxKAoaIJYiEa9TyoZPEZC+2HZxM=
+github.com/pion/webrtc/v3 v3.2.23/go.mod h1:1CaT2fcZzZ6VZA+O1i9yK2DU4EOcXVvSbWG9pr5jefs=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
-github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
-github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
-github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
-github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
-github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
+github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
+github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
-github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
-github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
+github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
+github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
-github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
-github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
-github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
-github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
-github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
+github.com/prometheus/common v0.47.0 h1:p5Cz0FNHo7SnWOmWmoRozVcjEp0bIVU8cV7OShpjL1k=
+github.com/prometheus/common v0.47.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
-github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
-github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
-github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
+github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
+github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
-github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=
-github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
-github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE=
-github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4=
-github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU=
-github.com/quic-go/webtransport-go v0.5.3/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU=
+github.com/quic-go/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
+github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
+github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY=
+github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc=
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
+github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
@@ -468,9 +393,6 @@ github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
-github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
-github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
@@ -484,13 +406,18 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
@@ -501,28 +428,24 @@ github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
-github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
-go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
-go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
-go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
-go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI=
-go.uber.org/dig v1.17.0/go.mod h1:rTxpf7l5I0eBTlE6/9RL+lDybC7WFwY2QH55ZSjy1mU=
-go.uber.org/fx v1.20.0 h1:ZMC/pnRvhsthOZh9MZjMq5U8Or3mA9zBSPaLnzs3ihQ=
-go.uber.org/fx v1.20.0/go.mod h1:qCUj0btiR3/JnanEr1TYEePfSw6o/4qYJscgvzQ5Ub0=
+go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc=
+go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
+go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk=
+go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
-go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
-go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
+go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
@@ -530,113 +453,79 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
-go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
-go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
-golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
+golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
+golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
+golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
+golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
+golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
-golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
-golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
-golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
-golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
-golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
-golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
-golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE=
+golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
-golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
-golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
-golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
-golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
-golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
-golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
+golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
-golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
-golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
+golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
+golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
+golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
+golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
+golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -644,90 +533,79 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
+golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
+golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
+golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
+golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
+golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -735,51 +613,19 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
-golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
-golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
-golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
-golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
+golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -787,93 +633,29 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
-google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
-google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
-google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
-google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
-google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
-google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
-google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
-google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
-google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
-google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
-google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
-google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
-google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
-google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
-google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
-google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
-google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
-google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
-google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
+google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -887,7 +669,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
@@ -899,15 +680,8 @@ grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJd
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
-honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
-rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
-rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
-rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
diff --git a/internal/sha256/post_go1_21.go b/internal/sha256/post_go1_21.go
deleted file mode 100644
index 98c14b609a..0000000000
--- a/internal/sha256/post_go1_21.go
+++ /dev/null
@@ -1,23 +0,0 @@
-//go:build go1.21
-
-// This package use build tags to select between github.com/minio/sha256-simd
-// for go1.20 and bellow and crypto/sha256 for go1.21 and above.
-// This is used because a fast SHANI implementation of sha256 is only avaiable
-// in the std for go1.21 and above. See https://go.dev/issue/50543.
-// TODO: Once go1.22 releases remove this package and replace all uses
-// with crypto/sha256 because the two supported version of go will have the fast
-// implementation.
-package sha256
-
-import (
- "crypto/sha256"
- "hash"
-)
-
-func Sum256(b []byte) [sha256.Size]byte {
- return sha256.Sum256(b)
-}
-
-func New() hash.Hash {
- return sha256.New()
-}
diff --git a/internal/sha256/pre_go1_21.go b/internal/sha256/pre_go1_21.go
deleted file mode 100644
index db05733338..0000000000
--- a/internal/sha256/pre_go1_21.go
+++ /dev/null
@@ -1,24 +0,0 @@
-//go:build !go1.21
-
-// This package use build tags to select between github.com/minio/sha256-simd
-// for go1.20 and bellow and crypto/sha256 for go1.21 and above.
-// This is used because a fast SHANI implementation of sha256 is only avaiable
-// in the std for go1.21 and above. See https://go.dev/issue/50543.
-// TODO: Once go1.22 releases remove this package and replace all uses
-// with crypto/sha256 because the two supported version of go will have the fast
-// implementation.
-package sha256
-
-import (
- "hash"
-
- "github.com/minio/sha256-simd"
-)
-
-func Sum256(b []byte) [sha256.Size]byte {
- return sha256.Sum256(b)
-}
-
-func New() hash.Hash {
- return sha256.New()
-}
diff --git a/libp2p.go b/libp2p.go
index db23253b14..9bb36b178f 100644
--- a/libp2p.go
+++ b/libp2p.go
@@ -42,7 +42,7 @@ func ChainOptions(opts ...Option) Option {
// - If no security transport is provided, the host uses the go-libp2p's noise
// and/or tls encrypted transport to encrypt all traffic;
//
-// - If no peer identity is provided, it generates a random RSA 2048 key-pair
+// - If no peer identity is provided, it generates a random Ed25519 key-pair
// and derives a new identity from it;
//
// - If no peerstore is provided, the host is initialized with an empty
diff --git a/libp2p_test.go b/libp2p_test.go
index 3ec272927e..3ae1ac62e5 100644
--- a/libp2p_test.go
+++ b/libp2p_test.go
@@ -199,7 +199,7 @@ func TestTransportConstructorQUIC(t *testing.T) {
err = h.Network().Listen(ma.StringCast("/ip4/127.0.0.1/tcp/0"))
require.Error(t, err)
require.Contains(t, err.Error(), swarm.ErrNoTransport.Error())
-}
+ }
type mockTransport struct{}
@@ -328,8 +328,8 @@ func TestTransportCustomAddressWebTransport(t *testing.T) {
require.NotEqual(t, addrs[0], customAddr)
restOfAddr, lastComp := ma.SplitLast(addrs[0])
restOfAddr, secondToLastComp := ma.SplitLast(restOfAddr)
- require.Equal(t, lastComp.Protocol().Code, ma.P_CERTHASH)
- require.Equal(t, secondToLastComp.Protocol().Code, ma.P_CERTHASH)
+ require.Equal(t, ma.P_CERTHASH, lastComp.Protocol().Code)
+ require.Equal(t, ma.P_CERTHASH, secondToLastComp.Protocol().Code)
require.True(t, restOfAddr.Equal(customAddr))
}
@@ -355,7 +355,7 @@ func TestTransportCustomAddressWebTransportDoesNotStall(t *testing.T) {
addrs := h.Addrs()
require.Len(t, addrs, 1)
_, lastComp := ma.SplitLast(addrs[0])
- require.NotEqual(t, lastComp.Protocol().Code, ma.P_CERTHASH)
+ require.NotEqual(t, ma.P_CERTHASH, lastComp.Protocol().Code)
// We did not add the certhash to the multiaddr
require.Equal(t, addrs[0], customAddr)
}
diff --git a/options.go b/options.go
index beb4930f7c..747d6c55e6 100644
--- a/options.go
+++ b/options.go
@@ -349,7 +349,7 @@ func EnableAutoRelayWithPeerSource(peerSource autorelay.PeerSource, opts ...auto
// forcing the local node to believe it is reachable externally.
func ForceReachabilityPublic() Option {
return func(cfg *Config) error {
- public := network.Reachability(network.ReachabilityPublic)
+ public := network.ReachabilityPublic
cfg.AutoNATConfig.ForceReachability = &public
return nil
}
@@ -359,7 +359,7 @@ func ForceReachabilityPublic() Option {
// forceing the local node to believe it is behind a NAT and not reachable externally.
func ForceReachabilityPrivate() Option {
return func(cfg *Config) error {
- private := network.Reachability(network.ReachabilityPrivate)
+ private := network.ReachabilityPrivate
cfg.AutoNATConfig.ForceReachability = &private
return nil
}
@@ -579,6 +579,7 @@ func PrometheusRegisterer(reg prometheus.Registerer) Option {
// DialRanker configures libp2p to use d as the dial ranker. To enable smart
// dialing use `swarm.DefaultDialRanker`. use `swarm.NoDelayDialRanker` to
// disable smart dialing.
+//
// Deprecated: use SwarmOpts(swarm.WithDialRanker(d)) instead
func DialRanker(d network.DialRanker) Option {
return func(cfg *Config) error {
diff --git a/p2p/discovery/backoff/backoffcache.go b/p2p/discovery/backoff/backoffcache.go
index 82c07241f6..c8f11802e7 100644
--- a/p2p/discovery/backoff/backoffcache.go
+++ b/p2p/discovery/backoff/backoffcache.go
@@ -82,14 +82,6 @@ func (c realClock) Now() time.Time {
return time.Now()
}
-// withClock lets you override the default time.Now() call. Useful for tests.
-func withClock(c clock) BackoffDiscoveryOption {
- return func(b *BackoffDiscovery) error {
- b.clock = c
- return nil
- }
-}
-
type backoffCache struct {
// strat is assigned on creation and not written to
strat BackoffStrategy
diff --git a/p2p/discovery/backoff/backoffcache_test.go b/p2p/discovery/backoff/backoffcache_test.go
index fe528cca1a..6679415a7f 100644
--- a/p2p/discovery/backoff/backoffcache_test.go
+++ b/p2p/discovery/backoff/backoffcache_test.go
@@ -80,6 +80,14 @@ func assertNumPeersWithLimit(t *testing.T, ctx context.Context, d discovery.Disc
}
}
+// withClock lets you override the default time.Now() call. Useful for tests.
+func withClock(c clock) BackoffDiscoveryOption {
+ return func(b *BackoffDiscovery) error {
+ b.clock = c
+ return nil
+ }
+}
+
func TestBackoffDiscoverySingleBackoff(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
diff --git a/p2p/host/autonat/svc.go b/p2p/host/autonat/svc.go
index 98b421c9b2..cf1dff8e72 100644
--- a/p2p/host/autonat/svc.go
+++ b/p2p/host/autonat/svc.go
@@ -68,7 +68,7 @@ func (as *autoNATService) handleStream(s network.Stream) {
defer s.Close()
pid := s.Conn().RemotePeer()
- log.Debugf("New stream from %s", pid.Pretty())
+ log.Debugf("New stream from %s", pid)
r := pbio.NewDelimitedReader(s, maxMsgSize)
w := pbio.NewDelimitedWriter(s)
@@ -78,14 +78,14 @@ func (as *autoNATService) handleStream(s network.Stream) {
err := r.ReadMsg(&req)
if err != nil {
- log.Debugf("Error reading message from %s: %s", pid.Pretty(), err.Error())
+ log.Debugf("Error reading message from %s: %s", pid, err.Error())
s.Reset()
return
}
t := req.GetType()
if t != pb.Message_DIAL {
- log.Debugf("Unexpected message from %s: %s (%d)", pid.Pretty(), t.String(), t)
+ log.Debugf("Unexpected message from %s: %s (%d)", pid, t.String(), t)
s.Reset()
return
}
@@ -96,7 +96,7 @@ func (as *autoNATService) handleStream(s network.Stream) {
err = w.WriteMsg(&res)
if err != nil {
- log.Debugf("Error writing response to %s: %s", pid.Pretty(), err.Error())
+ log.Debugf("Error writing response to %s: %s", pid, err.Error())
s.Reset()
return
}
@@ -234,7 +234,7 @@ func (as *autoNATService) doDial(pi peer.AddrInfo) *pb.Message_DialResponse {
conn, err := as.config.dialer.DialPeer(ctx, pi.ID)
if err != nil {
- log.Debugf("error dialing %s: %s", pi.ID.Pretty(), err.Error())
+ log.Debugf("error dialing %s: %s", pi.ID, err.Error())
// wait for the context to timeout to avoid leaking timing information
// this renders the service ineffective as a port scanner
<-ctx.Done()
diff --git a/p2p/host/autonat/svc_test.go b/p2p/host/autonat/svc_test.go
index 61e6038c53..d58a9b75e9 100644
--- a/p2p/host/autonat/svc_test.go
+++ b/p2p/host/autonat/svc_test.go
@@ -189,7 +189,7 @@ func TestAutoNATServiceRateLimitJitter(t *testing.T) {
svc.mx.Lock()
defer svc.mx.Unlock()
return svc.globalReqs == 0
- }, dur*5/2, 10*time.Millisecond, "reset of rate limitter occured slower than expected")
+ }, dur*5/2, 10*time.Millisecond, "reset of rate limiter occurred slower than expected")
}
func TestAutoNATServiceStartup(t *testing.T) {
diff --git a/p2p/host/autorelay/metrics.go b/p2p/host/autorelay/metrics.go
index 8028655b01..af4b53ed01 100644
--- a/p2p/host/autorelay/metrics.go
+++ b/p2p/host/autorelay/metrics.go
@@ -59,7 +59,7 @@ var (
prometheus.CounterOpts{
Namespace: metricNamespace,
Name: "candidates_circuit_v2_support_total",
- Help: "Candidiates supporting circuit v2",
+ Help: "Candidates supporting circuit v2",
},
[]string{"support"},
)
@@ -167,7 +167,7 @@ func NewMetricsTracer(opts ...MetricsTracerOption) MetricsTracer {
metricshelper.RegisterCollectors(setting.reg, collectors...)
// Initialise these counters to 0 otherwise the first reservation requests aren't handled
- // correctly when using promql increse function
+ // correctly when using promql increase function
reservationRequestsOutcomeTotal.WithLabelValues("refresh", "success")
reservationRequestsOutcomeTotal.WithLabelValues("new", "success")
candidatesCircuitV2SupportTotal.WithLabelValues("yes")
diff --git a/p2p/host/autorelay/relay_finder.go b/p2p/host/autorelay/relay_finder.go
index 3133b7a51b..13f8c63e6b 100644
--- a/p2p/host/autorelay/relay_finder.go
+++ b/p2p/host/autorelay/relay_finder.go
@@ -63,7 +63,7 @@ type relayFinder struct {
candidates map[peer.ID]*candidate
backoff map[peer.ID]time.Time
maybeConnectToRelayTrigger chan struct{} // cap: 1
- // Any time _something_ hapens that might cause us to need new candidates.
+ // Any time _something_ happens that might cause us to need new candidates.
// This could be
// * the disconnection of a relay
// * the failed attempt to obtain a reservation with a current candidate
@@ -736,7 +736,7 @@ func (rf *relayFinder) relayAddrs(addrs []ma.Multiaddr) []ma.Multiaddr {
for p := range rf.relays {
addrs := cleanupAddressSet(rf.host.Peerstore().Addrs(p))
relayAddrCnt += len(addrs)
- circuit := ma.StringCast(fmt.Sprintf("/p2p/%s/p2p-circuit", p.Pretty()))
+ circuit := ma.StringCast(fmt.Sprintf("/p2p/%s/p2p-circuit", p))
for _, addr := range addrs {
pub := addr.Encapsulate(circuit)
raddrs = append(raddrs, pub)
diff --git a/p2p/host/basic/basic_host.go b/p2p/host/basic/basic_host.go
index 3eaf9f4e35..2662e04bdc 100644
--- a/p2p/host/basic/basic_host.go
+++ b/p2p/host/basic/basic_host.go
@@ -171,12 +171,11 @@ func NewHost(n network.Network, opts *HostOpts) (*BasicHost, error) {
opts.EventBus = eventbus.NewBus()
}
- psManager, err := pstoremanager.NewPeerstoreManager(n.Peerstore(), opts.EventBus)
+ psManager, err := pstoremanager.NewPeerstoreManager(n.Peerstore(), opts.EventBus, n)
if err != nil {
return nil, err
}
hostCtx, cancel := context.WithCancel(context.Background())
-
h := &BasicHost{
network: n,
psManager: psManager,
@@ -437,7 +436,7 @@ func (h *BasicHost) newStreamHandler(s network.Stream) {
log.Debugf("negotiated: %s (took %s)", protoID, took)
- go handle(protoID, s)
+ handle(protoID, s)
}
// SignalAddressChange signals to the host that it needs to determine whether our listen addresses have recently
@@ -543,7 +542,7 @@ func (h *BasicHost) background() {
h.updateLocalIpAddr()
}
// Request addresses anyways because, technically, address filters still apply.
- // The underlying AllAddrs call is effectivley a no-op.
+ // The underlying AllAddrs call is effectively a no-op.
curr := h.Addrs()
emitAddrChange(curr, lastAddrs)
lastAddrs = curr
@@ -666,7 +665,9 @@ func (h *BasicHost) NewStream(ctx context.Context, p peer.ID, pids ...protocol.I
}
if pref != "" {
- s.SetProtocol(pref)
+ if err := s.SetProtocol(pref); err != nil {
+ return nil, err
+ }
lzcon := msmux.NewMSSelect(s, pref)
return &streamWrapper{
Stream: s,
diff --git a/p2p/host/basic/basic_host_test.go b/p2p/host/basic/basic_host_test.go
index ecaaeb20d7..1fb3b4a397 100644
--- a/p2p/host/basic/basic_host_test.go
+++ b/p2p/host/basic/basic_host_test.go
@@ -377,7 +377,7 @@ func TestHostProtoPreknowledge(t *testing.T) {
// This test implicitly relies on 1 connection. If a background identify
// completes after we set the stream handler below things break
- require.Equal(t, 1, len(h1.Network().ConnsToPeer(h2.ID())))
+ require.Len(t, h1.Network().ConnsToPeer(h2.ID()), 1)
// wait for identify handshake to finish completely
select {
@@ -469,7 +469,7 @@ func TestNewStreamResolve(t *testing.T) {
break
}
}
- assert.NotEqual(t, dialAddr, "")
+ assert.NotEqual(t, "", dialAddr)
// Add the DNS multiaddr to h1's peerstore.
maddr, err := ma.NewMultiaddr(dialAddr)
@@ -506,7 +506,7 @@ func TestProtoDowngrade(t *testing.T) {
defer s.Close()
result, err := io.ReadAll(s)
assert.NoError(t, err)
- assert.Equal(t, string(result), "bar")
+ assert.Equal(t, "bar", string(result))
connectedOn <- s.Protocol()
})
@@ -527,7 +527,7 @@ func TestProtoDowngrade(t *testing.T) {
defer s.Close()
result, err := io.ReadAll(s)
assert.NoError(t, err)
- assert.Equal(t, string(result), "foo")
+ assert.Equal(t, "foo", string(result))
connectedOn <- s.Protocol()
})
diff --git a/p2p/host/basic/mock_nat_test.go b/p2p/host/basic/mock_nat_test.go
index 4e686fac12..e601e7109d 100644
--- a/p2p/host/basic/mock_nat_test.go
+++ b/p2p/host/basic/mock_nat_test.go
@@ -1,5 +1,10 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/libp2p/go-libp2p/p2p/host/basic (interfaces: NAT)
+//
+// Generated by this command:
+//
+// mockgen -build_flags=-tags=gomock -package basichost -destination mock_nat_test.go github.com/libp2p/go-libp2p/p2p/host/basic NAT
+//
// Package basichost is a generated GoMock package.
package basichost
@@ -9,7 +14,7 @@ import (
netip "net/netip"
reflect "reflect"
- gomock "github.com/golang/mock/gomock"
+ gomock "go.uber.org/mock/gomock"
)
// MockNAT is a mock of NAT interface.
@@ -44,7 +49,7 @@ func (m *MockNAT) AddMapping(arg0 context.Context, arg1 string, arg2 int) error
}
// AddMapping indicates an expected call of AddMapping.
-func (mr *MockNATMockRecorder) AddMapping(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockNATMockRecorder) AddMapping(arg0, arg1, arg2 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddMapping", reflect.TypeOf((*MockNAT)(nil).AddMapping), arg0, arg1, arg2)
}
@@ -73,7 +78,7 @@ func (m *MockNAT) GetMapping(arg0 string, arg1 int) (netip.AddrPort, bool) {
}
// GetMapping indicates an expected call of GetMapping.
-func (mr *MockNATMockRecorder) GetMapping(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockNATMockRecorder) GetMapping(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMapping", reflect.TypeOf((*MockNAT)(nil).GetMapping), arg0, arg1)
}
@@ -87,7 +92,7 @@ func (m *MockNAT) RemoveMapping(arg0 context.Context, arg1 string, arg2 int) err
}
// RemoveMapping indicates an expected call of RemoveMapping.
-func (mr *MockNATMockRecorder) RemoveMapping(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockNATMockRecorder) RemoveMapping(arg0, arg1, arg2 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveMapping", reflect.TypeOf((*MockNAT)(nil).RemoveMapping), arg0, arg1, arg2)
}
diff --git a/p2p/host/basic/mocks.go b/p2p/host/basic/mocks.go
index 3ad4d4e90b..a29a0c5ef7 100644
--- a/p2p/host/basic/mocks.go
+++ b/p2p/host/basic/mocks.go
@@ -2,5 +2,5 @@
package basichost
-//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package basichost -destination mock_nat_test.go github.com/libp2p/go-libp2p/p2p/host/basic NAT"
+//go:generate sh -c "go run go.uber.org/mock/mockgen -build_flags=\"-tags=gomock\" -package basichost -destination mock_nat_test.go github.com/libp2p/go-libp2p/p2p/host/basic NAT"
type NAT nat
diff --git a/p2p/host/basic/natmgr.go b/p2p/host/basic/natmgr.go
index 8e8fbea347..bc55e4d76d 100644
--- a/p2p/host/basic/natmgr.go
+++ b/p2p/host/basic/natmgr.go
@@ -127,7 +127,7 @@ func (nmgr *natManager) background(ctx context.Context) {
for {
select {
case <-nmgr.syncFlag:
- nmgr.doSync() // sync when our listen addresses chnage.
+ nmgr.doSync() // sync when our listen addresses change.
case <-ctx.Done():
return
}
diff --git a/p2p/host/basic/natmgr_test.go b/p2p/host/basic/natmgr_test.go
index d22092d188..8cbe8618e1 100644
--- a/p2p/host/basic/natmgr_test.go
+++ b/p2p/host/basic/natmgr_test.go
@@ -12,7 +12,7 @@ import (
swarmt "github.com/libp2p/go-libp2p/p2p/net/swarm/testing"
- "github.com/golang/mock/gomock"
+ "go.uber.org/mock/gomock"
)
func setupMockNAT(t *testing.T) (mockNAT *MockNAT, reset func()) {
diff --git a/p2p/host/blank/blank.go b/p2p/host/blank/blank.go
index 24304498b0..0fdded30ff 100644
--- a/p2p/host/blank/blank.go
+++ b/p2p/host/blank/blank.go
@@ -210,7 +210,7 @@ func (bh *BlankHost) newStreamHandler(s network.Stream) {
s.SetProtocol(protoID)
- go handle(protoID, s)
+ handle(protoID, s)
}
// TODO: i'm not sure this really needs to be here
diff --git a/p2p/host/peerstore/pstoreds/addr_book.go b/p2p/host/peerstore/pstoreds/addr_book.go
index a7fcee9c21..2023de12b5 100644
--- a/p2p/host/peerstore/pstoreds/addr_book.go
+++ b/p2p/host/peerstore/pstoreds/addr_book.go
@@ -362,7 +362,7 @@ func (ab *dsAddrBook) storeSignedPeerRecord(p peer.ID, envelope *record.Envelope
func (ab *dsAddrBook) GetPeerRecord(p peer.ID) *record.Envelope {
pr, err := ab.loadRecord(p, true, false)
if err != nil {
- log.Errorf("unable to load record for peer %s: %v", p.Pretty(), err)
+ log.Errorf("unable to load record for peer %s: %v", p, err)
return nil
}
pr.RLock()
@@ -372,7 +372,7 @@ func (ab *dsAddrBook) GetPeerRecord(p peer.ID) *record.Envelope {
}
state, _, err := record.ConsumeEnvelope(pr.CertifiedRecord.Raw, peer.PeerRecordEnvelopeDomain)
if err != nil {
- log.Errorf("error unmarshaling stored signed peer record for peer %s: %v", p.Pretty(), err)
+ log.Errorf("error unmarshaling stored signed peer record for peer %s: %v", p, err)
return nil
}
return state
@@ -398,7 +398,7 @@ func (ab *dsAddrBook) SetAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duratio
func (ab *dsAddrBook) UpdateAddrs(p peer.ID, oldTTL time.Duration, newTTL time.Duration) {
pr, err := ab.loadRecord(p, true, false)
if err != nil {
- log.Errorf("failed to update ttls for peer %s: %s\n", p.Pretty(), err)
+ log.Errorf("failed to update ttls for peer %s: %s\n", p, err)
return
}
@@ -423,7 +423,7 @@ func (ab *dsAddrBook) UpdateAddrs(p peer.ID, oldTTL time.Duration, newTTL time.D
func (ab *dsAddrBook) Addrs(p peer.ID) []ma.Multiaddr {
pr, err := ab.loadRecord(p, true, true)
if err != nil {
- log.Warn("failed to load peerstore entry for peer %v while querying addrs, err: %v", p, err)
+ log.Warnf("failed to load peerstore entry for peer %s while querying addrs, err: %v", p, err)
return nil
}
@@ -466,7 +466,7 @@ func (ab *dsAddrBook) ClearAddrs(p peer.ID) {
key := addrBookBase.ChildString(b32.RawStdEncoding.EncodeToString([]byte(p)))
if err := ab.ds.Delete(context.TODO(), key); err != nil {
- log.Errorf("failed to clear addresses for peer %s: %v", p.Pretty(), err)
+ log.Errorf("failed to clear addresses for peer %s: %v", p, err)
}
}
@@ -477,7 +477,7 @@ func (ab *dsAddrBook) setAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duratio
pr, err := ab.loadRecord(p, true, false)
if err != nil {
- return fmt.Errorf("failed to load peerstore entry for peer %v while setting addrs, err: %v", p, err)
+ return fmt.Errorf("failed to load peerstore entry for peer %s while setting addrs, err: %v", p, err)
}
pr.Lock()
diff --git a/p2p/host/peerstore/pstoreds/addr_book_gc.go b/p2p/host/peerstore/pstoreds/addr_book_gc.go
index a509131e02..2e35e7aead 100644
--- a/p2p/host/peerstore/pstoreds/addr_book_gc.go
+++ b/p2p/host/peerstore/pstoreds/addr_book_gc.go
@@ -215,7 +215,7 @@ func (gc *dsAddrBookGc) purgeLookahead() {
cached.Lock()
if cached.clean(gc.ab.clock.Now()) {
if err = cached.flush(batch); err != nil {
- log.Warnf("failed to flush entry modified by GC for peer: &v, err: %v", id.Pretty(), err)
+ log.Warnf("failed to flush entry modified by GC for peer: %s, err: %v", id, err)
}
}
dropOrReschedule(gcKey, cached)
@@ -241,7 +241,7 @@ func (gc *dsAddrBookGc) purgeLookahead() {
if record.clean(gc.ab.clock.Now()) {
err = record.flush(batch)
if err != nil {
- log.Warnf("failed to flush entry modified by GC for peer: &v, err: %v", id.Pretty(), err)
+ log.Warnf("failed to flush entry modified by GC for peer: %s, err: %v", id, err)
}
}
dropOrReschedule(gcKey, record)
@@ -353,7 +353,7 @@ func (gc *dsAddrBookGc) populateLookahead() {
}
gcKey := gcLookaheadBase.ChildString(fmt.Sprintf("%d/%s", cached.Addrs[0].Expiry, idb32))
if err = batch.Put(context.TODO(), gcKey, []byte{}); err != nil {
- log.Warnf("failed while inserting GC entry for peer: %v, err: %v", id.Pretty(), err)
+ log.Warnf("failed while inserting GC entry for peer: %s, err: %v", id, err)
}
cached.RUnlock()
continue
@@ -363,17 +363,17 @@ func (gc *dsAddrBookGc) populateLookahead() {
val, err := gc.ab.ds.Get(context.TODO(), ds.RawKey(result.Key))
if err != nil {
- log.Warnf("failed which getting record from store for peer: %v, err: %v", id.Pretty(), err)
+ log.Warnf("failed which getting record from store for peer: %s, err: %v", id, err)
continue
}
if err := proto.Unmarshal(val, record); err != nil {
- log.Warnf("failed while unmarshalling record from store for peer: %v, err: %v", id.Pretty(), err)
+ log.Warnf("failed while unmarshalling record from store for peer: %s, err: %v", id, err)
continue
}
if len(record.Addrs) > 0 && record.Addrs[0].Expiry <= until {
gcKey := gcLookaheadBase.ChildString(fmt.Sprintf("%d/%s", record.Addrs[0].Expiry, idb32))
if err = batch.Put(context.TODO(), gcKey, []byte{}); err != nil {
- log.Warnf("failed while inserting GC entry for peer: %v, err: %v", id.Pretty(), err)
+ log.Warnf("failed while inserting GC entry for peer: %s, err: %v", id, err)
}
}
}
diff --git a/p2p/host/peerstore/pstoreds/keybook.go b/p2p/host/peerstore/pstoreds/keybook.go
index 9db799b172..63c7e30cfa 100644
--- a/p2p/host/peerstore/pstoreds/keybook.go
+++ b/p2p/host/peerstore/pstoreds/keybook.go
@@ -38,7 +38,7 @@ func (kb *dsKeyBook) PubKey(p peer.ID) ic.PubKey {
if value, err := kb.ds.Get(context.TODO(), key); err == nil {
pk, err = ic.UnmarshalPublicKey(value)
if err != nil {
- log.Errorf("error when unmarshalling pubkey from datastore for peer %s: %s\n", p.Pretty(), err)
+ log.Errorf("error when unmarshalling pubkey from datastore for peer %s: %s\n", p, err)
}
} else if err == ds.ErrNotFound {
pk, err = p.ExtractPublicKey()
@@ -47,20 +47,20 @@ func (kb *dsKeyBook) PubKey(p peer.ID) ic.PubKey {
case peer.ErrNoPublicKey:
return nil
default:
- log.Errorf("error when extracting pubkey from peer ID for peer %s: %s\n", p.Pretty(), err)
+ log.Errorf("error when extracting pubkey from peer ID for peer %s: %s\n", p, err)
return nil
}
pkb, err := ic.MarshalPublicKey(pk)
if err != nil {
- log.Errorf("error when turning extracted pubkey into bytes for peer %s: %s\n", p.Pretty(), err)
+ log.Errorf("error when turning extracted pubkey into bytes for peer %s: %s\n", p, err)
return nil
}
if err := kb.ds.Put(context.TODO(), key, pkb); err != nil {
- log.Errorf("error when adding extracted pubkey to peerstore for peer %s: %s\n", p.Pretty(), err)
+ log.Errorf("error when adding extracted pubkey to peerstore for peer %s: %s\n", p, err)
return nil
}
} else {
- log.Errorf("error when fetching pubkey from datastore for peer %s: %s\n", p.Pretty(), err)
+ log.Errorf("error when fetching pubkey from datastore for peer %s: %s\n", p, err)
}
return pk
@@ -74,11 +74,11 @@ func (kb *dsKeyBook) AddPubKey(p peer.ID, pk ic.PubKey) error {
val, err := ic.MarshalPublicKey(pk)
if err != nil {
- log.Errorf("error while converting pubkey byte string for peer %s: %s\n", p.Pretty(), err)
+ log.Errorf("error while converting pubkey byte string for peer %s: %s\n", p, err)
return err
}
if err := kb.ds.Put(context.TODO(), peerToKey(p, pubSuffix), val); err != nil {
- log.Errorf("error while updating pubkey in datastore for peer %s: %s\n", p.Pretty(), err)
+ log.Errorf("error while updating pubkey in datastore for peer %s: %s\n", p, err)
return err
}
return nil
@@ -107,11 +107,11 @@ func (kb *dsKeyBook) AddPrivKey(p peer.ID, sk ic.PrivKey) error {
val, err := ic.MarshalPrivateKey(sk)
if err != nil {
- log.Errorf("error while converting privkey byte string for peer %s: %s\n", p.Pretty(), err)
+ log.Errorf("error while converting privkey byte string for peer %s: %s\n", p, err)
return err
}
if err := kb.ds.Put(context.TODO(), peerToKey(p, privSuffix), val); err != nil {
- log.Errorf("error while updating privkey in datastore for peer %s: %s\n", p.Pretty(), err)
+ log.Errorf("error while updating privkey in datastore for peer %s: %s\n", p, err)
}
return err
}
diff --git a/p2p/host/peerstore/pstoreds/protobook.go b/p2p/host/peerstore/pstoreds/protobook.go
index f5d76573b4..40fa7d951b 100644
--- a/p2p/host/peerstore/pstoreds/protobook.go
+++ b/p2p/host/peerstore/pstoreds/protobook.go
@@ -17,7 +17,7 @@ type protoSegment struct {
type protoSegments [256]*protoSegment
func (s *protoSegments) get(p peer.ID) *protoSegment {
- return s[byte(p[len(p)-1])]
+ return s[p[len(p)-1]]
}
var errTooManyProtocols = errors.New("too many protocols")
diff --git a/p2p/host/peerstore/pstoremem/addr_book.go b/p2p/host/peerstore/pstoremem/addr_book.go
index 67f9f91462..209937ca83 100644
--- a/p2p/host/peerstore/pstoremem/addr_book.go
+++ b/p2p/host/peerstore/pstoremem/addr_book.go
@@ -49,7 +49,7 @@ func (segments *addrSegments) get(p peer.ID) *addrSegment {
if len(p) == 0 { // it's not terribly useful to use an empty peer ID, but at least we should not panic
return segments[0]
}
- return segments[uint8(p[len(p)-1])]
+ return segments[p[len(p)-1]]
}
type clock interface {
diff --git a/p2p/host/peerstore/pstoremem/protobook.go b/p2p/host/peerstore/pstoremem/protobook.go
index 0000f97ff1..51c4b0282a 100644
--- a/p2p/host/peerstore/pstoremem/protobook.go
+++ b/p2p/host/peerstore/pstoremem/protobook.go
@@ -17,7 +17,7 @@ type protoSegment struct {
type protoSegments [256]*protoSegment
func (s *protoSegments) get(p peer.ID) *protoSegment {
- return s[byte(p[len(p)-1])]
+ return s[p[len(p)-1]]
}
var errTooManyProtocols = errors.New("too many protocols")
diff --git a/p2p/host/peerstore/pstoremem/sorting_test.go b/p2p/host/peerstore/pstoremem/sorting_test.go
index 8ea52d130c..82c76ef170 100644
--- a/p2p/host/peerstore/pstoremem/sorting_test.go
+++ b/p2p/host/peerstore/pstoremem/sorting_test.go
@@ -16,5 +16,5 @@ func TestAddressSorting(t *testing.T) {
l := addrList{local, u1, u2l, norm}
sort.Sort(l)
- require.Equal(t, l, addrList{u2l, u1, local, norm})
+ require.Equal(t, addrList{u2l, u1, local, norm}, l)
}
diff --git a/p2p/host/peerstore/test/peerstore_suite.go b/p2p/host/peerstore/test/peerstore_suite.go
index 576b8fd47a..369b459d0f 100644
--- a/p2p/host/peerstore/test/peerstore_suite.go
+++ b/p2p/host/peerstore/test/peerstore_suite.go
@@ -144,7 +144,7 @@ func testGetStreamBeforePeerAdded(ps pstore.Peerstore) func(t *testing.T) {
t.Fatal("channel shouldnt be closed yet")
}
if a == nil {
- t.Fatal("got a nil address, thats weird")
+ t.Fatal("got a nil address, that's weird")
}
count++
if received[a.String()] {
@@ -195,7 +195,7 @@ func testAddrStreamDuplicates(ps pstore.Peerstore) func(t *testing.T) {
var count int
for a := range ach {
if a == nil {
- t.Fatal("got a nil address, thats weird")
+ t.Fatal("got a nil address, that's weird")
}
count++
if received[a.String()] {
@@ -337,11 +337,11 @@ func testMetadata(ps pstore.Peerstore) func(t *testing.T) {
for _, p := range pids {
v, err := ps.Get(p, "AgentVersion")
require.NoError(t, err)
- require.Equal(t, v, "string")
+ require.Equal(t, "string", v)
v, err = ps.Get(p, "bar")
require.NoError(t, err)
- require.Equal(t, v, 1)
+ require.Equal(t, 1, v)
}
})
@@ -359,7 +359,7 @@ func testMetadata(ps pstore.Peerstore) func(t *testing.T) {
// make sure that entries for otherP were not deleted
val, err := ps.Get(otherP, "AgentVersion")
require.NoError(t, err)
- require.Equal(t, val, "v1")
+ require.Equal(t, "v1", val)
})
}
}
diff --git a/p2p/host/peerstore/test/utils.go b/p2p/host/peerstore/test/utils.go
index 8d327f4525..254b713957 100644
--- a/p2p/host/peerstore/test/utils.go
+++ b/p2p/host/peerstore/test/utils.go
@@ -38,7 +38,7 @@ func RandomPeer(b *testing.B, addrCount int) *peerpair {
}
for i := 0; i < addrCount; i++ {
- if addrs[i], err = ma.NewMultiaddr(fmt.Sprintf(aFmt, i, pid.Pretty())); err != nil {
+ if addrs[i], err = ma.NewMultiaddr(fmt.Sprintf(aFmt, i, pid)); err != nil {
b.Fatal(err)
}
}
diff --git a/p2p/host/pstoremanager/mock_peerstore_test.go b/p2p/host/pstoremanager/mock_peerstore_test.go
index fb9a282501..b704cb1fd1 100644
--- a/p2p/host/pstoremanager/mock_peerstore_test.go
+++ b/p2p/host/pstoremanager/mock_peerstore_test.go
@@ -1,5 +1,10 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/libp2p/go-libp2p/core/peerstore (interfaces: Peerstore)
+//
+// Generated by this command:
+//
+// mockgen -package pstoremanager_test -destination mock_peerstore_test.go github.com/libp2p/go-libp2p/core/peerstore Peerstore
+//
// Package pstoremanager_test is a generated GoMock package.
package pstoremanager_test
@@ -9,11 +14,11 @@ import (
reflect "reflect"
time "time"
- gomock "github.com/golang/mock/gomock"
crypto "github.com/libp2p/go-libp2p/core/crypto"
peer "github.com/libp2p/go-libp2p/core/peer"
protocol "github.com/libp2p/go-libp2p/core/protocol"
multiaddr "github.com/multiformats/go-multiaddr"
+ gomock "go.uber.org/mock/gomock"
)
// MockPeerstore is a mock of Peerstore interface.
@@ -46,7 +51,7 @@ func (m *MockPeerstore) AddAddr(arg0 peer.ID, arg1 multiaddr.Multiaddr, arg2 tim
}
// AddAddr indicates an expected call of AddAddr.
-func (mr *MockPeerstoreMockRecorder) AddAddr(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) AddAddr(arg0, arg1, arg2 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddAddr", reflect.TypeOf((*MockPeerstore)(nil).AddAddr), arg0, arg1, arg2)
}
@@ -58,7 +63,7 @@ func (m *MockPeerstore) AddAddrs(arg0 peer.ID, arg1 []multiaddr.Multiaddr, arg2
}
// AddAddrs indicates an expected call of AddAddrs.
-func (mr *MockPeerstoreMockRecorder) AddAddrs(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) AddAddrs(arg0, arg1, arg2 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddAddrs", reflect.TypeOf((*MockPeerstore)(nil).AddAddrs), arg0, arg1, arg2)
}
@@ -72,7 +77,7 @@ func (m *MockPeerstore) AddPrivKey(arg0 peer.ID, arg1 crypto.PrivKey) error {
}
// AddPrivKey indicates an expected call of AddPrivKey.
-func (mr *MockPeerstoreMockRecorder) AddPrivKey(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) AddPrivKey(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddPrivKey", reflect.TypeOf((*MockPeerstore)(nil).AddPrivKey), arg0, arg1)
}
@@ -80,7 +85,7 @@ func (mr *MockPeerstoreMockRecorder) AddPrivKey(arg0, arg1 interface{}) *gomock.
// AddProtocols mocks base method.
func (m *MockPeerstore) AddProtocols(arg0 peer.ID, arg1 ...protocol.ID) error {
m.ctrl.T.Helper()
- varargs := []interface{}{arg0}
+ varargs := []any{arg0}
for _, a := range arg1 {
varargs = append(varargs, a)
}
@@ -90,9 +95,9 @@ func (m *MockPeerstore) AddProtocols(arg0 peer.ID, arg1 ...protocol.ID) error {
}
// AddProtocols indicates an expected call of AddProtocols.
-func (mr *MockPeerstoreMockRecorder) AddProtocols(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) AddProtocols(arg0 any, arg1 ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- varargs := append([]interface{}{arg0}, arg1...)
+ varargs := append([]any{arg0}, arg1...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddProtocols", reflect.TypeOf((*MockPeerstore)(nil).AddProtocols), varargs...)
}
@@ -105,7 +110,7 @@ func (m *MockPeerstore) AddPubKey(arg0 peer.ID, arg1 crypto.PubKey) error {
}
// AddPubKey indicates an expected call of AddPubKey.
-func (mr *MockPeerstoreMockRecorder) AddPubKey(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) AddPubKey(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddPubKey", reflect.TypeOf((*MockPeerstore)(nil).AddPubKey), arg0, arg1)
}
@@ -119,7 +124,7 @@ func (m *MockPeerstore) AddrStream(arg0 context.Context, arg1 peer.ID) <-chan mu
}
// AddrStream indicates an expected call of AddrStream.
-func (mr *MockPeerstoreMockRecorder) AddrStream(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) AddrStream(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddrStream", reflect.TypeOf((*MockPeerstore)(nil).AddrStream), arg0, arg1)
}
@@ -133,7 +138,7 @@ func (m *MockPeerstore) Addrs(arg0 peer.ID) []multiaddr.Multiaddr {
}
// Addrs indicates an expected call of Addrs.
-func (mr *MockPeerstoreMockRecorder) Addrs(arg0 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) Addrs(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Addrs", reflect.TypeOf((*MockPeerstore)(nil).Addrs), arg0)
}
@@ -145,7 +150,7 @@ func (m *MockPeerstore) ClearAddrs(arg0 peer.ID) {
}
// ClearAddrs indicates an expected call of ClearAddrs.
-func (mr *MockPeerstoreMockRecorder) ClearAddrs(arg0 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) ClearAddrs(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClearAddrs", reflect.TypeOf((*MockPeerstore)(nil).ClearAddrs), arg0)
}
@@ -167,7 +172,7 @@ func (mr *MockPeerstoreMockRecorder) Close() *gomock.Call {
// FirstSupportedProtocol mocks base method.
func (m *MockPeerstore) FirstSupportedProtocol(arg0 peer.ID, arg1 ...protocol.ID) (protocol.ID, error) {
m.ctrl.T.Helper()
- varargs := []interface{}{arg0}
+ varargs := []any{arg0}
for _, a := range arg1 {
varargs = append(varargs, a)
}
@@ -178,23 +183,23 @@ func (m *MockPeerstore) FirstSupportedProtocol(arg0 peer.ID, arg1 ...protocol.ID
}
// FirstSupportedProtocol indicates an expected call of FirstSupportedProtocol.
-func (mr *MockPeerstoreMockRecorder) FirstSupportedProtocol(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) FirstSupportedProtocol(arg0 any, arg1 ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- varargs := append([]interface{}{arg0}, arg1...)
+ varargs := append([]any{arg0}, arg1...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FirstSupportedProtocol", reflect.TypeOf((*MockPeerstore)(nil).FirstSupportedProtocol), varargs...)
}
// Get mocks base method.
-func (m *MockPeerstore) Get(arg0 peer.ID, arg1 string) (interface{}, error) {
+func (m *MockPeerstore) Get(arg0 peer.ID, arg1 string) (any, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Get", arg0, arg1)
- ret0, _ := ret[0].(interface{})
+ ret0, _ := ret[0].(any)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Get indicates an expected call of Get.
-func (mr *MockPeerstoreMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) Get(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockPeerstore)(nil).Get), arg0, arg1)
}
@@ -209,7 +214,7 @@ func (m *MockPeerstore) GetProtocols(arg0 peer.ID) ([]protocol.ID, error) {
}
// GetProtocols indicates an expected call of GetProtocols.
-func (mr *MockPeerstoreMockRecorder) GetProtocols(arg0 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) GetProtocols(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProtocols", reflect.TypeOf((*MockPeerstore)(nil).GetProtocols), arg0)
}
@@ -223,7 +228,7 @@ func (m *MockPeerstore) LatencyEWMA(arg0 peer.ID) time.Duration {
}
// LatencyEWMA indicates an expected call of LatencyEWMA.
-func (mr *MockPeerstoreMockRecorder) LatencyEWMA(arg0 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) LatencyEWMA(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LatencyEWMA", reflect.TypeOf((*MockPeerstore)(nil).LatencyEWMA), arg0)
}
@@ -237,7 +242,7 @@ func (m *MockPeerstore) PeerInfo(arg0 peer.ID) peer.AddrInfo {
}
// PeerInfo indicates an expected call of PeerInfo.
-func (mr *MockPeerstoreMockRecorder) PeerInfo(arg0 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) PeerInfo(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PeerInfo", reflect.TypeOf((*MockPeerstore)(nil).PeerInfo), arg0)
}
@@ -293,7 +298,7 @@ func (m *MockPeerstore) PrivKey(arg0 peer.ID) crypto.PrivKey {
}
// PrivKey indicates an expected call of PrivKey.
-func (mr *MockPeerstoreMockRecorder) PrivKey(arg0 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) PrivKey(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrivKey", reflect.TypeOf((*MockPeerstore)(nil).PrivKey), arg0)
}
@@ -307,13 +312,13 @@ func (m *MockPeerstore) PubKey(arg0 peer.ID) crypto.PubKey {
}
// PubKey indicates an expected call of PubKey.
-func (mr *MockPeerstoreMockRecorder) PubKey(arg0 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) PubKey(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PubKey", reflect.TypeOf((*MockPeerstore)(nil).PubKey), arg0)
}
// Put mocks base method.
-func (m *MockPeerstore) Put(arg0 peer.ID, arg1 string, arg2 interface{}) error {
+func (m *MockPeerstore) Put(arg0 peer.ID, arg1 string, arg2 any) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Put", arg0, arg1, arg2)
ret0, _ := ret[0].(error)
@@ -321,7 +326,7 @@ func (m *MockPeerstore) Put(arg0 peer.ID, arg1 string, arg2 interface{}) error {
}
// Put indicates an expected call of Put.
-func (mr *MockPeerstoreMockRecorder) Put(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) Put(arg0, arg1, arg2 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockPeerstore)(nil).Put), arg0, arg1, arg2)
}
@@ -333,7 +338,7 @@ func (m *MockPeerstore) RecordLatency(arg0 peer.ID, arg1 time.Duration) {
}
// RecordLatency indicates an expected call of RecordLatency.
-func (mr *MockPeerstoreMockRecorder) RecordLatency(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) RecordLatency(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordLatency", reflect.TypeOf((*MockPeerstore)(nil).RecordLatency), arg0, arg1)
}
@@ -345,7 +350,7 @@ func (m *MockPeerstore) RemovePeer(arg0 peer.ID) {
}
// RemovePeer indicates an expected call of RemovePeer.
-func (mr *MockPeerstoreMockRecorder) RemovePeer(arg0 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) RemovePeer(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemovePeer", reflect.TypeOf((*MockPeerstore)(nil).RemovePeer), arg0)
}
@@ -353,7 +358,7 @@ func (mr *MockPeerstoreMockRecorder) RemovePeer(arg0 interface{}) *gomock.Call {
// RemoveProtocols mocks base method.
func (m *MockPeerstore) RemoveProtocols(arg0 peer.ID, arg1 ...protocol.ID) error {
m.ctrl.T.Helper()
- varargs := []interface{}{arg0}
+ varargs := []any{arg0}
for _, a := range arg1 {
varargs = append(varargs, a)
}
@@ -363,9 +368,9 @@ func (m *MockPeerstore) RemoveProtocols(arg0 peer.ID, arg1 ...protocol.ID) error
}
// RemoveProtocols indicates an expected call of RemoveProtocols.
-func (mr *MockPeerstoreMockRecorder) RemoveProtocols(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) RemoveProtocols(arg0 any, arg1 ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- varargs := append([]interface{}{arg0}, arg1...)
+ varargs := append([]any{arg0}, arg1...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveProtocols", reflect.TypeOf((*MockPeerstore)(nil).RemoveProtocols), varargs...)
}
@@ -376,7 +381,7 @@ func (m *MockPeerstore) SetAddr(arg0 peer.ID, arg1 multiaddr.Multiaddr, arg2 tim
}
// SetAddr indicates an expected call of SetAddr.
-func (mr *MockPeerstoreMockRecorder) SetAddr(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) SetAddr(arg0, arg1, arg2 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetAddr", reflect.TypeOf((*MockPeerstore)(nil).SetAddr), arg0, arg1, arg2)
}
@@ -388,7 +393,7 @@ func (m *MockPeerstore) SetAddrs(arg0 peer.ID, arg1 []multiaddr.Multiaddr, arg2
}
// SetAddrs indicates an expected call of SetAddrs.
-func (mr *MockPeerstoreMockRecorder) SetAddrs(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) SetAddrs(arg0, arg1, arg2 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetAddrs", reflect.TypeOf((*MockPeerstore)(nil).SetAddrs), arg0, arg1, arg2)
}
@@ -396,7 +401,7 @@ func (mr *MockPeerstoreMockRecorder) SetAddrs(arg0, arg1, arg2 interface{}) *gom
// SetProtocols mocks base method.
func (m *MockPeerstore) SetProtocols(arg0 peer.ID, arg1 ...protocol.ID) error {
m.ctrl.T.Helper()
- varargs := []interface{}{arg0}
+ varargs := []any{arg0}
for _, a := range arg1 {
varargs = append(varargs, a)
}
@@ -406,16 +411,16 @@ func (m *MockPeerstore) SetProtocols(arg0 peer.ID, arg1 ...protocol.ID) error {
}
// SetProtocols indicates an expected call of SetProtocols.
-func (mr *MockPeerstoreMockRecorder) SetProtocols(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) SetProtocols(arg0 any, arg1 ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- varargs := append([]interface{}{arg0}, arg1...)
+ varargs := append([]any{arg0}, arg1...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetProtocols", reflect.TypeOf((*MockPeerstore)(nil).SetProtocols), varargs...)
}
// SupportsProtocols mocks base method.
func (m *MockPeerstore) SupportsProtocols(arg0 peer.ID, arg1 ...protocol.ID) ([]protocol.ID, error) {
m.ctrl.T.Helper()
- varargs := []interface{}{arg0}
+ varargs := []any{arg0}
for _, a := range arg1 {
varargs = append(varargs, a)
}
@@ -426,9 +431,9 @@ func (m *MockPeerstore) SupportsProtocols(arg0 peer.ID, arg1 ...protocol.ID) ([]
}
// SupportsProtocols indicates an expected call of SupportsProtocols.
-func (mr *MockPeerstoreMockRecorder) SupportsProtocols(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) SupportsProtocols(arg0 any, arg1 ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- varargs := append([]interface{}{arg0}, arg1...)
+ varargs := append([]any{arg0}, arg1...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SupportsProtocols", reflect.TypeOf((*MockPeerstore)(nil).SupportsProtocols), varargs...)
}
@@ -439,7 +444,7 @@ func (m *MockPeerstore) UpdateAddrs(arg0 peer.ID, arg1, arg2 time.Duration) {
}
// UpdateAddrs indicates an expected call of UpdateAddrs.
-func (mr *MockPeerstoreMockRecorder) UpdateAddrs(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockPeerstoreMockRecorder) UpdateAddrs(arg0, arg1, arg2 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateAddrs", reflect.TypeOf((*MockPeerstore)(nil).UpdateAddrs), arg0, arg1, arg2)
}
diff --git a/p2p/host/pstoremanager/pstoremanager.go b/p2p/host/pstoremanager/pstoremanager.go
index d9550f4945..2a22b2caee 100644
--- a/p2p/host/pstoremanager/pstoremanager.go
+++ b/p2p/host/pstoremanager/pstoremanager.go
@@ -41,6 +41,7 @@ func WithCleanupInterval(t time.Duration) Option {
type PeerstoreManager struct {
pstore peerstore.Peerstore
eventBus event.Bus
+ network network.Network
cancel context.CancelFunc
refCount sync.WaitGroup
@@ -49,11 +50,12 @@ type PeerstoreManager struct {
cleanupInterval time.Duration
}
-func NewPeerstoreManager(pstore peerstore.Peerstore, eventBus event.Bus, opts ...Option) (*PeerstoreManager, error) {
+func NewPeerstoreManager(pstore peerstore.Peerstore, eventBus event.Bus, network network.Network, opts ...Option) (*PeerstoreManager, error) {
m := &PeerstoreManager{
pstore: pstore,
gracePeriod: time.Minute,
eventBus: eventBus,
+ network: network,
}
for _, opt := range opts {
if err := opt(m); err != nil {
@@ -107,14 +109,21 @@ func (m *PeerstoreManager) background(ctx context.Context, sub event.Subscriptio
}
case network.Connected:
// If we reconnect to the peer before we've cleared the information, keep it.
+ // This is an optimization to keep the disconnected map small.
+ // We still need to check that a peer is actually disconnected before removing it from the peer store.
delete(disconnected, p)
}
case <-ticker.C:
now := time.Now()
for p, disconnectTime := range disconnected {
if disconnectTime.Add(m.gracePeriod).Before(now) {
- m.pstore.RemovePeer(p)
- delete(disconnected, p)
+ // Check that the peer is actually not connected at this point.
+ // This avoids a race condition where the Connected notification
+ // is processed after this time has fired.
+ if m.network.Connectedness(p) != network.Connected {
+ m.pstore.RemovePeer(p)
+ delete(disconnected, p)
+ }
}
}
case <-ctx.Done():
diff --git a/p2p/host/pstoremanager/pstoremanager_test.go b/p2p/host/pstoremanager/pstoremanager_test.go
index 8726740c39..9321031c5a 100644
--- a/p2p/host/pstoremanager/pstoremanager_test.go
+++ b/p2p/host/pstoremanager/pstoremanager_test.go
@@ -9,12 +9,13 @@ import (
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/p2p/host/eventbus"
"github.com/libp2p/go-libp2p/p2p/host/pstoremanager"
+ swarmt "github.com/libp2p/go-libp2p/p2p/net/swarm/testing"
- "github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
+ "go.uber.org/mock/gomock"
)
-//go:generate sh -c "go run github.com/golang/mock/mockgen -package pstoremanager_test -destination mock_peerstore_test.go github.com/libp2p/go-libp2p/core/peerstore Peerstore"
+//go:generate sh -c "go run go.uber.org/mock/mockgen -package pstoremanager_test -destination mock_peerstore_test.go github.com/libp2p/go-libp2p/core/peerstore Peerstore"
func TestGracePeriod(t *testing.T) {
t.Parallel()
@@ -23,7 +24,7 @@ func TestGracePeriod(t *testing.T) {
eventBus := eventbus.NewBus()
pstore := NewMockPeerstore(ctrl)
const gracePeriod = 250 * time.Millisecond
- man, err := pstoremanager.NewPeerstoreManager(pstore, eventBus, pstoremanager.WithGracePeriod(gracePeriod))
+ man, err := pstoremanager.NewPeerstoreManager(pstore, eventBus, swarmt.GenSwarm(t), pstoremanager.WithGracePeriod(gracePeriod))
require.NoError(t, err)
defer man.Close()
man.Start()
@@ -51,7 +52,7 @@ func TestReconnect(t *testing.T) {
eventBus := eventbus.NewBus()
pstore := NewMockPeerstore(ctrl)
const gracePeriod = 200 * time.Millisecond
- man, err := pstoremanager.NewPeerstoreManager(pstore, eventBus, pstoremanager.WithGracePeriod(gracePeriod))
+ man, err := pstoremanager.NewPeerstoreManager(pstore, eventBus, swarmt.GenSwarm(t), pstoremanager.WithGracePeriod(gracePeriod))
require.NoError(t, err)
defer man.Close()
man.Start()
@@ -77,7 +78,7 @@ func TestClose(t *testing.T) {
eventBus := eventbus.NewBus()
pstore := NewMockPeerstore(ctrl)
const gracePeriod = time.Hour
- man, err := pstoremanager.NewPeerstoreManager(pstore, eventBus, pstoremanager.WithGracePeriod(gracePeriod))
+ man, err := pstoremanager.NewPeerstoreManager(pstore, eventBus, swarmt.GenSwarm(t), pstoremanager.WithGracePeriod(gracePeriod))
require.NoError(t, err)
man.Start()
diff --git a/p2p/host/resource-manager/README.md b/p2p/host/resource-manager/README.md
index 9371832c9a..68ce0aa01b 100644
--- a/p2p/host/resource-manager/README.md
+++ b/p2p/host/resource-manager/README.md
@@ -161,7 +161,7 @@ belong to some service in the system. Hence, this suggests that apart
from global limits, we can constrain stream usage at finer
granularity, at the protocol and service level.
-Once again, we disinguish between inbound and outbound streams.
+Once again, we distinguish between inbound and outbound streams.
Inbound streams are initiated by remote peers and consume resources in
response to network events; controlling inbound stream usage is again
paramount for protecting the system from overload or attack.
@@ -541,7 +541,7 @@ works best.
## Examples
-Here we consider some concrete examples that can ellucidate the abstract
+Here we consider some concrete examples that can elucidate the abstract
design as described so far.
### Stream Lifetime
@@ -578,7 +578,7 @@ More specifically the following constraints apply:
- the peer scope, where the limits for the peer at the other end of the stream
apply.
- the service scope, where the limits of the specific service owning the stream apply.
-- the protcol scope, where the limits of the specific protocol for the stream apply.
+- the protocol scope, where the limits of the specific protocol for the stream apply.
The resource transfer that happens in the `SetProtocol` and `SetService`
diff --git a/p2p/host/resource-manager/docs/allowlist.md b/p2p/host/resource-manager/docs/allowlist.md
index 4ada09cc45..6cf88e042d 100644
--- a/p2p/host/resource-manager/docs/allowlist.md
+++ b/p2p/host/resource-manager/docs/allowlist.md
@@ -47,7 +47,7 @@ creates the connection resource scope using the allowlisted specific system and
transient resource scopes. If it wasn't an allowlisted multiaddr it fails as
before.
-When an allowlisted connection is tied to a peer id and transfered with
+When an allowlisted connection is tied to a peer id and transferred with
`ConnManagementScope.SetPeer`, we check if that peer id matches the expected
value in the allowlist (if it exists). If it does not match, we attempt to
transfer this resource to the normal system and peer scope. If that transfer
diff --git a/p2p/host/resource-manager/extapi.go b/p2p/host/resource-manager/extapi.go
index 03edcd79ea..415d7f8bd1 100644
--- a/p2p/host/resource-manager/extapi.go
+++ b/p2p/host/resource-manager/extapi.go
@@ -145,3 +145,7 @@ func (r *resourceManager) Stat() (result ResourceManagerStat) {
return result
}
+
+func (r *resourceManager) GetConnLimit() int {
+ return r.limits.GetSystemLimits().GetConnTotalLimit()
+}
diff --git a/p2p/host/resource-manager/limit_test.go b/p2p/host/resource-manager/limit_test.go
index 68d6bf29cd..8d9f3919e1 100644
--- a/p2p/host/resource-manager/limit_test.go
+++ b/p2p/host/resource-manager/limit_test.go
@@ -110,7 +110,6 @@ func TestScaling(t *testing.T) {
require.Equal(t, 20+4*2, scaled.service["B"].Streams)
require.Equal(t, int64(200+4*3), scaled.service["B"].Memory)
require.Equal(t, 400, scaled.service["B"].FD)
-
})
}
@@ -157,7 +156,7 @@ func TestJSONMarshalling(t *testing.T) {
jsonEncoded, err := json.Marshal(bl)
require.NoError(t, err)
- require.Equal(t, string(jsonEncoded), `{"StreamsInbound":10,"StreamsOutbound":"blockAll","Conns":10,"ConnsOutbound":"unlimited","Memory":"unlimited"}`)
+ require.Equal(t, `{"StreamsInbound":10,"StreamsOutbound":"blockAll","Conns":10,"ConnsOutbound":"unlimited","Memory":"unlimited"}`, string(jsonEncoded))
// Roundtrip
var blDecoded ResourceLimits
@@ -175,7 +174,7 @@ func TestJSONRoundTripInt64(t *testing.T) {
jsonEncoded, err := json.Marshal(bl)
require.NoError(t, err)
- require.Equal(t, string(jsonEncoded), `{"Memory":"9223372036854775807"}`)
+ require.Equal(t, `{"Memory":"9223372036854775807"}`, string(jsonEncoded))
// Roundtrip
var blDecoded ResourceLimits
diff --git a/p2p/host/resource-manager/scope.go b/p2p/host/resource-manager/scope.go
index 60089c3a57..bb70c10053 100644
--- a/p2p/host/resource-manager/scope.go
+++ b/p2p/host/resource-manager/scope.go
@@ -118,12 +118,10 @@ func (rc *resources) checkMemory(rsvp int64, prio uint8) error {
threshold, mulOk := mulInt64WithOverflow(1+int64(prio), limit)
if !mulOk {
thresholdBig := big.NewInt(limit)
- thresholdBig = thresholdBig.Mul(thresholdBig, big.NewInt(1+int64(prio)))
+ thresholdBig.Mul(thresholdBig, big.NewInt(1+int64(prio)))
thresholdBig.Rsh(thresholdBig, 8) // Divide 256
- if !thresholdBig.IsInt64() {
- // Shouldn't happen since the threshold can only be <= limit
- threshold = limit
- }
+ // necessarily a Int64 since we multiplied a int64 != MaxInt64 with
+ // a uint8+1 (max 255+1 = 256) and divided by 256
threshold = thresholdBig.Int64()
} else {
threshold = threshold / 256
diff --git a/p2p/host/resource-manager/scope_test.go b/p2p/host/resource-manager/scope_test.go
index 0464cb0c05..7bf7ff721b 100644
--- a/p2p/host/resource-manager/scope_test.go
+++ b/p2p/host/resource-manager/scope_test.go
@@ -74,7 +74,7 @@ func TestCheckMemory(t *testing.T) {
limit = 1024
}
currentMem = (currentMem % limit) // We can't have reserved more than our limit
- res = (res >> 14) // We won't resonably ever have a reservation > 2^50
+ res = (res >> 14) // We won't reasonably ever have a reservation > 2^50
rc := resources{limit: &BaseLimit{
Memory: int64(limit),
StreamsInbound: 1,
@@ -88,7 +88,7 @@ func TestCheckMemory(t *testing.T) {
rc.memory = int64(currentMem)
priShift = (priShift % 9)
- // Check different priorties at 2^0, 2^1,...2^8. This lets our math be correct in the check below (and avoid overflows).
+ // Check different priorities at 2^0, 2^1,...2^8. This lets our math be correct in the check below (and avoid overflows).
pri := uint8((1 << priShift) - 1)
err := rc.checkMemory(int64(res), pri)
@@ -97,7 +97,7 @@ func TestCheckMemory(t *testing.T) {
return true
}
- return (err != nil) == (uint64(res)+uint64(rc.memory) > (uint64(limit) >> uint64(8-priShift)))
+ return (err != nil) == (res+uint64(rc.memory) > (limit >> uint64(8-priShift)))
}
require.NoError(t, quick.Check(f, nil))
diff --git a/p2p/http/example_test.go b/p2p/http/example_test.go
index f0b49b0e9d..bad042e95c 100644
--- a/p2p/http/example_test.go
+++ b/p2p/http/example_test.go
@@ -61,6 +61,8 @@ func ExampleHost_listenOnHTTPTransportAndStreams() {
if err != nil {
log.Fatal(err)
}
+ defer serverStreamHost.Close()
+
server := libp2phttp.Host{
InsecureAllowHTTP: true, // For our example, we'll allow insecure HTTP
ListenAddrs: []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/50124/http")},
diff --git a/p2p/http/libp2phttp.go b/p2p/http/libp2phttp.go
index d8158153ac..fbd8a64f4e 100644
--- a/p2p/http/libp2phttp.go
+++ b/p2p/http/libp2phttp.go
@@ -48,7 +48,7 @@ type WellKnownHandler struct {
wellKnownCache []byte
}
-// streamHostListen retuns a net.Listener that listens on libp2p streams for HTTP/1.1 messages.
+// streamHostListen returns a net.Listener that listens on libp2p streams for HTTP/1.1 messages.
func streamHostListen(streamHost host.Host) (net.Listener, error) {
return gostream.Listen(streamHost, ProtocolIDForMultistreamSelect)
}
@@ -370,7 +370,9 @@ func (h *Host) SetHTTPHandlerAtPath(p protocol.ID, path string, handler http.Han
}
h.WellKnownHandler.AddProtocolMeta(p, ProtocolMeta{Path: path})
h.serveMuxInit()
- h.ServeMux.Handle(path, http.StripPrefix(path, handler))
+ // Do not trim the trailing / from path
+ // This allows us to serve `/a/b` when we mount a handler for `/b` at path `/a`
+ h.ServeMux.Handle(path, http.StripPrefix(strings.TrimSuffix(path, "/"), handler))
}
// PeerMetadataGetter lets RoundTrippers implement a specific way of caching a peer's protocol mapping.
diff --git a/p2p/http/libp2phttp_test.go b/p2p/http/libp2phttp_test.go
index 8a95bed6d7..57dd0cc8e2 100644
--- a/p2p/http/libp2phttp_test.go
+++ b/p2p/http/libp2phttp_test.go
@@ -10,6 +10,7 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/json"
+ "fmt"
"io"
"math/big"
"net"
@@ -407,7 +408,7 @@ func TestCustomServeMux(t *testing.T) {
defer server.Close()
addrs := server.Addrs()
- require.Equal(t, len(addrs), 1)
+ require.Len(t, addrs, 1)
var clientHttpHost libp2phttp.Host
rt, err := clientHttpHost.NewConstrainedRoundTripper(peer.AddrInfo{Addrs: addrs}, libp2phttp.PreferHTTPTransport)
require.NoError(t, err)
@@ -419,3 +420,67 @@ func TestCustomServeMux(t *testing.T) {
require.NoError(t, err)
require.Equal(t, 200, resp.StatusCode)
}
+
+func TestSetHandlerAtPath(t *testing.T) {
+ hf := func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Add("Content-Type", "text/plain")
+ w.Write([]byte("Hello World"))
+ }
+ tests := []struct {
+ prefix, rest string
+ paths200 []string
+ paths404 []string
+ }{
+ {
+ prefix: "/",
+ rest: "/",
+ paths200: []string{"/", "/a/", "/b", "/a/b"},
+ },
+ {
+ prefix: "/a",
+ rest: "/b/",
+ paths200: []string{"/a/b/", "///a///b/", "/a/b/c"},
+ // Not being able to serve /a/b when handling /a/b/ is a rather annoying limitation
+ // of http.StripPrefix mechanism. This happens because /a/b is redirected to /b/
+ // as the prefix /a is stripped when the redirect happens
+ paths404: []string{"/a/b", "/a", "/b", "/a/a"},
+ },
+ {
+ prefix: "/",
+ rest: "/b/",
+ paths200: []string{"/b", "/b/c", "/b/c/"},
+ paths404: []string{"/", "/a/b"},
+ },
+ }
+ for i, tc := range tests {
+ t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
+ nestedMx := http.NewServeMux()
+ nestedMx.HandleFunc(tc.rest, hf)
+ server := libp2phttp.Host{
+ ListenAddrs: []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/0/http")},
+ InsecureAllowHTTP: true,
+ }
+ server.SetHTTPHandlerAtPath("test", tc.prefix, nestedMx)
+ go func() {
+ server.Serve()
+ }()
+ defer server.Close()
+ addrs := server.Addrs()
+ require.Len(t, addrs, 1)
+ port, err := addrs[0].ValueForProtocol(ma.P_TCP)
+ require.NoError(t, err)
+ httpAddr := fmt.Sprintf("http://127.0.0.1:%s", port)
+ for _, p := range tc.paths200 {
+ resp, err := http.Get(httpAddr + p)
+ require.NoError(t, err)
+ require.Equal(t, 200, resp.StatusCode, "path:%s", p)
+ resp.Body.Close()
+ }
+ for _, p := range tc.paths404 {
+ resp, _ := http.Get(httpAddr + p)
+ require.Equal(t, 404, resp.StatusCode, "path:%s", p)
+ resp.Body.Close()
+ }
+ })
+ }
+}
diff --git a/p2p/metricshelper/conn.go b/p2p/metricshelper/conn.go
index ef367ac9b1..b07016ce84 100644
--- a/p2p/metricshelper/conn.go
+++ b/p2p/metricshelper/conn.go
@@ -2,7 +2,7 @@ package metricshelper
import ma "github.com/multiformats/go-multiaddr"
-var transports = [...]int{ma.P_CIRCUIT, ma.P_WEBRTC, ma.P_WEBTRANSPORT, ma.P_QUIC, ma.P_QUIC_V1, ma.P_WSS, ma.P_WS, ma.P_TCP}
+var transports = [...]int{ma.P_CIRCUIT, ma.P_WEBRTC, ma.P_WEBRTC_DIRECT, ma.P_WEBTRANSPORT, ma.P_QUIC, ma.P_QUIC_V1, ma.P_WSS, ma.P_WS, ma.P_TCP}
func GetTransport(a ma.Multiaddr) string {
for _, t := range transports {
diff --git a/p2p/net/connmgr/connmgr.go b/p2p/net/connmgr/connmgr.go
index b42a122fac..cf6bb58e43 100644
--- a/p2p/net/connmgr/connmgr.go
+++ b/p2p/net/connmgr/connmgr.go
@@ -2,6 +2,7 @@ package connmgr
import (
"context"
+ "fmt"
"sort"
"sync"
"sync/atomic"
@@ -72,7 +73,7 @@ type segments struct {
}
func (ss *segments) get(p peer.ID) *segment {
- return ss.buckets[byte(p[len(p)-1])]
+ return ss.buckets[p[len(p)-1]]
}
func (ss *segments) countPeers() (count int) {
@@ -239,6 +240,17 @@ func (cm *BasicConnMgr) IsProtected(id peer.ID, tag string) (protected bool) {
return protected
}
+func (cm *BasicConnMgr) CheckLimit(systemLimit connmgr.GetConnLimiter) error {
+ if cm.cfg.highWater > systemLimit.GetConnLimit() {
+ return fmt.Errorf(
+ "conn manager high watermark limit: %d, exceeds the system connection limit of: %d",
+ cm.cfg.highWater,
+ systemLimit.GetConnLimit(),
+ )
+ }
+ return nil
+}
+
// peerInfo stores metadata for a given peer.
type peerInfo struct {
id peer.ID
diff --git a/p2p/net/connmgr/connmgr_test.go b/p2p/net/connmgr/connmgr_test.go
index 8b5bbad440..2c657255f0 100644
--- a/p2p/net/connmgr/connmgr_test.go
+++ b/p2p/net/connmgr/connmgr_test.go
@@ -662,7 +662,6 @@ func TestPeerProtectionMultipleTags(t *testing.T) {
t.Error("protected connection was closed by connection manager")
}
}
-
}
func TestPeerProtectionIdempotent(t *testing.T) {
@@ -835,7 +834,7 @@ func TestPeerInfoSorting(t *testing.T) {
p2 := &peerInfo{id: peer.ID("peer2"), temp: true}
pis := peerInfos{p1, p2}
pis.SortByValueAndStreams(makeSegmentsWithPeerInfos(pis), false)
- require.Equal(t, pis, peerInfos{p2, p1})
+ require.Equal(t, peerInfos{p2, p1}, pis)
})
t.Run("starts with low-value connections", func(t *testing.T) {
@@ -843,7 +842,7 @@ func TestPeerInfoSorting(t *testing.T) {
p2 := &peerInfo{id: peer.ID("peer2"), value: 20}
pis := peerInfos{p1, p2}
pis.SortByValueAndStreams(makeSegmentsWithPeerInfos(pis), false)
- require.Equal(t, pis, peerInfos{p2, p1})
+ require.Equal(t, peerInfos{p2, p1}, pis)
})
t.Run("prefer peers with no streams", func(t *testing.T) {
@@ -859,7 +858,7 @@ func TestPeerInfoSorting(t *testing.T) {
}
pis := peerInfos{p2, p1}
pis.SortByValueAndStreams(makeSegmentsWithPeerInfos(pis), false)
- require.Equal(t, pis, peerInfos{p1, p2})
+ require.Equal(t, peerInfos{p1, p2}, pis)
})
t.Run("in a memory emergency, starts with incoming connections and higher streams", func(t *testing.T) {
@@ -902,7 +901,7 @@ func TestPeerInfoSorting(t *testing.T) {
// p3 is first because it is inactive (no streams).
// p4 is second because it has the most streams and we priortize killing
// connections with the higher number of streams.
- require.Equal(t, pis, peerInfos{p3, p4, p2, p1})
+ require.Equal(t, peerInfos{p3, p4, p2, p1}, pis)
})
t.Run("in a memory emergency, starts with connections that have many streams", func(t *testing.T) {
@@ -921,7 +920,7 @@ func TestPeerInfoSorting(t *testing.T) {
}
pis := peerInfos{p1, p2}
pis.SortByValueAndStreams(makeSegmentsWithPeerInfos(pis), true)
- require.Equal(t, pis, peerInfos{p2, p1})
+ require.Equal(t, peerInfos{p2, p1}, pis)
})
}
@@ -966,3 +965,24 @@ func TestSafeConcurrency(t *testing.T) {
wg.Wait()
})
}
+
+func TestCheckLimit(t *testing.T) {
+ low, hi := 1, 2
+ cm, err := NewConnManager(low, hi)
+ require.NoError(t, err)
+
+ err = cm.CheckLimit(testLimitGetter{hi + 1})
+ require.NoError(t, err)
+ err = cm.CheckLimit(testLimitGetter{hi})
+ require.NoError(t, err)
+ err = cm.CheckLimit(testLimitGetter{hi - 1})
+ require.Error(t, err)
+}
+
+type testLimitGetter struct {
+ limit int
+}
+
+func (g testLimitGetter) GetConnLimit() int {
+ return g.limit
+}
diff --git a/p2p/net/connmgr/decay.go b/p2p/net/connmgr/decay.go
index bdac0bef77..76f1c68725 100644
--- a/p2p/net/connmgr/decay.go
+++ b/p2p/net/connmgr/decay.go
@@ -320,7 +320,7 @@ func (t *decayingTag) Bump(p peer.ID, delta int) error {
default:
return fmt.Errorf(
"unable to bump decaying tag for peer %s, tag %s, delta %d; queue full (len=%d)",
- p.Pretty(), t.name, delta, len(t.trkr.bumpTagCh))
+ p, t.name, delta, len(t.trkr.bumpTagCh))
}
}
@@ -337,7 +337,7 @@ func (t *decayingTag) Remove(p peer.ID) error {
default:
return fmt.Errorf(
"unable to remove decaying tag for peer %s, tag %s; queue full (len=%d)",
- p.Pretty(), t.name, len(t.trkr.removeTagCh))
+ p, t.name, len(t.trkr.removeTagCh))
}
}
diff --git a/p2p/net/connmgr/decay_test.go b/p2p/net/connmgr/decay_test.go
index e6844f1a44..d51ca298c2 100644
--- a/p2p/net/connmgr/decay_test.go
+++ b/p2p/net/connmgr/decay_test.go
@@ -49,7 +49,7 @@ func TestMultipleBumps(t *testing.T) {
require.NoError(t, tag.Bump(id, 5))
waitForTag(t, mgr, id)
- require.Equal(t, mgr.GetTagInfo(id).Value, 10)
+ require.Equal(t, 10, mgr.GetTagInfo(id).Value)
require.NoError(t, tag.Bump(id, 100))
require.Eventually(t, func() bool { return mgr.GetTagInfo(id).Value == 20 }, 100*time.Millisecond, 10*time.Millisecond, "expected tag value to decay to 20")
@@ -77,7 +77,7 @@ func TestMultipleTagsNoDecay(t *testing.T) {
// all tags are upper-bounded, so the score must be 300
ti := mgr.GetTagInfo(id)
- require.Equal(t, ti.Value, 300)
+ require.Equal(t, 300, ti.Value)
for _, s := range []string{"beep", "bop", "foo"} {
if v, ok := ti.Tags[s]; !ok || v != 100 {
diff --git a/p2p/net/gostream/gostream_test.go b/p2p/net/gostream/gostream_test.go
index e961546ed6..c024cabc8b 100644
--- a/p2p/net/gostream/gostream_test.go
+++ b/p2p/net/gostream/gostream_test.go
@@ -51,7 +51,7 @@ func TestServerClient(t *testing.T) {
}
defer listener.Close()
- if listener.Addr().String() != srvHost.ID().Pretty() {
+ if listener.Addr().String() != srvHost.ID().String() {
t.Error("bad listener address")
return
}
@@ -91,11 +91,11 @@ func TestServerClient(t *testing.T) {
t.Fatal(err)
}
- if clientConn.LocalAddr().String() != clientHost.ID().Pretty() {
+ if clientConn.LocalAddr().String() != clientHost.ID().String() {
t.Fatal("Bad LocalAddr")
}
- if clientConn.RemoteAddr().String() != srvHost.ID().Pretty() {
+ if clientConn.RemoteAddr().String() != srvHost.ID().String() {
t.Fatal("Bad RemoteAddr")
}
@@ -129,7 +129,7 @@ func TestServerClient(t *testing.T) {
t.Fatal(err)
}
- if string(resp) != "yes it is\n" {
+ if resp != "yes it is\n" {
t.Errorf("Bad response: %s", resp)
}
diff --git a/p2p/net/mock/mock_test.go b/p2p/net/mock/mock_test.go
index 863e54f1c7..aed12548db 100644
--- a/p2p/net/mock/mock_test.go
+++ b/p2p/net/mock/mock_test.go
@@ -463,11 +463,11 @@ func TestRateLimiting(t *testing.T) {
}
rl.UpdateBandwidth(100)
- if !within(rl.Limit(1), time.Duration(time.Millisecond*10), time.Millisecond) {
+ if !within(rl.Limit(1), time.Millisecond*10, time.Millisecond) {
t.Fatal()
}
- if within(rl.Limit(1), time.Duration(time.Millisecond*10), time.Millisecond) {
+ if within(rl.Limit(1), time.Millisecond*10, time.Millisecond) {
t.Fatal()
}
}
diff --git a/p2p/net/nat/mock_nat_test.go b/p2p/net/nat/mock_nat_test.go
index c7a151fd10..3e453f65fa 100644
--- a/p2p/net/nat/mock_nat_test.go
+++ b/p2p/net/nat/mock_nat_test.go
@@ -1,5 +1,10 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/libp2p/go-nat (interfaces: NAT)
+//
+// Generated by this command:
+//
+// mockgen -package nat -destination mock_nat_test.go github.com/libp2p/go-nat NAT
+//
// Package nat is a generated GoMock package.
package nat
@@ -10,7 +15,7 @@ import (
reflect "reflect"
time "time"
- gomock "github.com/golang/mock/gomock"
+ gomock "go.uber.org/mock/gomock"
)
// MockNAT is a mock of NAT interface.
@@ -46,7 +51,7 @@ func (m *MockNAT) AddPortMapping(arg0 context.Context, arg1 string, arg2 int, ar
}
// AddPortMapping indicates an expected call of AddPortMapping.
-func (mr *MockNATMockRecorder) AddPortMapping(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
+func (mr *MockNATMockRecorder) AddPortMapping(arg0, arg1, arg2, arg3, arg4 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddPortMapping", reflect.TypeOf((*MockNAT)(nil).AddPortMapping), arg0, arg1, arg2, arg3, arg4)
}
@@ -60,7 +65,7 @@ func (m *MockNAT) DeletePortMapping(arg0 context.Context, arg1 string, arg2 int)
}
// DeletePortMapping indicates an expected call of DeletePortMapping.
-func (mr *MockNATMockRecorder) DeletePortMapping(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockNATMockRecorder) DeletePortMapping(arg0, arg1, arg2 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePortMapping", reflect.TypeOf((*MockNAT)(nil).DeletePortMapping), arg0, arg1, arg2)
}
diff --git a/p2p/net/nat/nat_test.go b/p2p/net/nat/nat_test.go
index ea47edc0b3..50e1eb3a23 100644
--- a/p2p/net/nat/nat_test.go
+++ b/p2p/net/nat/nat_test.go
@@ -9,11 +9,11 @@ import (
"github.com/libp2p/go-nat"
- "github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
+ "go.uber.org/mock/gomock"
)
-//go:generate sh -c "go run github.com/golang/mock/mockgen -package nat -destination mock_nat_test.go github.com/libp2p/go-nat NAT"
+//go:generate sh -c "go run go.uber.org/mock/mockgen -package nat -destination mock_nat_test.go github.com/libp2p/go-nat NAT"
func setupMockNAT(t *testing.T) (mockNAT *MockNAT, reset func()) {
t.Helper()
diff --git a/p2p/net/reuseport/dialer.go b/p2p/net/reuseport/dialer.go
index 2efc02d393..ec3769a7ac 100644
--- a/p2p/net/reuseport/dialer.go
+++ b/p2p/net/reuseport/dialer.go
@@ -33,7 +33,7 @@ func randAddr(addrs []*net.TCPAddr) *net.TCPAddr {
//
// In-order:
//
-// 1. If we're _explicitly_ listening on the prefered source address for the destination address
+// 1. If we're _explicitly_ listening on the preferred source address for the destination address
// (per the system's routes), we'll use that listener's port as the source port.
// 2. If we're listening on one or more _unspecified_ addresses (zero address), we'll pick a source
// port from one of these listener's.
diff --git a/p2p/net/swarm/addrs.go b/p2p/net/swarm/addrs.go
deleted file mode 100644
index 392900e069..0000000000
--- a/p2p/net/swarm/addrs.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package swarm
-
-import (
- ma "github.com/multiformats/go-multiaddr"
- manet "github.com/multiformats/go-multiaddr/net"
-)
-
-// http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
-var lowTimeoutFilters = ma.NewFilters()
-
-func init() {
- for _, p := range []string{
- "/ip4/10.0.0.0/ipcidr/8",
- "/ip4/100.64.0.0/ipcidr/10",
- "/ip4/169.254.0.0/ipcidr/16",
- "/ip4/172.16.0.0/ipcidr/12",
- "/ip4/192.0.0.0/ipcidr/24",
- "/ip4/192.0.0.0/ipcidr/29",
- "/ip4/192.0.0.8/ipcidr/32",
- "/ip4/192.0.0.170/ipcidr/32",
- "/ip4/192.0.0.171/ipcidr/32",
- "/ip4/192.0.2.0/ipcidr/24",
- "/ip4/192.168.0.0/ipcidr/16",
- "/ip4/198.18.0.0/ipcidr/15",
- "/ip4/198.51.100.0/ipcidr/24",
- "/ip4/203.0.113.0/ipcidr/24",
- "/ip4/240.0.0.0/ipcidr/4",
- } {
- f, err := ma.NewMultiaddr(p)
- if err != nil {
- panic("error in lowTimeoutFilters init: " + err.Error())
- }
- ipnet, err := manet.MultiaddrToIPNet(f)
- if err != nil {
- panic("error in lowTimeoutFilters init: " + err.Error())
- }
- lowTimeoutFilters.AddFilter(*ipnet, ma.ActionDeny)
- }
-}
diff --git a/p2p/net/swarm/dial_ranker.go b/p2p/net/swarm/dial_ranker.go
index 3725884e2e..7e58876b91 100644
--- a/p2p/net/swarm/dial_ranker.go
+++ b/p2p/net/swarm/dial_ranker.go
@@ -58,8 +58,19 @@ func NoDelayDialRanker(addrs []ma.Multiaddr) []network.AddrDelay {
// 3. If a QUIC or WebTransport address is present, TCP addresses dials are delayed relative to the last QUIC dial:
// We prefer to end up with a QUIC connection. For public addresses, the delay introduced is 250ms (PublicTCPDelay),
// and for private addresses 30ms (PrivateTCPDelay).
+// 4. For the TCP addresses we follow a strategy similar to QUIC with an optimisation for handling the long TCP
+// handshake time described in 6. If both IPv6 TCP and IPv4 TCP addresses are present, we do a Happy Eyeballs
+// style ranking. First dial the IPv6 TCP address with the lowest port. After this, dial the IPv4 TCP address
+// with the lowest port delayed by 250ms (PublicTCPDelay) for public addresses, and 30ms (PrivateTCPDelay)
+// for local addresses. After this we dial all the rest of the addresses delayed by 250ms (PublicTCPDelay) for
+// public addresses, and 30ms (PrivateTCPDelay) for local addresses.
+// 5. If only one of TCP IPv6 or TCP IPv4 addresses are present, dial the TCP address with the lowest port
+// first. After this we dial the rest of the TCP addresses delayed by 250ms (PublicTCPDelay) for public
+// addresses, and 30ms (PrivateTCPDelay) for local addresses.
+// 6. When a TCP socket is connected and awaiting security and muxer upgrade, we stop new dials for 2*PrivateTCPDelay
+// to allow for the upgrade to complete.
//
-// We dial lowest ports first for QUIC addresses as they are more likely to be the listen port.
+// We dial lowest ports first as they are more likely to be the listen port.
func DefaultDialRanker(addrs []ma.Multiaddr) []network.AddrDelay {
relay, addrs := filterAddrs(addrs, isRelayAddr)
pvt, addrs := filterAddrs(addrs, manet.IsPrivateAddr)
@@ -88,22 +99,57 @@ func DefaultDialRanker(addrs []ma.Multiaddr) []network.AddrDelay {
// addresses relative to direct addresses.
func getAddrDelay(addrs []ma.Multiaddr, tcpDelay time.Duration, quicDelay time.Duration,
offset time.Duration) []network.AddrDelay {
+ if len(addrs) == 0 {
+ return nil
+ }
sort.Slice(addrs, func(i, j int) bool { return score(addrs[i]) < score(addrs[j]) })
- // If the first address is (QUIC, IPv6), make the second address (QUIC, IPv4).
- happyEyeballs := false
- if len(addrs) > 0 {
+ // addrs is now sorted by (Transport, IPVersion). Reorder addrs for happy eyeballs dialing.
+ // For QUIC and TCP, if we have both IPv6 and IPv4 addresses, move the
+ // highest priority IPv4 address to the second position.
+ happyEyeballsQUIC := false
+ happyEyeballsTCP := false
+ // tcpStartIdx is the index of the first TCP Address
+ var tcpStartIdx int
+ {
+ i := 0
+ // If the first QUIC address is IPv6 move the first QUIC IPv4 address to second position
if isQUICAddr(addrs[0]) && isProtocolAddr(addrs[0], ma.P_IP6) {
- for i := 1; i < len(addrs); i++ {
- if isQUICAddr(addrs[i]) && isProtocolAddr(addrs[i], ma.P_IP4) {
- // make IPv4 address the second element
- if i > 1 {
- a := addrs[i]
- copy(addrs[2:], addrs[1:i])
+ for j := 1; j < len(addrs); j++ {
+ if isQUICAddr(addrs[j]) && isProtocolAddr(addrs[j], ma.P_IP4) {
+ // The first IPv4 address is at position j
+ // Move the jth element at position 1 shifting the affected elements
+ if j > 1 {
+ a := addrs[j]
+ copy(addrs[2:], addrs[1:j])
addrs[1] = a
}
- happyEyeballs = true
+ happyEyeballsQUIC = true
+ i = j + 1
+ break
+ }
+ }
+ }
+
+ for tcpStartIdx = i; tcpStartIdx < len(addrs); tcpStartIdx++ {
+ if isProtocolAddr(addrs[tcpStartIdx], ma.P_TCP) {
+ break
+ }
+ }
+
+ // If the first TCP address is IPv6 move the first TCP IPv4 address to second position
+ if tcpStartIdx < len(addrs) && isProtocolAddr(addrs[tcpStartIdx], ma.P_IP6) {
+ for j := tcpStartIdx + 1; j < len(addrs); j++ {
+ if isProtocolAddr(addrs[j], ma.P_TCP) && isProtocolAddr(addrs[j], ma.P_IP4) {
+ // First TCP IPv4 address is at position j, move it to position tcpStartIdx+1
+ // which is the second priority TCP address
+ if j > tcpStartIdx+1 {
+ a := addrs[j]
+ copy(addrs[tcpStartIdx+2:], addrs[tcpStartIdx+1:j])
+ addrs[tcpStartIdx+1] = a
+ }
+ happyEyeballsTCP = true
break
}
}
@@ -111,25 +157,42 @@ func getAddrDelay(addrs []ma.Multiaddr, tcpDelay time.Duration, quicDelay time.D
}
res := make([]network.AddrDelay, 0, len(addrs))
-
- var totalTCPDelay time.Duration
+ var tcpFirstDialDelay time.Duration
for i, addr := range addrs {
var delay time.Duration
switch {
case isQUICAddr(addr):
- // For QUIC addresses we dial an IPv6 address, then after quicDelay an IPv4
- // address, then after quicDelay we dial rest of the addresses.
+ // We dial an IPv6 address, then after quicDelay an IPv4
+ // address, then after a further quicDelay we dial the rest of the addresses.
if i == 1 {
delay = quicDelay
}
- if i > 1 && happyEyeballs {
- delay = 2 * quicDelay
- } else if i > 1 {
- delay = quicDelay
+ if i > 1 {
+ // If we have happy eyeballs for QUIC, dials after the second position
+ // will be delayed by 2*quicDelay
+ if happyEyeballsQUIC {
+ delay = 2 * quicDelay
+ } else {
+ delay = quicDelay
+ }
}
- totalTCPDelay = delay + tcpDelay
+ tcpFirstDialDelay = delay + tcpDelay
case isProtocolAddr(addr, ma.P_TCP):
- delay = totalTCPDelay
+ // We dial an IPv6 address, then after tcpDelay an IPv4
+ // address, then after a further tcpDelay we dial the rest of the addresses.
+ if i == tcpStartIdx+1 {
+ delay = tcpDelay
+ }
+ if i > tcpStartIdx+1 {
+ // If we have happy eyeballs for TCP, dials after the second position
+ // will be delayed by 2*tcpDelay
+ if happyEyeballsTCP {
+ delay = 2 * tcpDelay
+ } else {
+ delay = tcpDelay
+ }
+ }
+ delay += tcpFirstDialDelay
}
res = append(res, network.AddrDelay{Addr: addr, Delay: offset + delay})
}
diff --git a/p2p/net/swarm/dial_ranker_test.go b/p2p/net/swarm/dial_ranker_test.go
index ec3d10a0b3..5ef3cc27f1 100644
--- a/p2p/net/swarm/dial_ranker_test.go
+++ b/p2p/net/swarm/dial_ranker_test.go
@@ -161,6 +161,7 @@ func TestDelayRankerTCPDelay(t *testing.T) {
t1 := ma.StringCast("/ip4/1.2.3.5/tcp/1/")
t1v6 := ma.StringCast("/ip6/1::2/tcp/1")
t2 := ma.StringCast("/ip4/1.2.3.4/tcp/2")
+ t3 := ma.StringCast("/ip4/1.2.3.4/tcp/3")
testCase := []struct {
name string
@@ -169,36 +170,63 @@ func TestDelayRankerTCPDelay(t *testing.T) {
}{
{
name: "quic-with-tcp-ip6-ip4",
- addrs: []ma.Multiaddr{q1v1, q1v16, q2v16, q3v16, q2v1, t1, t2},
+ addrs: []ma.Multiaddr{q1v1, q1v16, q2v16, q3v16, q2v1, t1, t1v6, t2, t3},
output: []network.AddrDelay{
{Addr: q1v16, Delay: 0},
{Addr: q1v1, Delay: PublicQUICDelay},
{Addr: q2v16, Delay: 2 * PublicQUICDelay},
{Addr: q3v16, Delay: 2 * PublicQUICDelay},
{Addr: q2v1, Delay: 2 * PublicQUICDelay},
- {Addr: t1, Delay: 3 * PublicQUICDelay},
- {Addr: t2, Delay: 3 * PublicQUICDelay},
+ {Addr: t1v6, Delay: 3 * PublicQUICDelay},
+ {Addr: t1, Delay: 4 * PublicQUICDelay},
+ {Addr: t2, Delay: 5 * PublicQUICDelay},
+ {Addr: t3, Delay: 5 * PublicQUICDelay},
},
},
{
name: "quic-ip4-with-tcp",
- addrs: []ma.Multiaddr{q1v1, t1, t2, t1v6},
+ addrs: []ma.Multiaddr{q1v1, t2, t1v6, t1},
+ output: []network.AddrDelay{
+ {Addr: q1v1, Delay: 0},
+ {Addr: t1v6, Delay: PublicQUICDelay},
+ {Addr: t1, Delay: 2 * PublicQUICDelay},
+ {Addr: t2, Delay: 3 * PublicQUICDelay},
+ },
+ },
+ {
+ name: "quic-ip4-with-tcp-ipv4",
+ addrs: []ma.Multiaddr{q1v1, t2, t3, t1},
output: []network.AddrDelay{
{Addr: q1v1, Delay: 0},
{Addr: t1, Delay: PublicTCPDelay},
- {Addr: t2, Delay: PublicTCPDelay},
+ {Addr: t2, Delay: 2 * PublicQUICDelay},
+ {Addr: t3, Delay: 2 * PublicTCPDelay},
+ },
+ },
+ {
+ name: "quic-ip4-with-two-tcp",
+ addrs: []ma.Multiaddr{q1v1, t1v6, t2},
+ output: []network.AddrDelay{
+ {Addr: q1v1, Delay: 0},
{Addr: t1v6, Delay: PublicTCPDelay},
+ {Addr: t2, Delay: 2 * PublicTCPDelay},
},
},
{
name: "tcp-ip4-ip6",
- addrs: []ma.Multiaddr{t1, t2, t1v6},
+ addrs: []ma.Multiaddr{t1, t2, t1v6, t3},
output: []network.AddrDelay{
{Addr: t1v6, Delay: 0},
- {Addr: t1, Delay: 0},
- {Addr: t2, Delay: 0},
+ {Addr: t1, Delay: PublicTCPDelay},
+ {Addr: t2, Delay: 2 * PublicTCPDelay},
+ {Addr: t3, Delay: 2 * PublicTCPDelay},
},
},
+ {
+ name: "empty",
+ addrs: []ma.Multiaddr{},
+ output: []network.AddrDelay{},
+ },
}
for _, tc := range testCase {
t.Run(tc.name, func(t *testing.T) {
diff --git a/p2p/net/swarm/dial_test.go b/p2p/net/swarm/dial_test.go
index a614183bba..3b139ef389 100644
--- a/p2p/net/swarm/dial_test.go
+++ b/p2p/net/swarm/dial_test.go
@@ -562,7 +562,7 @@ func TestDialSimultaneousJoin(t *testing.T) {
return
}
- t.Logf("first dial succedded; conn: %+v", c)
+ t.Logf("first dial succeeded; conn: %+v", c)
connch <- c
errs <- nil
@@ -587,7 +587,7 @@ func TestDialSimultaneousJoin(t *testing.T) {
return
}
- t.Logf("second dial succedded; conn: %+v", c)
+ t.Logf("second dial succeeded; conn: %+v", c)
connch <- c
errs <- nil
@@ -605,7 +605,7 @@ func TestDialSimultaneousJoin(t *testing.T) {
return
}
- t.Logf("third dial succedded; conn: %+v", c)
+ t.Logf("third dial succeeded; conn: %+v", c)
connch <- c
errs <- nil
diff --git a/p2p/net/swarm/dial_worker.go b/p2p/net/swarm/dial_worker.go
index 78795f17b3..0cac6e4fa3 100644
--- a/p2p/net/swarm/dial_worker.go
+++ b/p2p/net/swarm/dial_worker.go
@@ -8,8 +8,10 @@ import (
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
+ tpt "github.com/libp2p/go-libp2p/core/transport"
ma "github.com/multiformats/go-multiaddr"
+ manet "github.com/multiformats/go-multiaddr/net"
)
// dialRequest is structure used to request dials to the peer associated with a
@@ -62,6 +64,8 @@ type addrDial struct {
createdAt time.Time
// dialRankingDelay is the delay in dialing this address introduced by the ranking logic
dialRankingDelay time.Duration
+ // expectedTCPUpgradeTime is the expected time by which security upgrade will complete
+ expectedTCPUpgradeTime time.Time
}
// dialWorker synchronises concurrent dials to a peer. It ensures that we make at most one dial to a
@@ -77,7 +81,7 @@ type dialWorker struct {
// we dial an address at most once
trackedDials map[string]*addrDial
// resch is used to receive response for dials to the peers addresses.
- resch chan dialResult
+ resch chan tpt.DialUpdate
connected bool // true when a connection has been successfully established
@@ -96,7 +100,7 @@ func newDialWorker(s *Swarm, p peer.ID, reqch <-chan dialRequest, cl Clock) *dia
reqch: reqch,
pendingRequests: make(map[*pendRequest]struct{}),
trackedDials: make(map[string]*addrDial),
- resch: make(chan dialResult),
+ resch: make(chan tpt.DialUpdate),
cl: cl,
}
}
@@ -116,6 +120,8 @@ func (w *dialWorker) loop() {
startTime := w.cl.Now()
// dialTimer is the dialTimer used to trigger dials
dialTimer := w.cl.InstantTimer(startTime.Add(math.MaxInt64))
+ defer dialTimer.Stop()
+
timerRunning := true
// scheduleNextDial updates timer for triggering the next dial
scheduleNextDial := func() {
@@ -123,12 +129,18 @@ func (w *dialWorker) loop() {
<-dialTimer.Ch()
}
timerRunning = false
- if dq.len() > 0 {
+ if dq.Len() > 0 {
if dialsInFlight == 0 && !w.connected {
// if there are no dials in flight, trigger the next dials immediately
dialTimer.Reset(startTime)
} else {
- dialTimer.Reset(startTime.Add(dq.top().Delay))
+ resetTime := startTime.Add(dq.top().Delay)
+ for _, ad := range w.trackedDials {
+ if !ad.expectedTCPUpgradeTime.IsZero() && ad.expectedTCPUpgradeTime.After(resetTime) {
+ resetTime = ad.expectedTCPUpgradeTime
+ }
+ }
+ dialTimer.Reset(resetTime)
}
timerRunning = true
}
@@ -159,9 +171,9 @@ loop:
// Enqueue the peer's addresses relevant to this request in dq and
// track dials to the addresses relevant to this request.
- c, err := w.s.bestAcceptableConnToPeer(req.ctx, w.peer)
- if c != nil || err != nil {
- req.resch <- dialResponse{conn: c, err: err}
+ c := w.s.bestAcceptableConnToPeer(req.ctx, w.peer)
+ if c != nil {
+ req.resch <- dialResponse{conn: c}
continue loop
}
@@ -303,16 +315,29 @@ loop:
// Update all requests waiting on this address. On success, complete the request.
// On error, record the error
- dialsInFlight--
ad, ok := w.trackedDials[string(res.Addr.Bytes())]
if !ok {
log.Errorf("SWARM BUG: no entry for address %s in trackedDials", res.Addr)
if res.Conn != nil {
res.Conn.Close()
}
+ dialsInFlight--
continue
}
+ // TCP Connection has been established. Wait for connection upgrade on this address
+ // before making new dials.
+ if res.Kind == tpt.UpdateKindHandshakeProgressed {
+ // Only wait for public addresses to complete dialing since private dials
+ // are quick any way
+ if manet.IsPublicAddr(res.Addr) {
+ ad.expectedTCPUpgradeTime = w.cl.Now().Add(PublicTCPDelay)
+ }
+ scheduleNextDial()
+ continue
+ }
+ dialsInFlight--
+ ad.expectedTCPUpgradeTime = time.Time{}
if res.Conn != nil {
// we got a connection, add it to the swarm
conn, err := w.s.addConn(res.Conn, network.DirOutbound)
@@ -373,7 +398,7 @@ func (w *dialWorker) dispatchError(ad *addrDial, err error) {
// all addrs have erred, dispatch dial error
// but first do a last one check in case an acceptable connection has landed from
// a simultaneous dial that started later and added new acceptable addrs
- c, _ := w.s.bestAcceptableConnToPeer(pr.req.ctx, w.peer)
+ c := w.s.bestAcceptableConnToPeer(pr.req.ctx, w.peer)
if c != nil {
pr.req.resch <- dialResponse{conn: c}
} else {
@@ -417,7 +442,7 @@ func newDialQueue() *dialQueue {
// Add adds adelay to the queue. If another element exists in the queue with
// the same address, it replaces that element.
func (dq *dialQueue) Add(adelay network.AddrDelay) {
- for i := 0; i < dq.len(); i++ {
+ for i := 0; i < dq.Len(); i++ {
if dq.q[i].Addr.Equal(adelay.Addr) {
if dq.q[i].Delay == adelay.Delay {
// existing element is the same. nothing to do
@@ -430,7 +455,7 @@ func (dq *dialQueue) Add(adelay network.AddrDelay) {
}
}
- for i := 0; i < dq.len(); i++ {
+ for i := 0; i < dq.Len(); i++ {
if dq.q[i].Delay > adelay.Delay {
dq.q = append(dq.q, network.AddrDelay{}) // extend the slice
copy(dq.q[i+1:], dq.q[i:])
@@ -443,13 +468,13 @@ func (dq *dialQueue) Add(adelay network.AddrDelay) {
// NextBatch returns all the elements in the queue with the highest priority
func (dq *dialQueue) NextBatch() []network.AddrDelay {
- if dq.len() == 0 {
+ if dq.Len() == 0 {
return nil
}
// i is the index of the second highest priority element
var i int
- for i = 0; i < dq.len(); i++ {
+ for i = 0; i < dq.Len(); i++ {
if dq.q[i].Delay != dq.q[0].Delay {
break
}
@@ -464,7 +489,7 @@ func (dq *dialQueue) top() network.AddrDelay {
return dq.q[0]
}
-// len returns the number of elements in the queue
-func (dq *dialQueue) len() int {
+// Len returns the number of elements in the queue
+func (dq *dialQueue) Len() int {
return len(dq.q)
}
diff --git a/p2p/net/swarm/dial_worker_test.go b/p2p/net/swarm/dial_worker_test.go
index 6679bd9587..9e9465fcb1 100644
--- a/p2p/net/swarm/dial_worker_test.go
+++ b/p2p/net/swarm/dial_worker_test.go
@@ -26,12 +26,13 @@ import (
"github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem"
"github.com/libp2p/go-libp2p/p2p/muxer/yamux"
tptu "github.com/libp2p/go-libp2p/p2p/net/upgrader"
- quic "github.com/libp2p/go-libp2p/p2p/transport/quic"
+ libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic"
"github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
+ "github.com/quic-go/quic-go"
"github.com/stretchr/testify/require"
)
@@ -88,11 +89,11 @@ func makeSwarmWithNoListenAddrs(t *testing.T, opts ...Option) *Swarm {
if err := s.AddTransport(tcpTransport); err != nil {
t.Fatal(err)
}
- reuse, err := quicreuse.NewConnManager([32]byte{})
+ reuse, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{})
if err != nil {
t.Fatal(err)
}
- quicTransport, err := quic.NewTransport(priv, reuse, nil, nil, nil)
+ quicTransport, err := libp2pquic.NewTransport(priv, reuse, nil, nil, nil)
if err != nil {
t.Fatal(err)
}
@@ -484,8 +485,8 @@ func TestDialQueueNextBatch(t *testing.T) {
}
}
}
- if q.len() != 0 {
- t.Errorf("expected queue to be empty at end. got: %d", q.len())
+ if q.Len() != 0 {
+ t.Errorf("expected queue to be empty at end. got: %d", q.Len())
}
})
}
@@ -968,7 +969,7 @@ func TestDialWorkerLoopHolePunching(t *testing.T) {
for i := 0; i < len(addrs); i++ {
delay := 10 * time.Second
if addrs[i].Equal(t1) {
- //fire t1 immediately
+ // fire t1 immediately
delay = 0
} else if addrs[i].Equal(t2) {
// delay t2 by 100ms
@@ -1081,3 +1082,61 @@ func TestDialWorkerLoopAddrDedup(t *testing.T) {
t.Errorf("expected a fail response")
}
}
+
+func TestDialWorkerLoopTCPConnUpgradeWait(t *testing.T) {
+ s1 := makeSwarmWithNoListenAddrs(t, WithDialTimeout(10*time.Second))
+ s2 := makeSwarmWithNoListenAddrs(t, WithDialTimeout(10*time.Second))
+ defer s1.Close()
+ defer s2.Close()
+ // Connection to a1 will fail but a1 is a public address so we can test waiting for tcp
+ // connection established dial update. ipv4only.arpa reserved address.
+ a1 := ma.StringCast(fmt.Sprintf("/ip4/192.0.0.170/tcp/%d", 10001))
+ // Connection to a2 will succeed.
+ a2 := ma.StringCast(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", 10002))
+ s2.Listen(a2)
+
+ s1.Peerstore().AddAddrs(s2.LocalPeer(), []ma.Multiaddr{a1, a2}, peerstore.PermanentAddrTTL)
+
+ rankerCalled := make(chan struct{})
+ s1.dialRanker = func(addrs []ma.Multiaddr) []network.AddrDelay {
+ defer close(rankerCalled)
+ return []network.AddrDelay{{Addr: a1, Delay: 0}, {Addr: a2, Delay: 100 * time.Millisecond}}
+ }
+
+ reqch := make(chan dialRequest)
+ resch := make(chan dialResponse, 2)
+ cl := newMockClock()
+ worker := newDialWorker(s1, s2.LocalPeer(), reqch, cl)
+ go worker.loop()
+ defer worker.wg.Wait()
+ defer close(reqch)
+
+ reqch <- dialRequest{ctx: context.Background(), resch: resch}
+
+ <-rankerCalled
+ // Wait a bit to let the loop make the dial attempt to a1
+ time.Sleep(1 * time.Second)
+ // Send conn established for a1
+ worker.resch <- transport.DialUpdate{Kind: transport.UpdateKindHandshakeProgressed, Addr: a1}
+ // Dial to a2 shouldn't happen even if a2 is scheduled to dial by now
+ cl.AdvanceBy(200 * time.Millisecond)
+ select {
+ case r := <-resch:
+ t.Fatalf("didn't expect any event on resch %s %s", r.err, r.conn)
+ case <-time.After(500 * time.Millisecond):
+ }
+
+ // Dial to a2 should happen now
+ // This number is high because there's a race between this goroutine advancing the clock
+ // and the worker loop goroutine processing the TCPConnectionEstablished event.
+ // In case it processes the event after the previous clock advancement we need to wait
+ // 2 * PublicTCPDelay.
+ cl.AdvanceBy(2 * PublicTCPDelay)
+ select {
+ case r := <-resch:
+ require.NoError(t, r.err)
+ require.NotNil(t, r.conn)
+ case <-time.After(3 * time.Second):
+ t.Errorf("expected a fail response")
+ }
+}
diff --git a/p2p/net/swarm/limiter.go b/p2p/net/swarm/limiter.go
index ccfe7d2371..f5638bbe72 100644
--- a/p2p/net/swarm/limiter.go
+++ b/p2p/net/swarm/limiter.go
@@ -13,17 +13,11 @@ import (
ma "github.com/multiformats/go-multiaddr"
)
-type dialResult struct {
- Conn transport.CapableConn
- Addr ma.Multiaddr
- Err error
-}
-
type dialJob struct {
addr ma.Multiaddr
peer peer.ID
ctx context.Context
- resp chan dialResult
+ resp chan transport.DialUpdate
timeout time.Duration
}
@@ -45,7 +39,7 @@ type dialLimiter struct {
waitingOnPeerLimit map[peer.ID][]*dialJob
}
-type dialfunc func(context.Context, peer.ID, ma.Multiaddr) (transport.CapableConn, error)
+type dialfunc func(context.Context, peer.ID, ma.Multiaddr, chan<- transport.DialUpdate) (transport.CapableConn, error)
func newDialLimiter(df dialfunc) *dialLimiter {
fd := ConcurrentFdDials
@@ -216,9 +210,13 @@ func (dl *dialLimiter) executeDial(j *dialJob) {
dctx, cancel := context.WithTimeout(j.ctx, j.timeout)
defer cancel()
- con, err := dl.dialFunc(dctx, j.peer, j.addr)
+ con, err := dl.dialFunc(dctx, j.peer, j.addr, j.resp)
+ kind := transport.UpdateKindDialSuccessful
+ if err != nil {
+ kind = transport.UpdateKindDialFailed
+ }
select {
- case j.resp <- dialResult{Conn: con, Addr: j.addr, Err: err}:
+ case j.resp <- transport.DialUpdate{Kind: kind, Conn: con, Addr: j.addr, Err: err}:
case <-j.ctx.Done():
if con != nil {
con.Close()
diff --git a/p2p/net/swarm/limiter_test.go b/p2p/net/swarm/limiter_test.go
index 046b4c754e..8e61958cf7 100644
--- a/p2p/net/swarm/limiter_test.go
+++ b/p2p/net/swarm/limiter_test.go
@@ -39,7 +39,7 @@ func tcpPortOver(a ma.Multiaddr, n int) bool {
return pnum > n
}
-func tryDialAddrs(ctx context.Context, l *dialLimiter, p peer.ID, addrs []ma.Multiaddr, res chan dialResult) {
+func tryDialAddrs(ctx context.Context, l *dialLimiter, p peer.ID, addrs []ma.Multiaddr, res chan transport.DialUpdate) {
for _, a := range addrs {
l.AddDialJob(&dialJob{
ctx: ctx,
@@ -51,7 +51,7 @@ func tryDialAddrs(ctx context.Context, l *dialLimiter, p peer.ID, addrs []ma.Mul
}
func hangDialFunc(hang chan struct{}) dialfunc {
- return func(ctx context.Context, p peer.ID, a ma.Multiaddr) (transport.CapableConn, error) {
+ return func(ctx context.Context, p peer.ID, a ma.Multiaddr, _ chan<- transport.DialUpdate) (transport.CapableConn, error) {
if mafmt.UTP.Matches(a) {
return transport.CapableConn(nil), nil
}
@@ -79,7 +79,7 @@ func TestLimiterBasicDials(t *testing.T) {
bads := []ma.Multiaddr{addrWithPort(1), addrWithPort(2), addrWithPort(3), addrWithPort(4)}
good := addrWithPort(20)
- resch := make(chan dialResult)
+ resch := make(chan transport.DialUpdate)
pid := peer.ID("testpeer")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -130,7 +130,7 @@ func TestFDLimiting(t *testing.T) {
goodTCP := addrWithPort(20)
ctx := context.Background()
- resch := make(chan dialResult)
+ resch := make(chan transport.DialUpdate)
// take all fd limit tokens with hang dials
for _, pid := range pids {
@@ -188,7 +188,7 @@ func TestFDLimiting(t *testing.T) {
func TestTokenRedistribution(t *testing.T) {
var lk sync.Mutex
hangchs := make(map[peer.ID]chan struct{})
- df := func(ctx context.Context, p peer.ID, a ma.Multiaddr) (transport.CapableConn, error) {
+ df := func(ctx context.Context, p peer.ID, a ma.Multiaddr, _ chan<- transport.DialUpdate) (transport.CapableConn, error) {
if tcpPortOver(a, 10) {
return (transport.CapableConn)(nil), nil
}
@@ -205,7 +205,7 @@ func TestTokenRedistribution(t *testing.T) {
pids := []peer.ID{"testpeer1", "testpeer2"}
ctx := context.Background()
- resch := make(chan dialResult)
+ resch := make(chan transport.DialUpdate)
// take all fd limit tokens with hang dials
for _, pid := range pids {
@@ -281,7 +281,7 @@ func TestTokenRedistribution(t *testing.T) {
}
func TestStressLimiter(t *testing.T) {
- df := func(ctx context.Context, p peer.ID, a ma.Multiaddr) (transport.CapableConn, error) {
+ df := func(ctx context.Context, p peer.ID, a ma.Multiaddr, _ chan<- transport.DialUpdate) (transport.CapableConn, error) {
if tcpPortOver(a, 1000) {
return transport.CapableConn(nil), nil
}
@@ -305,7 +305,7 @@ func TestStressLimiter(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- resp := make(chan dialResult)
+ resp := make(chan transport.DialUpdate)
time.Sleep(time.Duration(rand.Intn(10)) * time.Millisecond)
for _, i := range rand.Perm(len(addresses)) {
l.AddDialJob(&dialJob{
@@ -335,7 +335,7 @@ func TestStressLimiter(t *testing.T) {
}
func TestFDLimitUnderflow(t *testing.T) {
- df := func(ctx context.Context, p peer.ID, addr ma.Multiaddr) (transport.CapableConn, error) {
+ df := func(ctx context.Context, p peer.ID, addr ma.Multiaddr, _ chan<- transport.DialUpdate) (transport.CapableConn, error) {
select {
case <-ctx.Done():
case <-time.After(5 * time.Second):
@@ -361,7 +361,7 @@ func TestFDLimitUnderflow(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- resp := make(chan dialResult)
+ resp := make(chan transport.DialUpdate)
l.AddDialJob(&dialJob{
addr: addrs[i],
ctx: ctx,
diff --git a/p2p/net/swarm/swarm.go b/p2p/net/swarm/swarm.go
index 5155cd2228..f1a0f590de 100644
--- a/p2p/net/swarm/swarm.go
+++ b/p2p/net/swarm/swarm.go
@@ -17,6 +17,7 @@ import (
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/peerstore"
"github.com/libp2p/go-libp2p/core/transport"
+ "golang.org/x/exp/slices"
logging "github.com/ipfs/go-log/v2"
ma "github.com/multiformats/go-multiaddr"
@@ -136,8 +137,8 @@ func WithIPv6BlackHoleConfig(enabled bool, n, min int) Option {
// communication. The Chan sends/receives Messages, which note the
// destination or source Peer.
type Swarm struct {
- nextConnID uint64 // guarded by atomic
- nextStreamID uint64 // guarded by atomic
+ nextConnID atomic.Uint64
+ nextStreamID atomic.Uint64
// Close refcount. This allows us to fully wait for the swarm to be torn
// down before continuing.
@@ -172,6 +173,11 @@ type Swarm struct {
m map[network.Notifiee]struct{}
}
+ directConnNotifs struct {
+ sync.Mutex
+ m map[peer.ID][]chan struct{}
+ }
+
transports struct {
sync.RWMutex
m map[int]transport.Transport
@@ -231,6 +237,7 @@ func NewSwarm(local peer.ID, peers peerstore.Peerstore, eventBus event.Bus, opts
s.listeners.m = make(map[transport.Listener]struct{})
s.transports.m = make(map[int]transport.Transport)
s.notifs.m = make(map[network.Notifiee]struct{})
+ s.directConnNotifs.m = make(map[peer.ID][]chan struct{})
for _, opt := range opts {
if err := opt(s); err != nil {
@@ -274,9 +281,10 @@ func (s *Swarm) close() {
// Lots of goroutines but we might as well do this in parallel. We want to shut down as fast as
// possible.
-
+ s.refs.Add(len(listeners))
for l := range listeners {
go func(l transport.Listener) {
+ defer s.refs.Done()
if err := l.Close(); err != nil && err != transport.ErrListenerClosed {
log.Errorf("error when shutting down listener: %s", err)
}
@@ -343,7 +351,7 @@ func (s *Swarm) addConn(tc transport.CapableConn, dir network.Direction) (*Conn,
conn: tc,
swarm: s,
stat: stat,
- id: atomic.AddUint64(&s.nextConnID, 1),
+ id: s.nextConnID.Add(1),
}
// we ONLY check upgraded connections here so we can send them a Disconnect message.
@@ -353,7 +361,7 @@ func (s *Swarm) addConn(tc transport.CapableConn, dir network.Direction) (*Conn,
// TODO Send disconnect with reason here
err := tc.Close()
if err != nil {
- log.Warnf("failed to close connection with peer %s and addr %s; err: %s", p.Pretty(), addr, err)
+ log.Warnf("failed to close connection with peer %s and addr %s; err: %s", p, addr, err)
}
return nil, ErrGaterDisallowedConnection
}
@@ -390,6 +398,19 @@ func (s *Swarm) addConn(tc transport.CapableConn, dir network.Direction) (*Conn,
c.notifyLk.Lock()
s.conns.Unlock()
+ // Notify goroutines waiting for a direct connection
+ if !c.Stat().Transient {
+ // Go routines interested in waiting for direct connection first acquire this lock
+ // and then acquire s.conns.RLock. Do not acquire this lock before conns.Unlock to
+ // prevent deadlock.
+ s.directConnNotifs.Lock()
+ for _, ch := range s.directConnNotifs.m[p] {
+ close(ch)
+ }
+ delete(s.directConnNotifs.m, p)
+ s.directConnNotifs.Unlock()
+ }
+
// Emit event after releasing `s.conns` lock so that a consumer can still
// use swarm methods that need the `s.conns` lock.
if isFirstConnection {
@@ -429,54 +450,110 @@ func (s *Swarm) StreamHandler() network.StreamHandler {
// NewStream creates a new stream on any available connection to peer, dialing
// if necessary.
+// Use network.WithUseTransient to open a stream over a transient(relayed)
+// connection.
func (s *Swarm) NewStream(ctx context.Context, p peer.ID) (network.Stream, error) {
log.Debugf("[%s] opening stream to peer [%s]", s.local, p)
// Algorithm:
// 1. Find the best connection, otherwise, dial.
- // 2. Try opening a stream.
- // 3. If the underlying connection is, in fact, closed, close the outer
+ // 2. If the best connection is transient, wait for a direct conn via conn
+ // reversal or hole punching.
+ // 3. Try opening a stream.
+ // 4. If the underlying connection is, in fact, closed, close the outer
// connection and try again. We do this in case we have a closed
// connection but don't notice it until we actually try to open a
// stream.
//
- // Note: We only dial once.
- //
// TODO: Try all connections even if we get an error opening a stream on
// a non-closed connection.
- dials := 0
+ numDials := 0
for {
- // will prefer direct connections over relayed connections for opening streams
- c, err := s.bestAcceptableConnToPeer(ctx, p)
- if err != nil {
- return nil, err
- }
-
+ c := s.bestConnToPeer(p)
if c == nil {
- if nodial, _ := network.GetNoDial(ctx); nodial {
+ if nodial, _ := network.GetNoDial(ctx); !nodial {
+ numDials++
+ if numDials > DialAttempts {
+ return nil, errors.New("max dial attempts exceeded")
+ }
+ var err error
+ c, err = s.dialPeer(ctx, p)
+ if err != nil {
+ return nil, err
+ }
+ } else {
return nil, network.ErrNoConn
}
+ }
- if dials >= DialAttempts {
- return nil, errors.New("max dial attempts exceeded")
- }
- dials++
-
+ useTransient, _ := network.GetUseTransient(ctx)
+ if !useTransient && c.Stat().Transient {
var err error
- c, err = s.dialPeer(ctx, p)
+ c, err = s.waitForDirectConn(ctx, p)
if err != nil {
return nil, err
}
}
- s, err := c.NewStream(ctx)
+ str, err := c.NewStream(ctx)
if err != nil {
if c.conn.IsClosed() {
continue
}
return nil, err
}
- return s, nil
+ return str, nil
+ }
+}
+
+// waitForDirectConn waits for a direct connection established through hole punching or connection reversal.
+func (s *Swarm) waitForDirectConn(ctx context.Context, p peer.ID) (*Conn, error) {
+ s.directConnNotifs.Lock()
+ c := s.bestConnToPeer(p)
+ if c == nil {
+ s.directConnNotifs.Unlock()
+ return nil, network.ErrNoConn
+ } else if !c.Stat().Transient {
+ s.directConnNotifs.Unlock()
+ return c, nil
+ }
+
+ // Wait for transient connection to upgrade to a direct connection either by
+ // connection reversal or hole punching.
+ ch := make(chan struct{})
+ s.directConnNotifs.m[p] = append(s.directConnNotifs.m[p], ch)
+ s.directConnNotifs.Unlock()
+
+ // apply the DialPeer timeout
+ ctx, cancel := context.WithTimeout(ctx, network.GetDialPeerTimeout(ctx))
+ defer cancel()
+
+ // Wait for notification.
+ select {
+ case <-ctx.Done():
+ // Remove ourselves from the notification list
+ s.directConnNotifs.Lock()
+ defer s.directConnNotifs.Unlock()
+
+ s.directConnNotifs.m[p] = slices.DeleteFunc(
+ s.directConnNotifs.m[p],
+ func(c chan struct{}) bool { return c == ch },
+ )
+ if len(s.directConnNotifs.m[p]) == 0 {
+ delete(s.directConnNotifs.m, p)
+ }
+ return nil, ctx.Err()
+ case <-ch:
+ // We do not need to remove ourselves from the list here as the notifier
+ // clears the map entry
+ c := s.bestConnToPeer(p)
+ if c == nil {
+ return nil, network.ErrNoConn
+ }
+ if c.Stat().Transient {
+ return nil, network.ErrTransientConn
+ }
+ return c, nil
}
}
@@ -548,26 +625,17 @@ func (s *Swarm) bestConnToPeer(p peer.ID) *Conn {
return best
}
-// - Returns the best "acceptable" connection, if available.
-// - Returns nothing if no such connection exists, but if we should try dialing anyways.
-// - Returns an error if no such connection exists, but we should not try dialing.
-func (s *Swarm) bestAcceptableConnToPeer(ctx context.Context, p peer.ID) (*Conn, error) {
+// bestAcceptableConnToPeer returns the best acceptable connection, considering the passed in ctx.
+// If network.WithForceDirectDial is used, it only returns a direct connections, ignoring
+// any transient (relayed) connections to the peer.
+func (s *Swarm) bestAcceptableConnToPeer(ctx context.Context, p peer.ID) *Conn {
conn := s.bestConnToPeer(p)
- if conn == nil {
- return nil, nil
- }
forceDirect, _ := network.GetForceDirectDial(ctx)
if forceDirect && !isDirectConn(conn) {
- return nil, nil
- }
-
- useTransient, _ := network.GetUseTransient(ctx)
- if useTransient || !conn.Stat().Transient {
- return conn, nil
+ return nil
}
-
- return nil, network.ErrTransientConn
+ return conn
}
func isDirectConn(c *Conn) bool {
diff --git a/p2p/net/swarm/swarm_addr_test.go b/p2p/net/swarm/swarm_addr_test.go
index 8ab7d18bf6..435866e920 100644
--- a/p2p/net/swarm/swarm_addr_test.go
+++ b/p2p/net/swarm/swarm_addr_test.go
@@ -2,6 +2,7 @@ package swarm_test
import (
"context"
+ "crypto/sha256"
"fmt"
"testing"
@@ -9,12 +10,11 @@ import (
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/peerstore"
"github.com/libp2p/go-libp2p/core/test"
- "github.com/libp2p/go-libp2p/internal/sha256"
"github.com/libp2p/go-libp2p/p2p/host/eventbus"
"github.com/libp2p/go-libp2p/p2p/net/swarm"
swarmt "github.com/libp2p/go-libp2p/p2p/net/swarm/testing"
circuitv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client"
- quic "github.com/libp2p/go-libp2p/p2p/transport/quic"
+ libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic"
"github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
webtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport"
@@ -22,6 +22,7 @@ import (
ma "github.com/multiformats/go-multiaddr"
"github.com/multiformats/go-multibase"
"github.com/multiformats/go-multihash"
+ "github.com/quic-go/quic-go"
"github.com/stretchr/testify/require"
)
@@ -81,10 +82,10 @@ func TestDialAddressSelection(t *testing.T) {
tcpTr, err := tcp.NewTCPTransport(nil, nil)
require.NoError(t, err)
require.NoError(t, s.AddTransport(tcpTr))
- reuse, err := quicreuse.NewConnManager([32]byte{})
+ reuse, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{})
require.NoError(t, err)
defer reuse.Close()
- quicTr, err := quic.NewTransport(priv, reuse, nil, nil, nil)
+ quicTr, err := libp2pquic.NewTransport(priv, reuse, nil, nil, nil)
require.NoError(t, err)
require.NoError(t, s.AddTransport(quicTr))
webtransportTr, err := webtransport.New(priv, nil, reuse, nil, nil)
diff --git a/p2p/net/swarm/swarm_conn.go b/p2p/net/swarm/swarm_conn.go
index e770381a2e..8c3ce7c5ac 100644
--- a/p2p/net/swarm/swarm_conn.go
+++ b/p2p/net/swarm/swarm_conn.go
@@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"sync"
- "sync/atomic"
"time"
ic "github.com/libp2p/go-libp2p/core/crypto"
@@ -49,7 +48,7 @@ func (c *Conn) IsClosed() bool {
func (c *Conn) ID() string {
// format: -
- return fmt.Sprintf("%s-%d", c.RemotePeer().Pretty()[0:10], c.id)
+ return fmt.Sprintf("%s-%d", c.RemotePeer().String()[:10], c.id)
}
// Close closes this connection.
@@ -137,6 +136,7 @@ func (c *Conn) start() {
if h := c.swarm.StreamHandler(); h != nil {
h(s)
}
+ s.completeAcceptStreamGoroutine()
}()
}
}()
@@ -147,9 +147,9 @@ func (c *Conn) String() string {
" %s (%s)>",
c.conn.Transport(),
c.conn.LocalMultiaddr(),
- c.conn.LocalPeer().Pretty(),
+ c.conn.LocalPeer(),
c.conn.RemoteMultiaddr(),
- c.conn.RemotePeer().Pretty(),
+ c.conn.RemotePeer(),
)
}
@@ -238,7 +238,8 @@ func (c *Conn) addStream(ts network.MuxedStream, dir network.Direction, scope ne
Direction: dir,
Opened: time.Now(),
},
- id: atomic.AddUint64(&c.swarm.nextStreamID, 1),
+ id: c.swarm.nextStreamID.Add(1),
+ acceptStreamGoroutineCompleted: dir != network.DirInbound,
}
c.stat.NumStreams++
c.streams.m[s] = struct{}{}
diff --git a/p2p/net/swarm/swarm_dial.go b/p2p/net/swarm/swarm_dial.go
index aa6e077f4b..f639ce16a2 100644
--- a/p2p/net/swarm/swarm_dial.go
+++ b/p2p/net/swarm/swarm_dial.go
@@ -216,7 +216,8 @@ func (db *DialBackoff) cleanup() {
}
}
-// DialPeer connects to a peer.
+// DialPeer connects to a peer. Use network.WithForceDirectDial to force a
+// direct connection.
//
// The idea is that the client of Swarm does not need to know what network
// the connection will happen over. Swarm can use whichever it choses.
@@ -246,15 +247,14 @@ func (s *Swarm) dialPeer(ctx context.Context, p peer.ID) (*Conn, error) {
return nil, ErrDialToSelf
}
- // check if we already have an open (usable) connection first, or can't have a usable
- // connection.
- conn, err := s.bestAcceptableConnToPeer(ctx, p)
- if conn != nil || err != nil {
- return conn, err
+ // check if we already have an open (usable) connection.
+ conn := s.bestAcceptableConnToPeer(ctx, p)
+ if conn != nil {
+ return conn, nil
}
if s.gater != nil && !s.gater.InterceptPeerDial(p) {
- log.Debugf("gater disallowed outbound connection to peer %s", p.Pretty())
+ log.Debugf("gater disallowed outbound connection to peer %s", p)
return nil, &DialError{Peer: p, Cause: ErrGaterDisallowedConnection}
}
@@ -301,27 +301,8 @@ func (s *Swarm) addrsForDial(ctx context.Context, p peer.ID) (goodAddrs []ma.Mul
return nil, nil, ErrNoAddresses
}
- peerAddrsAfterTransportResolved := make([]ma.Multiaddr, 0, len(peerAddrs))
- for _, a := range peerAddrs {
- tpt := s.TransportForDialing(a)
- resolver, ok := tpt.(transport.Resolver)
- if ok {
- resolvedAddrs, err := resolver.Resolve(ctx, a)
- if err != nil {
- log.Warnf("Failed to resolve multiaddr %s by transport %v: %v", a, tpt, err)
- continue
- }
- peerAddrsAfterTransportResolved = append(peerAddrsAfterTransportResolved, resolvedAddrs...)
- } else {
- peerAddrsAfterTransportResolved = append(peerAddrsAfterTransportResolved, a)
- }
- }
-
// Resolve dns or dnsaddrs
- resolved, err := s.resolveAddrs(ctx, peer.AddrInfo{
- ID: p,
- Addrs: peerAddrsAfterTransportResolved,
- })
+ resolved, err := s.resolveAddrs(ctx, peer.AddrInfo{ID: p, Addrs: peerAddrs})
if err != nil {
return nil, nil, err
}
@@ -342,21 +323,19 @@ func (s *Swarm) addrsForDial(ctx context.Context, p peer.ID) (goodAddrs []ma.Mul
}
func (s *Swarm) resolveAddrs(ctx context.Context, pi peer.AddrInfo) ([]ma.Multiaddr, error) {
- proto := ma.ProtocolWithCode(ma.P_P2P).Name
- p2paddr, err := ma.NewMultiaddr("/" + proto + "/" + pi.ID.Pretty())
+ p2paddr, err := ma.NewMultiaddr("/" + ma.ProtocolWithCode(ma.P_P2P).Name + "/" + pi.ID.String())
if err != nil {
return nil, err
}
- resolveSteps := 0
-
+ var resolveSteps int
// Recursively resolve all addrs.
//
// While the toResolve list is non-empty:
// * Pop an address off.
// * If the address is fully resolved, add it to the resolved list.
// * Otherwise, resolve it and add the results to the "to resolve" list.
- toResolve := append(([]ma.Multiaddr)(nil), pi.Addrs...)
+ toResolve := append([]ma.Multiaddr{}, pi.Addrs...)
resolved := make([]ma.Multiaddr, 0, len(pi.Addrs))
for len(toResolve) > 0 {
// pop the last addr off.
@@ -383,6 +362,26 @@ func (s *Swarm) resolveAddrs(ctx context.Context, pi peer.AddrInfo) ([]ma.Multia
continue
}
+ tpt := s.TransportForDialing(addr)
+ resolver, ok := tpt.(transport.Resolver)
+ if ok {
+ resolvedAddrs, err := resolver.Resolve(ctx, addr)
+ if err != nil {
+ log.Warnf("Failed to resolve multiaddr %s by transport %v: %v", addr, tpt, err)
+ continue
+ }
+ var added bool
+ for _, a := range resolvedAddrs {
+ if !addr.Equal(a) {
+ toResolve = append(toResolve, a)
+ added = true
+ }
+ }
+ if added {
+ continue
+ }
+ }
+
// otherwise, resolve it
reqaddr := addr.Encapsulate(p2paddr)
resaddrs, err := s.maResolver.Resolve(ctx, reqaddr)
@@ -403,7 +402,7 @@ func (s *Swarm) resolveAddrs(ctx context.Context, pi peer.AddrInfo) ([]ma.Multia
return resolved, nil
}
-func (s *Swarm) dialNextAddr(ctx context.Context, p peer.ID, addr ma.Multiaddr, resch chan dialResult) error {
+func (s *Swarm) dialNextAddr(ctx context.Context, p peer.ID, addr ma.Multiaddr, resch chan transport.DialUpdate) error {
// check the dial backoff
if forceDirect, _ := network.GetForceDirectDial(ctx); !forceDirect {
if s.backf.Backoff(p, addr) {
@@ -427,7 +426,7 @@ var quicDraft29DialMatcher = mafmt.And(mafmt.IP, mafmt.Base(ma.P_UDP), mafmt.Bas
// filterKnownUndialables takes a list of multiaddrs, and removes those
// that we definitely don't want to dial: addresses configured to be blocked,
// IPv6 link-local addresses, addresses without a dial-capable transport,
-// addresses that we know to be our own, and addresses with a better tranport
+// addresses that we know to be our own, and addresses with a better transport
// available. This is an optimization to avoid wasting time on dials that we
// know are going to fail or for which we have a better alternative.
func (s *Swarm) filterKnownUndialables(p peer.ID, addrs []ma.Multiaddr) (goodAddrs []ma.Multiaddr, addrErrs []TransportError) {
@@ -475,6 +474,14 @@ func (s *Swarm) filterKnownUndialables(p peer.ID, addrs []ma.Multiaddr) (goodAdd
}
return ma.FilterAddrs(addrs,
+ // Linux and BSD treat an unspecified address when dialing as a localhost address.
+ // Windows doesn't support this. We filter all such addresses out because peers
+ // listening on unspecified addresses will advertise more specific addresses.
+ // https://unix.stackexchange.com/a/419881
+ // https://superuser.com/a/1755455
+ func(addr ma.Multiaddr) bool {
+ return !manet.IsIPUnspecified(addr)
+ },
func(addr ma.Multiaddr) bool {
if ma.Contains(ourAddrs, addr) {
addrErrs = append(addrErrs, TransportError{Address: addr, Cause: ErrDialToSelf})
@@ -497,9 +504,9 @@ func (s *Swarm) filterKnownUndialables(p peer.ID, addrs []ma.Multiaddr) (goodAdd
// limitedDial will start a dial to the given peer when
// it is able, respecting the various different types of rate
// limiting that occur without using extra goroutines per addr
-func (s *Swarm) limitedDial(ctx context.Context, p peer.ID, a ma.Multiaddr, resp chan dialResult) {
+func (s *Swarm) limitedDial(ctx context.Context, p peer.ID, a ma.Multiaddr, resp chan transport.DialUpdate) {
timeout := s.dialTimeout
- if lowTimeoutFilters.AddrBlocked(a) && s.dialTimeoutLocal < s.dialTimeout {
+ if manet.IsPrivateAddr(a) && s.dialTimeoutLocal < s.dialTimeout {
timeout = s.dialTimeoutLocal
}
s.limiter.AddDialJob(&dialJob{
@@ -512,7 +519,7 @@ func (s *Swarm) limitedDial(ctx context.Context, p peer.ID, a ma.Multiaddr, resp
}
// dialAddr is the actual dial for an addr, indirectly invoked through the limiter
-func (s *Swarm) dialAddr(ctx context.Context, p peer.ID, addr ma.Multiaddr) (transport.CapableConn, error) {
+func (s *Swarm) dialAddr(ctx context.Context, p peer.ID, addr ma.Multiaddr, updCh chan<- transport.DialUpdate) (transport.CapableConn, error) {
// Just to double check. Costs nothing.
if s.local == p {
return nil, ErrDialToSelf
@@ -530,10 +537,16 @@ func (s *Swarm) dialAddr(ctx context.Context, p peer.ID, addr ma.Multiaddr) (tra
}
start := time.Now()
- connC, err := tpt.Dial(ctx, addr, p)
+ var connC transport.CapableConn
+ var err error
+ if du, ok := tpt.(transport.DialUpdater); ok {
+ connC, err = du.DialWithUpdates(ctx, addr, p, updCh)
+ } else {
+ connC, err = tpt.Dial(ctx, addr, p)
+ }
// We're recording any error as a failure here.
- // Notably, this also applies to cancelations (i.e. if another dial attempt was faster).
+ // Notably, this also applies to cancellations (i.e. if another dial attempt was faster).
// This is ok since the black hole detector uses a very low threshold (5%).
s.bhd.RecordResult(addr, err == nil)
diff --git a/p2p/net/swarm/swarm_dial_test.go b/p2p/net/swarm/swarm_dial_test.go
index 47310978fe..021c368bd6 100644
--- a/p2p/net/swarm/swarm_dial_test.go
+++ b/p2p/net/swarm/swarm_dial_test.go
@@ -114,7 +114,7 @@ func TestDedupAddrsForDial(t *testing.T) {
mas, _, err := s.addrsForDial(ctx, otherPeer)
require.NoError(t, err)
- require.Equal(t, 1, len(mas))
+ require.Len(t, mas, 1)
}
func newTestSwarmWithResolver(t *testing.T, resolver *madns.Resolver) *Swarm {
@@ -139,7 +139,7 @@ func newTestSwarmWithResolver(t *testing.T, resolver *madns.Resolver) *Swarm {
err = s.AddTransport(tpt)
require.NoError(t, err)
- connmgr, err := quicreuse.NewConnManager(quic.StatelessResetKey{})
+ connmgr, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{})
require.NoError(t, err)
quicTpt, err := libp2pquic.NewTransport(priv, connmgr, nil, nil, &network.NullResourceManager{})
require.NoError(t, err)
@@ -167,8 +167,8 @@ func TestAddrResolution(t *testing.T) {
addr1 := ma.StringCast("/dnsaddr/example.com")
addr2 := ma.StringCast("/ip4/192.0.2.1/tcp/123")
- p2paddr2 := ma.StringCast("/ip4/192.0.2.1/tcp/123/p2p/" + p1.Pretty())
- p2paddr3 := ma.StringCast("/ip4/192.0.2.1/tcp/123/p2p/" + p2.Pretty())
+ p2paddr2 := ma.StringCast("/ip4/192.0.2.1/tcp/123/p2p/" + p1.String())
+ p2paddr3 := ma.StringCast("/ip4/192.0.2.1/tcp/123/p2p/" + p2.String())
backend := &madns.MockResolver{
TXT: map[string][]string{"_dnsaddr.example.com": {
@@ -197,23 +197,16 @@ func TestAddrResolution(t *testing.T) {
}
func TestAddrResolutionRecursive(t *testing.T) {
- ctx := context.Background()
+ p1 := test.RandPeerIDFatal(t)
+ p2 := test.RandPeerIDFatal(t)
- p1, err := test.RandPeerID()
- if err != nil {
- t.Error(err)
- }
- p2, err := test.RandPeerID()
- if err != nil {
- t.Error(err)
- }
addr1 := ma.StringCast("/dnsaddr/example.com")
addr2 := ma.StringCast("/ip4/192.0.2.1/tcp/123")
- p2paddr1 := ma.StringCast("/dnsaddr/example.com/p2p/" + p1.Pretty())
- p2paddr2 := ma.StringCast("/dnsaddr/example.com/p2p/" + p2.Pretty())
- p2paddr1i := ma.StringCast("/dnsaddr/foo.example.com/p2p/" + p1.Pretty())
- p2paddr2i := ma.StringCast("/dnsaddr/bar.example.com/p2p/" + p2.Pretty())
- p2paddr1f := ma.StringCast("/ip4/192.0.2.1/tcp/123/p2p/" + p1.Pretty())
+ p2paddr1 := ma.StringCast("/dnsaddr/example.com/p2p/" + p1.String())
+ p2paddr2 := ma.StringCast("/dnsaddr/example.com/p2p/" + p2.String())
+ p2paddr1i := ma.StringCast("/dnsaddr/foo.example.com/p2p/" + p1.String())
+ p2paddr2i := ma.StringCast("/dnsaddr/bar.example.com/p2p/" + p2.String())
+ p2paddr1f := ma.StringCast("/ip4/192.0.2.1/tcp/123/p2p/" + p1.String())
backend := &madns.MockResolver{
TXT: map[string][]string{
@@ -221,25 +214,19 @@ func TestAddrResolutionRecursive(t *testing.T) {
"dnsaddr=" + p2paddr1i.String(),
"dnsaddr=" + p2paddr2i.String(),
},
- "_dnsaddr.foo.example.com": {
- "dnsaddr=" + p2paddr1f.String(),
- },
- "_dnsaddr.bar.example.com": {
- "dnsaddr=" + p2paddr2i.String(),
- },
+ "_dnsaddr.foo.example.com": {"dnsaddr=" + p2paddr1f.String()},
+ "_dnsaddr.bar.example.com": {"dnsaddr=" + p2paddr2i.String()},
},
}
resolver, err := madns.NewResolver(madns.WithDefaultResolver(backend))
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
s := newTestSwarmWithResolver(t, resolver)
pi1, err := peer.AddrInfoFromP2pAddr(p2paddr1)
require.NoError(t, err)
- tctx, cancel := context.WithTimeout(ctx, time.Millisecond*100)
+ tctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*100)
defer cancel()
s.Peerstore().AddAddrs(pi1.ID, pi1.Addrs, peerstore.TempAddrTTL)
_, _, err = s.addrsForDial(tctx, p1)
@@ -263,6 +250,34 @@ func TestAddrResolutionRecursive(t *testing.T) {
require.Contains(t, addrs2, addr1)
}
+// see https://github.com/libp2p/go-libp2p/issues/2562
+func TestAddrResolutionRecursiveTransportSpecific(t *testing.T) {
+ p := test.RandPeerIDFatal(t)
+
+ backend := &madns.MockResolver{
+ IP: map[string][]net.IPAddr{
+ "sub.example.com": {net.IPAddr{IP: net.IPv4(1, 2, 3, 4)}},
+ },
+ TXT: map[string][]string{
+ "_dnsaddr.example.com": {"dnsaddr=/dns4/sub.example.com/tcp/443/wss/p2p/" + p.String()},
+ },
+ }
+ resolver, err := madns.NewResolver(madns.WithDefaultResolver(backend))
+ require.NoError(t, err)
+
+ s := newTestSwarmWithResolver(t, resolver)
+ pi1, err := peer.AddrInfoFromP2pAddr(ma.StringCast("/dnsaddr/example.com/p2p/" + p.String()))
+ require.NoError(t, err)
+
+ tctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*100)
+ defer cancel()
+ s.Peerstore().AddAddrs(pi1.ID, pi1.Addrs, peerstore.TempAddrTTL)
+ addrs, _, err := s.addrsForDial(tctx, p)
+ require.NoError(t, err)
+ require.Len(t, addrs, 1)
+ require.Equal(t, "/ip4/1.2.3.4/tcp/443/tls/sni/sub.example.com/ws", addrs[0].String())
+}
+
func TestAddrsForDialFiltering(t *testing.T) {
q1 := ma.StringCast("/ip4/1.2.3.4/udp/1/quic-v1")
q1v1 := ma.StringCast("/ip4/1.2.3.4/udp/1/quic-v1")
@@ -277,6 +292,9 @@ func TestAddrsForDialFiltering(t *testing.T) {
t1 := ma.StringCast("/ip4/1.2.3.4/tcp/1")
ws1 := ma.StringCast("/ip4/1.2.3.4/tcp/1/ws")
+ unSpecQ := ma.StringCast("/ip4/0.0.0.0/udp/2/quic-v1")
+ unSpecT := ma.StringCast("/ip6/::/tcp/2/")
+
resolver, err := madns.NewResolver(madns.WithDefaultResolver(&madns.MockResolver{}))
require.NoError(t, err)
s := newTestSwarmWithResolver(t, resolver)
@@ -307,6 +325,11 @@ func TestAddrsForDialFiltering(t *testing.T) {
input: append([]ma.Multiaddr{q1}, ourAddrs...),
output: []ma.Multiaddr{q1},
},
+ {
+ name: "unspecified-filtered",
+ input: []ma.Multiaddr{q1v1, t1, unSpecQ, unSpecT},
+ output: []ma.Multiaddr{q1v1, t1},
+ },
}
ctx := context.Background()
diff --git a/p2p/net/swarm/swarm_metrics.go b/p2p/net/swarm/swarm_metrics.go
index 9cc34599d8..b5c0f2e499 100644
--- a/p2p/net/swarm/swarm_metrics.go
+++ b/p2p/net/swarm/swarm_metrics.go
@@ -166,7 +166,7 @@ func appendConnectionState(tags []string, cs network.ConnectionState) []string {
// This shouldn't happen, unless the transport doesn't properly set the Transport field in the ConnectionState.
tags = append(tags, "unknown")
} else {
- tags = append(tags, string(cs.Transport))
+ tags = append(tags, cs.Transport)
}
// These might be empty, depending on the transport.
// For example, QUIC doesn't set security nor muxer.
diff --git a/p2p/net/swarm/swarm_stream.go b/p2p/net/swarm/swarm_stream.go
index d372bcd8e4..b7846adec2 100644
--- a/p2p/net/swarm/swarm_stream.go
+++ b/p2p/net/swarm/swarm_stream.go
@@ -22,7 +22,10 @@ type Stream struct {
conn *Conn
scope network.StreamManagementScope
- closeOnce sync.Once
+ closeMx sync.Mutex
+ isClosed bool
+ // acceptStreamGoroutineCompleted indicates whether the goroutine handling the incoming stream has exited
+ acceptStreamGoroutineCompleted bool
protocol atomic.Pointer[protocol.ID]
@@ -76,7 +79,7 @@ func (s *Stream) Write(p []byte) (int, error) {
// resources.
func (s *Stream) Close() error {
err := s.stream.Close()
- s.closeOnce.Do(s.remove)
+ s.closeAndRemoveStream()
return err
}
@@ -84,10 +87,25 @@ func (s *Stream) Close() error {
// associated resources.
func (s *Stream) Reset() error {
err := s.stream.Reset()
- s.closeOnce.Do(s.remove)
+ s.closeAndRemoveStream()
return err
}
+func (s *Stream) closeAndRemoveStream() {
+ s.closeMx.Lock()
+ defer s.closeMx.Unlock()
+ if s.isClosed {
+ return
+ }
+ s.isClosed = true
+ // We don't want to keep swarm from closing till the stream handler has exited
+ s.conn.swarm.refs.Done()
+ // Cleanup the stream from connection only after the stream handler has completed
+ if s.acceptStreamGoroutineCompleted {
+ s.conn.removeStream(s)
+ }
+}
+
// CloseWrite closes the stream for writing, flushing all data and sending an EOF.
// This function does not free resources, call Close or Reset when done with the
// stream.
@@ -101,9 +119,16 @@ func (s *Stream) CloseRead() error {
return s.stream.CloseRead()
}
-func (s *Stream) remove() {
- s.conn.removeStream(s)
- s.conn.swarm.refs.Done()
+func (s *Stream) completeAcceptStreamGoroutine() {
+ s.closeMx.Lock()
+ defer s.closeMx.Unlock()
+ if s.acceptStreamGoroutineCompleted {
+ return
+ }
+ s.acceptStreamGoroutineCompleted = true
+ if s.isClosed {
+ s.conn.removeStream(s)
+ }
}
// Protocol returns the protocol negotiated on this stream (if set).
diff --git a/p2p/net/swarm/swarm_test.go b/p2p/net/swarm/swarm_test.go
index c795b68afb..3d92690b98 100644
--- a/p2p/net/swarm/swarm_test.go
+++ b/p2p/net/swarm/swarm_test.go
@@ -21,11 +21,11 @@ import (
"github.com/libp2p/go-libp2p/p2p/net/swarm"
. "github.com/libp2p/go-libp2p/p2p/net/swarm/testing"
- "github.com/golang/mock/gomock"
logging "github.com/ipfs/go-log/v2"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
"github.com/stretchr/testify/require"
+ "go.uber.org/mock/gomock"
)
var log = logging.Logger("swarm_test")
@@ -445,16 +445,16 @@ func TestStreamCount(t *testing.T) {
<-streamAccepted
}
require.Eventually(t, func() bool { return len(streams) == 10 }, 5*time.Second, 10*time.Millisecond)
- require.Equal(t, countStreams(), 10)
+ require.Equal(t, 10, countStreams())
(<-streams).Reset()
(<-streams).Close()
- require.Equal(t, countStreams(), 8)
+ require.Equal(t, 8, countStreams())
str, err := s1.NewStream(context.Background(), s2.LocalPeer())
require.NoError(t, err)
- require.Equal(t, countStreams(), 9)
+ require.Equal(t, 9, countStreams())
str.Close()
- require.Equal(t, countStreams(), 8)
+ require.Equal(t, 8, countStreams())
}
func TestResourceManager(t *testing.T) {
@@ -552,7 +552,7 @@ func TestListenCloseCount(t *testing.T) {
t.Fatal(err)
}
listenedAddrs := s.ListenAddresses()
- require.Equal(t, 2, len(listenedAddrs))
+ require.Len(t, listenedAddrs, 2)
var addrToClose ma.Multiaddr
for _, addr := range listenedAddrs {
if _, err := addr.ValueForProtocol(ma.P_QUIC_V1); err == nil {
@@ -564,7 +564,7 @@ func TestListenCloseCount(t *testing.T) {
s.ListenClose(addrToClose)
remainingAddrs := s.ListenAddresses()
- require.Equal(t, 1, len(remainingAddrs))
+ require.Len(t, remainingAddrs, 1)
_, err := remainingAddrs[0].ValueForProtocol(ma.P_TCP)
require.NoError(t, err, "expected the TCP address to still be present")
}
diff --git a/p2p/net/swarm/testing/testing.go b/p2p/net/swarm/testing/testing.go
index 071a828b54..627114f645 100644
--- a/p2p/net/swarm/testing/testing.go
+++ b/p2p/net/swarm/testing/testing.go
@@ -21,11 +21,12 @@ import (
"github.com/libp2p/go-libp2p/p2p/muxer/yamux"
"github.com/libp2p/go-libp2p/p2p/net/swarm"
tptu "github.com/libp2p/go-libp2p/p2p/net/upgrader"
- quic "github.com/libp2p/go-libp2p/p2p/transport/quic"
+ libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic"
"github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
ma "github.com/multiformats/go-multiaddr"
+ "github.com/quic-go/quic-go"
"github.com/stretchr/testify/require"
)
@@ -175,11 +176,11 @@ func GenSwarm(t *testing.T, opts ...Option) *swarm.Swarm {
}
}
if !cfg.disableQUIC {
- reuse, err := quicreuse.NewConnManager([32]byte{})
+ reuse, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{})
if err != nil {
t.Fatal(err)
}
- quicTransport, err := quic.NewTransport(priv, reuse, nil, cfg.connectionGater, nil)
+ quicTransport, err := libp2pquic.NewTransport(priv, reuse, nil, cfg.connectionGater, nil)
if err != nil {
t.Fatal(err)
}
diff --git a/p2p/net/upgrader/listener.go b/p2p/net/upgrader/listener.go
index 0871d2f5af..8af2791b36 100644
--- a/p2p/net/upgrader/listener.go
+++ b/p2p/net/upgrader/listener.go
@@ -37,7 +37,7 @@ type listener struct {
// Close closes the listener.
func (l *listener) Close() error {
- // Do this first to try to get any relevent errors.
+ // Do this first to try to get any relevant errors.
err := l.Listener.Close()
l.cancel()
diff --git a/p2p/net/upgrader/listener_test.go b/p2p/net/upgrader/listener_test.go
index 331e973ed1..14800e5983 100644
--- a/p2p/net/upgrader/listener_test.go
+++ b/p2p/net/upgrader/listener_test.go
@@ -18,10 +18,10 @@ import (
"github.com/libp2p/go-libp2p/core/transport"
"github.com/libp2p/go-libp2p/p2p/net/upgrader"
- "github.com/golang/mock/gomock"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
"github.com/stretchr/testify/require"
+ "go.uber.org/mock/gomock"
)
func createListener(t *testing.T, u transport.Upgrader) transport.Listener {
@@ -112,7 +112,7 @@ func TestConnectionsClosedIfNotAccepted(t *testing.T) {
}
time.Sleep(timeout)
- require.Nil(<-errCh)
+ require.NoError(<-errCh)
}
func TestFailedUpgradeOnListen(t *testing.T) {
diff --git a/p2p/net/upgrader/upgrader.go b/p2p/net/upgrader/upgrader.go
index d18c16ea00..3a6f8b9f52 100644
--- a/p2p/net/upgrader/upgrader.go
+++ b/p2p/net/upgrader/upgrader.go
@@ -152,7 +152,8 @@ func (u *upgrader) upgrade(ctx context.Context, t transport.Transport, maconn ma
return nil, ipnet.ErrNotInPrivateNetwork
}
- sconn, security, server, err := u.setupSecurity(ctx, conn, p, dir)
+ isServer := dir == network.DirInbound
+ sconn, security, err := u.setupSecurity(ctx, conn, p, isServer)
if err != nil {
conn.Close()
return nil, fmt.Errorf("failed to negotiate security protocol: %w", err)
@@ -179,7 +180,7 @@ func (u *upgrader) upgrade(ctx context.Context, t transport.Transport, maconn ma
}
}
- muxer, smconn, err := u.setupMuxer(ctx, sconn, server, connScope.PeerScope())
+ muxer, smconn, err := u.setupMuxer(ctx, sconn, isServer, connScope.PeerScope())
if err != nil {
sconn.Close()
return nil, fmt.Errorf("failed to negotiate stream multiplexer: %w", err)
@@ -199,20 +200,17 @@ func (u *upgrader) upgrade(ctx context.Context, t transport.Transport, maconn ma
return tc, nil
}
-func (u *upgrader) setupSecurity(ctx context.Context, conn net.Conn, p peer.ID, dir network.Direction) (sec.SecureConn, protocol.ID, bool, error) {
- isServer := dir == network.DirInbound
- var st sec.SecureTransport
- var err error
- st, isServer, err = u.negotiateSecurity(ctx, conn, isServer)
+func (u *upgrader) setupSecurity(ctx context.Context, conn net.Conn, p peer.ID, isServer bool) (sec.SecureConn, protocol.ID, error) {
+ st, err := u.negotiateSecurity(ctx, conn, isServer)
if err != nil {
- return nil, "", false, err
+ return nil, "", err
}
if isServer {
sconn, err := st.SecureInbound(ctx, conn, p)
- return sconn, st.ID(), true, err
+ return sconn, st.ID(), err
}
sconn, err := st.SecureOutbound(ctx, conn, p)
- return sconn, st.ID(), false, err
+ return sconn, st.ID(), err
}
func (u *upgrader) negotiateMuxer(nc net.Conn, isServer bool) (*StreamMuxer, error) {
@@ -308,41 +306,38 @@ func (u *upgrader) getSecurityByID(id protocol.ID) sec.SecureTransport {
return nil
}
-func (u *upgrader) negotiateSecurity(ctx context.Context, insecure net.Conn, server bool) (sec.SecureTransport, bool, error) {
+func (u *upgrader) negotiateSecurity(ctx context.Context, insecure net.Conn, server bool) (sec.SecureTransport, error) {
type result struct {
- proto protocol.ID
- iamserver bool
- err error
+ proto protocol.ID
+ err error
}
done := make(chan result, 1)
go func() {
if server {
var r result
- r.iamserver = true
r.proto, _, r.err = u.securityMuxer.Negotiate(insecure)
done <- r
return
}
var r result
- r.proto, r.iamserver, r.err = mss.SelectWithSimopenOrFail(u.securityIDs, insecure)
+ r.proto, r.err = mss.SelectOneOf(u.securityIDs, insecure)
done <- r
}()
select {
case r := <-done:
if r.err != nil {
- return nil, false, r.err
+ return nil, r.err
}
if s := u.getSecurityByID(r.proto); s != nil {
- return s, r.iamserver, nil
+ return s, nil
}
- return nil, false, fmt.Errorf("selected unknown security transport: %s", r.proto)
+ return nil, fmt.Errorf("selected unknown security transport: %s", r.proto)
case <-ctx.Done():
- // We *must* do this. We have outstanding work on the connection
- // and it's no longer safe to use.
+ // We *must* do this. We have outstanding work on the connection, and it's no longer safe to use.
insecure.Close()
<-done // wait to stop using the connection.
- return nil, false, ctx.Err()
+ return nil, ctx.Err()
}
}
diff --git a/p2p/net/upgrader/upgrader_test.go b/p2p/net/upgrader/upgrader_test.go
index b61ba8a61e..920ccaab9b 100644
--- a/p2p/net/upgrader/upgrader_test.go
+++ b/p2p/net/upgrader/upgrader_test.go
@@ -18,10 +18,10 @@ import (
"github.com/libp2p/go-libp2p/p2p/muxer/yamux"
"github.com/libp2p/go-libp2p/p2p/net/upgrader"
- "github.com/golang/mock/gomock"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
"github.com/stretchr/testify/require"
+ "go.uber.org/mock/gomock"
)
func createUpgrader(t *testing.T) (peer.ID, transport.Upgrader) {
diff --git a/p2p/protocol/circuitv2/relay/constraints.go b/p2p/protocol/circuitv2/relay/constraints.go
index 24353086f6..28698d9c06 100644
--- a/p2p/protocol/circuitv2/relay/constraints.go
+++ b/p2p/protocol/circuitv2/relay/constraints.go
@@ -29,7 +29,7 @@ type constraints struct {
total []time.Time
peers map[peer.ID][]time.Time
ips map[string][]time.Time
- asns map[string][]time.Time
+ asns map[uint32][]time.Time
}
// newConstraints creates a new constraints object.
@@ -40,7 +40,7 @@ func newConstraints(rc *Resources) *constraints {
rc: rc,
peers: make(map[peer.ID][]time.Time),
ips: make(map[string][]time.Time),
- asns: make(map[string][]time.Time),
+ asns: make(map[uint32][]time.Time),
}
}
@@ -73,10 +73,10 @@ func (c *constraints) AddReservation(p peer.ID, a ma.Multiaddr) error {
}
var asnReservations []time.Time
- var asn string
+ var asn uint32
if ip.To4() == nil {
- asn, _ = asnutil.Store.AsnForIPv6(ip)
- if asn != "" {
+ asn = asnutil.AsnForIPv6(ip)
+ if asn != 0 {
asnReservations = c.asns[asn]
if len(asnReservations) >= c.rc.MaxReservationsPerASN {
return errTooManyReservationsForASN
@@ -93,7 +93,7 @@ func (c *constraints) AddReservation(p peer.ID, a ma.Multiaddr) error {
ipReservations = append(ipReservations, expiry)
c.ips[ip.String()] = ipReservations
- if asn != "" {
+ if asn != 0 {
asnReservations = append(asnReservations, expiry)
c.asns[asn] = asnReservations
}
diff --git a/p2p/protocol/circuitv2/relay/relay.go b/p2p/protocol/circuitv2/relay/relay.go
index e3c8f47580..0ad36168fd 100644
--- a/p2p/protocol/circuitv2/relay/relay.go
+++ b/p2p/protocol/circuitv2/relay/relay.go
@@ -19,7 +19,6 @@ import (
logging "github.com/ipfs/go-log/v2"
pool "github.com/libp2p/go-buffer-pool"
- asnutil "github.com/libp2p/go-libp2p-asn-util"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
)
@@ -296,7 +295,7 @@ func (r *Relay) handleConnect(s network.Stream, msg *pbv2.HopMessage) pbv2.Statu
destConns := r.conns[dest.ID]
if destConns >= r.rc.MaxCircuits {
r.mx.Unlock()
- log.Debugf("refusing connection from %s to %s; too many connecitons to %s", src, dest.ID, dest.ID)
+ log.Debugf("refusing connection from %s to %s; too many connections to %s", src, dest.ID, dest.ID)
fail(pbv2.Status_RESOURCE_LIMIT_EXCEEDED)
return pbv2.Status_RESOURCE_LIMIT_EXCEEDED
}
@@ -624,8 +623,6 @@ func (r *Relay) makeLimitMsg(p peer.ID) *pbv2.Limit {
}
func (r *Relay) background() {
- asnutil.Store.Init()
-
ticker := time.NewTicker(time.Minute)
defer ticker.Stop()
diff --git a/p2p/protocol/holepunch/holepunch_test.go b/p2p/protocol/holepunch/holepunch_test.go
index 29d589cd7a..1f3d9263df 100644
--- a/p2p/protocol/holepunch/holepunch_test.go
+++ b/p2p/protocol/holepunch/holepunch_test.go
@@ -96,8 +96,8 @@ func TestNoHolePunchIfDirectConnExists(t *testing.T) {
require.GreaterOrEqual(t, nc2, 1)
require.NoError(t, hps.DirectConnect(h2.ID()))
- require.Equal(t, len(h1.Network().ConnsToPeer(h2.ID())), nc1)
- require.Equal(t, len(h2.Network().ConnsToPeer(h1.ID())), nc2)
+ require.Len(t, h1.Network().ConnsToPeer(h2.ID()), nc1)
+ require.Len(t, h2.Network().ConnsToPeer(h1.ID()), nc2)
require.Empty(t, tr.getEvents())
}
@@ -120,13 +120,13 @@ func TestDirectDialWorks(t *testing.T) {
h1.Peerstore().AddAddrs(h2.ID(), h2.Addrs(), peerstore.ConnectedAddrTTL)
// try to hole punch without any connection and streams, if it works -> it's a direct connection
- require.Len(t, h1.Network().ConnsToPeer(h2.ID()), 0)
+ require.Empty(t, h1.Network().ConnsToPeer(h2.ID()))
require.NoError(t, h1ps.DirectConnect(h2.ID()))
require.GreaterOrEqual(t, len(h1.Network().ConnsToPeer(h2.ID())), 1)
require.GreaterOrEqual(t, len(h2.Network().ConnsToPeer(h1.ID())), 1)
events := tr.getEvents()
require.Len(t, events, 1)
- require.Equal(t, events[0].Type, holepunch.DirectDialEvtT)
+ require.Equal(t, holepunch.DirectDialEvtT, events[0].Type)
}
func TestEndToEndSimConnect(t *testing.T) {
@@ -247,7 +247,6 @@ func TestFailuresOnInitiator(t *testing.T) {
require.Contains(t, err.Error(), tc.errMsg)
}
})
-
}
}
@@ -361,7 +360,6 @@ func TestFailuresOnResponder(t *testing.T) {
require.Len(t, errs, 1)
require.Contains(t, errs[0], tc.errMsg)
})
-
}
}
diff --git a/p2p/protocol/holepunch/svc.go b/p2p/protocol/holepunch/svc.go
index 47bf434fb1..9de0a11e0c 100644
--- a/p2p/protocol/holepunch/svc.go
+++ b/p2p/protocol/holepunch/svc.go
@@ -182,7 +182,7 @@ func (s *Service) incomingHolePunch(str network.Stream) (rtt time.Duration, remo
}
if err := str.Scope().ReserveMemory(maxMsgSize, network.ReservationPriorityAlways); err != nil {
- log.Debugf("error reserving memory for stream: %s, err")
+ log.Debugf("error reserving memory for stream: %s", err)
return 0, nil, nil, err
}
defer str.Scope().ReleaseMemory(maxMsgSize)
@@ -196,7 +196,7 @@ func (s *Service) incomingHolePunch(str network.Stream) (rtt time.Duration, remo
str.SetDeadline(time.Now().Add(StreamTimeout))
if err := rd.ReadMsg(msg); err != nil {
- return 0, nil, nil, fmt.Errorf("failed to read message from initator: %w", err)
+ return 0, nil, nil, fmt.Errorf("failed to read message from initiator: %w", err)
}
if t := msg.GetType(); t != pb.HolePunch_CONNECT {
return 0, nil, nil, fmt.Errorf("expected CONNECT message from initiator but got %d", t)
@@ -218,13 +218,13 @@ func (s *Service) incomingHolePunch(str network.Stream) (rtt time.Duration, remo
msg.ObsAddrs = addrsToBytes(ownAddrs)
tstart := time.Now()
if err := wr.WriteMsg(msg); err != nil {
- return 0, nil, nil, fmt.Errorf("failed to write CONNECT message to initator: %w", err)
+ return 0, nil, nil, fmt.Errorf("failed to write CONNECT message to initiator: %w", err)
}
// Read SYNC message
msg.Reset()
if err := rd.ReadMsg(msg); err != nil {
- return 0, nil, nil, fmt.Errorf("failed to read message from initator: %w", err)
+ return 0, nil, nil, fmt.Errorf("failed to read message from initiator: %w", err)
}
if t := msg.GetType(); t != pb.HolePunch_SYNC {
return 0, nil, nil, fmt.Errorf("expected SYNC message from initiator but got %d", t)
diff --git a/p2p/protocol/identify/id_glass_test.go b/p2p/protocol/identify/id_glass_test.go
index 777cef01ed..ff303b23ec 100644
--- a/p2p/protocol/identify/id_glass_test.go
+++ b/p2p/protocol/identify/id_glass_test.go
@@ -12,6 +12,7 @@ import (
recordPb "github.com/libp2p/go-libp2p/core/record/pb"
blhost "github.com/libp2p/go-libp2p/p2p/host/blank"
swarmt "github.com/libp2p/go-libp2p/p2p/net/swarm/testing"
+ ma "github.com/multiformats/go-multiaddr"
"google.golang.org/protobuf/proto"
"github.com/stretchr/testify/assert"
@@ -173,3 +174,35 @@ func TestInvalidSignedPeerRecord(t *testing.T) {
require.True(t, ok)
require.Nil(t, cab.GetPeerRecord(h2.ID()))
}
+
+func TestIncomingAddrFilter(t *testing.T) {
+ lhAddr := ma.StringCast("/ip4/127.0.0.1/udp/123/quic-v1")
+ privAddr := ma.StringCast("/ip4/192.168.1.101/tcp/123")
+ pubAddr := ma.StringCast("/ip6/2::1/udp/123/quic-v1")
+ pubDNSAddr := ma.StringCast("/dns/example.com/udp/123/quic-v1")
+ privDNSAddr := ma.StringCast("/dns4/localhost/udp/123/quic-v1")
+ tests := []struct {
+ output []ma.Multiaddr
+ remote ma.Multiaddr
+ }{
+ {
+ output: []ma.Multiaddr{lhAddr, privAddr, pubAddr, pubDNSAddr, privDNSAddr},
+ remote: lhAddr,
+ },
+ {
+ output: []ma.Multiaddr{privAddr, pubAddr, pubDNSAddr, privDNSAddr},
+ remote: privAddr,
+ },
+ {
+ output: []ma.Multiaddr{pubAddr, pubDNSAddr},
+ remote: pubAddr,
+ },
+ }
+ for _, tc := range tests {
+ t.Run(fmt.Sprintf("remote:%s", tc.remote), func(t *testing.T) {
+ input := []ma.Multiaddr{lhAddr, privAddr, pubAddr, pubDNSAddr, privDNSAddr}
+ got := filterAddrs(input, tc.remote)
+ require.ElementsMatch(t, tc.output, got, "%s\n%s", tc.output, got)
+ })
+ }
+}
diff --git a/p2p/protocol/identify/id_test.go b/p2p/protocol/identify/id_test.go
index 8a71ddd8fe..0f92035682 100644
--- a/p2p/protocol/identify/id_test.go
+++ b/p2p/protocol/identify/id_test.go
@@ -614,7 +614,7 @@ func TestLargeIdentifyMessage(t *testing.T) {
require.NoError(t, h1.Connect(context.Background(), h2pi))
h1t2c := h1.Network().ConnsToPeer(h2p)
- require.Equal(t, 1, len(h1t2c), "should have a conn here")
+ require.Len(t, h1t2c, 1, "should have a conn here")
ids1.IdentifyConn(h1t2c[0])
@@ -843,8 +843,10 @@ func TestIncomingIDStreamsTimeout(t *testing.T) {
func TestOutOfOrderConnectedNotifs(t *testing.T) {
h1, err := libp2p.New(libp2p.NoListenAddrs)
require.NoError(t, err)
+ defer h1.Close()
h2, err := libp2p.New(libp2p.ListenAddrs(ma.StringCast("/ip4/127.0.0.1/udp/0/quic-v1")))
require.NoError(t, err)
+ defer h2.Close()
doneCh := make(chan struct{})
errCh := make(chan error)
diff --git a/p2p/protocol/identify/obsaddr_test.go b/p2p/protocol/identify/obsaddr_test.go
index 2987b01bd8..a738dc5384 100644
--- a/p2p/protocol/identify/obsaddr_test.go
+++ b/p2p/protocol/identify/obsaddr_test.go
@@ -369,7 +369,6 @@ func TestEmitNATDeviceTypeSymmetric(t *testing.T) {
case <-time.After(5 * time.Second):
t.Fatal("did not get Symmetric NAT event")
}
-
}
func TestEmitNATDeviceTypeCone(t *testing.T) {
@@ -431,6 +430,6 @@ func TestObserveWebtransport(t *testing.T) {
harness.observe(observedAddr, pb4)
harness.observe(observedAddr, pb5)
- require.Equal(t, 1, len(harness.oas.Addrs()))
+ require.Len(t, harness.oas.Addrs(), 1)
require.Equal(t, "/ip4/1.2.3.4/udp/1231/quic-v1/webtransport", harness.oas.Addrs()[0].String())
}
diff --git a/p2p/protocol/ping/ping.go b/p2p/protocol/ping/ping.go
index 6ff5c3fb6f..1c78229084 100644
--- a/p2p/protocol/ping/ping.go
+++ b/p2p/protocol/ping/ping.go
@@ -158,11 +158,10 @@ func Ping(ctx context.Context, h host.Host, p peer.ID) <-chan Result {
}
}
}()
- go func() {
+ context.AfterFunc(ctx, func() {
// forces the ping to abort.
- <-ctx.Done()
s.Reset()
- }()
+ })
return out
}
diff --git a/p2p/security/noise/LICENSE.md b/p2p/security/noise/LICENSE.md
deleted file mode 100644
index 15601cba67..0000000000
--- a/p2p/security/noise/LICENSE.md
+++ /dev/null
@@ -1,229 +0,0 @@
-The contents of this repository are Copyright (c) corresponding authors and
-contributors, licensed under the `Permissive License Stack` meaning either of:
-
-- Apache-2.0 Software License: https://www.apache.org/licenses/LICENSE-2.0
- ([...4tr2kfsq](https://gateway.ipfs.io/ipfs/bafkreiankqxazcae4onkp436wag2lj3ccso4nawxqkkfckd6cg4tr2kfsq))
-
-- MIT Software License: https://opensource.org/licenses/MIT
- ([...vljevcba](https://gateway.ipfs.io/ipfs/bafkreiepofszg4gfe2gzuhojmksgemsub2h4uy2gewdnr35kswvljevcba))
-
-You may not use the contents of this repository except in compliance
-with one of the listed Licenses. For an extended clarification of the
-intent behind the choice of Licensing please refer to
-https://protocol.ai/blog/announcing-the-permissive-license-stack/
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the terms listed in this notice is distributed on
-an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
-either express or implied. See each License for the specific language
-governing permissions and limitations under that License.
-
-
-`SPDX-License-Identifier: Apache-2.0 OR MIT`
-
-Verbatim copies of both licenses are included below:
-
-Apache-2.0 Software License
-
-```
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-```
-
-
-MIT Software License
-
-```
-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.
-```
-
diff --git a/p2p/security/noise/handshake.go b/p2p/security/noise/handshake.go
index a9493bf8d8..c89f709a47 100644
--- a/p2p/security/noise/handshake.go
+++ b/p2p/security/noise/handshake.go
@@ -3,6 +3,7 @@ package noise
import (
"context"
"crypto/rand"
+ "crypto/sha256"
"encoding/binary"
"fmt"
"hash"
@@ -13,7 +14,6 @@ import (
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/sec"
- "github.com/libp2p/go-libp2p/internal/sha256"
"github.com/libp2p/go-libp2p/p2p/security/noise/pb"
"github.com/flynn/noise"
diff --git a/p2p/security/noise/transport_test.go b/p2p/security/noise/transport_test.go
index d3a4b45d90..ea7916fc0d 100644
--- a/p2p/security/noise/transport_test.go
+++ b/p2p/security/noise/transport_test.go
@@ -182,16 +182,16 @@ func TestPeerIDMatch(t *testing.T) {
defer close(done)
conn, err := initTransport.SecureOutbound(context.Background(), init, respTransport.localID)
assert.NoError(t, err)
- assert.Equal(t, conn.RemotePeer(), respTransport.localID)
+ assert.Equal(t, respTransport.localID, conn.RemotePeer())
b := make([]byte, 6)
_, err = conn.Read(b)
assert.NoError(t, err)
- assert.Equal(t, b, []byte("foobar"))
+ assert.Equal(t, []byte("foobar"), b)
}()
conn, err := respTransport.SecureInbound(context.Background(), resp, initTransport.localID)
require.NoError(t, err)
- require.Equal(t, conn.RemotePeer(), initTransport.localID)
+ require.Equal(t, initTransport.localID, conn.RemotePeer())
_, err = conn.Write([]byte("foobar"))
require.NoError(t, err)
}
@@ -214,8 +214,8 @@ func TestPeerIDMismatchOutboundFailsHandshake(t *testing.T) {
require.Error(t, initErr, "expected initiator to fail with peer ID mismatch error")
var mismatchErr sec.ErrPeerIDMismatch
require.ErrorAs(t, initErr, &mismatchErr)
- require.Equal(t, peer.ID("a-random-peer-id"), mismatchErr.Expected)
- require.Equal(t, respTransport.localID, mismatchErr.Actual)
+ require.Equal(t, mismatchErr.Expected, peer.ID("a-random-peer-id"))
+ require.Equal(t, mismatchErr.Actual, respTransport.localID)
}
func TestPeerIDMismatchInboundFailsHandshake(t *testing.T) {
@@ -236,8 +236,8 @@ func TestPeerIDMismatchInboundFailsHandshake(t *testing.T) {
require.Error(t, err, "expected responder to fail with peer ID mismatch error")
var mismatchErr sec.ErrPeerIDMismatch
require.ErrorAs(t, err, &mismatchErr)
- require.Equal(t, peer.ID("a-random-peer-id"), mismatchErr.Expected)
- require.Equal(t, initTransport.localID, mismatchErr.Actual)
+ require.Equal(t, mismatchErr.Expected, peer.ID("a-random-peer-id"))
+ require.Equal(t, mismatchErr.Actual, initTransport.localID)
<-done
}
@@ -354,7 +354,7 @@ func TestBufferEqEncPayload(t *testing.T) {
afterLen, err := respConn.Read(after)
require.NoError(t, err)
- require.Equal(t, len(before), afterLen)
+ require.Len(t, before, afterLen)
require.Equal(t, before, after[:len(before)])
}
@@ -374,7 +374,7 @@ func TestBufferEqDecryptedPayload(t *testing.T) {
afterLen, err := respConn.Read(after)
require.NoError(t, err)
- require.Equal(t, len(before), afterLen)
+ require.Len(t, before, afterLen)
require.Equal(t, before, after[:len(before)])
}
@@ -393,7 +393,7 @@ func TestReadUnencryptedFails(t *testing.T) {
copy(msg[LengthPrefixLength:], before)
n, err := initConn.insecureConn.Write(msg)
require.NoError(t, err)
- require.Equal(t, len(msg), n)
+ require.Len(t, msg, n)
after := make([]byte, len(msg)+1)
afterLen, err := respConn.Read(after)
@@ -414,7 +414,7 @@ func TestReadUnencryptedFails(t *testing.T) {
copy(msg[LengthPrefixLength:], before)
n, err = initConn.insecureConn.Write(msg)
require.NoError(t, err)
- require.Equal(t, len(msg), n)
+ require.Len(t, msg, n)
after = make([]byte, 1)
afterLen, err = respConn.Read(after)
@@ -595,7 +595,6 @@ func TestEarlyDataRejected(t *testing.T) {
clientErr, serverErr := handshake(t, sendingEDH, receivingEDH)
require.Error(t, clientErr)
require.EqualError(t, serverErr, "nope")
-
})
t.Run("server sending", func(t *testing.T) {
diff --git a/p2p/security/tls/LICENSE.md b/p2p/security/tls/LICENSE.md
deleted file mode 100644
index a94e82cceb..0000000000
--- a/p2p/security/tls/LICENSE.md
+++ /dev/null
@@ -1,7 +0,0 @@
-Copyright 2018 Marten Seemann
-
-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.
diff --git a/p2p/security/tls/cmd/tlsdiag/client.go b/p2p/security/tls/cmd/tlsdiag/client.go
index 3868afebb0..a29189a375 100644
--- a/p2p/security/tls/cmd/tlsdiag/client.go
+++ b/p2p/security/tls/cmd/tlsdiag/client.go
@@ -33,7 +33,7 @@ func StartClient() error {
if err != nil {
return err
}
- fmt.Printf(" Peer ID: %s\n", id.Pretty())
+ fmt.Printf(" Peer ID: %s\n", id)
tp, err := libp2ptls.New(libp2ptls.ID, priv, nil)
if err != nil {
return err
@@ -53,7 +53,7 @@ func StartClient() error {
if err != nil {
return err
}
- fmt.Printf("Authenticated server: %s\n", sconn.RemotePeer().Pretty())
+ fmt.Printf("Authenticated server: %s\n", sconn.RemotePeer())
data, err := io.ReadAll(sconn)
if err != nil {
return err
diff --git a/p2p/security/tls/cmd/tlsdiag/server.go b/p2p/security/tls/cmd/tlsdiag/server.go
index 76c45a155e..cd702a7334 100644
--- a/p2p/security/tls/cmd/tlsdiag/server.go
+++ b/p2p/security/tls/cmd/tlsdiag/server.go
@@ -26,7 +26,7 @@ func StartServer() error {
if err != nil {
return err
}
- fmt.Printf(" Peer ID: %s\n", id.Pretty())
+ fmt.Printf(" Peer ID: %s\n", id)
tp, err := libp2ptls.New(libp2ptls.ID, priv, nil)
if err != nil {
return err
@@ -38,7 +38,7 @@ func StartServer() error {
}
fmt.Printf("Listening for new connections on %s\n", ln.Addr())
fmt.Printf("Now run the following command in a separate terminal:\n")
- fmt.Printf("\tgo run cmd/tlsdiag.go client -p %d -id %s\n", *port, id.Pretty())
+ fmt.Printf("\tgo run cmd/tlsdiag.go client -p %d -id %s\n", *port, id)
for {
conn, err := ln.Accept()
@@ -61,7 +61,7 @@ func handleConn(tp *libp2ptls.Transport, conn net.Conn) error {
if err != nil {
return err
}
- fmt.Printf("Authenticated client: %s\n", sconn.RemotePeer().Pretty())
+ fmt.Printf("Authenticated client: %s\n", sconn.RemotePeer())
fmt.Fprintf(sconn, "Hello client!")
fmt.Printf("Closing connection to %s\n", conn.RemoteAddr())
return sconn.Close()
diff --git a/p2p/security/tls/crypto_test.go b/p2p/security/tls/crypto_test.go
index 872f588586..efec949095 100644
--- a/p2p/security/tls/crypto_test.go
+++ b/p2p/security/tls/crypto_test.go
@@ -19,31 +19,31 @@ func TestNewIdentityCertificates(t *testing.T) {
t.Run("NewIdentity with default template", func(t *testing.T) {
// Generate an identity using the default template
id, err := NewIdentity(key)
- assert.NoError(t, err)
+ require.NoError(t, err)
// Extract the x509 certificate
x509Cert, err := x509.ParseCertificate(id.config.Certificates[0].Certificate[0])
- assert.NoError(t, err)
+ require.NoError(t, err)
// verify the common name and email are not set
- assert.Empty(t, x509Cert.Subject.CommonName)
- assert.Empty(t, x509Cert.EmailAddresses)
+ require.Empty(t, x509Cert.Subject.CommonName)
+ require.Empty(t, x509Cert.EmailAddresses)
})
t.Run("NewIdentity with custom template", func(t *testing.T) {
tmpl, err := certTemplate()
- assert.NoError(t, err)
+ require.NoError(t, err)
tmpl.Subject.CommonName = cn
tmpl.EmailAddresses = []string{email}
// Generate an identity using the custom template
id, err := NewIdentity(key, WithCertTemplate(tmpl))
- assert.NoError(t, err)
+ require.NoError(t, err)
// Extract the x509 certificate
x509Cert, err := x509.ParseCertificate(id.config.Certificates[0].Certificate[0])
- assert.NoError(t, err)
+ require.NoError(t, err)
// verify the common name and email are set
assert.Equal(t, cn, x509Cert.Subject.CommonName)
diff --git a/p2p/security/tls/extension_test.go b/p2p/security/tls/extension_test.go
index f50695a248..6bed72590d 100644
--- a/p2p/security/tls/extension_test.go
+++ b/p2p/security/tls/extension_test.go
@@ -7,7 +7,7 @@ import (
)
func TestExtensionGenerating(t *testing.T) {
- require.Equal(t, getPrefixedExtensionID([]int{13, 37}), []int{1, 3, 6, 1, 4, 1, 53594, 13, 37})
+ require.Equal(t, []int{1, 3, 6, 1, 4, 1, 53594, 13, 37}, getPrefixedExtensionID([]int{13, 37}))
}
func TestExtensionComparison(t *testing.T) {
diff --git a/p2p/security/tls/transport.go b/p2p/security/tls/transport.go
index 7c28efe37e..0c494a7fdc 100644
--- a/p2p/security/tls/transport.go
+++ b/p2p/security/tls/transport.go
@@ -113,7 +113,7 @@ func (t *Transport) SecureOutbound(ctx context.Context, insecure net.Conn, p pee
for _, muxer := range t.muxers {
muxers = append(muxers, (string)(muxer))
}
- // Prepend the prefered muxers list to TLS config.
+ // Prepend the preferred muxers list to TLS config.
config.NextProtos = append(muxers, config.NextProtos...)
cs, err := t.handshake(ctx, tls.Client(insecure, config), keyCh)
if err != nil {
diff --git a/p2p/security/tls/transport_test.go b/p2p/security/tls/transport_test.go
index 62521238ae..b53d9bf0f6 100644
--- a/p2p/security/tls/transport_test.go
+++ b/p2p/security/tls/transport_test.go
@@ -46,7 +46,7 @@ func createPeer(t *testing.T) (peer.ID, ic.PrivKey) {
require.NoError(t, err)
id, err := peer.IDFromPrivateKey(priv)
require.NoError(t, err)
- t.Logf("using a %s key: %s", priv.Type(), id.Pretty())
+ t.Logf("using a %s key: %s", priv.Type(), id)
return id, priv
}
@@ -121,7 +121,7 @@ func TestHandshakeSucceeds(t *testing.T) {
b := make([]byte, 6)
_, err = clientConn.Read(b)
require.NoError(t, err)
- require.Equal(t, string(b), "foobar")
+ require.Equal(t, "foobar", string(b))
}
// Use standard transports with default TLS configuration
@@ -245,21 +245,21 @@ func TestHandshakeWithNextProtoSucceeds(t *testing.T) {
}
defer serverConn.Close()
- require.Equal(t, clientConn.LocalPeer(), clientID)
- require.Equal(t, serverConn.LocalPeer(), serverID)
- require.Equal(t, clientConn.RemotePeer(), serverID)
- require.Equal(t, serverConn.RemotePeer(), clientID)
+ require.Equal(t, clientID, clientConn.LocalPeer())
+ require.Equal(t, serverID, serverConn.LocalPeer())
+ require.Equal(t, serverID, clientConn.RemotePeer())
+ require.Equal(t, clientID, serverConn.RemotePeer())
require.True(t, clientConn.RemotePublicKey().Equals(serverKey.GetPublic()), "server public key mismatch")
require.True(t, serverConn.RemotePublicKey().Equals(clientKey.GetPublic()), "client public key mismatch")
- require.Equal(t, clientConn.ConnState().StreamMultiplexer, expectedMuxer)
- require.Equal(t, clientConn.ConnState().UsedEarlyMuxerNegotiation, expectedMuxer != "")
+ require.Equal(t, expectedMuxer, clientConn.ConnState().StreamMultiplexer)
+ require.Equal(t, expectedMuxer != "", clientConn.ConnState().UsedEarlyMuxerNegotiation)
// exchange some data
_, err = serverConn.Write([]byte("foobar"))
require.NoError(t, err)
b := make([]byte, 6)
_, err = clientConn.Read(b)
require.NoError(t, err)
- require.Equal(t, string(b), "foobar")
+ require.Equal(t, "foobar", string(b))
}
// Iterate through the StreamMultiplexer combinations.
@@ -378,8 +378,8 @@ func TestPeerIDMismatch(t *testing.T) {
require.Error(t, err)
var mismatchErr sec.ErrPeerIDMismatch
require.ErrorAs(t, err, &mismatchErr)
- require.Equal(t, thirdPartyID, mismatchErr.Expected)
- require.Equal(t, serverID, mismatchErr.Actual)
+ require.Equal(t, mismatchErr.Expected, thirdPartyID)
+ require.Equal(t, mismatchErr.Actual, serverID)
var serverErr error
select {
@@ -417,8 +417,8 @@ func TestPeerIDMismatch(t *testing.T) {
require.Error(t, serverErr)
var mismatchErr sec.ErrPeerIDMismatch
require.ErrorAs(t, serverErr, &mismatchErr)
- require.Equal(t, thirdPartyID, mismatchErr.Expected)
- require.Equal(t, clientTransport.localPeer, mismatchErr.Actual)
+ require.Equal(t, mismatchErr.Expected, thirdPartyID)
+ require.Equal(t, mismatchErr.Actual, clientTransport.localPeer)
})
}
diff --git a/p2p/test/basichost/basic_host_test.go b/p2p/test/basichost/basic_host_test.go
index 6b010ed2aa..98d8cf45f1 100644
--- a/p2p/test/basichost/basic_host_test.go
+++ b/p2p/test/basichost/basic_host_test.go
@@ -4,13 +4,16 @@ import (
"context"
"fmt"
"testing"
+ "time"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
+ "github.com/libp2p/go-libp2p/core/peerstore"
"github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client"
"github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay"
ma "github.com/multiformats/go-multiaddr"
+ "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -18,12 +21,14 @@ func TestNoStreamOverTransientConnection(t *testing.T) {
h1, err := libp2p.New(
libp2p.NoListenAddrs,
libp2p.EnableRelay(),
+ libp2p.ResourceManager(&network.NullResourceManager{}),
)
require.NoError(t, err)
h2, err := libp2p.New(
libp2p.NoListenAddrs,
libp2p.EnableRelay(),
+ libp2p.ResourceManager(&network.NullResourceManager{}),
)
require.NoError(t, err)
@@ -62,11 +67,94 @@ func TestNoStreamOverTransientConnection(t *testing.T) {
err = h1.Connect(context.Background(), h2Info)
require.NoError(t, err)
- ctx := network.WithNoDial(context.Background(), "test")
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+ defer cancel()
+ ctx = network.WithNoDial(ctx, "test")
_, err = h1.NewStream(ctx, h2.ID(), "/testprotocol")
- require.ErrorIs(t, err, network.ErrTransientConn)
+ require.Error(t, err)
_, err = h1.NewStream(network.WithUseTransient(context.Background(), "test"), h2.ID(), "/testprotocol")
require.NoError(t, err)
}
+
+func TestNewStreamTransientConnection(t *testing.T) {
+ h1, err := libp2p.New(
+ libp2p.ListenAddrStrings("/ip4/127.0.0.1/udp/0/quic-v1"),
+ libp2p.EnableRelay(),
+ libp2p.ResourceManager(&network.NullResourceManager{}),
+ )
+ require.NoError(t, err)
+
+ h2, err := libp2p.New(
+ libp2p.ListenAddrStrings("/ip4/127.0.0.1/udp/0/quic-v1"),
+ libp2p.EnableRelay(),
+ libp2p.ResourceManager(&network.NullResourceManager{}),
+ )
+ require.NoError(t, err)
+
+ relay1, err := libp2p.New()
+ require.NoError(t, err)
+
+ _, err = relay.New(relay1)
+ require.NoError(t, err)
+
+ relay1info := peer.AddrInfo{
+ ID: relay1.ID(),
+ Addrs: relay1.Addrs(),
+ }
+ err = h1.Connect(context.Background(), relay1info)
+ require.NoError(t, err)
+
+ err = h2.Connect(context.Background(), relay1info)
+ require.NoError(t, err)
+
+ h2.SetStreamHandler("/testprotocol", func(s network.Stream) {
+ fmt.Println("testprotocol")
+
+ // End the example
+ s.Close()
+ })
+
+ _, err = client.Reserve(context.Background(), h2, relay1info)
+ require.NoError(t, err)
+
+ relayaddr := ma.StringCast("/p2p/" + relay1info.ID.String() + "/p2p-circuit/p2p/" + h2.ID().String())
+
+ h1.Peerstore().AddAddr(h2.ID(), relayaddr, peerstore.TempAddrTTL)
+
+ // NewStream should block transient connections till we have a direct connection
+ ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
+ defer cancel()
+ s, err := h1.NewStream(ctx, h2.ID(), "/testprotocol")
+ require.ErrorIs(t, err, context.DeadlineExceeded)
+ require.Nil(t, s)
+
+ // NewStream should return a stream if a direct connection is established
+ // while waiting
+ done := make(chan bool, 2)
+ go func() {
+ h1.Peerstore().AddAddrs(h2.ID(), h2.Addrs(), peerstore.TempAddrTTL)
+ ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+ ctx = network.WithNoDial(ctx, "test")
+ s, err = h1.NewStream(ctx, h2.ID(), "/testprotocol")
+ require.NoError(t, err)
+ require.NotNil(t, s)
+ defer s.Close()
+ require.Equal(t, network.DirInbound, s.Conn().Stat().Direction)
+ done <- true
+ }()
+ go func() {
+ // connect h2 to h1 simulating connection reversal
+ h2.Peerstore().AddAddrs(h1.ID(), h1.Addrs(), peerstore.TempAddrTTL)
+ ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
+ defer cancel()
+ ctx = network.WithForceDirectDial(ctx, "test")
+ err := h2.Connect(ctx, peer.AddrInfo{ID: h1.ID()})
+ assert.NoError(t, err)
+ done <- true
+ }()
+ <-done
+ <-done
+}
diff --git a/p2p/test/notifications/notification_test.go b/p2p/test/notifications/notification_test.go
index b6159ac7d9..eb26a3fe5e 100644
--- a/p2p/test/notifications/notification_test.go
+++ b/p2p/test/notifications/notification_test.go
@@ -41,7 +41,7 @@ func TestListenAddressNotif(t *testing.T) {
ev := e.(event.EvtLocalAddressesUpdated)
require.Empty(t, ev.Removed)
require.Len(t, ev.Current, 1)
- require.Equal(t, ev.Current[0].Action, event.Added)
+ require.Equal(t, event.Added, ev.Current[0].Action)
initialAddr = ev.Current[0].Address
portStr, err := initialAddr.ValueForProtocol(ma.P_TCP)
require.NoError(t, err)
diff --git a/p2p/test/security/bench_test.go b/p2p/test/security/bench_test.go
new file mode 100644
index 0000000000..fb50e3fa99
--- /dev/null
+++ b/p2p/test/security/bench_test.go
@@ -0,0 +1,130 @@
+package benchmark
+
+import (
+ "context"
+ crand "crypto/rand"
+ "io"
+ "net"
+ "sync"
+ "testing"
+
+ "github.com/libp2p/go-libp2p/core/crypto"
+ "github.com/libp2p/go-libp2p/core/peer"
+ "github.com/libp2p/go-libp2p/core/sec"
+ "github.com/libp2p/go-libp2p/p2p/security/noise"
+ tls "github.com/libp2p/go-libp2p/p2p/security/tls"
+ "github.com/stretchr/testify/assert"
+)
+
+type Factory func(*testing.B, crypto.PrivKey) sec.SecureTransport
+
+func benchmarkThroughput(b *testing.B, size int, factory Factory) {
+ privA, pubA, err := crypto.GenerateEd25519Key(crand.Reader)
+ assert.NoError(b, err)
+ idA, err := peer.IDFromPublicKey(pubA)
+ assert.NoError(b, err)
+ tptA := factory(b, privA)
+
+ privB, pubB, err := crypto.GenerateEd25519Key(crand.Reader)
+ assert.NoError(b, err)
+ idB, err := peer.IDFromPublicKey(pubB)
+ assert.NoError(b, err)
+ tptB := factory(b, privB)
+
+ // pipe here serialize the decryption and encryption, we might want both parallelised to reduce context switching impact on the benchmark.
+ // https://github.com/golang/go/issues/34502 would be ideal for the parallel usecase.
+ p1, p2 := net.Pipe()
+ var ready sync.Mutex // wait for completed handshake
+ var finished sync.Mutex // wait until all data has been received
+ ready.Lock()
+ finished.Lock()
+ go func() {
+ defer finished.Unlock()
+ conn, err := tptB.SecureInbound(context.Background(), p2, idA)
+ assert.NoError(b, err)
+ ready.Unlock()
+
+ _, err = io.Copy(io.Discard, conn)
+ assert.NoError(b, err)
+ }()
+
+ conn, err := tptA.SecureOutbound(context.Background(), p1, idB)
+ assert.NoError(b, err)
+ ready.Lock()
+
+ buf := make([]byte, size)
+ b.SetBytes(int64(len(buf)))
+ b.ResetTimer()
+
+ for i := b.N; i != 0; i-- {
+ _, err = conn.Write(buf[:])
+ assert.NoError(b, err)
+ }
+ conn.Close()
+
+ finished.Lock()
+}
+func benchmarkHandshakes(b *testing.B, factory Factory) {
+ privA, pubA, err := crypto.GenerateEd25519Key(crand.Reader)
+ assert.NoError(b, err)
+ idA, err := peer.IDFromPublicKey(pubA)
+ assert.NoError(b, err)
+ tptA := factory(b, privA)
+
+ privB, pubB, err := crypto.GenerateEd25519Key(crand.Reader)
+ assert.NoError(b, err)
+ idB, err := peer.IDFromPublicKey(pubB)
+ assert.NoError(b, err)
+ tptB := factory(b, privB)
+
+ pipes := make(chan net.Conn, 1)
+
+ var finished sync.Mutex // wait until all data has been transferred
+ finished.Lock()
+ go func() {
+ defer finished.Unlock()
+ var throwAway [1]byte
+ for p := range pipes {
+ conn, err := tptB.SecureInbound(context.Background(), p, idA)
+ assert.NoError(b, err)
+ _, err = conn.Read(throwAway[:]) // read because currently the tls transport handshake when calling Read.
+ assert.ErrorIs(b, err, io.EOF)
+ }
+ }()
+ b.ResetTimer()
+
+ for i := b.N; i != 0; i-- {
+ p1, p2 := net.Pipe()
+ pipes <- p2
+ conn, err := tptA.SecureOutbound(context.Background(), p1, idB)
+ assert.NoError(b, err)
+ assert.NoError(b, conn.Close())
+ }
+ close(pipes)
+
+ finished.Lock()
+}
+
+func bench(b *testing.B, factory Factory) {
+ b.Run("throughput", func(b *testing.B) {
+ b.Run("32KiB", func(b *testing.B) { benchmarkThroughput(b, 32*1024, factory) })
+ b.Run("1MiB", func(b *testing.B) { benchmarkThroughput(b, 1024*1024, factory) })
+ })
+ b.Run("handshakes", func(b *testing.B) { benchmarkHandshakes(b, factory) })
+}
+
+func BenchmarkNoise(b *testing.B) {
+ bench(b, func(b *testing.B, priv crypto.PrivKey) sec.SecureTransport {
+ tpt, err := noise.New("", priv, nil)
+ assert.NoError(b, err)
+ return tpt
+ })
+}
+
+func BenchmarkTLS(b *testing.B) {
+ bench(b, func(b *testing.B, priv crypto.PrivKey) sec.SecureTransport {
+ tpt, err := tls.New("", priv, nil)
+ assert.NoError(b, err)
+ return tpt
+ })
+}
diff --git a/p2p/test/swarm/swarm_test.go b/p2p/test/swarm/swarm_test.go
new file mode 100644
index 0000000000..8027cebe53
--- /dev/null
+++ b/p2p/test/swarm/swarm_test.go
@@ -0,0 +1,245 @@
+package swarm_test
+
+import (
+ "context"
+ "io"
+ "sync"
+ "testing"
+ "time"
+
+ "github.com/libp2p/go-libp2p"
+ "github.com/libp2p/go-libp2p/core/network"
+ "github.com/libp2p/go-libp2p/core/peer"
+ "github.com/libp2p/go-libp2p/core/peerstore"
+ rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
+ "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client"
+ "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay"
+ ma "github.com/multiformats/go-multiaddr"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestDialPeerTransientConnection(t *testing.T) {
+ h1, err := libp2p.New(
+ libp2p.NoListenAddrs,
+ libp2p.EnableRelay(),
+ )
+ require.NoError(t, err)
+
+ h2, err := libp2p.New(
+ libp2p.NoListenAddrs,
+ libp2p.EnableRelay(),
+ )
+ require.NoError(t, err)
+
+ relay1, err := libp2p.New()
+ require.NoError(t, err)
+
+ _, err = relay.New(relay1)
+ require.NoError(t, err)
+
+ relay1info := peer.AddrInfo{
+ ID: relay1.ID(),
+ Addrs: relay1.Addrs(),
+ }
+ err = h1.Connect(context.Background(), relay1info)
+ require.NoError(t, err)
+
+ err = h2.Connect(context.Background(), relay1info)
+ require.NoError(t, err)
+
+ _, err = client.Reserve(context.Background(), h2, relay1info)
+ require.NoError(t, err)
+
+ relayaddr := ma.StringCast("/p2p/" + relay1info.ID.String() + "/p2p-circuit/p2p/" + h2.ID().String())
+
+ h1.Peerstore().AddAddr(h2.ID(), relayaddr, peerstore.TempAddrTTL)
+
+ // swarm.DialPeer should connect over transient connections
+ conn1, err := h1.Network().DialPeer(context.Background(), h2.ID())
+ require.NoError(t, err)
+ require.NotNil(t, conn1)
+
+ // Test that repeated calls return the same connection.
+ conn2, err := h1.Network().DialPeer(context.Background(), h2.ID())
+ require.NoError(t, err)
+ require.NotNil(t, conn2)
+
+ require.Equal(t, conn1, conn2)
+
+ // swarm.DialPeer should fail if forceDirect is used
+ ctx := network.WithForceDirectDial(context.Background(), "test")
+ conn, err := h1.Network().DialPeer(ctx, h2.ID())
+ require.Error(t, err)
+ require.Nil(t, conn)
+}
+
+func TestNewStreamTransientConnection(t *testing.T) {
+ h1, err := libp2p.New(
+ libp2p.ListenAddrStrings("/ip4/127.0.0.1/udp/0/quic-v1"),
+ libp2p.EnableRelay(),
+ )
+ require.NoError(t, err)
+
+ h2, err := libp2p.New(
+ libp2p.ListenAddrStrings("/ip4/127.0.0.1/udp/0/quic-v1"),
+ libp2p.EnableRelay(),
+ )
+ require.NoError(t, err)
+
+ relay1, err := libp2p.New()
+ require.NoError(t, err)
+
+ _, err = relay.New(relay1)
+ require.NoError(t, err)
+
+ relay1info := peer.AddrInfo{
+ ID: relay1.ID(),
+ Addrs: relay1.Addrs(),
+ }
+ err = h1.Connect(context.Background(), relay1info)
+ require.NoError(t, err)
+
+ err = h2.Connect(context.Background(), relay1info)
+ require.NoError(t, err)
+
+ _, err = client.Reserve(context.Background(), h2, relay1info)
+ require.NoError(t, err)
+
+ relayaddr := ma.StringCast("/p2p/" + relay1info.ID.String() + "/p2p-circuit/p2p/" + h2.ID().String())
+
+ h1.Peerstore().AddAddr(h2.ID(), relayaddr, peerstore.TempAddrTTL)
+
+ // WithUseTransient should succeed
+ ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
+ defer cancel()
+ ctx = network.WithUseTransient(ctx, "test")
+ s, err := h1.Network().NewStream(ctx, h2.ID())
+ require.NoError(t, err)
+ require.NotNil(t, s)
+ defer s.Close()
+
+ // Without WithUseTransient should fail with context deadline exceeded
+ ctx, cancel = context.WithTimeout(context.Background(), 200*time.Millisecond)
+ defer cancel()
+ s, err = h1.Network().NewStream(ctx, h2.ID())
+ require.ErrorIs(t, err, context.DeadlineExceeded)
+ require.Nil(t, s)
+
+ // Provide h2's direct address to h1.
+ h1.Peerstore().AddAddrs(h2.ID(), h2.Addrs(), peerstore.TempAddrTTL)
+ // network.NoDial should also fail
+ ctx, cancel = context.WithTimeout(context.Background(), 200*time.Millisecond)
+ defer cancel()
+ ctx = network.WithNoDial(ctx, "test")
+ s, err = h1.Network().NewStream(ctx, h2.ID())
+ require.ErrorIs(t, err, context.DeadlineExceeded)
+ require.Nil(t, s)
+
+ done := make(chan bool, 2)
+ // NewStream should return a stream if an incoming direct connection is established
+ go func() {
+ ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+ ctx = network.WithNoDial(ctx, "test")
+ s, err = h1.Network().NewStream(ctx, h2.ID())
+ assert.NoError(t, err)
+ assert.NotNil(t, s)
+ defer s.Close()
+ require.Equal(t, network.DirInbound, s.Conn().Stat().Direction)
+ done <- true
+ }()
+ go func() {
+ // connect h2 to h1 simulating connection reversal
+ h2.Peerstore().AddAddrs(h1.ID(), h1.Addrs(), peerstore.TempAddrTTL)
+ ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
+ defer cancel()
+ ctx = network.WithForceDirectDial(ctx, "test")
+ err := h2.Connect(ctx, peer.AddrInfo{ID: h1.ID()})
+ assert.NoError(t, err)
+ done <- true
+ }()
+
+ <-done
+ <-done
+}
+
+func TestLimitStreamsWhenHangingHandlers(t *testing.T) {
+ var partial rcmgr.PartialLimitConfig
+ const streamLimit = 10
+ partial.System.Streams = streamLimit
+ mgr, err := rcmgr.NewResourceManager(rcmgr.NewFixedLimiter(partial.Build(rcmgr.InfiniteLimits)))
+ require.NoError(t, err)
+
+ maddr, err := ma.NewMultiaddr("/ip4/127.0.0.1/udp/0/quic-v1")
+ require.NoError(t, err)
+
+ receiver, err := libp2p.New(
+ libp2p.ResourceManager(mgr),
+ libp2p.ListenAddrs(maddr),
+ )
+ require.NoError(t, err)
+ t.Cleanup(func() { receiver.Close() })
+
+ var wg sync.WaitGroup
+ wg.Add(1)
+
+ const pid = "/test"
+ receiver.SetStreamHandler(pid, func(s network.Stream) {
+ defer s.Close()
+ s.Write([]byte{42})
+ wg.Wait()
+ })
+
+ // Open streamLimit streams
+ success := 0
+ // we make a lot of tries because identify and identify push take up a few streams
+ for i := 0; i < 1000 && success < streamLimit; i++ {
+ mgr, err = rcmgr.NewResourceManager(rcmgr.NewFixedLimiter(rcmgr.InfiniteLimits))
+ require.NoError(t, err)
+
+ sender, err := libp2p.New(libp2p.ResourceManager(mgr))
+ require.NoError(t, err)
+ t.Cleanup(func() { sender.Close() })
+
+ sender.Peerstore().AddAddrs(receiver.ID(), receiver.Addrs(), peerstore.PermanentAddrTTL)
+
+ s, err := sender.NewStream(context.Background(), receiver.ID(), pid)
+ if err != nil {
+ continue
+ }
+
+ var b [1]byte
+ _, err = io.ReadFull(s, b[:])
+ if err == nil {
+ success++
+ }
+ sender.Close()
+ }
+ require.Equal(t, streamLimit, success)
+ // We have the maximum number of streams open. Next call should fail.
+ mgr, err = rcmgr.NewResourceManager(rcmgr.NewFixedLimiter(rcmgr.InfiniteLimits))
+ require.NoError(t, err)
+
+ sender, err := libp2p.New(libp2p.ResourceManager(mgr))
+ require.NoError(t, err)
+ t.Cleanup(func() { sender.Close() })
+
+ sender.Peerstore().AddAddrs(receiver.ID(), receiver.Addrs(), peerstore.PermanentAddrTTL)
+
+ _, err = sender.NewStream(context.Background(), receiver.ID(), pid)
+ require.Error(t, err)
+
+ // Close the open streams
+ wg.Done()
+
+ // Next call should succeed
+ require.Eventually(t, func() bool {
+ s, err := sender.NewStream(context.Background(), receiver.ID(), pid)
+ if err == nil {
+ s.Close()
+ return true
+ }
+ return false
+ }, 5*time.Second, 100*time.Millisecond)
+}
diff --git a/p2p/test/transport/deadline_test.go b/p2p/test/transport/deadline_test.go
index 5c8bcf18eb..55fa7a4fbc 100644
--- a/p2p/test/transport/deadline_test.go
+++ b/p2p/test/transport/deadline_test.go
@@ -43,7 +43,9 @@ func TestReadWriteDeadlines(t *testing.T) {
buf := make([]byte, 1)
_, err = s.Read(buf)
require.Error(t, err)
- require.True(t, err.(net.Error).Timeout())
+ var nerr net.Error
+ require.ErrorAs(t, err, &nerr)
+ require.True(t, nerr.Timeout())
require.Less(t, time.Since(start), 1*time.Second)
})
@@ -80,7 +82,9 @@ func TestReadWriteDeadlines(t *testing.T) {
_, err = s.Write(sendBuf)
}
require.Error(t, err)
- require.True(t, err.(net.Error).Timeout())
+ var nerr net.Error
+ require.ErrorAs(t, err, &nerr)
+ require.True(t, nerr.Timeout())
require.Less(t, time.Since(start), 1*time.Second)
})
}
diff --git a/p2p/test/transport/gating_test.go b/p2p/test/transport/gating_test.go
index 426fc906e5..df53da6eeb 100644
--- a/p2p/test/transport/gating_test.go
+++ b/p2p/test/transport/gating_test.go
@@ -2,6 +2,7 @@ package transport_integration
import (
"context"
+ "strings"
"testing"
"time"
@@ -12,12 +13,12 @@ import (
"github.com/libp2p/go-libp2p-testing/race"
- "github.com/golang/mock/gomock"
ma "github.com/multiformats/go-multiaddr"
"github.com/stretchr/testify/require"
+ "go.uber.org/mock/gomock"
)
-//go:generate go run github.com/golang/mock/mockgen -package transport_integration -destination mock_connection_gater_test.go github.com/libp2p/go-libp2p/core/connmgr ConnectionGater
+//go:generate go run go.uber.org/mock/mockgen -package transport_integration -destination mock_connection_gater_test.go github.com/libp2p/go-libp2p/core/connmgr ConnectionGater
func stripCertHash(addr ma.Multiaddr) ma.Multiaddr {
for {
@@ -88,6 +89,8 @@ func TestInterceptSecuredOutgoing(t *testing.T) {
h1 := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true, ConnGater: connGater})
h2 := tc.HostGenerator(t, TransportTestCaseOpts{})
+ defer h1.Close()
+ defer h2.Close()
require.Len(t, h2.Addrs(), 1)
require.Len(t, h2.Addrs(), 1)
@@ -97,7 +100,7 @@ func TestInterceptSecuredOutgoing(t *testing.T) {
connGater.EXPECT().InterceptPeerDial(h2.ID()).Return(true),
connGater.EXPECT().InterceptAddrDial(h2.ID(), gomock.Any()).Return(true),
connGater.EXPECT().InterceptSecured(network.DirOutbound, h2.ID(), gomock.Any()).Do(func(_ network.Direction, _ peer.ID, addrs network.ConnMultiaddrs) {
- // remove the certhash component from WebTransport addresses
+ // remove the certhash component from WebTransport and WebRTC addresses
require.Equal(t, stripCertHash(h2.Addrs()[0]).String(), addrs.RemoteMultiaddr().String())
}),
)
@@ -120,6 +123,8 @@ func TestInterceptUpgradedOutgoing(t *testing.T) {
h1 := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true, ConnGater: connGater})
h2 := tc.HostGenerator(t, TransportTestCaseOpts{})
+ defer h1.Close()
+ defer h2.Close()
require.Len(t, h2.Addrs(), 1)
require.Len(t, h2.Addrs(), 1)
@@ -154,19 +159,35 @@ func TestInterceptAccept(t *testing.T) {
h1 := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true})
h2 := tc.HostGenerator(t, TransportTestCaseOpts{ConnGater: connGater})
+ defer h1.Close()
+ defer h2.Close()
require.Len(t, h2.Addrs(), 1)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
// The basic host dials the first connection.
- connGater.EXPECT().InterceptAccept(gomock.Any()).Do(func(addrs network.ConnMultiaddrs) {
- // remove the certhash component from WebTransport addresses
- require.Equal(t, stripCertHash(h2.Addrs()[0]), addrs.LocalMultiaddr())
- })
+ if strings.Contains(tc.Name, "WebRTC") {
+ // In WebRTC, retransmissions of the STUN packet might cause us to create multiple connections,
+ // if the first connection attempt is rejected.
+ connGater.EXPECT().InterceptAccept(gomock.Any()).Do(func(addrs network.ConnMultiaddrs) {
+ // remove the certhash component from WebTransport addresses
+ require.Equal(t, stripCertHash(h2.Addrs()[0]), addrs.LocalMultiaddr())
+ }).AnyTimes()
+ } else {
+ connGater.EXPECT().InterceptAccept(gomock.Any()).Do(func(addrs network.ConnMultiaddrs) {
+ // remove the certhash component from WebTransport addresses
+ require.Equal(t, stripCertHash(h2.Addrs()[0]), addrs.LocalMultiaddr())
+ })
+ }
+
h1.Peerstore().AddAddrs(h2.ID(), h2.Addrs(), time.Hour)
_, err := h1.NewStream(ctx, h2.ID(), protocol.TestingID)
require.Error(t, err)
- require.NotErrorIs(t, err, context.DeadlineExceeded)
+ if _, err := h2.Addrs()[0].ValueForProtocol(ma.P_WEBRTC_DIRECT); err != nil {
+ // WebRTC rejects connection attempt before an error can be sent to the client.
+ // This means that the connection attempt will time out.
+ require.NotErrorIs(t, err, context.DeadlineExceeded)
+ }
})
}
}
@@ -183,6 +204,8 @@ func TestInterceptSecuredIncoming(t *testing.T) {
h1 := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true})
h2 := tc.HostGenerator(t, TransportTestCaseOpts{ConnGater: connGater})
+ defer h1.Close()
+ defer h2.Close()
require.Len(t, h2.Addrs(), 1)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
@@ -214,6 +237,8 @@ func TestInterceptUpgradedIncoming(t *testing.T) {
h1 := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true})
h2 := tc.HostGenerator(t, TransportTestCaseOpts{ConnGater: connGater})
+ defer h1.Close()
+ defer h2.Close()
require.Len(t, h2.Addrs(), 1)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
diff --git a/p2p/test/transport/mock_connection_gater_test.go b/p2p/test/transport/mock_connection_gater_test.go
index d6efc8b022..d617f72fce 100644
--- a/p2p/test/transport/mock_connection_gater_test.go
+++ b/p2p/test/transport/mock_connection_gater_test.go
@@ -1,5 +1,10 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/libp2p/go-libp2p/core/connmgr (interfaces: ConnectionGater)
+//
+// Generated by this command:
+//
+// mockgen -package transport_integration -destination mock_connection_gater_test.go github.com/libp2p/go-libp2p/core/connmgr ConnectionGater
+//
// Package transport_integration is a generated GoMock package.
package transport_integration
@@ -7,11 +12,11 @@ package transport_integration
import (
reflect "reflect"
- gomock "github.com/golang/mock/gomock"
control "github.com/libp2p/go-libp2p/core/control"
network "github.com/libp2p/go-libp2p/core/network"
peer "github.com/libp2p/go-libp2p/core/peer"
multiaddr "github.com/multiformats/go-multiaddr"
+ gomock "go.uber.org/mock/gomock"
)
// MockConnectionGater is a mock of ConnectionGater interface.
@@ -46,7 +51,7 @@ func (m *MockConnectionGater) InterceptAccept(arg0 network.ConnMultiaddrs) bool
}
// InterceptAccept indicates an expected call of InterceptAccept.
-func (mr *MockConnectionGaterMockRecorder) InterceptAccept(arg0 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptAccept(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptAccept", reflect.TypeOf((*MockConnectionGater)(nil).InterceptAccept), arg0)
}
@@ -60,7 +65,7 @@ func (m *MockConnectionGater) InterceptAddrDial(arg0 peer.ID, arg1 multiaddr.Mul
}
// InterceptAddrDial indicates an expected call of InterceptAddrDial.
-func (mr *MockConnectionGaterMockRecorder) InterceptAddrDial(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptAddrDial(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptAddrDial", reflect.TypeOf((*MockConnectionGater)(nil).InterceptAddrDial), arg0, arg1)
}
@@ -74,7 +79,7 @@ func (m *MockConnectionGater) InterceptPeerDial(arg0 peer.ID) bool {
}
// InterceptPeerDial indicates an expected call of InterceptPeerDial.
-func (mr *MockConnectionGaterMockRecorder) InterceptPeerDial(arg0 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptPeerDial(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptPeerDial", reflect.TypeOf((*MockConnectionGater)(nil).InterceptPeerDial), arg0)
}
@@ -88,7 +93,7 @@ func (m *MockConnectionGater) InterceptSecured(arg0 network.Direction, arg1 peer
}
// InterceptSecured indicates an expected call of InterceptSecured.
-func (mr *MockConnectionGaterMockRecorder) InterceptSecured(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptSecured(arg0, arg1, arg2 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptSecured", reflect.TypeOf((*MockConnectionGater)(nil).InterceptSecured), arg0, arg1, arg2)
}
@@ -103,7 +108,7 @@ func (m *MockConnectionGater) InterceptUpgraded(arg0 network.Conn) (bool, contro
}
// InterceptUpgraded indicates an expected call of InterceptUpgraded.
-func (mr *MockConnectionGaterMockRecorder) InterceptUpgraded(arg0 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptUpgraded(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptUpgraded", reflect.TypeOf((*MockConnectionGater)(nil).InterceptUpgraded), arg0)
}
diff --git a/p2p/test/transport/rcmgr_test.go b/p2p/test/transport/rcmgr_test.go
index 8e8629cf39..04001e5bfa 100644
--- a/p2p/test/transport/rcmgr_test.go
+++ b/p2p/test/transport/rcmgr_test.go
@@ -16,8 +16,8 @@ import (
"github.com/libp2p/go-libp2p/p2p/protocol/identify"
"github.com/libp2p/go-libp2p/p2p/protocol/ping"
- "github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
+ "go.uber.org/mock/gomock"
)
func TestResourceManagerIsUsed(t *testing.T) {
@@ -56,7 +56,7 @@ func TestResourceManagerIsUsed(t *testing.T) {
}
expectFd := true
- if strings.Contains(tc.Name, "QUIC") || strings.Contains(tc.Name, "WebTransport") {
+ if strings.Contains(tc.Name, "QUIC") || strings.Contains(tc.Name, "WebTransport") || strings.Contains(tc.Name, "WebRTC") {
expectFd = false
}
@@ -87,7 +87,7 @@ func TestResourceManagerIsUsed(t *testing.T) {
}
return nil
})
- connScope.EXPECT().Done()
+ connScope.EXPECT().Done().MinTimes(1)
var allStreamsDone sync.WaitGroup
diff --git a/p2p/test/transport/transport_test.go b/p2p/test/transport/transport_test.go
index 370ef9b114..e39b72a71a 100644
--- a/p2p/test/transport/transport_test.go
+++ b/p2p/test/transport/transport_test.go
@@ -9,6 +9,7 @@ import (
"io"
"net"
"runtime"
+ "strings"
"sync"
"sync/atomic"
"testing"
@@ -27,6 +28,8 @@ import (
"github.com/libp2p/go-libp2p/p2p/protocol/ping"
"github.com/libp2p/go-libp2p/p2p/security/noise"
tls "github.com/libp2p/go-libp2p/p2p/security/tls"
+ libp2pwebrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc"
+
"github.com/multiformats/go-multiaddr"
"github.com/stretchr/testify/require"
)
@@ -134,6 +137,21 @@ var transportsToTest = []TransportTestCase{
return h
},
},
+ {
+ Name: "WebRTC",
+ HostGenerator: func(t *testing.T, opts TransportTestCaseOpts) host.Host {
+ libp2pOpts := transformOpts(opts)
+ libp2pOpts = append(libp2pOpts, libp2p.Transport(libp2pwebrtc.New))
+ if opts.NoListen {
+ libp2pOpts = append(libp2pOpts, libp2p.NoListenAddrs)
+ } else {
+ libp2pOpts = append(libp2pOpts, libp2p.ListenAddrStrings("/ip4/127.0.0.1/udp/0/webrtc-direct"))
+ }
+ h, err := libp2p.New(libp2pOpts...)
+ require.NoError(t, err)
+ return h
+ },
+ },
}
func TestPing(t *testing.T) {
@@ -229,7 +247,7 @@ func TestLotsOfDataManyStreams(t *testing.T) {
// 64k buffer
const bufSize = 64 << 10
sendBuf := [bufSize]byte{}
- const totalStreams = 512
+ const totalStreams = 500
const parallel = 8
// Total sends are > 20MiB
require.Greater(t, len(sendBuf)*totalStreams, 20<<20)
@@ -361,6 +379,9 @@ func TestMoreStreamsThanOurLimits(t *testing.T) {
const streamCount = 1024
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
+ if strings.Contains(tc.Name, "WebRTC") {
+ t.Skip("This test potentially exhausts the uint16 WebRTC stream ID space.")
+ }
listenerLimits := rcmgr.PartialLimitConfig{
PeerDefault: rcmgr.ResourceLimits{
Streams: 32,
@@ -455,6 +476,8 @@ func TestMoreStreamsThanOurLimits(t *testing.T) {
time.Sleep(50 * time.Millisecond)
continue
}
+ t.Logf("opening stream failed: %v", err)
+ return
}
err = func(s network.Stream) error {
defer s.Close()
@@ -489,7 +512,6 @@ func TestMoreStreamsThanOurLimits(t *testing.T) {
continue
}
return
-
}
}()
}
@@ -596,8 +618,8 @@ func TestStreamReadDeadline(t *testing.T) {
_, err = s.Read([]byte{0})
require.Error(t, err)
require.Contains(t, err.Error(), "deadline")
- nerr, ok := err.(net.Error)
- require.True(t, ok, "expected a net.Error")
+ var nerr net.Error
+ require.ErrorAs(t, err, &nerr, "expected a net.Error")
require.True(t, nerr.Timeout(), "expected net.Error.Timeout() == true")
// now test that the stream is still usable
s.SetReadDeadline(time.Time{})
@@ -628,58 +650,41 @@ func TestDiscoverPeerIDFromSecurityNegotiation(t *testing.T) {
return "", inputErr
}
- // runs a test to verify we can extract the peer ID from a target with just its address
- runTest := func(t *testing.T, h host.Host) {
- t.Helper()
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- // Use a bogus peer ID so that when we connect to the target we get an error telling
- // us the targets real peer ID
- bogusPeerId, err := peer.Decode("QmadAdJ3f63JyNs65X7HHzqDwV53ynvCcKtNFvdNaz3nhk")
- if err != nil {
- t.Fatal("the hard coded bogus peerID is invalid")
- }
+ for _, tc := range transportsToTest {
+ t.Run(tc.Name, func(t *testing.T) {
+ h1 := tc.HostGenerator(t, TransportTestCaseOpts{})
+ h2 := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true})
+ defer h1.Close()
+ defer h2.Close()
- ai := &peer.AddrInfo{
- ID: bogusPeerId,
- Addrs: []multiaddr.Multiaddr{h.Addrs()[0]},
- }
+ // runs a test to verify we can extract the peer ID from a target with just its address
+ t.Helper()
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
- testHost, err := libp2p.New()
- if err != nil {
- t.Fatal(err)
- }
+ // Use a bogus peer ID so that when we connect to the target we get an error telling
+ // us the targets real peer ID
+ bogusPeerId, err := peer.Decode("QmadAdJ3f63JyNs65X7HHzqDwV53ynvCcKtNFvdNaz3nhk")
+ require.NoError(t, err, "the hard coded bogus peerID is invalid")
+
+ ai := &peer.AddrInfo{
+ ID: bogusPeerId,
+ Addrs: []multiaddr.Multiaddr{h1.Addrs()[0]},
+ }
+
+ // Try connecting with the bogus peer ID
+ err = h2.Connect(ctx, *ai)
+ require.Error(t, err, "somehow we successfully connected to a bogus peerID!")
- // Try connecting with the bogus peer ID
- if err := testHost.Connect(ctx, *ai); err != nil {
// Extract the actual peer ID from the error
newPeerId, err := extractPeerIDFromError(err)
- if err != nil {
- t.Fatal(err)
- }
+ require.NoError(t, err)
ai.ID = newPeerId
-
// Make sure the new ID is what we expected
- if ai.ID != h.ID() {
- t.Fatalf("peerID mismatch: expected %s, got %s", h.ID(), ai.ID)
- }
+ require.Equal(t, h1.ID(), ai.ID)
// and just to double-check try connecting again to make sure it works
- if err := testHost.Connect(ctx, *ai); err != nil {
- t.Fatal(err)
- }
- } else {
- t.Fatal("somehow we successfully connected to a bogus peerID!")
- }
- }
-
- for _, tc := range transportsToTest {
- t.Run(tc.Name, func(t *testing.T) {
- h := tc.HostGenerator(t, TransportTestCaseOpts{})
- defer h.Close()
-
- runTest(t, h)
+ require.NoError(t, h2.Connect(ctx, *ai))
})
}
}
diff --git a/p2p/transport/quic/cmd/client/main.go b/p2p/transport/quic/cmd/client/main.go
index f33d65ecd4..7873625321 100644
--- a/p2p/transport/quic/cmd/client/main.go
+++ b/p2p/transport/quic/cmd/client/main.go
@@ -8,13 +8,13 @@ import (
"log"
"os"
- "github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
-
ic "github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic"
+ "github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
ma "github.com/multiformats/go-multiaddr"
+ "github.com/quic-go/quic-go"
)
func main() {
@@ -41,7 +41,7 @@ func run(raddr string, p string) error {
return err
}
- reuse, err := quicreuse.NewConnManager([32]byte{})
+ reuse, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{})
if err != nil {
return err
}
diff --git a/p2p/transport/quic/cmd/server/main.go b/p2p/transport/quic/cmd/server/main.go
index e5144f496d..222841d42a 100644
--- a/p2p/transport/quic/cmd/server/main.go
+++ b/p2p/transport/quic/cmd/server/main.go
@@ -7,14 +7,14 @@ import (
"log"
"os"
- "github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
-
ic "github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
tpt "github.com/libp2p/go-libp2p/core/transport"
libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic"
+ "github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
ma "github.com/multiformats/go-multiaddr"
+ "github.com/quic-go/quic-go"
)
func main() {
@@ -41,7 +41,7 @@ func run(port string) error {
return err
}
- reuse, err := quicreuse.NewConnManager([32]byte{})
+ reuse, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{})
if err != nil {
return err
}
diff --git a/p2p/transport/quic/conn_test.go b/p2p/transport/quic/conn_test.go
index 65f733a879..d3e27a7e16 100644
--- a/p2p/transport/quic/conn_test.go
+++ b/p2p/transport/quic/conn_test.go
@@ -20,14 +20,14 @@ import (
tpt "github.com/libp2p/go-libp2p/core/transport"
"github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
- "github.com/golang/mock/gomock"
ma "github.com/multiformats/go-multiaddr"
"github.com/quic-go/quic-go"
quicproxy "github.com/quic-go/quic-go/integrationtests/tools/proxy"
"github.com/stretchr/testify/require"
+ "go.uber.org/mock/gomock"
)
-//go:generate sh -c "go run github.com/golang/mock/mockgen -package libp2pquic -destination mock_connection_gater_test.go github.com/libp2p/go-libp2p/core/connmgr ConnectionGater && go run golang.org/x/tools/cmd/goimports -w mock_connection_gater_test.go"
+//go:generate sh -c "go run go.uber.org/mock/mockgen -package libp2pquic -destination mock_connection_gater_test.go github.com/libp2p/go-libp2p/core/connmgr ConnectionGater && go run golang.org/x/tools/cmd/goimports -w mock_connection_gater_test.go"
type connTestCase struct {
Name string
@@ -55,7 +55,7 @@ func createPeer(t *testing.T) (peer.ID, ic.PrivKey) {
require.NoError(t, err)
id, err := peer.IDFromPrivateKey(priv)
require.NoError(t, err)
- t.Logf("using a %s key: %s", priv.Type(), id.Pretty())
+ t.Logf("using a %s key: %s", priv.Type(), id)
return id, priv
}
@@ -69,7 +69,7 @@ func runServer(t *testing.T, tr tpt.Transport, addr string) tpt.Listener {
func newConnManager(t *testing.T, opts ...quicreuse.Option) *quicreuse.ConnManager {
t.Helper()
- cm, err := quicreuse.NewConnManager([32]byte{}, opts...)
+ cm, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}, opts...)
require.NoError(t, err)
t.Cleanup(func() { cm.Close() })
return cm
diff --git a/p2p/transport/quic/listener_test.go b/p2p/transport/quic/listener_test.go
index b9dda92c20..d739c82c44 100644
--- a/p2p/transport/quic/listener_test.go
+++ b/p2p/transport/quic/listener_test.go
@@ -109,8 +109,7 @@ func TestCorrectNumberOfVirtualListeners(t *testing.T) {
require.NoError(t, err)
require.NoError(t, err)
- require.Equal(t, 1, len(tpt.listeners[udpAddr.String()]))
+ require.Len(t, tpt.listeners[udpAddr.String()], 1)
ln.Close()
- require.Equal(t, 0, len(tpt.listeners[udpAddr.String()]))
-
+ require.Empty(t, tpt.listeners[udpAddr.String()])
}
diff --git a/p2p/transport/quic/mock_connection_gater_test.go b/p2p/transport/quic/mock_connection_gater_test.go
index 4ee4008536..8e23aad370 100644
--- a/p2p/transport/quic/mock_connection_gater_test.go
+++ b/p2p/transport/quic/mock_connection_gater_test.go
@@ -1,5 +1,10 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/libp2p/go-libp2p/core/connmgr (interfaces: ConnectionGater)
+//
+// Generated by this command:
+//
+// mockgen -package libp2pquic -destination mock_connection_gater_test.go github.com/libp2p/go-libp2p/core/connmgr ConnectionGater
+//
// Package libp2pquic is a generated GoMock package.
package libp2pquic
@@ -7,11 +12,11 @@ package libp2pquic
import (
reflect "reflect"
- gomock "github.com/golang/mock/gomock"
control "github.com/libp2p/go-libp2p/core/control"
network "github.com/libp2p/go-libp2p/core/network"
peer "github.com/libp2p/go-libp2p/core/peer"
multiaddr "github.com/multiformats/go-multiaddr"
+ gomock "go.uber.org/mock/gomock"
)
// MockConnectionGater is a mock of ConnectionGater interface.
@@ -46,7 +51,7 @@ func (m *MockConnectionGater) InterceptAccept(arg0 network.ConnMultiaddrs) bool
}
// InterceptAccept indicates an expected call of InterceptAccept.
-func (mr *MockConnectionGaterMockRecorder) InterceptAccept(arg0 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptAccept(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptAccept", reflect.TypeOf((*MockConnectionGater)(nil).InterceptAccept), arg0)
}
@@ -60,7 +65,7 @@ func (m *MockConnectionGater) InterceptAddrDial(arg0 peer.ID, arg1 multiaddr.Mul
}
// InterceptAddrDial indicates an expected call of InterceptAddrDial.
-func (mr *MockConnectionGaterMockRecorder) InterceptAddrDial(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptAddrDial(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptAddrDial", reflect.TypeOf((*MockConnectionGater)(nil).InterceptAddrDial), arg0, arg1)
}
@@ -74,7 +79,7 @@ func (m *MockConnectionGater) InterceptPeerDial(arg0 peer.ID) bool {
}
// InterceptPeerDial indicates an expected call of InterceptPeerDial.
-func (mr *MockConnectionGaterMockRecorder) InterceptPeerDial(arg0 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptPeerDial(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptPeerDial", reflect.TypeOf((*MockConnectionGater)(nil).InterceptPeerDial), arg0)
}
@@ -88,7 +93,7 @@ func (m *MockConnectionGater) InterceptSecured(arg0 network.Direction, arg1 peer
}
// InterceptSecured indicates an expected call of InterceptSecured.
-func (mr *MockConnectionGaterMockRecorder) InterceptSecured(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptSecured(arg0, arg1, arg2 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptSecured", reflect.TypeOf((*MockConnectionGater)(nil).InterceptSecured), arg0, arg1, arg2)
}
@@ -103,7 +108,7 @@ func (m *MockConnectionGater) InterceptUpgraded(arg0 network.Conn) (bool, contro
}
// InterceptUpgraded indicates an expected call of InterceptUpgraded.
-func (mr *MockConnectionGaterMockRecorder) InterceptUpgraded(arg0 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptUpgraded(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptUpgraded", reflect.TypeOf((*MockConnectionGater)(nil).InterceptUpgraded), arg0)
}
diff --git a/p2p/transport/quicreuse/config.go b/p2p/transport/quicreuse/config.go
index 11264be436..45b1d4b8c6 100644
--- a/p2p/transport/quicreuse/config.go
+++ b/p2p/transport/quicreuse/config.go
@@ -20,6 +20,4 @@ var quicConfig = &quic.Config{
Versions: []quic.VersionNumber{quic.Version1},
// We don't use datagrams (yet), but this is necessary for WebTransport
EnableDatagrams: true,
- // The multiaddress encodes the QUIC version, thus there's no need to send Version Negotiation packets.
- DisableVersionNegotiationPackets: true,
}
diff --git a/p2p/transport/quicreuse/connmgr.go b/p2p/transport/quicreuse/connmgr.go
index 60c0daa1a3..0add5ddfc3 100644
--- a/p2p/transport/quicreuse/connmgr.go
+++ b/p2p/transport/quicreuse/connmgr.go
@@ -25,8 +25,8 @@ type ConnManager struct {
quicListenersMu sync.Mutex
quicListeners map[string]quicListenerEntry
- srk quic.StatelessResetKey
- mt *metricsTracer
+ srk quic.StatelessResetKey
+ tokenKey quic.TokenGeneratorKey
}
type quicListenerEntry struct {
@@ -34,11 +34,12 @@ type quicListenerEntry struct {
ln *quicListener
}
-func NewConnManager(statelessResetKey quic.StatelessResetKey, opts ...Option) (*ConnManager, error) {
+func NewConnManager(statelessResetKey quic.StatelessResetKey, tokenKey quic.TokenGeneratorKey, opts ...Option) (*ConnManager, error) {
cm := &ConnManager{
enableReuseport: true,
quicListeners: make(map[string]quicListenerEntry),
srk: statelessResetKey,
+ tokenKey: tokenKey,
}
for _, o := range opts {
if err := o(cm); err != nil {
@@ -48,26 +49,20 @@ func NewConnManager(statelessResetKey quic.StatelessResetKey, opts ...Option) (*
quicConf := quicConfig.Clone()
- if cm.enableMetrics {
- cm.mt = newMetricsTracer()
- }
- quicConf.Tracer = func(ctx context.Context, p quiclogging.Perspective, ci quic.ConnectionID) quiclogging.ConnectionTracer {
- tracers := make([]quiclogging.ConnectionTracer, 0, 2)
+ quicConf.Tracer = func(ctx context.Context, p quiclogging.Perspective, ci quic.ConnectionID) *quiclogging.ConnectionTracer {
+ var tracer *quiclogging.ConnectionTracer
if qlogTracerDir != "" {
- tracers = append(tracers, qloggerForDir(qlogTracerDir, p, ci))
- }
- if cm.mt != nil {
- tracers = append(tracers, cm.mt.TracerForConnection(ctx, p, ci))
+ tracer = qloggerForDir(qlogTracerDir, p, ci)
}
- return quiclogging.NewMultiplexedConnectionTracer(tracers...)
+ return tracer
}
serverConfig := quicConf.Clone()
cm.clientConfig = quicConf
cm.serverConfig = serverConfig
if cm.enableReuseport {
- cm.reuseUDP4 = newReuse(&statelessResetKey, cm.mt)
- cm.reuseUDP6 = newReuse(&statelessResetKey, cm.mt)
+ cm.reuseUDP4 = newReuse(&statelessResetKey, &tokenKey)
+ cm.reuseUDP6 = newReuse(&statelessResetKey, &tokenKey)
}
return cm, nil
}
@@ -149,11 +144,14 @@ func (c *ConnManager) transportForListen(network string, laddr *net.UDPAddr) (re
if err != nil {
return nil, err
}
- tr := &singleOwnerTransport{Transport: quic.Transport{Conn: conn, StatelessResetKey: &c.srk}, packetConn: conn}
- if c.mt != nil {
- tr.Transport.Tracer = c.mt
- }
- return tr, nil
+ return &singleOwnerTransport{
+ packetConn: conn,
+ Transport: quic.Transport{
+ Conn: conn,
+ StatelessResetKey: &c.srk,
+ TokenGeneratorKey: &c.tokenKey,
+ },
+ }, nil
}
func (c *ConnManager) DialQUIC(ctx context.Context, raddr ma.Multiaddr, tlsConf *tls.Config, allowWindowIncrease func(conn quic.Connection, delta uint64) bool) (quic.Connection, error) {
@@ -208,12 +206,7 @@ func (c *ConnManager) TransportForDial(network string, raddr *net.UDPAddr) (refC
if err != nil {
return nil, err
}
- tr := &singleOwnerTransport{Transport: quic.Transport{Conn: conn, StatelessResetKey: &c.srk}, packetConn: conn}
- if c.mt != nil {
- tr.Transport.Tracer = c.mt
- }
-
- return tr, nil
+ return &singleOwnerTransport{Transport: quic.Transport{Conn: conn, StatelessResetKey: &c.srk}, packetConn: conn}, nil
}
func (c *ConnManager) Protocols() []int {
diff --git a/p2p/transport/quicreuse/connmgr_test.go b/p2p/transport/quicreuse/connmgr_test.go
index 14809ac736..f3576a3905 100644
--- a/p2p/transport/quicreuse/connmgr_test.go
+++ b/p2p/transport/quicreuse/connmgr_test.go
@@ -54,7 +54,7 @@ func testListenOnSameProto(t *testing.T, enableReuseport bool) {
if !enableReuseport {
opts = append(opts, DisableReuseport())
}
- cm, err := NewConnManager([32]byte{}, opts...)
+ cm, err := NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}, opts...)
require.NoError(t, err)
defer checkClosed(t, cm)
defer cm.Close()
@@ -83,7 +83,7 @@ func TestConnectionPassedToQUICForListening(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("skipping on windows. Windows doesn't support these optimizations")
}
- cm, err := NewConnManager([32]byte{}, DisableReuseport())
+ cm, err := NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}, DisableReuseport())
require.NoError(t, err)
defer cm.Close()
@@ -107,7 +107,7 @@ func TestConnectionPassedToQUICForListening(t *testing.T) {
func TestAcceptErrorGetCleanedUp(t *testing.T) {
raddr := ma.StringCast("/ip4/127.0.0.1/udp/0/quic-v1")
- cm, err := NewConnManager([32]byte{}, DisableReuseport())
+ cm, err := NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}, DisableReuseport())
require.NoError(t, err)
defer cm.Close()
@@ -143,7 +143,7 @@ func TestConnectionPassedToQUICForDialing(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("skipping on windows. Windows doesn't support these optimizations")
}
- cm, err := NewConnManager([32]byte{}, DisableReuseport())
+ cm, err := NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}, DisableReuseport())
require.NoError(t, err)
defer cm.Close()
@@ -218,7 +218,7 @@ func testListener(t *testing.T, enableReuseport bool) {
if !enableReuseport {
opts = append(opts, DisableReuseport())
}
- cm, err := NewConnManager([32]byte{}, opts...)
+ cm, err := NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}, opts...)
require.NoError(t, err)
id1, tlsConf1 := getTLSConfForProto(t, "proto1")
diff --git a/p2p/transport/quicreuse/listener.go b/p2p/transport/quicreuse/listener.go
index 4ee20042d3..ee214ad94b 100644
--- a/p2p/transport/quicreuse/listener.go
+++ b/p2p/transport/quicreuse/listener.go
@@ -30,6 +30,7 @@ type protoConf struct {
type quicListener struct {
l *quic.Listener
+ closeMx sync.Mutex
transport refCountedQuicTransport
running chan struct{}
addrs []ma.Multiaddr
@@ -124,7 +125,13 @@ func (l *quicListener) Add(tlsConf *tls.Config, allowWindowIncrease func(conn qu
func (l *quicListener) Run() error {
defer close(l.running)
- defer l.transport.DecreaseCount()
+ defer func() {
+ // transport close is not safe to use concurrently with listener close.
+ // remove after https://github.com/quic-go/quic-go/issues/4266 is fixed.
+ l.closeMx.Lock()
+ defer l.closeMx.Unlock()
+ l.transport.DecreaseCount()
+ }()
for {
conn, err := l.l.Accept(context.Background())
if err != nil {
@@ -147,9 +154,14 @@ func (l *quicListener) Run() error {
}
func (l *quicListener) Close() error {
- err := l.l.Close()
+ // listener close is not safe to use concurrently with transport close.
+ // remove after https://github.com/quic-go/quic-go/issues/4266 is fixed.
+ l.closeMx.Lock()
+ err := l.l.Close()
+ l.closeMx.Unlock()
+
<-l.running // wait for Run to return
- return err
+ return err
}
const queueLen = 16
diff --git a/p2p/transport/quicreuse/quic_multiaddr_test.go b/p2p/transport/quicreuse/quic_multiaddr_test.go
index 5dfb64753b..a6242e2674 100644
--- a/p2p/transport/quicreuse/quic_multiaddr_test.go
+++ b/p2p/transport/quicreuse/quic_multiaddr_test.go
@@ -13,14 +13,14 @@ func TestConvertToQuicMultiaddr(t *testing.T) {
addr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 42), Port: 1337}
maddr, err := ToQuicMultiaddr(addr, quic.Version1)
require.NoError(t, err)
- require.Equal(t, maddr.String(), "/ip4/192.168.0.42/udp/1337/quic-v1")
+ require.Equal(t, "/ip4/192.168.0.42/udp/1337/quic-v1", maddr.String())
}
func TestConvertToQuicV1Multiaddr(t *testing.T) {
addr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 42), Port: 1337}
maddr, err := ToQuicMultiaddr(addr, quic.Version1)
require.NoError(t, err)
- require.Equal(t, maddr.String(), "/ip4/192.168.0.42/udp/1337/quic-v1")
+ require.Equal(t, "/ip4/192.168.0.42/udp/1337/quic-v1", maddr.String())
}
func TestConvertFromQuicV1Multiaddr(t *testing.T) {
@@ -28,7 +28,7 @@ func TestConvertFromQuicV1Multiaddr(t *testing.T) {
require.NoError(t, err)
udpAddr, v, err := FromQuicMultiaddr(maddr)
require.NoError(t, err)
- require.Equal(t, udpAddr.IP, net.IPv4(192, 168, 0, 42))
- require.Equal(t, udpAddr.Port, 1337)
- require.Equal(t, v, quic.Version1)
+ require.Equal(t, net.IPv4(192, 168, 0, 42), udpAddr.IP)
+ require.Equal(t, 1337, udpAddr.Port)
+ require.Equal(t, quic.Version1, v)
}
diff --git a/p2p/transport/quicreuse/reuse.go b/p2p/transport/quicreuse/reuse.go
index 2940e0d349..dc2b33b853 100644
--- a/p2p/transport/quicreuse/reuse.go
+++ b/p2p/transport/quicreuse/reuse.go
@@ -123,10 +123,10 @@ type reuse struct {
globalDialers map[int]*refcountedTransport
statelessResetKey *quic.StatelessResetKey
- metricsTracer *metricsTracer
+ tokenGeneratorKey *quic.TokenGeneratorKey
}
-func newReuse(srk *quic.StatelessResetKey, mt *metricsTracer) *reuse {
+func newReuse(srk *quic.StatelessResetKey, tokenKey *quic.TokenGeneratorKey) *reuse {
r := &reuse{
unicast: make(map[string]map[int]*refcountedTransport),
globalListeners: make(map[int]*refcountedTransport),
@@ -134,7 +134,7 @@ func newReuse(srk *quic.StatelessResetKey, mt *metricsTracer) *reuse {
closeChan: make(chan struct{}),
gcStopChan: make(chan struct{}),
statelessResetKey: srk,
- metricsTracer: mt,
+ tokenGeneratorKey: tokenKey,
}
go r.gc()
return r
@@ -270,10 +270,8 @@ func (r *reuse) transportForDialLocked(network string, source *net.IP) (*refcoun
tr := &refcountedTransport{Transport: quic.Transport{
Conn: conn,
StatelessResetKey: r.statelessResetKey,
+ TokenGeneratorKey: r.tokenGeneratorKey,
}, packetConn: conn}
- if r.metricsTracer != nil {
- tr.Transport.Tracer = r.metricsTracer
- }
r.globalDialers[conn.LocalAddr().(*net.UDPAddr).Port] = tr
return tr, nil
}
@@ -317,14 +315,13 @@ func (r *reuse) TransportForListen(network string, laddr *net.UDPAddr) (*refcoun
return nil, err
}
localAddr := conn.LocalAddr().(*net.UDPAddr)
- tr := &refcountedTransport{Transport: quic.Transport{
- Conn: conn,
- StatelessResetKey: r.statelessResetKey,
- }, packetConn: conn}
- if r.metricsTracer != nil {
- tr.Transport.Tracer = r.metricsTracer
+ tr := &refcountedTransport{
+ Transport: quic.Transport{
+ Conn: conn,
+ StatelessResetKey: r.statelessResetKey,
+ },
+ packetConn: conn,
}
-
tr.IncreaseCount()
// Deal with listen on a global address
diff --git a/p2p/transport/quicreuse/reuse_test.go b/p2p/transport/quicreuse/reuse_test.go
index b373f31fe4..b463094720 100644
--- a/p2p/transport/quicreuse/reuse_test.go
+++ b/p2p/transport/quicreuse/reuse_test.go
@@ -69,7 +69,7 @@ func TestReuseListenOnAllIPv4(t *testing.T) {
require.NoError(t, err)
conn, err := reuse.TransportForListen("udp4", addr)
require.NoError(t, err)
- require.Equal(t, conn.GetCount(), 1)
+ require.Equal(t, 1, conn.GetCount())
}
func TestReuseListenOnAllIPv6(t *testing.T) {
@@ -82,7 +82,7 @@ func TestReuseListenOnAllIPv6(t *testing.T) {
tr, err := reuse.TransportForListen("udp6", addr)
require.NoError(t, err)
defer tr.Close()
- require.Equal(t, tr.GetCount(), 1)
+ require.Equal(t, 1, tr.GetCount())
}
func TestReuseCreateNewGlobalConnOnDial(t *testing.T) {
@@ -93,10 +93,10 @@ func TestReuseCreateNewGlobalConnOnDial(t *testing.T) {
require.NoError(t, err)
conn, err := reuse.TransportForDial("udp4", addr)
require.NoError(t, err)
- require.Equal(t, conn.GetCount(), 1)
+ require.Equal(t, 1, conn.GetCount())
laddr := conn.LocalAddr().(*net.UDPAddr)
- require.Equal(t, laddr.IP.String(), "0.0.0.0")
- require.NotEqual(t, laddr.Port, 0)
+ require.Equal(t, "0.0.0.0", laddr.IP.String())
+ require.NotEqual(t, 0, laddr.Port)
}
func TestReuseConnectionWhenDialing(t *testing.T) {
@@ -107,13 +107,13 @@ func TestReuseConnectionWhenDialing(t *testing.T) {
require.NoError(t, err)
lconn, err := reuse.TransportForListen("udp4", addr)
require.NoError(t, err)
- require.Equal(t, lconn.GetCount(), 1)
+ require.Equal(t, 1, lconn.GetCount())
// dial
raddr, err := net.ResolveUDPAddr("udp4", "1.1.1.1:1234")
require.NoError(t, err)
conn, err := reuse.TransportForDial("udp4", raddr)
require.NoError(t, err)
- require.Equal(t, conn.GetCount(), 2)
+ require.Equal(t, 2, conn.GetCount())
}
func TestReuseConnectionWhenListening(t *testing.T) {
@@ -127,8 +127,8 @@ func TestReuseConnectionWhenListening(t *testing.T) {
laddr := &net.UDPAddr{IP: net.IPv4zero, Port: tr.LocalAddr().(*net.UDPAddr).Port}
lconn, err := reuse.TransportForListen("udp4", laddr)
require.NoError(t, err)
- require.Equal(t, lconn.GetCount(), 2)
- require.Equal(t, tr.GetCount(), 2)
+ require.Equal(t, 2, lconn.GetCount())
+ require.Equal(t, 2, tr.GetCount())
}
func TestReuseConnectionWhenDialBeforeListen(t *testing.T) {
@@ -151,15 +151,15 @@ func TestReuseConnectionWhenDialBeforeListen(t *testing.T) {
require.NoError(t, err)
tr, err := reuse.TransportForDial("udp4", raddr)
require.NoError(t, err)
- require.Equal(t, tr, lTr)
- require.Equal(t, tr.GetCount(), 2)
+ require.Equal(t, lTr, tr)
+ require.Equal(t, 2, tr.GetCount())
// a listener on an unspecified port should reuse the dialer
laddr2 := &net.UDPAddr{IP: net.IPv4zero, Port: 0}
lconn2, err := reuse.TransportForListen("udp4", laddr2)
require.NoError(t, err)
- require.Equal(t, lconn2, rTr)
- require.Equal(t, lconn2.GetCount(), 2)
+ require.Equal(t, rTr, lconn2)
+ require.Equal(t, 2, lconn2.GetCount())
}
func TestReuseListenOnSpecificInterface(t *testing.T) {
@@ -181,11 +181,11 @@ func TestReuseListenOnSpecificInterface(t *testing.T) {
require.NoError(t, err)
lconn, err := reuse.TransportForListen("udp4", addr)
require.NoError(t, err)
- require.Equal(t, lconn.GetCount(), 1)
+ require.Equal(t, 1, lconn.GetCount())
// dial
conn, err := reuse.TransportForDial("udp4", raddr)
require.NoError(t, err)
- require.Equal(t, conn.GetCount(), 1)
+ require.Equal(t, 1, conn.GetCount())
}
func TestReuseGarbageCollect(t *testing.T) {
@@ -216,13 +216,13 @@ func TestReuseGarbageCollect(t *testing.T) {
require.NoError(t, err)
dTr, err := reuse.TransportForDial("udp4", raddr)
require.NoError(t, err)
- require.Equal(t, dTr.GetCount(), 1)
+ require.Equal(t, 1, dTr.GetCount())
addr, err := net.ResolveUDPAddr("udp4", "0.0.0.0:1234")
require.NoError(t, err)
lTr, err := reuse.TransportForListen("udp4", addr)
require.NoError(t, err)
- require.Equal(t, lTr.GetCount(), 1)
+ require.Equal(t, 1, lTr.GetCount())
closeTime := time.Now()
lTr.DecreaseCount()
@@ -233,7 +233,7 @@ func TestReuseGarbageCollect(t *testing.T) {
if closeTime.Add(maxUnusedDuration).Before(time.Now()) {
break
}
- require.Equal(t, num, 2)
+ require.Equal(t, 2, num)
time.Sleep(2 * time.Millisecond)
}
require.Eventually(t, func() bool { return numGlobals() == 0 }, 4*garbageCollectInterval, 10*time.Millisecond)
diff --git a/p2p/transport/quicreuse/tracer.go b/p2p/transport/quicreuse/tracer.go
index 1386a5c3d1..16c7dce4f1 100644
--- a/p2p/transport/quicreuse/tracer.go
+++ b/p2p/transport/quicreuse/tracer.go
@@ -24,7 +24,7 @@ func init() {
qlogTracerDir = os.Getenv("QLOGDIR")
}
-func qloggerForDir(qlogDir string, p logging.Perspective, ci quic.ConnectionID) logging.ConnectionTracer {
+func qloggerForDir(qlogDir string, p logging.Perspective, ci quic.ConnectionID) *logging.ConnectionTracer {
// create the QLOGDIR, if it doesn't exist
if err := os.MkdirAll(qlogDir, 0777); err != nil {
log.Errorf("creating the QLOGDIR failed: %s", err)
diff --git a/p2p/transport/quicreuse/tracer_metrics.go b/p2p/transport/quicreuse/tracer_metrics.go
deleted file mode 100644
index 03e73fd25f..0000000000
--- a/p2p/transport/quicreuse/tracer_metrics.go
+++ /dev/null
@@ -1,372 +0,0 @@
-package quicreuse
-
-import (
- "context"
- "errors"
- "fmt"
- "net"
- "sync"
- "time"
-
- "github.com/prometheus/client_golang/prometheus"
- "github.com/quic-go/quic-go"
- "github.com/quic-go/quic-go/logging"
-)
-
-var (
- bytesTransferred *prometheus.CounterVec
- newConns *prometheus.CounterVec
- closedConns *prometheus.CounterVec
- sentPackets *prometheus.CounterVec
- rcvdPackets *prometheus.CounterVec
- bufferedPackets *prometheus.CounterVec
- droppedPackets *prometheus.CounterVec
- lostPackets *prometheus.CounterVec
- connErrors *prometheus.CounterVec
-)
-
-type aggregatingCollector struct {
- mutex sync.Mutex
-
- conns map[string] /* conn ID */ *metricsConnTracer
- rtts prometheus.Histogram
- connDurations prometheus.Histogram
-}
-
-func newAggregatingCollector() *aggregatingCollector {
- return &aggregatingCollector{
- conns: make(map[string]*metricsConnTracer),
- rtts: prometheus.NewHistogram(prometheus.HistogramOpts{
- Name: "quic_smoothed_rtt",
- Help: "Smoothed RTT",
- Buckets: prometheus.ExponentialBuckets(0.001, 1.25, 40), // 1ms to ~6000ms
- }),
- connDurations: prometheus.NewHistogram(prometheus.HistogramOpts{
- Name: "quic_connection_duration",
- Help: "Connection Duration",
- Buckets: prometheus.ExponentialBuckets(1, 1.5, 40), // 1s to ~12 weeks
- }),
- }
-}
-
-var _ prometheus.Collector = &aggregatingCollector{}
-
-func (c *aggregatingCollector) Describe(descs chan<- *prometheus.Desc) {
- descs <- c.rtts.Desc()
- descs <- c.connDurations.Desc()
-}
-
-func (c *aggregatingCollector) Collect(metrics chan<- prometheus.Metric) {
- now := time.Now()
- c.mutex.Lock()
- for _, conn := range c.conns {
- if rtt, valid := conn.getSmoothedRTT(); valid {
- c.rtts.Observe(rtt.Seconds())
- }
- c.connDurations.Observe(now.Sub(conn.startTime).Seconds())
- }
- c.mutex.Unlock()
- metrics <- c.rtts
- metrics <- c.connDurations
-}
-
-func (c *aggregatingCollector) AddConn(id string, t *metricsConnTracer) {
- c.mutex.Lock()
- c.conns[id] = t
- c.mutex.Unlock()
-}
-
-func (c *aggregatingCollector) RemoveConn(id string) {
- c.mutex.Lock()
- delete(c.conns, id)
- c.mutex.Unlock()
-}
-
-var collector *aggregatingCollector
-
-var initMetricsOnce sync.Once
-
-func initMetrics() {
- const (
- direction = "direction"
- encLevel = "encryption_level"
- )
-
- closedConns = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "quic_connections_closed_total",
- Help: "closed QUIC connection",
- },
- []string{direction},
- )
- prometheus.MustRegister(closedConns)
- newConns = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "quic_connections_new_total",
- Help: "new QUIC connection",
- },
- []string{direction, "handshake_successful"},
- )
- prometheus.MustRegister(newConns)
- bytesTransferred = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "quic_transferred_bytes",
- Help: "QUIC bytes transferred",
- },
- []string{direction}, // TODO: this is confusing. Other times, we use direction for the perspective
- )
- prometheus.MustRegister(bytesTransferred)
- sentPackets = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "quic_packets_sent_total",
- Help: "QUIC packets sent",
- },
- []string{encLevel},
- )
- prometheus.MustRegister(sentPackets)
- rcvdPackets = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "quic_packets_rcvd_total",
- Help: "QUIC packets received",
- },
- []string{encLevel},
- )
- prometheus.MustRegister(rcvdPackets)
- bufferedPackets = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "quic_packets_buffered_total",
- Help: "Buffered packets",
- },
- []string{"packet_type"},
- )
- prometheus.MustRegister(bufferedPackets)
- droppedPackets = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "quic_packets_dropped_total",
- Help: "Dropped packets",
- },
- []string{"packet_type", "reason"},
- )
- prometheus.MustRegister(droppedPackets)
- connErrors = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "quic_connection_errors_total",
- Help: "QUIC connection errors",
- },
- []string{"side", "error_code"},
- )
- prometheus.MustRegister(connErrors)
- lostPackets = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "quic_packets_lost_total",
- Help: "QUIC lost received",
- },
- []string{encLevel, "reason"},
- )
- prometheus.MustRegister(lostPackets)
- collector = newAggregatingCollector()
- prometheus.MustRegister(collector)
-}
-
-type metricsTracer struct {
- logging.NullTracer
-}
-
-var _ logging.Tracer = &metricsTracer{}
-
-func newMetricsTracer() *metricsTracer {
- initMetricsOnce.Do(func() { initMetrics() })
- return &metricsTracer{}
-}
-
-func (m *metricsTracer) TracerForConnection(_ context.Context, p logging.Perspective, connID logging.ConnectionID) logging.ConnectionTracer {
- return &metricsConnTracer{perspective: p, connID: connID}
-}
-
-func (m *metricsTracer) SentPacket(_ net.Addr, _ *logging.Header, size logging.ByteCount, _ []logging.Frame) {
- bytesTransferred.WithLabelValues("sent").Add(float64(size))
-}
-
-type metricsConnTracer struct {
- logging.NullConnectionTracer
-
- perspective logging.Perspective
- startTime time.Time
- connID logging.ConnectionID
- handshakeComplete bool
-
- mutex sync.Mutex
- numRTTMeasurements int
- rtt time.Duration
-}
-
-var _ logging.ConnectionTracer = &metricsConnTracer{}
-
-func (m *metricsConnTracer) getDirection() string {
- if m.perspective == logging.PerspectiveClient {
- return "outgoing"
- }
- return "incoming"
-}
-
-func (m *metricsConnTracer) getEncLevel(packetType logging.PacketType) string {
- switch packetType {
- case logging.PacketType0RTT:
- return "0-RTT"
- case logging.PacketTypeInitial:
- return "Initial"
- case logging.PacketTypeHandshake:
- return "Handshake"
- case logging.PacketTypeRetry:
- return "Retry"
- case logging.PacketType1RTT:
- return "1-RTT"
- default:
- return "unknown"
- }
-}
-
-func (m *metricsConnTracer) StartedConnection(net.Addr, net.Addr, logging.ConnectionID, logging.ConnectionID) {
- m.startTime = time.Now()
- collector.AddConn(m.connID.String(), m)
-}
-
-func (m *metricsConnTracer) ClosedConnection(e error) {
- var (
- applicationErr *quic.ApplicationError
- transportErr *quic.TransportError
- statelessResetErr *quic.StatelessResetError
- vnErr *quic.VersionNegotiationError
- idleTimeoutErr *quic.IdleTimeoutError
- handshakeTimeoutErr *quic.HandshakeTimeoutError
- remote bool
- desc string
- )
-
- switch {
- case errors.As(e, &applicationErr):
- return
- case errors.As(e, &transportErr):
- remote = transportErr.Remote
- desc = transportErr.ErrorCode.String()
- case errors.As(e, &statelessResetErr):
- remote = true
- desc = "stateless_reset"
- case errors.As(e, &vnErr):
- desc = "version_negotiation"
- case errors.As(e, &idleTimeoutErr):
- desc = "idle_timeout"
- case errors.As(e, &handshakeTimeoutErr):
- desc = "handshake_timeout"
- default:
- desc = fmt.Sprintf("unknown error: %v", e)
- }
-
- side := "local"
- if remote {
- side = "remote"
- }
- connErrors.WithLabelValues(side, desc).Inc()
-}
-func (m *metricsConnTracer) SentPacket(hdr *logging.ExtendedHeader, size logging.ByteCount, _ *logging.AckFrame, _ []logging.Frame) {
- bytesTransferred.WithLabelValues("sent").Add(float64(size))
- sentPackets.WithLabelValues(m.getEncLevel(logging.PacketTypeFromHeader(&hdr.Header))).Inc()
-}
-
-func (m *metricsConnTracer) ReceivedVersionNegotiationPacket(dst, src logging.ArbitraryLenConnectionID, v []logging.VersionNumber) {
- bytesTransferred.WithLabelValues("rcvd").Add(1 /* header form byte */ + 4 /* version number */ + 2 /* src and dest conn id length fields */ + float64(dst.Len()+src.Len()) + float64(4*len(v)))
- rcvdPackets.WithLabelValues("Version Negotiation").Inc()
-}
-
-func (m *metricsConnTracer) ReceivedRetry(*logging.Header) {
- rcvdPackets.WithLabelValues("Retry").Inc()
-}
-
-func (m *metricsConnTracer) ReceivedPacket(hdr *logging.ExtendedHeader, size logging.ByteCount, _ []logging.Frame) {
- bytesTransferred.WithLabelValues("rcvd").Add(float64(size))
- rcvdPackets.WithLabelValues(m.getEncLevel(logging.PacketTypeFromHeader(&hdr.Header))).Inc()
-}
-
-func (m *metricsConnTracer) BufferedPacket(packetType logging.PacketType, _ logging.ByteCount) {
- bufferedPackets.WithLabelValues(m.getEncLevel(packetType)).Inc()
-}
-
-func (m *metricsConnTracer) DroppedPacket(packetType logging.PacketType, size logging.ByteCount, r logging.PacketDropReason) {
- bytesTransferred.WithLabelValues("rcvd").Add(float64(size))
- var reason string
- switch r {
- case logging.PacketDropKeyUnavailable:
- reason = "key_unavailable"
- case logging.PacketDropUnknownConnectionID:
- reason = "unknown_connection_id"
- case logging.PacketDropHeaderParseError:
- reason = "header_parse_error"
- case logging.PacketDropPayloadDecryptError:
- reason = "payload_decrypt_error"
- case logging.PacketDropProtocolViolation:
- reason = "protocol_violation"
- case logging.PacketDropDOSPrevention:
- reason = "dos_prevention"
- case logging.PacketDropUnsupportedVersion:
- reason = "unsupported_version"
- case logging.PacketDropUnexpectedPacket:
- reason = "unexpected_packet"
- case logging.PacketDropUnexpectedSourceConnectionID:
- reason = "unexpected_source_connection_id"
- case logging.PacketDropUnexpectedVersion:
- reason = "unexpected_version"
- case logging.PacketDropDuplicate:
- reason = "duplicate"
- default:
- reason = "unknown"
- }
- droppedPackets.WithLabelValues(m.getEncLevel(packetType), reason).Inc()
-}
-
-func (m *metricsConnTracer) UpdatedMetrics(rttStats *logging.RTTStats, cwnd, bytesInFlight logging.ByteCount, packetsInFlight int) {
- m.mutex.Lock()
- m.rtt = rttStats.SmoothedRTT()
- m.numRTTMeasurements++
- m.mutex.Unlock()
-}
-
-func (m *metricsConnTracer) LostPacket(level logging.EncryptionLevel, _ logging.PacketNumber, r logging.PacketLossReason) {
- var reason string
- switch r {
- case logging.PacketLossReorderingThreshold:
- reason = "reordering_threshold"
- case logging.PacketLossTimeThreshold:
- reason = "time_threshold"
- default:
- reason = "unknown"
- }
- lostPackets.WithLabelValues(level.String(), reason).Inc()
-}
-
-func (m *metricsConnTracer) DroppedEncryptionLevel(level logging.EncryptionLevel) {
- if level == logging.EncryptionHandshake {
- m.handleHandshakeComplete()
- }
-}
-
-func (m *metricsConnTracer) Close() {
- if m.handshakeComplete {
- closedConns.WithLabelValues(m.getDirection()).Inc()
- } else {
- newConns.WithLabelValues(m.getDirection(), "false").Inc()
- }
- collector.RemoveConn(m.connID.String())
-}
-
-func (m *metricsConnTracer) handleHandshakeComplete() {
- m.handshakeComplete = true
- newConns.WithLabelValues(m.getDirection(), "true").Inc()
-}
-
-func (m *metricsConnTracer) getSmoothedRTT() (rtt time.Duration, valid bool) {
- m.mutex.Lock()
- rtt = m.rtt
- valid = m.numRTTMeasurements > 10
- m.mutex.Unlock()
- return
-}
diff --git a/p2p/transport/quicreuse/tracer_test.go b/p2p/transport/quicreuse/tracer_test.go
index 5d1d74feef..3347c5f7c4 100644
--- a/p2p/transport/quicreuse/tracer_test.go
+++ b/p2p/transport/quicreuse/tracer_test.go
@@ -33,12 +33,12 @@ func TestSaveQlog(t *testing.T) {
qlogDir := createLogDir(t)
logger := newQlogger(qlogDir, logging.PerspectiveServer, quic.ConnectionIDFromBytes([]byte{0xde, 0xad, 0xbe, 0xef}))
file := getFile(t, qlogDir)
- require.Equal(t, string(file.Name()[0]), ".")
+ require.Equal(t, ".", string(file.Name()[0]))
require.Truef(t, strings.HasSuffix(file.Name(), ".qlog.swp"), "expected %s to have the .qlog.swp file ending", file.Name())
// close the logger. This should move the file.
require.NoError(t, logger.Close())
file = getFile(t, qlogDir)
- require.NotEqual(t, string(file.Name()[0]), ".")
+ require.NotEqual(t, ".", string(file.Name()[0]))
require.Truef(t, strings.HasSuffix(file.Name(), ".qlog.zst"), "expected %s to have the .qlog.zst file ending", file.Name())
require.Contains(t, file.Name(), "server")
require.Contains(t, file.Name(), "deadbeef")
@@ -66,10 +66,10 @@ func TestQlogCompression(t *testing.T) {
require.NoError(t, logger.Close())
compressed, err := os.ReadFile(qlogDir + "/" + getFile(t, qlogDir).Name())
require.NoError(t, err)
- require.NotEqual(t, compressed, "foobar")
+ require.NotEqual(t, "foobar", compressed)
c, err := zstd.NewReader(bytes.NewReader(compressed))
require.NoError(t, err)
data, err := io.ReadAll(c)
require.NoError(t, err)
- require.Equal(t, data, []byte("foobar"))
+ require.Equal(t, []byte("foobar"), data)
}
diff --git a/p2p/transport/tcp/metrics.go b/p2p/transport/tcp/metrics.go
index fc2add49bd..4434b037bf 100644
--- a/p2p/transport/tcp/metrics.go
+++ b/p2p/transport/tcp/metrics.go
@@ -1,4 +1,4 @@
-//go:build !windows
+//go:build !windows && !riscv64 && !loong64
package tcp
diff --git a/p2p/transport/tcp/metrics_general.go b/p2p/transport/tcp/metrics_general.go
index 6b67283448..419fff360e 100644
--- a/p2p/transport/tcp/metrics_general.go
+++ b/p2p/transport/tcp/metrics_general.go
@@ -1,4 +1,4 @@
-//go:build !linux && !darwin && !windows
+//go:build !linux && !darwin && !windows && !riscv64 && !loong64
package tcp
diff --git a/p2p/transport/tcp/metrics_windows.go b/p2p/transport/tcp/metrics_none.go
similarity index 68%
rename from p2p/transport/tcp/metrics_windows.go
rename to p2p/transport/tcp/metrics_none.go
index 7142e7dbe3..8538b30c89 100644
--- a/p2p/transport/tcp/metrics_windows.go
+++ b/p2p/transport/tcp/metrics_none.go
@@ -1,4 +1,6 @@
-//go:build windows
+// riscv64 see: https://github.com/marten-seemann/tcp/pull/1
+
+//go:build windows || riscv64 || loong64
package tcp
diff --git a/p2p/transport/tcp/tcp.go b/p2p/transport/tcp/tcp.go
index f277b3f8f3..d52bb96019 100644
--- a/p2p/transport/tcp/tcp.go
+++ b/p2p/transport/tcp/tcp.go
@@ -131,6 +131,7 @@ type TcpTransport struct {
}
var _ transport.Transport = &TcpTransport{}
+var _ transport.DialUpdater = &TcpTransport{}
// NewTCPTransport creates a tcp transport object that tracks dialers and listeners
// created. It represents an entire TCP stack (though it might not necessarily be).
@@ -176,13 +177,17 @@ func (t *TcpTransport) maDial(ctx context.Context, raddr ma.Multiaddr) (manet.Co
// Dial dials the peer at the remote address.
func (t *TcpTransport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID) (transport.CapableConn, error) {
+ return t.DialWithUpdates(ctx, raddr, p, nil)
+}
+
+func (t *TcpTransport) DialWithUpdates(ctx context.Context, raddr ma.Multiaddr, p peer.ID, updateChan chan<- transport.DialUpdate) (transport.CapableConn, error) {
connScope, err := t.rcmgr.OpenConnection(network.DirOutbound, true, raddr)
if err != nil {
log.Debugw("resource manager blocked outgoing connection", "peer", p, "addr", raddr, "error", err)
return nil, err
}
- c, err := t.dialWithScope(ctx, raddr, p, connScope)
+ c, err := t.dialWithScope(ctx, raddr, p, connScope, updateChan)
if err != nil {
connScope.Done()
return nil, err
@@ -190,7 +195,7 @@ func (t *TcpTransport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID)
return c, nil
}
-func (t *TcpTransport) dialWithScope(ctx context.Context, raddr ma.Multiaddr, p peer.ID, connScope network.ConnManagementScope) (transport.CapableConn, error) {
+func (t *TcpTransport) dialWithScope(ctx context.Context, raddr ma.Multiaddr, p peer.ID, connScope network.ConnManagementScope, updateChan chan<- transport.DialUpdate) (transport.CapableConn, error) {
if err := connScope.SetPeer(p); err != nil {
log.Debugw("resource manager blocked outgoing connection for peer", "peer", p, "addr", raddr, "error", err)
return nil, err
@@ -212,6 +217,13 @@ func (t *TcpTransport) dialWithScope(ctx context.Context, raddr ma.Multiaddr, p
return nil, err
}
}
+ if updateChan != nil {
+ select {
+ case updateChan <- transport.DialUpdate{Kind: transport.UpdateKindHandshakeProgressed, Addr: raddr}:
+ default:
+ // It is better to skip the update than to delay upgrading the connection
+ }
+ }
direction := network.DirOutbound
if ok, isClient, _ := network.GetSimultaneousConnect(ctx); ok && !isClient {
direction = network.DirInbound
diff --git a/p2p/transport/tcp/tcp_test.go b/p2p/transport/tcp/tcp_test.go
index 05b6cb9352..a57a65e420 100644
--- a/p2p/transport/tcp/tcp_test.go
+++ b/p2p/transport/tcp/tcp_test.go
@@ -16,9 +16,10 @@ import (
tptu "github.com/libp2p/go-libp2p/p2p/net/upgrader"
ttransport "github.com/libp2p/go-libp2p/p2p/transport/testsuite"
- "github.com/golang/mock/gomock"
ma "github.com/multiformats/go-multiaddr"
+ manet "github.com/multiformats/go-multiaddr/net"
"github.com/stretchr/testify/require"
+ "go.uber.org/mock/gomock"
)
var muxers = []tptu.StreamMuxer{{ID: "/yamux", Muxer: yamux.DefaultTransport}}
@@ -147,6 +148,54 @@ func TestTcpTransportCantListenUtp(t *testing.T) {
envReuseportVal = true
}
+func TestDialWithUpdates(t *testing.T) {
+ peerA, ia := makeInsecureMuxer(t)
+ _, ib := makeInsecureMuxer(t)
+
+ ua, err := tptu.New(ia, muxers, nil, nil, nil)
+ require.NoError(t, err)
+ ta, err := NewTCPTransport(ua, nil)
+ require.NoError(t, err)
+ ln, err := ta.Listen(ma.StringCast("/ip4/127.0.0.1/tcp/0"))
+ require.NoError(t, err)
+ defer ln.Close()
+
+ ub, err := tptu.New(ib, muxers, nil, nil, nil)
+ require.NoError(t, err)
+ tb, err := NewTCPTransport(ub, nil)
+ require.NoError(t, err)
+
+ updCh := make(chan transport.DialUpdate, 1)
+ conn, err := tb.DialWithUpdates(context.Background(), ln.Multiaddr(), peerA, updCh)
+ upd := <-updCh
+ require.Equal(t, transport.UpdateKindHandshakeProgressed, upd.Kind)
+ require.NotNil(t, conn)
+ require.NoError(t, err)
+
+ acceptAndClose := func() manet.Listener {
+ li, err := manet.Listen(ma.StringCast("/ip4/127.0.0.1/tcp/0"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ go func() {
+ conn, err := li.Accept()
+ if err != nil {
+ return
+ }
+ conn.Close()
+ }()
+ return li
+ }
+ li := acceptAndClose()
+ defer li.Close()
+ // This dial will fail as acceptAndClose will not upgrade the connection
+ conn, err = tb.DialWithUpdates(context.Background(), li.Multiaddr(), peerA, updCh)
+ upd = <-updCh
+ require.Equal(t, transport.UpdateKindHandshakeProgressed, upd.Kind)
+ require.Nil(t, conn)
+ require.Error(t, err)
+}
+
func makeInsecureMuxer(t *testing.T) (peer.ID, []sec.SecureTransport) {
t.Helper()
priv, _, err := crypto.GenerateKeyPair(crypto.Ed25519, 256)
diff --git a/p2p/transport/webrtc/connection.go b/p2p/transport/webrtc/connection.go
new file mode 100644
index 0000000000..cd28ec3203
--- /dev/null
+++ b/p2p/transport/webrtc/connection.go
@@ -0,0 +1,255 @@
+package libp2pwebrtc
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "math"
+ "net"
+ "sync"
+ "sync/atomic"
+
+ ic "github.com/libp2p/go-libp2p/core/crypto"
+ "github.com/libp2p/go-libp2p/core/network"
+ "github.com/libp2p/go-libp2p/core/peer"
+ tpt "github.com/libp2p/go-libp2p/core/transport"
+
+ ma "github.com/multiformats/go-multiaddr"
+ "github.com/pion/datachannel"
+ "github.com/pion/webrtc/v3"
+)
+
+var _ tpt.CapableConn = &connection{}
+
+const maxAcceptQueueLen = 256
+
+type errConnectionTimeout struct{}
+
+var _ net.Error = &errConnectionTimeout{}
+
+func (errConnectionTimeout) Error() string { return "connection timeout" }
+func (errConnectionTimeout) Timeout() bool { return true }
+func (errConnectionTimeout) Temporary() bool { return false }
+
+type dataChannel struct {
+ stream datachannel.ReadWriteCloser
+ channel *webrtc.DataChannel
+}
+
+type connection struct {
+ pc *webrtc.PeerConnection
+ transport *WebRTCTransport
+ scope network.ConnManagementScope
+
+ closeOnce sync.Once
+ closeErr error
+
+ localPeer peer.ID
+ localMultiaddr ma.Multiaddr
+
+ remotePeer peer.ID
+ remoteKey ic.PubKey
+ remoteMultiaddr ma.Multiaddr
+
+ m sync.Mutex
+ streams map[uint16]*stream
+ nextStreamID atomic.Int32
+
+ acceptQueue chan dataChannel
+
+ ctx context.Context
+ cancel context.CancelFunc
+}
+
+func newConnection(
+ direction network.Direction,
+ pc *webrtc.PeerConnection,
+ transport *WebRTCTransport,
+ scope network.ConnManagementScope,
+
+ localPeer peer.ID,
+ localMultiaddr ma.Multiaddr,
+
+ remotePeer peer.ID,
+ remoteKey ic.PubKey,
+ remoteMultiaddr ma.Multiaddr,
+ incomingDataChannels chan dataChannel,
+) (*connection, error) {
+ ctx, cancel := context.WithCancel(context.Background())
+ c := &connection{
+ pc: pc,
+ transport: transport,
+ scope: scope,
+
+ localPeer: localPeer,
+ localMultiaddr: localMultiaddr,
+
+ remotePeer: remotePeer,
+ remoteKey: remoteKey,
+ remoteMultiaddr: remoteMultiaddr,
+ ctx: ctx,
+ cancel: cancel,
+ streams: make(map[uint16]*stream),
+
+ acceptQueue: incomingDataChannels,
+ }
+ switch direction {
+ case network.DirInbound:
+ c.nextStreamID.Store(1)
+ case network.DirOutbound:
+ // stream ID 0 is used for the Noise handshake stream
+ c.nextStreamID.Store(2)
+ }
+
+ pc.OnConnectionStateChange(c.onConnectionStateChange)
+ return c, nil
+}
+
+// ConnState implements transport.CapableConn
+func (c *connection) ConnState() network.ConnectionState {
+ return network.ConnectionState{Transport: "webrtc-direct"}
+}
+
+// Close closes the underlying peerconnection.
+func (c *connection) Close() error {
+ c.closeOnce.Do(func() { c.closeWithError(errors.New("connection closed")) })
+ return nil
+}
+
+// closeWithError is used to Close the connection when the underlying DTLS connection fails
+func (c *connection) closeWithError(err error) {
+ c.closeErr = err
+ // cancel must be called after closeErr is set. This ensures interested goroutines waiting on
+ // ctx.Done can read closeErr without holding the conn lock.
+ c.cancel()
+ // closing peerconnection will close the datachannels associated with the streams
+ c.pc.Close()
+
+ c.m.Lock()
+ streams := c.streams
+ c.streams = nil
+ c.m.Unlock()
+ for _, s := range streams {
+ s.closeForShutdown(err)
+ }
+ c.scope.Done()
+}
+
+func (c *connection) IsClosed() bool {
+ return c.ctx.Err() != nil
+}
+
+func (c *connection) OpenStream(ctx context.Context) (network.MuxedStream, error) {
+ if c.IsClosed() {
+ return nil, c.closeErr
+ }
+
+ id := c.nextStreamID.Add(2) - 2
+ if id > math.MaxUint16 {
+ return nil, errors.New("exhausted stream ID space")
+ }
+ streamID := uint16(id)
+ dc, err := c.pc.CreateDataChannel("", &webrtc.DataChannelInit{ID: &streamID})
+ if err != nil {
+ return nil, err
+ }
+ rwc, err := c.detachChannel(ctx, dc)
+ if err != nil {
+ dc.Close()
+ return nil, fmt.Errorf("detach channel failed for stream(%d): %w", streamID, err)
+ }
+ str := newStream(dc, rwc, func() { c.removeStream(streamID) })
+ if err := c.addStream(str); err != nil {
+ str.Reset()
+ return nil, fmt.Errorf("failed to add stream(%d) to connection: %w", streamID, err)
+ }
+ return str, nil
+}
+
+func (c *connection) AcceptStream() (network.MuxedStream, error) {
+ select {
+ case <-c.ctx.Done():
+ return nil, c.closeErr
+ case dc := <-c.acceptQueue:
+ str := newStream(dc.channel, dc.stream, func() { c.removeStream(*dc.channel.ID()) })
+ if err := c.addStream(str); err != nil {
+ str.Reset()
+ return nil, err
+ }
+ return str, nil
+ }
+}
+
+func (c *connection) LocalPeer() peer.ID { return c.localPeer }
+func (c *connection) RemotePeer() peer.ID { return c.remotePeer }
+func (c *connection) RemotePublicKey() ic.PubKey { return c.remoteKey }
+func (c *connection) LocalMultiaddr() ma.Multiaddr { return c.localMultiaddr }
+func (c *connection) RemoteMultiaddr() ma.Multiaddr { return c.remoteMultiaddr }
+func (c *connection) Scope() network.ConnScope { return c.scope }
+func (c *connection) Transport() tpt.Transport { return c.transport }
+
+func (c *connection) addStream(str *stream) error {
+ c.m.Lock()
+ defer c.m.Unlock()
+ if c.streams == nil {
+ return c.closeErr
+ }
+ if _, ok := c.streams[str.id]; ok {
+ return errors.New("stream ID already exists")
+ }
+ c.streams[str.id] = str
+ return nil
+}
+
+func (c *connection) removeStream(id uint16) {
+ c.m.Lock()
+ defer c.m.Unlock()
+ delete(c.streams, id)
+}
+
+func (c *connection) onConnectionStateChange(state webrtc.PeerConnectionState) {
+ if state == webrtc.PeerConnectionStateFailed || state == webrtc.PeerConnectionStateClosed {
+ c.closeOnce.Do(func() {
+ c.closeWithError(errConnectionTimeout{})
+ })
+ }
+}
+
+// detachChannel detaches an outgoing channel by taking into account the context
+// passed to `OpenStream` as well the closure of the underlying peerconnection
+//
+// The underlying SCTP stream for a datachannel implements a net.Conn interface.
+// However, the datachannel creates a goroutine which continuously reads from
+// the SCTP stream and surfaces the data using an OnMessage callback.
+//
+// The actual abstractions are as follows: webrtc.DataChannel
+// wraps pion.DataChannel, which wraps sctp.Stream.
+//
+// The goroutine for reading, Detach method,
+// and the OnMessage callback are present at the webrtc.DataChannel level.
+// Detach provides us abstracted access to the underlying pion.DataChannel,
+// which allows us to issue Read calls to the datachannel.
+// This was desired because it was not feasible to introduce backpressure
+// with the OnMessage callbacks. The tradeoff is a change in the semantics of
+// the OnOpen callback, and having to force close Read locally.
+func (c *connection) detachChannel(ctx context.Context, dc *webrtc.DataChannel) (datachannel.ReadWriteCloser, error) {
+ done := make(chan struct{})
+
+ var rwc datachannel.ReadWriteCloser
+ var err error
+ // OnOpen will return immediately for detached datachannels
+ // refer: https://github.com/pion/webrtc/blob/7ab3174640b3ce15abebc2516a2ca3939b5f105f/datachannel.go#L278-L282
+ dc.OnOpen(func() {
+ rwc, err = dc.Detach()
+ // this is safe since the function should return instantly if the peerconnection is closed
+ close(done)
+ })
+ select {
+ case <-c.ctx.Done():
+ return nil, c.closeErr
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ case <-done:
+ return rwc, err
+ }
+}
diff --git a/p2p/transport/webrtc/fingerprint.go b/p2p/transport/webrtc/fingerprint.go
new file mode 100644
index 0000000000..fd715865a8
--- /dev/null
+++ b/p2p/transport/webrtc/fingerprint.go
@@ -0,0 +1,53 @@
+package libp2pwebrtc
+
+import (
+ "crypto"
+ "crypto/x509"
+ "errors"
+
+ ma "github.com/multiformats/go-multiaddr"
+ "github.com/multiformats/go-multibase"
+ mh "github.com/multiformats/go-multihash"
+ "github.com/pion/webrtc/v3"
+)
+
+// parseFingerprint is forked from pion to avoid bytes to string alloc,
+// and to avoid the entire hex interspersing when we do not need it anyway
+
+var errHashUnavailable = errors.New("fingerprint: hash algorithm is not linked into the binary")
+
+// parseFingerprint creates a fingerprint for a certificate using the specified hash algorithm
+func parseFingerprint(cert *x509.Certificate, algo crypto.Hash) ([]byte, error) {
+ if !algo.Available() {
+ return nil, errHashUnavailable
+ }
+ h := algo.New()
+ // Hash.Writer is specified to be never returning an error.
+ // https://golang.org/pkg/hash/#Hash
+ h.Write(cert.Raw)
+ return h.Sum(nil), nil
+}
+
+func decodeRemoteFingerprint(maddr ma.Multiaddr) (*mh.DecodedMultihash, error) {
+ remoteFingerprintMultibase, err := maddr.ValueForProtocol(ma.P_CERTHASH)
+ if err != nil {
+ return nil, err
+ }
+ _, data, err := multibase.Decode(remoteFingerprintMultibase)
+ if err != nil {
+ return nil, err
+ }
+ return mh.Decode(data)
+}
+
+func encodeDTLSFingerprint(fp webrtc.DTLSFingerprint) (string, error) {
+ digest, err := decodeInterspersedHexFromASCIIString(fp.Value)
+ if err != nil {
+ return "", err
+ }
+ encoded, err := mh.Encode(digest, mh.SHA2_256)
+ if err != nil {
+ return "", err
+ }
+ return multibase.Encode(multibase.Base64url, encoded)
+}
diff --git a/p2p/transport/webrtc/hex.go b/p2p/transport/webrtc/hex.go
new file mode 100644
index 0000000000..482036540a
--- /dev/null
+++ b/p2p/transport/webrtc/hex.go
@@ -0,0 +1,70 @@
+package libp2pwebrtc
+
+// The code in this file is adapted from the Go standard library's hex package.
+// As found in https://cs.opensource.google/go/go/+/refs/tags/go1.20.2:src/encoding/hex/hex.go
+//
+// The reason we adapted the original code is to allow us to deal with interspersed requirements
+// while at the same time hex encoding/decoding, without having to do so in two passes.
+
+import (
+ "encoding/hex"
+ "errors"
+)
+
+// encodeInterspersedHex encodes a byte slice into a string of hex characters,
+// separating each encoded byte with a colon (':').
+//
+// Example: { 0x01, 0x02, 0x03 } -> "01:02:03"
+func encodeInterspersedHex(src []byte) string {
+ if len(src) == 0 {
+ return ""
+ }
+ s := hex.EncodeToString(src)
+ n := len(s)
+ // Determine number of colons
+ colons := n / 2
+ if n%2 == 0 {
+ colons--
+ }
+ buffer := make([]byte, n+colons)
+
+ for i, j := 0, 0; i < n; i, j = i+2, j+3 {
+ copy(buffer[j:j+2], s[i:i+2])
+ if j+3 < len(buffer) {
+ buffer[j+2] = ':'
+ }
+ }
+ return string(buffer)
+}
+
+var errUnexpectedIntersperseHexChar = errors.New("unexpected character in interspersed hex string")
+
+// decodeInterspersedHexFromASCIIString decodes an ASCII string of hex characters into a byte slice,
+// where the hex characters are expected to be separated by a colon (':').
+//
+// NOTE that this function returns an error in case the input string contains non-ASCII characters.
+//
+// Example: "01:02:03" -> { 0x01, 0x02, 0x03 }
+func decodeInterspersedHexFromASCIIString(s string) ([]byte, error) {
+ n := len(s)
+ buffer := make([]byte, n/3*2+n%3)
+ j := 0
+ for i := 0; i < n; i++ {
+ if i%3 == 2 {
+ if s[i] != ':' {
+ return nil, errUnexpectedIntersperseHexChar
+ }
+ } else {
+ if s[i] == ':' {
+ return nil, errUnexpectedIntersperseHexChar
+ }
+ buffer[j] = s[i]
+ j++
+ }
+ }
+ dst := make([]byte, hex.DecodedLen(len(buffer)))
+ if _, err := hex.Decode(dst, buffer); err != nil {
+ return nil, err
+ }
+ return dst, nil
+}
diff --git a/p2p/transport/webrtc/hex_test.go b/p2p/transport/webrtc/hex_test.go
new file mode 100644
index 0000000000..c8a7147498
--- /dev/null
+++ b/p2p/transport/webrtc/hex_test.go
@@ -0,0 +1,132 @@
+package libp2pwebrtc
+
+import (
+ "encoding/hex"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestEncodeInterspersedHex(t *testing.T) {
+ b, err := hex.DecodeString("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
+ require.NoError(t, err)
+ require.Equal(t, "ba:78:16:bf:8f:01:cf:ea:41:41:40:de:5d:ae:22:23:b0:03:61:a3:96:17:7a:9c:b4:10:ff:61:f2:00:15:ad", encodeInterspersedHex(b))
+}
+
+func BenchmarkEncodeInterspersedHex(b *testing.B) {
+ data, err := hex.DecodeString("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
+ require.NoError(b, err)
+
+ for i := 0; i < b.N; i++ {
+ encodeInterspersedHex(data)
+ }
+}
+
+func TestDecodeInterpersedHexStringLowerCase(t *testing.T) {
+ b, err := decodeInterspersedHexFromASCIIString("ba:78:16:bf:8f:01:cf:ea:41:41:40:de:5d:ae:22:23:b0:03:61:a3:96:17:7a:9c:b4:10:ff:61:f2:00:15:ad")
+ require.NoError(t, err)
+ require.Equal(t, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", hex.EncodeToString(b))
+}
+
+func TestDecodeInterpersedHexStringMixedCase(t *testing.T) {
+ b, err := decodeInterspersedHexFromASCIIString("Ba:78:16:BF:8F:01:cf:ea:41:41:40:De:5d:ae:22:23:b0:03:61:a3:96:17:7a:9c:b4:10:FF:61:f2:00:15:ad")
+ require.NoError(t, err)
+ require.Equal(t, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", hex.EncodeToString(b))
+}
+
+func TestDecodeInterpersedHexStringOneByte(t *testing.T) {
+ b, err := decodeInterspersedHexFromASCIIString("ba")
+ require.NoError(t, err)
+ require.Equal(t, "ba", hex.EncodeToString(b))
+}
+
+func TestDecodeInterpersedHexBytesLowerCase(t *testing.T) {
+ b, err := decodeInterspersedHexFromASCIIString("ba:78:16:bf:8f:01:cf:ea:41:41:40:de:5d:ae:22:23:b0:03:61:a3:96:17:7a:9c:b4:10:ff:61:f2:00:15:ad")
+ require.NoError(t, err)
+ require.Equal(t, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", hex.EncodeToString(b))
+}
+
+func BenchmarkDecode(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ _, err := decodeInterspersedHexFromASCIIString("ba:78:16:bf:8f:01:cf:ea:41:41:40:de:5d:ae:22:23:b0:03:61:a3:96:17:7a:9c:b4:10:ff:61:f2:00:15:ad")
+ require.NoError(b, err)
+ }
+}
+
+func TestDecodeInterpersedHexBytesMixedCase(t *testing.T) {
+ b, err := decodeInterspersedHexFromASCIIString("Ba:78:16:BF:8F:01:cf:ea:41:41:40:De:5d:ae:22:23:b0:03:61:a3:96:17:7a:9c:b4:10:FF:61:f2:00:15:ad")
+ require.NoError(t, err)
+ require.Equal(t, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", hex.EncodeToString(b))
+}
+
+func TestDecodeInterpersedHexBytesOneByte(t *testing.T) {
+ b, err := decodeInterspersedHexFromASCIIString("ba")
+ require.NoError(t, err)
+ require.Equal(t, "ba", hex.EncodeToString(b))
+}
+
+func TestEncodeInterperseHexNilSlice(t *testing.T) {
+ require.Equal(t, "", encodeInterspersedHex(nil))
+ require.Equal(t, "", encodeInterspersedHex([]byte{}))
+}
+
+func TestDecodeInterspersedHexEmpty(t *testing.T) {
+ b, err := decodeInterspersedHexFromASCIIString("")
+ require.NoError(t, err)
+ require.Equal(t, []byte{}, b)
+}
+
+func TestDecodeInterpersedHexFromASCIIStringEmpty(t *testing.T) {
+ b, err := decodeInterspersedHexFromASCIIString("")
+ require.NoError(t, err)
+ require.Equal(t, []byte{}, b)
+}
+
+func TestDecodeInterpersedHexInvalid(t *testing.T) {
+ for _, v := range []string{"0", "0000", "000"} {
+ _, err := decodeInterspersedHexFromASCIIString(v)
+ require.Error(t, err)
+ }
+}
+
+func TestDecodeInterpersedHexValid(t *testing.T) {
+ b, err := decodeInterspersedHexFromASCIIString("00")
+ require.NoError(t, err)
+ require.Equal(t, []byte{0}, b)
+}
+
+func TestDecodeInterpersedHexFromASCIIStringInvalid(t *testing.T) {
+ for _, v := range []string{"0", "0000", "000"} {
+ _, err := decodeInterspersedHexFromASCIIString(v)
+ require.Error(t, err)
+ }
+}
+
+func TestDecodeInterpersedHexFromASCIIStringValid(t *testing.T) {
+ b, err := decodeInterspersedHexFromASCIIString("00")
+ require.NoError(t, err)
+ require.Equal(t, []byte{0}, b)
+}
+
+func FuzzInterpersedHex(f *testing.F) {
+ f.Fuzz(func(t *testing.T, b []byte) {
+ decoded, err := decodeInterspersedHexFromASCIIString(string(b))
+ if err != nil {
+ return
+ }
+ encoded := encodeInterspersedHex(decoded)
+ require.Equal(t, strings.ToLower(string(b)), encoded)
+ })
+}
+
+func FuzzInterspersedHexASCII(f *testing.F) {
+ f.Fuzz(func(t *testing.T, s string) {
+ decoded, err := decodeInterspersedHexFromASCIIString(s)
+ if err != nil {
+ return
+ }
+ encoded := encodeInterspersedHex(decoded)
+ require.Equal(t, strings.ToLower(s), encoded)
+ })
+}
diff --git a/p2p/transport/webrtc/listener.go b/p2p/transport/webrtc/listener.go
new file mode 100644
index 0000000000..13fdcab05e
--- /dev/null
+++ b/p2p/transport/webrtc/listener.go
@@ -0,0 +1,342 @@
+package libp2pwebrtc
+
+import (
+ "context"
+ "crypto"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "net"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/libp2p/go-libp2p/core/network"
+ "github.com/libp2p/go-libp2p/core/peer"
+ tpt "github.com/libp2p/go-libp2p/core/transport"
+ "github.com/libp2p/go-libp2p/p2p/transport/webrtc/udpmux"
+
+ ma "github.com/multiformats/go-multiaddr"
+ manet "github.com/multiformats/go-multiaddr/net"
+ "github.com/multiformats/go-multibase"
+ "github.com/multiformats/go-multihash"
+ "github.com/pion/webrtc/v3"
+)
+
+type connMultiaddrs struct {
+ local, remote ma.Multiaddr
+}
+
+var _ network.ConnMultiaddrs = &connMultiaddrs{}
+
+func (c *connMultiaddrs) LocalMultiaddr() ma.Multiaddr { return c.local }
+func (c *connMultiaddrs) RemoteMultiaddr() ma.Multiaddr { return c.remote }
+
+const (
+ candidateSetupTimeout = 20 * time.Second
+ DefaultMaxInFlightConnections = 10
+)
+
+type listener struct {
+ transport *WebRTCTransport
+
+ mux *udpmux.UDPMux
+
+ config webrtc.Configuration
+ localFingerprint webrtc.DTLSFingerprint
+ localFingerprintMultibase string
+
+ localAddr net.Addr
+ localMultiaddr ma.Multiaddr
+
+ // buffered incoming connections
+ acceptQueue chan tpt.CapableConn
+
+ // used to control the lifecycle of the listener
+ ctx context.Context
+ cancel context.CancelFunc
+ wg sync.WaitGroup
+}
+
+var _ tpt.Listener = &listener{}
+
+func newListener(transport *WebRTCTransport, laddr ma.Multiaddr, socket net.PacketConn, config webrtc.Configuration) (*listener, error) {
+ localFingerprints, err := config.Certificates[0].GetFingerprints()
+ if err != nil {
+ return nil, err
+ }
+
+ localMh, err := hex.DecodeString(strings.ReplaceAll(localFingerprints[0].Value, ":", ""))
+ if err != nil {
+ return nil, err
+ }
+ localMhBuf, err := multihash.Encode(localMh, multihash.SHA2_256)
+ if err != nil {
+ return nil, err
+ }
+ localFpMultibase, err := multibase.Encode(multibase.Base64url, localMhBuf)
+ if err != nil {
+ return nil, err
+ }
+
+ l := &listener{
+ transport: transport,
+ config: config,
+ localFingerprint: localFingerprints[0],
+ localFingerprintMultibase: localFpMultibase,
+ localMultiaddr: laddr,
+ localAddr: socket.LocalAddr(),
+ acceptQueue: make(chan tpt.CapableConn),
+ }
+
+ l.ctx, l.cancel = context.WithCancel(context.Background())
+ l.mux = udpmux.NewUDPMux(socket)
+ l.mux.Start()
+
+ l.wg.Add(1)
+ go func() {
+ defer l.wg.Done()
+ l.listen()
+ }()
+
+ return l, err
+}
+
+func (l *listener) listen() {
+ // Accepting a connection requires instantiating a peerconnection and a noise connection
+ // which is expensive. We therefore limit the number of in-flight connection requests. A
+ // connection is considered to be in flight from the instant it is handled until it is
+ // dequeued by a call to Accept, or errors out in some way.
+ inFlightSemaphore := make(chan struct{}, l.transport.maxInFlightConnections)
+ for {
+ select {
+ case inFlightSemaphore <- struct{}{}:
+ case <-l.ctx.Done():
+ return
+ }
+
+ candidate, err := l.mux.Accept(l.ctx)
+ if err != nil {
+ if l.ctx.Err() == nil {
+ log.Debugf("accepting candidate failed: %s", err)
+ }
+ return
+ }
+
+ go func() {
+ defer func() { <-inFlightSemaphore }()
+
+ ctx, cancel := context.WithTimeout(l.ctx, candidateSetupTimeout)
+ defer cancel()
+
+ conn, err := l.handleCandidate(ctx, candidate)
+ if err != nil {
+ l.mux.RemoveConnByUfrag(candidate.Ufrag)
+ log.Debugf("could not accept connection: %s: %v", candidate.Ufrag, err)
+ return
+ }
+
+ select {
+ case <-ctx.Done():
+ log.Warn("could not push connection: ctx done")
+ conn.Close()
+ case l.acceptQueue <- conn:
+ // acceptQueue is an unbuffered channel, so this blocks until the connection is accepted.
+ }
+ }()
+ }
+}
+
+func (l *listener) handleCandidate(ctx context.Context, candidate udpmux.Candidate) (tpt.CapableConn, error) {
+ remoteMultiaddr, err := manet.FromNetAddr(candidate.Addr)
+ if err != nil {
+ return nil, err
+ }
+ if l.transport.gater != nil {
+ localAddr, _ := ma.SplitFunc(l.localMultiaddr, func(c ma.Component) bool { return c.Protocol().Code == ma.P_CERTHASH })
+ if !l.transport.gater.InterceptAccept(&connMultiaddrs{local: localAddr, remote: remoteMultiaddr}) {
+ // The connection attempt is rejected before we can send the client an error.
+ // This means that the connection attempt will time out.
+ return nil, errors.New("connection gated")
+ }
+ }
+ scope, err := l.transport.rcmgr.OpenConnection(network.DirInbound, false, remoteMultiaddr)
+ if err != nil {
+ return nil, err
+ }
+ conn, err := l.setupConnection(ctx, scope, remoteMultiaddr, candidate)
+ if err != nil {
+ scope.Done()
+ return nil, err
+ }
+ if l.transport.gater != nil && !l.transport.gater.InterceptSecured(network.DirInbound, conn.RemotePeer(), conn) {
+ conn.Close()
+ return nil, errors.New("connection gated")
+ }
+ return conn, nil
+}
+
+func (l *listener) setupConnection(
+ ctx context.Context, scope network.ConnManagementScope,
+ remoteMultiaddr ma.Multiaddr, candidate udpmux.Candidate,
+) (tConn tpt.CapableConn, err error) {
+ var w webRTCConnection
+ defer func() {
+ if err != nil {
+ if w.PeerConnection != nil {
+ _ = w.PeerConnection.Close()
+ }
+ if tConn != nil {
+ _ = tConn.Close()
+ }
+ }
+ }()
+
+ settingEngine := webrtc.SettingEngine{LoggerFactory: pionLoggerFactory}
+ settingEngine.SetAnsweringDTLSRole(webrtc.DTLSRoleServer)
+ settingEngine.SetICECredentials(candidate.Ufrag, candidate.Ufrag)
+ settingEngine.SetLite(true)
+ settingEngine.SetICEUDPMux(l.mux)
+ settingEngine.SetIncludeLoopbackCandidate(true)
+ settingEngine.DisableCertificateFingerprintVerification(true)
+ settingEngine.SetICETimeouts(
+ l.transport.peerConnectionTimeouts.Disconnect,
+ l.transport.peerConnectionTimeouts.Failed,
+ l.transport.peerConnectionTimeouts.Keepalive,
+ )
+ settingEngine.DetachDataChannels()
+
+ w, err = newWebRTCConnection(settingEngine, l.config)
+ if err != nil {
+ return nil, fmt.Errorf("instantiating peer connection failed: %w", err)
+ }
+
+ errC := addOnConnectionStateChangeCallback(w.PeerConnection)
+ // Infer the client SDP from the incoming STUN message by setting the ice-ufrag.
+ if err := w.PeerConnection.SetRemoteDescription(webrtc.SessionDescription{
+ SDP: createClientSDP(candidate.Addr, candidate.Ufrag),
+ Type: webrtc.SDPTypeOffer,
+ }); err != nil {
+ return nil, err
+ }
+ answer, err := w.PeerConnection.CreateAnswer(nil)
+ if err != nil {
+ return nil, err
+ }
+ if err := w.PeerConnection.SetLocalDescription(answer); err != nil {
+ return nil, err
+ }
+
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ case err := <-errC:
+ if err != nil {
+ return nil, fmt.Errorf("peer connection failed for ufrag: %s", candidate.Ufrag)
+ }
+ }
+
+ // Run the noise handshake.
+ rwc, err := detachHandshakeDataChannel(ctx, w.HandshakeDataChannel)
+ if err != nil {
+ return nil, err
+ }
+ handshakeChannel := newStream(w.HandshakeDataChannel, rwc, func() {})
+ // we do not yet know A's peer ID so accept any inbound
+ remotePubKey, err := l.transport.noiseHandshake(ctx, w.PeerConnection, handshakeChannel, "", crypto.SHA256, true)
+ if err != nil {
+ return nil, err
+ }
+ remotePeer, err := peer.IDFromPublicKey(remotePubKey)
+ if err != nil {
+ return nil, err
+ }
+ // earliest point where we know the remote's peerID
+ if err := scope.SetPeer(remotePeer); err != nil {
+ return nil, err
+ }
+
+ localMultiaddrWithoutCerthash, _ := ma.SplitFunc(l.localMultiaddr, func(c ma.Component) bool { return c.Protocol().Code == ma.P_CERTHASH })
+ conn, err := newConnection(
+ network.DirInbound,
+ w.PeerConnection,
+ l.transport,
+ scope,
+ l.transport.localPeerId,
+ localMultiaddrWithoutCerthash,
+ remotePeer,
+ remotePubKey,
+ remoteMultiaddr,
+ w.IncomingDataChannels,
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ return conn, err
+}
+
+func (l *listener) Accept() (tpt.CapableConn, error) {
+ select {
+ case <-l.ctx.Done():
+ return nil, tpt.ErrListenerClosed
+ case conn := <-l.acceptQueue:
+ return conn, nil
+ }
+}
+
+func (l *listener) Close() error {
+ select {
+ case <-l.ctx.Done():
+ default:
+ }
+ l.cancel()
+ l.mux.Close()
+ l.wg.Wait()
+loop:
+ for {
+ select {
+ case conn := <-l.acceptQueue:
+ conn.Close()
+ default:
+ break loop
+ }
+ }
+ return nil
+}
+
+func (l *listener) Addr() net.Addr {
+ return l.localAddr
+}
+
+func (l *listener) Multiaddr() ma.Multiaddr {
+ return l.localMultiaddr
+}
+
+// addOnConnectionStateChangeCallback adds the OnConnectionStateChange to the PeerConnection.
+// The channel returned here:
+// * is closed when the state changes to Connection
+// * receives an error when the state changes to Failed
+// * doesn't receive anything (nor is closed) when the state changes to Disconnected
+func addOnConnectionStateChangeCallback(pc *webrtc.PeerConnection) <-chan error {
+ errC := make(chan error, 1)
+ var once sync.Once
+ pc.OnConnectionStateChange(func(state webrtc.PeerConnectionState) {
+ switch state {
+ case webrtc.PeerConnectionStateConnected:
+ once.Do(func() { close(errC) })
+ case webrtc.PeerConnectionStateFailed:
+ once.Do(func() {
+ errC <- errors.New("peerconnection failed")
+ close(errC)
+ })
+ case webrtc.PeerConnectionStateDisconnected:
+ // the connection can move to a disconnected state and back to a connected state without ICE renegotiation.
+ // This could happen when underlying UDP packets are lost, and therefore the connection moves to the disconnected state.
+ // If the connection then receives packets on the connection, it can move back to the connected state.
+ // If no packets are received until the failed timeout is triggered, the connection moves to the failed state.
+ log.Warn("peerconnection disconnected")
+ }
+ })
+ return errC
+}
diff --git a/p2p/transport/webrtc/logger.go b/p2p/transport/webrtc/logger.go
new file mode 100644
index 0000000000..ac9fab7672
--- /dev/null
+++ b/p2p/transport/webrtc/logger.go
@@ -0,0 +1,58 @@
+package libp2pwebrtc
+
+import (
+ logging "github.com/ipfs/go-log/v2"
+ pionLogging "github.com/pion/logging"
+)
+
+var log = logging.Logger("webrtc-transport")
+
+// pionLog is the logger provided to pion for internal logging
+var pionLog = logging.Logger("webrtc-transport-pion")
+
+// pionLogger wraps the StandardLogger interface to provide a LeveledLogger interface
+// as expected by pion
+type pionLogger struct {
+ logging.StandardLogger
+}
+
+var pLog = pionLogger{pionLog}
+
+var _ pionLogging.LeveledLogger = pLog
+
+func (l pionLogger) Debug(s string) {
+ l.StandardLogger.Debug(s)
+}
+
+func (l pionLogger) Error(s string) {
+ l.StandardLogger.Error(s)
+}
+
+func (l pionLogger) Info(s string) {
+ l.StandardLogger.Info(s)
+}
+func (l pionLogger) Warn(s string) {
+ l.StandardLogger.Warn(s)
+}
+
+func (l pionLogger) Trace(s string) {
+ l.StandardLogger.Debug(s)
+}
+
+func (l pionLogger) Tracef(s string, args ...interface{}) {
+ l.StandardLogger.Debugf(s, args...)
+}
+
+// loggerFactory returns pLog for all new logger instances
+type loggerFactory struct{}
+
+// NewLogger returns pLog for all new logger instances. Internally pion creates lots of
+// separate logging objects unnecessarily. To avoid the allocations we use a single log
+// object for all of pion logging.
+func (loggerFactory) NewLogger(scope string) pionLogging.LeveledLogger {
+ return pLog
+}
+
+var _ pionLogging.LoggerFactory = loggerFactory{}
+
+var pionLoggerFactory = loggerFactory{}
diff --git a/p2p/transport/webrtc/message.go b/p2p/transport/webrtc/message.go
new file mode 100644
index 0000000000..8b57fc8078
--- /dev/null
+++ b/p2p/transport/webrtc/message.go
@@ -0,0 +1,3 @@
+package libp2pwebrtc
+
+//go:generate protoc --go_out=. --go_opt=Mpb/message.proto=./pb pb/message.proto
diff --git a/p2p/transport/webrtc/pb/generate.go b/p2p/transport/webrtc/pb/generate.go
new file mode 100644
index 0000000000..5785a95251
--- /dev/null
+++ b/p2p/transport/webrtc/pb/generate.go
@@ -0,0 +1,3 @@
+package pb
+
+//go:generate protoc --go_out=. --go_opt=paths=source_relative -I . message.proto
diff --git a/p2p/transport/webrtc/pb/message.pb.go b/p2p/transport/webrtc/pb/message.pb.go
new file mode 100644
index 0000000000..384bddd289
--- /dev/null
+++ b/p2p/transport/webrtc/pb/message.pb.go
@@ -0,0 +1,231 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
+// source: message.proto
+
+package pb
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type Message_Flag int32
+
+const (
+ // The sender will no longer send messages on the stream.
+ Message_FIN Message_Flag = 0
+ // The sender will no longer read messages on the stream. Incoming data is
+ // being discarded on receipt.
+ Message_STOP_SENDING Message_Flag = 1
+ // The sender abruptly terminates the sending part of the stream. The
+ // receiver can discard any data that it already received on that stream.
+ Message_RESET Message_Flag = 2
+ // Sending the FIN_ACK flag acknowledges the previous receipt of a message
+ // with the FIN flag set. Receiving a FIN_ACK flag gives the recipient
+ // confidence that the remote has received all sent messages.
+ Message_FIN_ACK Message_Flag = 3
+)
+
+// Enum value maps for Message_Flag.
+var (
+ Message_Flag_name = map[int32]string{
+ 0: "FIN",
+ 1: "STOP_SENDING",
+ 2: "RESET",
+ 3: "FIN_ACK",
+ }
+ Message_Flag_value = map[string]int32{
+ "FIN": 0,
+ "STOP_SENDING": 1,
+ "RESET": 2,
+ "FIN_ACK": 3,
+ }
+)
+
+func (x Message_Flag) Enum() *Message_Flag {
+ p := new(Message_Flag)
+ *p = x
+ return p
+}
+
+func (x Message_Flag) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (Message_Flag) Descriptor() protoreflect.EnumDescriptor {
+ return file_message_proto_enumTypes[0].Descriptor()
+}
+
+func (Message_Flag) Type() protoreflect.EnumType {
+ return &file_message_proto_enumTypes[0]
+}
+
+func (x Message_Flag) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *Message_Flag) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = Message_Flag(num)
+ return nil
+}
+
+// Deprecated: Use Message_Flag.Descriptor instead.
+func (Message_Flag) EnumDescriptor() ([]byte, []int) {
+ return file_message_proto_rawDescGZIP(), []int{0, 0}
+}
+
+type Message struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Flag *Message_Flag `protobuf:"varint,1,opt,name=flag,enum=Message_Flag" json:"flag,omitempty"`
+ Message []byte `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
+}
+
+func (x *Message) Reset() {
+ *x = Message{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_message_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Message) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Message) ProtoMessage() {}
+
+func (x *Message) ProtoReflect() protoreflect.Message {
+ mi := &file_message_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Message.ProtoReflect.Descriptor instead.
+func (*Message) Descriptor() ([]byte, []int) {
+ return file_message_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Message) GetFlag() Message_Flag {
+ if x != nil && x.Flag != nil {
+ return *x.Flag
+ }
+ return Message_FIN
+}
+
+func (x *Message) GetMessage() []byte {
+ if x != nil {
+ return x.Message
+ }
+ return nil
+}
+
+var File_message_proto protoreflect.FileDescriptor
+
+var file_message_proto_rawDesc = []byte{
+ 0x0a, 0x0d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
+ 0x81, 0x01, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x21, 0x0a, 0x04, 0x66,
+ 0x6c, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x2e, 0x46, 0x6c, 0x61, 0x67, 0x52, 0x04, 0x66, 0x6c, 0x61, 0x67, 0x12, 0x18,
+ 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52,
+ 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x39, 0x0a, 0x04, 0x46, 0x6c, 0x61, 0x67,
+ 0x12, 0x07, 0x0a, 0x03, 0x46, 0x49, 0x4e, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x4f,
+ 0x50, 0x5f, 0x53, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x52,
+ 0x45, 0x53, 0x45, 0x54, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x49, 0x4e, 0x5f, 0x41, 0x43,
+ 0x4b, 0x10, 0x03, 0x42, 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x2f, 0x6c, 0x69, 0x62, 0x70, 0x32, 0x70, 0x2f, 0x67, 0x6f, 0x2d, 0x6c, 0x69, 0x62, 0x70,
+ 0x32, 0x70, 0x2f, 0x70, 0x32, 0x70, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74,
+ 0x2f, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, 0x2f, 0x70, 0x62,
+}
+
+var (
+ file_message_proto_rawDescOnce sync.Once
+ file_message_proto_rawDescData = file_message_proto_rawDesc
+)
+
+func file_message_proto_rawDescGZIP() []byte {
+ file_message_proto_rawDescOnce.Do(func() {
+ file_message_proto_rawDescData = protoimpl.X.CompressGZIP(file_message_proto_rawDescData)
+ })
+ return file_message_proto_rawDescData
+}
+
+var file_message_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
+var file_message_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_message_proto_goTypes = []interface{}{
+ (Message_Flag)(0), // 0: Message.Flag
+ (*Message)(nil), // 1: Message
+}
+var file_message_proto_depIdxs = []int32{
+ 0, // 0: Message.flag:type_name -> Message.Flag
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_message_proto_init() }
+func file_message_proto_init() {
+ if File_message_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_message_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Message); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_message_proto_rawDesc,
+ NumEnums: 1,
+ NumMessages: 1,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_message_proto_goTypes,
+ DependencyIndexes: file_message_proto_depIdxs,
+ EnumInfos: file_message_proto_enumTypes,
+ MessageInfos: file_message_proto_msgTypes,
+ }.Build()
+ File_message_proto = out.File
+ file_message_proto_rawDesc = nil
+ file_message_proto_goTypes = nil
+ file_message_proto_depIdxs = nil
+}
diff --git a/p2p/transport/webrtc/pb/message.proto b/p2p/transport/webrtc/pb/message.proto
new file mode 100644
index 0000000000..aab885b0da
--- /dev/null
+++ b/p2p/transport/webrtc/pb/message.proto
@@ -0,0 +1,24 @@
+syntax = "proto2";
+
+option go_package = "github.com/libp2p/go-libp2p/p2p/transport/webrtc/pb";
+
+message Message {
+ enum Flag {
+ // The sender will no longer send messages on the stream.
+ FIN = 0;
+ // The sender will no longer read messages on the stream. Incoming data is
+ // being discarded on receipt.
+ STOP_SENDING = 1;
+ // The sender abruptly terminates the sending part of the stream. The
+ // receiver can discard any data that it already received on that stream.
+ RESET = 2;
+ // Sending the FIN_ACK flag acknowledges the previous receipt of a message
+ // with the FIN flag set. Receiving a FIN_ACK flag gives the recipient
+ // confidence that the remote has received all sent messages.
+ FIN_ACK = 3;
+ }
+
+ optional Flag flag=1;
+
+ optional bytes message = 2;
+}
diff --git a/p2p/transport/webrtc/sdp.go b/p2p/transport/webrtc/sdp.go
new file mode 100644
index 0000000000..878b668a18
--- /dev/null
+++ b/p2p/transport/webrtc/sdp.go
@@ -0,0 +1,143 @@
+package libp2pwebrtc
+
+import (
+ "crypto"
+ "fmt"
+ "net"
+ "strings"
+
+ "github.com/multiformats/go-multihash"
+)
+
+// clientSDP describes an SDP format string which can be used
+// to infer a client's SDP offer from the incoming STUN message.
+// The fingerprint used to render a client SDP is arbitrary since
+// it fingerprint verification is disabled in favour of a noise
+// handshake. The max message size is fixed to 16384 bytes.
+const clientSDP = `v=0
+o=- 0 0 IN %[1]s %[2]s
+s=-
+c=IN %[1]s %[2]s
+t=0 0
+
+m=application %[3]d UDP/DTLS/SCTP webrtc-datachannel
+a=mid:0
+a=ice-options:ice2
+a=ice-ufrag:%[4]s
+a=ice-pwd:%[4]s
+a=fingerprint:sha-256 ba:78:16:bf:8f:01:cf:ea:41:41:40:de:5d:ae:22:23:b0:03:61:a3:96:17:7a:9c:b4:10:ff:61:f2:00:15:ad
+a=setup:actpass
+a=sctp-port:5000
+a=max-message-size:16384
+`
+
+func createClientSDP(addr *net.UDPAddr, ufrag string) string {
+ ipVersion := "IP4"
+ if addr.IP.To4() == nil {
+ ipVersion = "IP6"
+ }
+ return fmt.Sprintf(
+ clientSDP,
+ ipVersion,
+ addr.IP,
+ addr.Port,
+ ufrag,
+ )
+}
+
+// serverSDP defines an SDP format string used by a dialer
+// to infer the SDP answer of a server based on the provided
+// multiaddr, and the locally set ICE credentials. The max
+// message size is fixed to 16384 bytes.
+const serverSDP = `v=0
+o=- 0 0 IN %[1]s %[2]s
+s=-
+t=0 0
+a=ice-lite
+m=application %[3]d UDP/DTLS/SCTP webrtc-datachannel
+c=IN %[1]s %[2]s
+a=mid:0
+a=ice-options:ice2
+a=ice-ufrag:%[4]s
+a=ice-pwd:%[4]s
+a=fingerprint:%[5]s
+
+a=setup:passive
+a=sctp-port:5000
+a=max-message-size:16384
+a=candidate:1 1 UDP 1 %[2]s %[3]d typ host
+a=end-of-candidates
+`
+
+func createServerSDP(addr *net.UDPAddr, ufrag string, fingerprint multihash.DecodedMultihash) (string, error) {
+ ipVersion := "IP4"
+ if addr.IP.To4() == nil {
+ ipVersion = "IP6"
+ }
+
+ sdpString, err := getSupportedSDPString(fingerprint.Code)
+ if err != nil {
+ return "", err
+ }
+
+ var builder strings.Builder
+ builder.Grow(len(fingerprint.Digest)*3 + 8)
+ builder.WriteString(sdpString)
+ builder.WriteByte(' ')
+ builder.WriteString(encodeInterspersedHex(fingerprint.Digest))
+ fp := builder.String()
+
+ return fmt.Sprintf(
+ serverSDP,
+ ipVersion,
+ addr.IP,
+ addr.Port,
+ ufrag,
+ fp,
+ ), nil
+}
+
+// getSupportedSDPHash converts a multihash code to the
+// corresponding crypto.Hash for supported protocols. If a
+// crypto.Hash cannot be found, it returns `(0, false)`
+func getSupportedSDPHash(code uint64) (crypto.Hash, bool) {
+ switch code {
+ case multihash.MD5:
+ return crypto.MD5, true
+ case multihash.SHA1:
+ return crypto.SHA1, true
+ case multihash.SHA3_224:
+ return crypto.SHA3_224, true
+ case multihash.SHA2_256:
+ return crypto.SHA256, true
+ case multihash.SHA3_384:
+ return crypto.SHA3_384, true
+ case multihash.SHA2_512:
+ return crypto.SHA512, true
+ default:
+ return 0, false
+ }
+}
+
+// getSupportedSDPString converts a multihash code
+// to a string format recognised by pion for fingerprint
+// algorithms
+func getSupportedSDPString(code uint64) (string, error) {
+ // values based on (cryto.Hash).String()
+ switch code {
+ case multihash.MD5:
+ return "md5", nil
+ case multihash.SHA1:
+ return "sha-1", nil
+ case multihash.SHA3_224:
+ return "sha3-224", nil
+ case multihash.SHA2_256:
+ return "sha-256", nil
+ case multihash.SHA3_384:
+ return "sha3-384", nil
+ case multihash.SHA2_512:
+ return "sha-512", nil
+ default:
+ return "", fmt.Errorf("unsupported hash code (%d)", code)
+ }
+}
diff --git a/p2p/transport/webrtc/sdp_test.go b/p2p/transport/webrtc/sdp_test.go
new file mode 100644
index 0000000000..2e7ac5b3e8
--- /dev/null
+++ b/p2p/transport/webrtc/sdp_test.go
@@ -0,0 +1,101 @@
+package libp2pwebrtc
+
+import (
+ "encoding/hex"
+ "net"
+ "testing"
+
+ "github.com/multiformats/go-multihash"
+ "github.com/stretchr/testify/require"
+)
+
+const expectedServerSDP = `v=0
+o=- 0 0 IN IP4 0.0.0.0
+s=-
+t=0 0
+a=ice-lite
+m=application 37826 UDP/DTLS/SCTP webrtc-datachannel
+c=IN IP4 0.0.0.0
+a=mid:0
+a=ice-options:ice2
+a=ice-ufrag:d2c0fc07-8bb3-42ae-bae2-a6fce8a0b581
+a=ice-pwd:d2c0fc07-8bb3-42ae-bae2-a6fce8a0b581
+a=fingerprint:sha-256 ba:78:16:bf:8f:01:cf:ea:41:41:40:de:5d:ae:22:23:b0:03:61:a3:96:17:7a:9c:b4:10:ff:61:f2:00:15:ad
+
+a=setup:passive
+a=sctp-port:5000
+a=max-message-size:16384
+a=candidate:1 1 UDP 1 0.0.0.0 37826 typ host
+a=end-of-candidates
+`
+
+func TestRenderServerSDP(t *testing.T) {
+ encoded, err := hex.DecodeString("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
+ require.NoError(t, err)
+
+ testMultihash := multihash.DecodedMultihash{
+ Code: multihash.SHA2_256,
+ Name: multihash.Codes[multihash.SHA2_256],
+ Digest: encoded,
+ Length: len(encoded),
+ }
+ addr := &net.UDPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 37826}
+ ufrag := "d2c0fc07-8bb3-42ae-bae2-a6fce8a0b581"
+ fingerprint := testMultihash
+
+ sdp, err := createServerSDP(addr, ufrag, fingerprint)
+ require.NoError(t, err)
+ require.Equal(t, expectedServerSDP, sdp)
+}
+
+const expectedClientSDP = `v=0
+o=- 0 0 IN IP4 0.0.0.0
+s=-
+c=IN IP4 0.0.0.0
+t=0 0
+
+m=application 37826 UDP/DTLS/SCTP webrtc-datachannel
+a=mid:0
+a=ice-options:ice2
+a=ice-ufrag:d2c0fc07-8bb3-42ae-bae2-a6fce8a0b581
+a=ice-pwd:d2c0fc07-8bb3-42ae-bae2-a6fce8a0b581
+a=fingerprint:sha-256 ba:78:16:bf:8f:01:cf:ea:41:41:40:de:5d:ae:22:23:b0:03:61:a3:96:17:7a:9c:b4:10:ff:61:f2:00:15:ad
+a=setup:actpass
+a=sctp-port:5000
+a=max-message-size:16384
+`
+
+func TestRenderClientSDP(t *testing.T) {
+ addr := &net.UDPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 37826}
+ ufrag := "d2c0fc07-8bb3-42ae-bae2-a6fce8a0b581"
+ sdp := createClientSDP(addr, ufrag)
+ require.Equal(t, expectedClientSDP, sdp)
+}
+
+func BenchmarkRenderClientSDP(b *testing.B) {
+ addr := &net.UDPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 37826}
+ ufrag := "d2c0fc07-8bb3-42ae-bae2-a6fce8a0b581"
+
+ for i := 0; i < b.N; i++ {
+ createClientSDP(addr, ufrag)
+ }
+}
+
+func BenchmarkRenderServerSDP(b *testing.B) {
+ encoded, _ := hex.DecodeString("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
+
+ testMultihash := multihash.DecodedMultihash{
+ Code: multihash.SHA2_256,
+ Name: multihash.Codes[multihash.SHA2_256],
+ Digest: encoded,
+ Length: len(encoded),
+ }
+ addr := &net.UDPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 37826}
+ ufrag := "d2c0fc07-8bb3-42ae-bae2-a6fce8a0b581"
+ fingerprint := testMultihash
+
+ for i := 0; i < b.N; i++ {
+ createServerSDP(addr, ufrag, fingerprint)
+ }
+
+}
diff --git a/p2p/transport/webrtc/stream.go b/p2p/transport/webrtc/stream.go
new file mode 100644
index 0000000000..135940e4ce
--- /dev/null
+++ b/p2p/transport/webrtc/stream.go
@@ -0,0 +1,292 @@
+package libp2pwebrtc
+
+import (
+ "errors"
+ "os"
+ "sync"
+ "time"
+
+ "github.com/libp2p/go-libp2p/core/network"
+ "github.com/libp2p/go-libp2p/p2p/transport/webrtc/pb"
+ "github.com/libp2p/go-msgio/pbio"
+
+ "github.com/pion/datachannel"
+ "github.com/pion/webrtc/v3"
+)
+
+const (
+ // maxMessageSize is the maximum message size of the Protobuf message we send / receive.
+ maxMessageSize = 16384
+ // Pion SCTP association has an internal receive buffer of 1MB (roughly, 1MB per connection).
+ // We can change this value in the SettingEngine before creating the peerconnection.
+ // https://github.com/pion/webrtc/blob/v3.1.49/sctptransport.go#L341
+ maxBufferedAmount = 2 * maxMessageSize
+ // maxTotalControlMessagesSize is the maximum total size of all control messages we will
+ // write on this stream.
+ // 4 control messages of size 10 bytes + 10 bytes buffer. This number doesn't need to be
+ // exact. In the worst case, we enqueue these many bytes more in the webrtc peer connection
+ // send queue.
+ maxTotalControlMessagesSize = 50
+ // bufferedAmountLowThreshold and maxBufferedAmount are bound
+ // to a stream but congestion control is done on the whole
+ // SCTP association. This means that a single stream can monopolize
+ // the complete congestion control window (cwnd) if it does not
+ // read stream data and it's remote continues to send. We can
+ // add messages to the send buffer once there is space for 1 full
+ // sized message.
+ bufferedAmountLowThreshold = maxBufferedAmount / 2
+
+ // Proto overhead assumption is 5 bytes
+ protoOverhead = 5
+ // Varint overhead is assumed to be 2 bytes. This is safe since
+ // 1. This is only used and when writing message, and
+ // 2. We only send messages in chunks of `maxMessageSize - varintOverhead`
+ // which includes the data and the protobuf header. Since `maxMessageSize`
+ // is less than or equal to 2 ^ 14, the varint will not be more than
+ // 2 bytes in length.
+ varintOverhead = 2
+ // maxFINACKWait is the maximum amount of time a stream will wait to read
+ // FIN_ACK before closing the data channel
+ maxFINACKWait = 10 * time.Second
+)
+
+type receiveState uint8
+
+const (
+ receiveStateReceiving receiveState = iota
+ receiveStateDataRead // received and read the FIN
+ receiveStateReset // either by calling CloseRead locally, or by receiving
+)
+
+type sendState uint8
+
+const (
+ sendStateSending sendState = iota
+ sendStateDataSent
+ sendStateDataReceived
+ sendStateReset
+)
+
+// Package pion detached data channel into a net.Conn
+// and then a network.MuxedStream
+type stream struct {
+ mx sync.Mutex
+
+ // readerMx ensures that only a single goroutine reads from the reader. Read is not threadsafe
+ // But we may need to read from reader for control messages from a different goroutine.
+ readerMx sync.Mutex
+ reader pbio.Reader
+
+ // this buffer is limited up to a single message. Reason we need it
+ // is because a reader might read a message midway, and so we need a
+ // wait to buffer that for as long as the remaining part is not (yet) read
+ nextMessage *pb.Message
+ receiveState receiveState
+
+ writer pbio.Writer // concurrent writes prevented by mx
+ writeStateChanged chan struct{}
+ sendState sendState
+ writeDeadline time.Time
+
+ controlMessageReaderOnce sync.Once
+ // controlMessageReaderEndTime is the end time for reading FIN_ACK from the control
+ // message reader. We cannot rely on SetReadDeadline to do this since that is prone to
+ // race condition where a previous deadline timer fires after the latest call to
+ // SetReadDeadline
+ // See: https://github.com/pion/sctp/pull/290
+ controlMessageReaderEndTime time.Time
+ controlMessageReaderDone sync.WaitGroup
+
+ onDone func()
+ id uint16 // for logging purposes
+ dataChannel *datachannel.DataChannel
+ closeForShutdownErr error
+}
+
+var _ network.MuxedStream = &stream{}
+
+func newStream(
+ channel *webrtc.DataChannel,
+ rwc datachannel.ReadWriteCloser,
+ onDone func(),
+) *stream {
+ s := &stream{
+ reader: pbio.NewDelimitedReader(rwc, maxMessageSize),
+ writer: pbio.NewDelimitedWriter(rwc),
+ writeStateChanged: make(chan struct{}, 1),
+ id: *channel.ID(),
+ dataChannel: rwc.(*datachannel.DataChannel),
+ onDone: onDone,
+ }
+ // released when the controlMessageReader goroutine exits
+ s.controlMessageReaderDone.Add(1)
+ s.dataChannel.SetBufferedAmountLowThreshold(bufferedAmountLowThreshold)
+ s.dataChannel.OnBufferedAmountLow(func() {
+ s.notifyWriteStateChanged()
+
+ })
+ return s
+}
+
+func (s *stream) Close() error {
+ s.mx.Lock()
+ isClosed := s.closeForShutdownErr != nil
+ s.mx.Unlock()
+ if isClosed {
+ return nil
+ }
+
+ closeWriteErr := s.CloseWrite()
+ closeReadErr := s.CloseRead()
+ if closeWriteErr != nil || closeReadErr != nil {
+ s.Reset()
+ return errors.Join(closeWriteErr, closeReadErr)
+ }
+
+ s.mx.Lock()
+ if s.controlMessageReaderEndTime.IsZero() {
+ s.controlMessageReaderEndTime = time.Now().Add(maxFINACKWait)
+ s.setDataChannelReadDeadline(time.Now().Add(-1 * time.Hour))
+ go func() {
+ s.controlMessageReaderDone.Wait()
+ s.cleanup()
+ }()
+ }
+ s.mx.Unlock()
+ return nil
+}
+
+func (s *stream) Reset() error {
+ s.mx.Lock()
+ isClosed := s.closeForShutdownErr != nil
+ s.mx.Unlock()
+ if isClosed {
+ return nil
+ }
+
+ defer s.cleanup()
+ cancelWriteErr := s.cancelWrite()
+ closeReadErr := s.CloseRead()
+ s.setDataChannelReadDeadline(time.Now().Add(-1 * time.Hour))
+ return errors.Join(closeReadErr, cancelWriteErr)
+}
+
+func (s *stream) closeForShutdown(closeErr error) {
+ defer s.cleanup()
+
+ s.mx.Lock()
+ defer s.mx.Unlock()
+
+ s.closeForShutdownErr = closeErr
+ s.notifyWriteStateChanged()
+}
+
+func (s *stream) SetDeadline(t time.Time) error {
+ _ = s.SetReadDeadline(t)
+ return s.SetWriteDeadline(t)
+}
+
+// processIncomingFlag process the flag on an incoming message
+// It needs to be called while the mutex is locked.
+func (s *stream) processIncomingFlag(flag *pb.Message_Flag) {
+ if flag == nil {
+ return
+ }
+
+ switch *flag {
+ case pb.Message_STOP_SENDING:
+ // We must process STOP_SENDING after sending a FIN(sendStateDataSent). Remote peer
+ // may not send a FIN_ACK once it has sent a STOP_SENDING
+ if s.sendState == sendStateSending || s.sendState == sendStateDataSent {
+ s.sendState = sendStateReset
+ }
+ s.notifyWriteStateChanged()
+ case pb.Message_FIN_ACK:
+ s.sendState = sendStateDataReceived
+ s.notifyWriteStateChanged()
+ case pb.Message_FIN:
+ if s.receiveState == receiveStateReceiving {
+ s.receiveState = receiveStateDataRead
+ }
+ if err := s.writer.WriteMsg(&pb.Message{Flag: pb.Message_FIN_ACK.Enum()}); err != nil {
+ log.Debugf("failed to send FIN_ACK: %s", err)
+ // Remote has finished writing all the data It'll stop waiting for the
+ // FIN_ACK eventually or will be notified when we close the datachannel
+ }
+ s.spawnControlMessageReader()
+ case pb.Message_RESET:
+ if s.receiveState == receiveStateReceiving {
+ s.receiveState = receiveStateReset
+ }
+ s.spawnControlMessageReader()
+ }
+}
+
+// spawnControlMessageReader is used for processing control messages after the reader is closed.
+func (s *stream) spawnControlMessageReader() {
+ s.controlMessageReaderOnce.Do(func() {
+ // Spawn a goroutine to ensure that we're not holding any locks
+ go func() {
+ defer s.controlMessageReaderDone.Done()
+ // cleanup the sctp deadline timer goroutine
+ defer s.setDataChannelReadDeadline(time.Time{})
+
+ setDeadline := func() bool {
+ if s.controlMessageReaderEndTime.IsZero() || time.Now().Before(s.controlMessageReaderEndTime) {
+ s.setDataChannelReadDeadline(s.controlMessageReaderEndTime)
+ return true
+ }
+ return false
+ }
+
+ // Unblock any Read call waiting on reader.ReadMsg
+ s.setDataChannelReadDeadline(time.Now().Add(-1 * time.Hour))
+
+ s.readerMx.Lock()
+ // We have the lock: any readers blocked on reader.ReadMsg have exited.
+ s.mx.Lock()
+ defer s.mx.Unlock()
+ // From this point onwards only this goroutine will do reader.ReadMsg.
+ // We just wanted to ensure any exising readers have exited.
+ // Read calls from this point onwards will exit immediately on checking
+ // s.readState
+ s.readerMx.Unlock()
+
+ if s.nextMessage != nil {
+ s.processIncomingFlag(s.nextMessage.Flag)
+ s.nextMessage = nil
+ }
+ for s.closeForShutdownErr == nil &&
+ s.sendState != sendStateDataReceived && s.sendState != sendStateReset {
+ var msg pb.Message
+ if !setDeadline() {
+ return
+ }
+ s.mx.Unlock()
+ err := s.reader.ReadMsg(&msg)
+ s.mx.Lock()
+ if err != nil {
+ // We have to manually manage deadline exceeded errors since pion/sctp can
+ // return deadline exceeded error for cancelled deadlines
+ // see: https://github.com/pion/sctp/pull/290/files
+ if errors.Is(err, os.ErrDeadlineExceeded) {
+ continue
+ }
+ return
+ }
+ s.processIncomingFlag(msg.Flag)
+ }
+ }()
+ })
+}
+
+func (s *stream) cleanup() {
+ // Even if we close the datachannel pion keeps a reference to the datachannel around.
+ // Remove the onBufferedAmountLow callback to ensure that we at least garbage collect
+ // memory we allocated for this stream.
+ s.dataChannel.OnBufferedAmountLow(nil)
+ s.dataChannel.Close()
+ if s.onDone != nil {
+ s.onDone()
+ }
+}
diff --git a/p2p/transport/webrtc/stream_read.go b/p2p/transport/webrtc/stream_read.go
new file mode 100644
index 0000000000..80d99ea91c
--- /dev/null
+++ b/p2p/transport/webrtc/stream_read.go
@@ -0,0 +1,113 @@
+package libp2pwebrtc
+
+import (
+ "io"
+ "time"
+
+ "github.com/libp2p/go-libp2p/core/network"
+ "github.com/libp2p/go-libp2p/p2p/transport/webrtc/pb"
+)
+
+func (s *stream) Read(b []byte) (int, error) {
+ s.readerMx.Lock()
+ defer s.readerMx.Unlock()
+
+ s.mx.Lock()
+ defer s.mx.Unlock()
+
+ if s.closeForShutdownErr != nil {
+ return 0, s.closeForShutdownErr
+ }
+ switch s.receiveState {
+ case receiveStateDataRead:
+ return 0, io.EOF
+ case receiveStateReset:
+ return 0, network.ErrReset
+ }
+
+ if len(b) == 0 {
+ return 0, nil
+ }
+
+ var read int
+ for {
+ if s.nextMessage == nil {
+ // load the next message
+ s.mx.Unlock()
+ var msg pb.Message
+ err := s.reader.ReadMsg(&msg)
+ s.mx.Lock()
+ if err != nil {
+ // connection was closed
+ if s.closeForShutdownErr != nil {
+ return 0, s.closeForShutdownErr
+ }
+ if err == io.EOF {
+ // if the channel was properly closed, return EOF
+ if s.receiveState == receiveStateDataRead {
+ return 0, io.EOF
+ }
+ // This case occurs when remote closes the datachannel without writing a FIN
+ // message. Some implementations discard the buffered data on closing the
+ // datachannel. For these implementations a stream reset will be observed as an
+ // abrupt closing of the datachannel.
+ s.receiveState = receiveStateReset
+ return 0, network.ErrReset
+ }
+ if s.receiveState == receiveStateReset {
+ return 0, network.ErrReset
+ }
+ if s.receiveState == receiveStateDataRead {
+ return 0, io.EOF
+ }
+ return 0, err
+ }
+ s.nextMessage = &msg
+ }
+
+ if len(s.nextMessage.Message) > 0 {
+ n := copy(b, s.nextMessage.Message)
+ read += n
+ s.nextMessage.Message = s.nextMessage.Message[n:]
+ return read, nil
+ }
+
+ // process flags on the message after reading all the data
+ s.processIncomingFlag(s.nextMessage.Flag)
+ s.nextMessage = nil
+ if s.closeForShutdownErr != nil {
+ return read, s.closeForShutdownErr
+ }
+ switch s.receiveState {
+ case receiveStateDataRead:
+ return read, io.EOF
+ case receiveStateReset:
+ return read, network.ErrReset
+ }
+ }
+}
+
+func (s *stream) SetReadDeadline(t time.Time) error {
+ s.mx.Lock()
+ defer s.mx.Unlock()
+ if s.receiveState == receiveStateReceiving {
+ s.setDataChannelReadDeadline(t)
+ }
+ return nil
+}
+
+func (s *stream) setDataChannelReadDeadline(t time.Time) error {
+ return s.dataChannel.SetReadDeadline(t)
+}
+
+func (s *stream) CloseRead() error {
+ s.mx.Lock()
+ defer s.mx.Unlock()
+ var err error
+ if s.receiveState == receiveStateReceiving && s.closeForShutdownErr == nil {
+ err = s.writer.WriteMsg(&pb.Message{Flag: pb.Message_STOP_SENDING.Enum()})
+ s.receiveState = receiveStateReset
+ }
+ s.spawnControlMessageReader()
+ return err
+}
diff --git a/p2p/transport/webrtc/stream_test.go b/p2p/transport/webrtc/stream_test.go
new file mode 100644
index 0000000000..52b464c0e4
--- /dev/null
+++ b/p2p/transport/webrtc/stream_test.go
@@ -0,0 +1,528 @@
+package libp2pwebrtc
+
+import (
+ "crypto/rand"
+ "errors"
+ "io"
+ "os"
+ "sync/atomic"
+ "testing"
+ "time"
+
+ "github.com/libp2p/go-libp2p/p2p/transport/webrtc/pb"
+ "github.com/libp2p/go-msgio/pbio"
+
+ "github.com/libp2p/go-libp2p/core/network"
+
+ "github.com/pion/datachannel"
+ "github.com/pion/webrtc/v3"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+type detachedChan struct {
+ rwc datachannel.ReadWriteCloser
+ dc *webrtc.DataChannel
+}
+
+func getDetachedDataChannels(t *testing.T) (detachedChan, detachedChan) {
+ s := webrtc.SettingEngine{}
+ s.SetIncludeLoopbackCandidate(true)
+ s.DetachDataChannels()
+ api := webrtc.NewAPI(webrtc.WithSettingEngine(s))
+
+ offerPC, err := api.NewPeerConnection(webrtc.Configuration{})
+ require.NoError(t, err)
+ t.Cleanup(func() { offerPC.Close() })
+ offerRWCChan := make(chan detachedChan, 1)
+ offerDC, err := offerPC.CreateDataChannel("data", nil)
+ require.NoError(t, err)
+ offerDC.OnOpen(func() {
+ rwc, err := offerDC.Detach()
+ require.NoError(t, err)
+ offerRWCChan <- detachedChan{rwc: rwc, dc: offerDC}
+ })
+
+ answerPC, err := api.NewPeerConnection(webrtc.Configuration{})
+ require.NoError(t, err)
+
+ answerChan := make(chan detachedChan, 1)
+ answerPC.OnDataChannel(func(dc *webrtc.DataChannel) {
+ dc.OnOpen(func() {
+ rwc, err := dc.Detach()
+ require.NoError(t, err)
+ answerChan <- detachedChan{rwc: rwc, dc: dc}
+ })
+ })
+ t.Cleanup(func() { answerPC.Close() })
+
+ // Set ICE Candidate handlers. As soon as a PeerConnection has gathered a candidate send it to the other peer
+ answerPC.OnICECandidate(func(candidate *webrtc.ICECandidate) {
+ if candidate != nil {
+ require.NoError(t, offerPC.AddICECandidate(candidate.ToJSON()))
+ }
+ })
+ offerPC.OnICECandidate(func(candidate *webrtc.ICECandidate) {
+ if candidate != nil {
+ require.NoError(t, answerPC.AddICECandidate(candidate.ToJSON()))
+ }
+ })
+
+ // Set the handler for Peer connection state
+ // This will notify you when the peer has connected/disconnected
+ offerPC.OnConnectionStateChange(func(s webrtc.PeerConnectionState) {
+ if s == webrtc.PeerConnectionStateFailed {
+ t.Log("peer connection failed on offerer")
+ }
+ })
+
+ // Set the handler for Peer connection state
+ // This will notify you when the peer has connected/disconnected
+ answerPC.OnConnectionStateChange(func(s webrtc.PeerConnectionState) {
+ if s == webrtc.PeerConnectionStateFailed {
+ t.Log("peer connection failed on answerer")
+ }
+ })
+
+ // Now, create an offer
+ offer, err := offerPC.CreateOffer(nil)
+ require.NoError(t, err)
+ require.NoError(t, answerPC.SetRemoteDescription(offer))
+ require.NoError(t, offerPC.SetLocalDescription(offer))
+
+ answer, err := answerPC.CreateAnswer(nil)
+ require.NoError(t, err)
+ require.NoError(t, offerPC.SetRemoteDescription(answer))
+ require.NoError(t, answerPC.SetLocalDescription(answer))
+
+ return <-answerChan, <-offerRWCChan
+}
+
+func TestStreamSimpleReadWriteClose(t *testing.T) {
+ client, server := getDetachedDataChannels(t)
+
+ var clientDone, serverDone atomic.Bool
+ clientStr := newStream(client.dc, client.rwc, func() { clientDone.Store(true) })
+ serverStr := newStream(server.dc, server.rwc, func() { serverDone.Store(true) })
+
+ // send a foobar from the client
+ n, err := clientStr.Write([]byte("foobar"))
+ require.NoError(t, err)
+ require.Equal(t, 6, n)
+ require.NoError(t, clientStr.CloseWrite())
+ // writing after closing should error
+ _, err = clientStr.Write([]byte("foobar"))
+ require.Error(t, err)
+ require.False(t, clientDone.Load())
+
+ // now read all the data on the server side
+ b, err := io.ReadAll(serverStr)
+ require.NoError(t, err)
+ require.Equal(t, []byte("foobar"), b)
+ // reading again should give another io.EOF
+ n, err = serverStr.Read(make([]byte, 10))
+ require.Zero(t, n)
+ require.ErrorIs(t, err, io.EOF)
+ require.False(t, serverDone.Load())
+
+ // send something back
+ _, err = serverStr.Write([]byte("lorem ipsum"))
+ require.NoError(t, err)
+ require.NoError(t, serverStr.CloseWrite())
+
+ // and read it at the client
+ require.False(t, clientDone.Load())
+ b, err = io.ReadAll(clientStr)
+ require.NoError(t, err)
+ require.Equal(t, []byte("lorem ipsum"), b)
+
+ // stream is only cleaned up on calling Close or Reset
+ clientStr.Close()
+ serverStr.Close()
+ require.Eventually(t, func() bool { return clientDone.Load() }, 5*time.Second, 100*time.Millisecond)
+ // Need to call Close for cleanup. Otherwise the FIN_ACK is never read
+ require.NoError(t, serverStr.Close())
+ require.Eventually(t, func() bool { return serverDone.Load() }, 5*time.Second, 100*time.Millisecond)
+}
+
+func TestStreamPartialReads(t *testing.T) {
+ client, server := getDetachedDataChannels(t)
+
+ clientStr := newStream(client.dc, client.rwc, func() {})
+ serverStr := newStream(server.dc, server.rwc, func() {})
+
+ _, err := serverStr.Write([]byte("foobar"))
+ require.NoError(t, err)
+ require.NoError(t, serverStr.CloseWrite())
+
+ n, err := clientStr.Read([]byte{}) // empty read
+ require.NoError(t, err)
+ require.Zero(t, n)
+ b := make([]byte, 3)
+ n, err = clientStr.Read(b)
+ require.Equal(t, 3, n)
+ require.NoError(t, err)
+ require.Equal(t, []byte("foo"), b)
+ b, err = io.ReadAll(clientStr)
+ require.NoError(t, err)
+ require.Equal(t, []byte("bar"), b)
+}
+
+func TestStreamSkipEmptyFrames(t *testing.T) {
+ client, server := getDetachedDataChannels(t)
+
+ clientStr := newStream(client.dc, client.rwc, func() {})
+ serverStr := newStream(server.dc, server.rwc, func() {})
+
+ for i := 0; i < 10; i++ {
+ require.NoError(t, serverStr.writer.WriteMsg(&pb.Message{}))
+ }
+ require.NoError(t, serverStr.writer.WriteMsg(&pb.Message{Message: []byte("foo")}))
+ for i := 0; i < 10; i++ {
+ require.NoError(t, serverStr.writer.WriteMsg(&pb.Message{}))
+ }
+ require.NoError(t, serverStr.writer.WriteMsg(&pb.Message{Message: []byte("bar")}))
+ for i := 0; i < 10; i++ {
+ require.NoError(t, serverStr.writer.WriteMsg(&pb.Message{}))
+ }
+ require.NoError(t, serverStr.writer.WriteMsg(&pb.Message{Flag: pb.Message_FIN.Enum()}))
+
+ var read []byte
+ var count int
+ for i := 0; i < 100; i++ {
+ b := make([]byte, 10)
+ count++
+ n, err := clientStr.Read(b)
+ read = append(read, b[:n]...)
+ if err == io.EOF {
+ break
+ }
+ require.NoError(t, err)
+ }
+ require.LessOrEqual(t, count, 3, "should've taken a maximum of 3 reads")
+ require.Equal(t, []byte("foobar"), read)
+}
+
+func TestStreamReadReturnsOnClose(t *testing.T) {
+ client, _ := getDetachedDataChannels(t)
+
+ clientStr := newStream(client.dc, client.rwc, func() {})
+ errChan := make(chan error, 1)
+ go func() {
+ _, err := clientStr.Read([]byte{0})
+ errChan <- err
+ }()
+ time.Sleep(100 * time.Millisecond) // give the Read call some time to hit the loop
+ require.NoError(t, clientStr.Close())
+ select {
+ case err := <-errChan:
+ require.ErrorIs(t, err, network.ErrReset)
+ case <-time.After(500 * time.Millisecond):
+ t.Fatal("timeout")
+ }
+
+ _, err := clientStr.Read([]byte{0})
+ require.ErrorIs(t, err, network.ErrReset)
+}
+
+func TestStreamResets(t *testing.T) {
+ client, server := getDetachedDataChannels(t)
+
+ var clientDone, serverDone atomic.Bool
+ clientStr := newStream(client.dc, client.rwc, func() { clientDone.Store(true) })
+ serverStr := newStream(server.dc, server.rwc, func() { serverDone.Store(true) })
+
+ // send a foobar from the client
+ _, err := clientStr.Write([]byte("foobar"))
+ require.NoError(t, err)
+ _, err = serverStr.Write([]byte("lorem ipsum"))
+ require.NoError(t, err)
+ require.NoError(t, clientStr.Reset()) // resetting resets both directions
+ require.True(t, clientDone.Load())
+ // attempting to write more data should result in a reset error
+ _, err = clientStr.Write([]byte("foobar"))
+ require.ErrorIs(t, err, network.ErrReset)
+ // read what the server sent
+ b, err := io.ReadAll(clientStr)
+ require.Empty(t, b)
+ require.ErrorIs(t, err, network.ErrReset)
+
+ // read the data on the server side
+ require.False(t, serverDone.Load())
+ b, err = io.ReadAll(serverStr)
+ require.Equal(t, []byte("foobar"), b)
+ require.ErrorIs(t, err, network.ErrReset)
+ require.Eventually(t, func() bool {
+ _, err := serverStr.Write([]byte("foobar"))
+ return errors.Is(err, network.ErrReset)
+ }, time.Second, 50*time.Millisecond)
+ serverStr.Close()
+ require.Eventually(t, func() bool {
+ return serverDone.Load()
+ }, time.Second, 50*time.Millisecond)
+}
+
+func TestStreamReadDeadlineAsync(t *testing.T) {
+ client, server := getDetachedDataChannels(t)
+
+ clientStr := newStream(client.dc, client.rwc, func() {})
+ serverStr := newStream(server.dc, server.rwc, func() {})
+
+ timeout := 100 * time.Millisecond
+ if os.Getenv("CI") != "" {
+ timeout *= 5
+ }
+ start := time.Now()
+ clientStr.SetReadDeadline(start.Add(timeout))
+ _, err := clientStr.Read([]byte{0})
+ require.ErrorIs(t, err, os.ErrDeadlineExceeded)
+ took := time.Since(start)
+ require.GreaterOrEqual(t, took, timeout)
+ require.LessOrEqual(t, took, timeout*3/2)
+ // repeated calls should return immediately
+ start = time.Now()
+ _, err = clientStr.Read([]byte{0})
+ require.ErrorIs(t, err, os.ErrDeadlineExceeded)
+ require.LessOrEqual(t, time.Since(start), timeout/3)
+ // clear the deadline
+ clientStr.SetReadDeadline(time.Time{})
+ _, err = serverStr.Write([]byte("foobar"))
+ require.NoError(t, err)
+ _, err = clientStr.Read([]byte{0})
+ require.NoError(t, err)
+ require.LessOrEqual(t, time.Since(start), timeout/3)
+}
+
+func TestStreamWriteDeadlineAsync(t *testing.T) {
+ client, server := getDetachedDataChannels(t)
+
+ clientStr := newStream(client.dc, client.rwc, func() {})
+ serverStr := newStream(server.dc, server.rwc, func() {})
+ _ = serverStr
+
+ b := make([]byte, 1024)
+ rand.Read(b)
+ start := time.Now()
+ timeout := 100 * time.Millisecond
+ if os.Getenv("CI") != "" {
+ timeout *= 5
+ }
+ clientStr.SetWriteDeadline(start.Add(timeout))
+ var hitDeadline bool
+ for i := 0; i < 2000; i++ {
+ if _, err := clientStr.Write(b); err != nil {
+ t.Logf("wrote %d kB", i)
+ require.ErrorIs(t, err, os.ErrDeadlineExceeded)
+ hitDeadline = true
+ break
+ }
+ }
+ require.True(t, hitDeadline)
+ took := time.Since(start)
+ require.GreaterOrEqual(t, took, timeout)
+ require.LessOrEqual(t, took, timeout*3/2)
+}
+
+func TestStreamReadAfterClose(t *testing.T) {
+ client, server := getDetachedDataChannels(t)
+
+ clientStr := newStream(client.dc, client.rwc, func() {})
+ serverStr := newStream(server.dc, server.rwc, func() {})
+
+ serverStr.Close()
+ b := make([]byte, 1)
+ _, err := clientStr.Read(b)
+ require.Equal(t, io.EOF, err)
+ _, err = clientStr.Read(nil)
+ require.Equal(t, io.EOF, err)
+
+ client, server = getDetachedDataChannels(t)
+
+ clientStr = newStream(client.dc, client.rwc, func() {})
+ serverStr = newStream(server.dc, server.rwc, func() {})
+
+ serverStr.Reset()
+ b = make([]byte, 1)
+ _, err = clientStr.Read(b)
+ require.ErrorIs(t, err, network.ErrReset)
+ _, err = clientStr.Read(nil)
+ require.ErrorIs(t, err, network.ErrReset)
+}
+
+func TestStreamCloseAfterFINACK(t *testing.T) {
+ client, server := getDetachedDataChannels(t)
+
+ done := make(chan bool, 1)
+ clientStr := newStream(client.dc, client.rwc, func() { done <- true })
+ serverStr := newStream(server.dc, server.rwc, func() {})
+
+ go func() {
+ done <- true
+ err := clientStr.Close()
+ assert.NoError(t, err)
+ }()
+ <-done
+
+ select {
+ case <-done:
+ t.Fatalf("Close should not have completed without processing FIN_ACK")
+ case <-time.After(200 * time.Millisecond):
+ }
+
+ b := make([]byte, 1)
+ _, err := serverStr.Read(b)
+ require.Error(t, err)
+ require.ErrorIs(t, err, io.EOF)
+ select {
+ case <-done:
+ case <-time.After(3 * time.Second):
+ t.Errorf("Close should have completed")
+ }
+}
+
+// TestStreamFinAckAfterStopSending tests that FIN_ACK is sent even after the write half
+// of the stream is closed.
+func TestStreamFinAckAfterStopSending(t *testing.T) {
+ client, server := getDetachedDataChannels(t)
+
+ done := make(chan bool, 1)
+ clientStr := newStream(client.dc, client.rwc, func() { done <- true })
+ serverStr := newStream(server.dc, server.rwc, func() {})
+
+ go func() {
+ clientStr.CloseRead()
+ clientStr.Write([]byte("hello world"))
+ done <- true
+ err := clientStr.Close()
+ assert.NoError(t, err)
+ }()
+ <-done
+
+ select {
+ case <-done:
+ t.Errorf("Close should not have completed without processing FIN_ACK")
+ case <-time.After(500 * time.Millisecond):
+ }
+
+ // serverStr has write half closed and read half open
+ // serverStr should still send FIN_ACK
+ b := make([]byte, 24)
+ _, err := serverStr.Read(b)
+ require.NoError(t, err)
+ serverStr.Close() // Sends stop_sending, fin
+ select {
+ case <-done:
+ case <-time.After(5 * time.Second):
+ t.Fatalf("Close should have completed")
+ }
+}
+
+func TestStreamConcurrentClose(t *testing.T) {
+ client, server := getDetachedDataChannels(t)
+
+ start := make(chan bool, 2)
+ done := make(chan bool, 2)
+ clientStr := newStream(client.dc, client.rwc, func() { done <- true })
+ serverStr := newStream(server.dc, server.rwc, func() { done <- true })
+
+ go func() {
+ start <- true
+ clientStr.Close()
+ }()
+ go func() {
+ start <- true
+ serverStr.Close()
+ }()
+ <-start
+ <-start
+
+ select {
+ case <-done:
+ case <-time.After(2 * time.Second):
+ t.Fatalf("concurrent close should succeed quickly")
+ }
+ select {
+ case <-done:
+ case <-time.After(2 * time.Second):
+ t.Fatalf("concurrent close should succeed quickly")
+ }
+}
+
+func TestStreamResetAfterClose(t *testing.T) {
+ client, _ := getDetachedDataChannels(t)
+
+ done := make(chan bool, 2)
+ clientStr := newStream(client.dc, client.rwc, func() { done <- true })
+ clientStr.Close()
+
+ select {
+ case <-done:
+ t.Fatalf("Close shouldn't run cleanup immediately")
+ case <-time.After(500 * time.Millisecond):
+ }
+
+ clientStr.Reset()
+ select {
+ case <-done:
+ case <-time.After(2 * time.Second):
+ t.Fatalf("Reset should run callback immediately")
+ }
+}
+
+func TestStreamDataChannelCloseOnFINACK(t *testing.T) {
+ client, server := getDetachedDataChannels(t)
+
+ done := make(chan bool, 1)
+ clientStr := newStream(client.dc, client.rwc, func() { done <- true })
+
+ clientStr.Close()
+
+ select {
+ case <-done:
+ t.Fatalf("Close shouldn't run cleanup immediately")
+ case <-time.After(500 * time.Millisecond):
+ }
+
+ serverWriter := pbio.NewDelimitedWriter(server.rwc)
+ err := serverWriter.WriteMsg(&pb.Message{Flag: pb.Message_FIN_ACK.Enum()})
+ require.NoError(t, err)
+ select {
+ case <-done:
+ case <-time.After(2 * time.Second):
+ t.Fatalf("Callback should be run on reading FIN_ACK")
+ }
+ b := make([]byte, 100)
+ N := 0
+ for {
+ n, err := server.rwc.Read(b)
+ N += n
+ if err != nil {
+ require.ErrorIs(t, err, io.EOF)
+ break
+ }
+ }
+ require.Less(t, N, 10)
+}
+
+func TestStreamChunking(t *testing.T) {
+ client, server := getDetachedDataChannels(t)
+
+ clientStr := newStream(client.dc, client.rwc, func() {})
+ serverStr := newStream(server.dc, server.rwc, func() {})
+
+ const N = (16 << 10) + 1000
+ go func() {
+ data := make([]byte, N)
+ _, err := clientStr.Write(data)
+ require.NoError(t, err)
+ }()
+
+ data := make([]byte, N)
+ n, err := serverStr.Read(data)
+ require.NoError(t, err)
+ require.LessOrEqual(t, n, 16<<10)
+
+ nn, err := serverStr.Read(data)
+ require.NoError(t, err)
+ require.Equal(t, nn+n, N)
+}
diff --git a/p2p/transport/webrtc/stream_write.go b/p2p/transport/webrtc/stream_write.go
new file mode 100644
index 0000000000..82d4ac287d
--- /dev/null
+++ b/p2p/transport/webrtc/stream_write.go
@@ -0,0 +1,159 @@
+package libp2pwebrtc
+
+import (
+ "errors"
+ "os"
+ "time"
+
+ "github.com/libp2p/go-libp2p/core/network"
+ "github.com/libp2p/go-libp2p/p2p/transport/webrtc/pb"
+)
+
+var errWriteAfterClose = errors.New("write after close")
+
+// If we have less space than minMessageSize, we don't put a new message on the data channel.
+// Instead, we wait until more space opens up.
+const minMessageSize = 1 << 10
+
+func (s *stream) Write(b []byte) (int, error) {
+ s.mx.Lock()
+ defer s.mx.Unlock()
+
+ if s.closeForShutdownErr != nil {
+ return 0, s.closeForShutdownErr
+ }
+ switch s.sendState {
+ case sendStateReset:
+ return 0, network.ErrReset
+ case sendStateDataSent, sendStateDataReceived:
+ return 0, errWriteAfterClose
+ }
+
+ if !s.writeDeadline.IsZero() && time.Now().After(s.writeDeadline) {
+ return 0, os.ErrDeadlineExceeded
+ }
+
+ var writeDeadlineTimer *time.Timer
+ defer func() {
+ if writeDeadlineTimer != nil {
+ writeDeadlineTimer.Stop()
+ }
+ }()
+
+ var n int
+ var msg pb.Message
+ for len(b) > 0 {
+ if s.closeForShutdownErr != nil {
+ return n, s.closeForShutdownErr
+ }
+ switch s.sendState {
+ case sendStateReset:
+ return n, network.ErrReset
+ case sendStateDataSent, sendStateDataReceived:
+ return n, errWriteAfterClose
+ }
+
+ writeDeadline := s.writeDeadline
+ // deadline deleted, stop and remove the timer
+ if writeDeadline.IsZero() && writeDeadlineTimer != nil {
+ writeDeadlineTimer.Stop()
+ writeDeadlineTimer = nil
+ }
+ var writeDeadlineChan <-chan time.Time
+ if !writeDeadline.IsZero() {
+ if writeDeadlineTimer == nil {
+ writeDeadlineTimer = time.NewTimer(time.Until(writeDeadline))
+ } else {
+ if !writeDeadlineTimer.Stop() {
+ <-writeDeadlineTimer.C
+ }
+ writeDeadlineTimer.Reset(time.Until(writeDeadline))
+ }
+ writeDeadlineChan = writeDeadlineTimer.C
+ }
+
+ availableSpace := s.availableSendSpace()
+ if availableSpace < minMessageSize {
+ s.mx.Unlock()
+ select {
+ case <-writeDeadlineChan:
+ s.mx.Lock()
+ return n, os.ErrDeadlineExceeded
+ case <-s.writeStateChanged:
+ }
+ s.mx.Lock()
+ continue
+ }
+ end := maxMessageSize
+ if end > availableSpace {
+ end = availableSpace
+ }
+ end -= protoOverhead + varintOverhead
+ if end > len(b) {
+ end = len(b)
+ }
+ msg = pb.Message{Message: b[:end]}
+ if err := s.writer.WriteMsg(&msg); err != nil {
+ return n, err
+ }
+ n += end
+ b = b[end:]
+ }
+ return n, nil
+}
+
+func (s *stream) SetWriteDeadline(t time.Time) error {
+ s.mx.Lock()
+ defer s.mx.Unlock()
+ s.writeDeadline = t
+ s.notifyWriteStateChanged()
+ return nil
+}
+
+func (s *stream) availableSendSpace() int {
+ buffered := int(s.dataChannel.BufferedAmount())
+ availableSpace := maxBufferedAmount - buffered
+ if availableSpace+maxTotalControlMessagesSize < 0 { // this should never happen, but better check
+ log.Errorw("data channel buffered more data than the maximum amount", "max", maxBufferedAmount, "buffered", buffered)
+ }
+ return availableSpace
+}
+
+func (s *stream) cancelWrite() error {
+ s.mx.Lock()
+ defer s.mx.Unlock()
+
+ // There's no need to reset the write half if the write half has been closed
+ // successfully or has been reset previously
+ if s.sendState == sendStateDataReceived || s.sendState == sendStateReset {
+ return nil
+ }
+ s.sendState = sendStateReset
+ s.notifyWriteStateChanged()
+ if err := s.writer.WriteMsg(&pb.Message{Flag: pb.Message_RESET.Enum()}); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (s *stream) CloseWrite() error {
+ s.mx.Lock()
+ defer s.mx.Unlock()
+
+ if s.sendState != sendStateSending {
+ return nil
+ }
+ s.sendState = sendStateDataSent
+ s.notifyWriteStateChanged()
+ if err := s.writer.WriteMsg(&pb.Message{Flag: pb.Message_FIN.Enum()}); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (s *stream) notifyWriteStateChanged() {
+ select {
+ case s.writeStateChanged <- struct{}{}:
+ default:
+ }
+}
diff --git a/p2p/transport/webrtc/transport.go b/p2p/transport/webrtc/transport.go
new file mode 100644
index 0000000000..20bfdf98eb
--- /dev/null
+++ b/p2p/transport/webrtc/transport.go
@@ -0,0 +1,594 @@
+// Package libp2pwebrtc implements the WebRTC transport for go-libp2p,
+// as described in https://github.com/libp2p/specs/tree/master/webrtc.
+//
+// At this point, this package is EXPERIMENTAL, and the WebRTC transport is not enabled by default.
+// While we're fairly confident that the implementation correctly implements the specification,
+// we're not making any guarantees regarding its security (especially regarding resource exhaustion attacks).
+// Fixes, even for security-related issues, will be conducted in the open.
+//
+// Experimentation is encouraged. Please open an issue if you encounter any problems with this transport.
+//
+// The udpmux subpackage contains the logic for multiplexing multiple WebRTC (ICE)
+// connections over a single UDP socket.
+package libp2pwebrtc
+
+import (
+ "context"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/x509"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "net"
+ "time"
+
+ mrand "golang.org/x/exp/rand"
+ "google.golang.org/protobuf/proto"
+
+ "github.com/libp2p/go-libp2p/core/connmgr"
+ ic "github.com/libp2p/go-libp2p/core/crypto"
+ "github.com/libp2p/go-libp2p/core/network"
+ "github.com/libp2p/go-libp2p/core/peer"
+ "github.com/libp2p/go-libp2p/core/pnet"
+ "github.com/libp2p/go-libp2p/core/sec"
+ tpt "github.com/libp2p/go-libp2p/core/transport"
+ "github.com/libp2p/go-libp2p/p2p/security/noise"
+ "github.com/libp2p/go-libp2p/p2p/transport/webrtc/pb"
+ "github.com/libp2p/go-msgio"
+
+ ma "github.com/multiformats/go-multiaddr"
+ mafmt "github.com/multiformats/go-multiaddr-fmt"
+ manet "github.com/multiformats/go-multiaddr/net"
+ "github.com/multiformats/go-multihash"
+
+ "github.com/pion/datachannel"
+ "github.com/pion/webrtc/v3"
+)
+
+var dialMatcher = mafmt.And(mafmt.UDP, mafmt.Base(ma.P_WEBRTC_DIRECT), mafmt.Base(ma.P_CERTHASH))
+
+var webrtcComponent *ma.Component
+
+func init() {
+ var err error
+ webrtcComponent, err = ma.NewComponent(ma.ProtocolWithCode(ma.P_WEBRTC_DIRECT).Name, "")
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+const (
+ // handshakeChannelNegotiated is used to specify that the
+ // handshake data channel does not need negotiation via DCEP.
+ // A constant is used since the `DataChannelInit` struct takes
+ // references instead of values.
+ handshakeChannelNegotiated = true
+ // handshakeChannelID is the agreed ID for the handshake data
+ // channel. A constant is used since the `DataChannelInit` struct takes
+ // references instead of values. We specify the type here as this
+ // value is only ever copied and passed by reference
+ handshakeChannelID = uint16(0)
+)
+
+// timeout values for the peerconnection
+// https://github.com/pion/webrtc/blob/v3.1.50/settingengine.go#L102-L109
+const (
+ DefaultDisconnectedTimeout = 20 * time.Second
+ DefaultFailedTimeout = 30 * time.Second
+ DefaultKeepaliveTimeout = 15 * time.Second
+)
+
+type WebRTCTransport struct {
+ webrtcConfig webrtc.Configuration
+ rcmgr network.ResourceManager
+ gater connmgr.ConnectionGater
+ privKey ic.PrivKey
+ noiseTpt *noise.Transport
+ localPeerId peer.ID
+
+ // timeouts
+ peerConnectionTimeouts iceTimeouts
+
+ // in-flight connections
+ maxInFlightConnections uint32
+}
+
+var _ tpt.Transport = &WebRTCTransport{}
+
+type Option func(*WebRTCTransport) error
+
+type iceTimeouts struct {
+ Disconnect time.Duration
+ Failed time.Duration
+ Keepalive time.Duration
+}
+
+func New(privKey ic.PrivKey, psk pnet.PSK, gater connmgr.ConnectionGater, rcmgr network.ResourceManager, opts ...Option) (*WebRTCTransport, error) {
+ if psk != nil {
+ log.Error("WebRTC doesn't support private networks yet.")
+ return nil, fmt.Errorf("WebRTC doesn't support private networks yet")
+ }
+ localPeerID, err := peer.IDFromPrivateKey(privKey)
+ if err != nil {
+ return nil, fmt.Errorf("get local peer ID: %w", err)
+ }
+ // We use elliptic P-256 since it is widely supported by browsers.
+ //
+ // Implementation note: Testing with the browser,
+ // it seems like Chromium only supports ECDSA P-256 or RSA key signatures in the webrtc TLS certificate.
+ // We tried using P-228 and P-384 which caused the DTLS handshake to fail with Illegal Parameter
+ //
+ // Please refer to this is a list of suggested algorithms for the WebCrypto API.
+ // The algorithm for generating a certificate for an RTCPeerConnection
+ // must adhere to the WebCrpyto API. From my observation,
+ // RSA and ECDSA P-256 is supported on almost all browsers.
+ // Ed25519 is not present on the list.
+ pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ return nil, fmt.Errorf("generate key for cert: %w", err)
+ }
+ cert, err := webrtc.GenerateCertificate(pk)
+ if err != nil {
+ return nil, fmt.Errorf("generate certificate: %w", err)
+ }
+ config := webrtc.Configuration{
+ Certificates: []webrtc.Certificate{*cert},
+ }
+ noiseTpt, err := noise.New(noise.ID, privKey, nil)
+ if err != nil {
+ return nil, fmt.Errorf("unable to create noise transport: %w", err)
+ }
+ transport := &WebRTCTransport{
+ rcmgr: rcmgr,
+ gater: gater,
+ webrtcConfig: config,
+ privKey: privKey,
+ noiseTpt: noiseTpt,
+ localPeerId: localPeerID,
+
+ peerConnectionTimeouts: iceTimeouts{
+ Disconnect: DefaultDisconnectedTimeout,
+ Failed: DefaultFailedTimeout,
+ Keepalive: DefaultKeepaliveTimeout,
+ },
+
+ maxInFlightConnections: DefaultMaxInFlightConnections,
+ }
+ for _, opt := range opts {
+ if err := opt(transport); err != nil {
+ return nil, err
+ }
+ }
+ return transport, nil
+}
+
+func (t *WebRTCTransport) Protocols() []int {
+ return []int{ma.P_WEBRTC_DIRECT}
+}
+
+func (t *WebRTCTransport) Proxy() bool {
+ return false
+}
+
+func (t *WebRTCTransport) CanDial(addr ma.Multiaddr) bool {
+ return dialMatcher.Matches(addr)
+}
+
+// Listen returns a listener for addr.
+//
+// The IP, Port combination for addr must be exclusive to this listener as a WebRTC listener cannot
+// be multiplexed on the same port as other UDP based transports like QUIC and WebTransport.
+// See https://github.com/libp2p/go-libp2p/issues/2446 for details.
+func (t *WebRTCTransport) Listen(addr ma.Multiaddr) (tpt.Listener, error) {
+ addr, wrtcComponent := ma.SplitLast(addr)
+ isWebrtc := wrtcComponent.Equal(webrtcComponent)
+ if !isWebrtc {
+ return nil, fmt.Errorf("must listen on webrtc multiaddr")
+ }
+ nw, host, err := manet.DialArgs(addr)
+ if err != nil {
+ return nil, fmt.Errorf("listener could not fetch dialargs: %w", err)
+ }
+ udpAddr, err := net.ResolveUDPAddr(nw, host)
+ if err != nil {
+ return nil, fmt.Errorf("listener could not resolve udp address: %w", err)
+ }
+
+ socket, err := net.ListenUDP(nw, udpAddr)
+ if err != nil {
+ return nil, fmt.Errorf("listen on udp: %w", err)
+ }
+
+ listener, err := t.listenSocket(socket)
+ if err != nil {
+ socket.Close()
+ return nil, err
+ }
+ return listener, nil
+}
+
+func (t *WebRTCTransport) listenSocket(socket *net.UDPConn) (tpt.Listener, error) {
+ listenerMultiaddr, err := manet.FromNetAddr(socket.LocalAddr())
+ if err != nil {
+ return nil, err
+ }
+
+ listenerFingerprint, err := t.getCertificateFingerprint()
+ if err != nil {
+ return nil, err
+ }
+
+ encodedLocalFingerprint, err := encodeDTLSFingerprint(listenerFingerprint)
+ if err != nil {
+ return nil, err
+ }
+
+ certComp, err := ma.NewComponent(ma.ProtocolWithCode(ma.P_CERTHASH).Name, encodedLocalFingerprint)
+ if err != nil {
+ return nil, err
+ }
+ listenerMultiaddr = listenerMultiaddr.Encapsulate(webrtcComponent).Encapsulate(certComp)
+
+ return newListener(
+ t,
+ listenerMultiaddr,
+ socket,
+ t.webrtcConfig,
+ )
+}
+
+func (t *WebRTCTransport) Dial(ctx context.Context, remoteMultiaddr ma.Multiaddr, p peer.ID) (tpt.CapableConn, error) {
+ scope, err := t.rcmgr.OpenConnection(network.DirOutbound, false, remoteMultiaddr)
+ if err != nil {
+ return nil, err
+ }
+ if err := scope.SetPeer(p); err != nil {
+ scope.Done()
+ return nil, err
+ }
+ conn, err := t.dial(ctx, scope, remoteMultiaddr, p)
+ if err != nil {
+ scope.Done()
+ return nil, err
+ }
+ return conn, nil
+}
+
+func (t *WebRTCTransport) dial(ctx context.Context, scope network.ConnManagementScope, remoteMultiaddr ma.Multiaddr, p peer.ID) (tConn tpt.CapableConn, err error) {
+ var w webRTCConnection
+ defer func() {
+ if err != nil {
+ if w.PeerConnection != nil {
+ _ = w.PeerConnection.Close()
+ }
+ if tConn != nil {
+ _ = tConn.Close()
+ }
+ }
+ }()
+
+ remoteMultihash, err := decodeRemoteFingerprint(remoteMultiaddr)
+ if err != nil {
+ return nil, fmt.Errorf("decode fingerprint: %w", err)
+ }
+ remoteHashFunction, ok := getSupportedSDPHash(remoteMultihash.Code)
+ if !ok {
+ return nil, fmt.Errorf("unsupported hash function: %w", nil)
+ }
+
+ rnw, rhost, err := manet.DialArgs(remoteMultiaddr)
+ if err != nil {
+ return nil, fmt.Errorf("generate dial args: %w", err)
+ }
+
+ raddr, err := net.ResolveUDPAddr(rnw, rhost)
+ if err != nil {
+ return nil, fmt.Errorf("resolve udp address: %w", err)
+ }
+
+ // Instead of encoding the local fingerprint we
+ // generate a random UUID as the connection ufrag.
+ // The only requirement here is that the ufrag and password
+ // must be equal, which will allow the server to determine
+ // the password using the STUN message.
+ ufrag := genUfrag()
+
+ settingEngine := webrtc.SettingEngine{
+ LoggerFactory: pionLoggerFactory,
+ }
+ settingEngine.SetICECredentials(ufrag, ufrag)
+ settingEngine.DetachDataChannels()
+ // use the first best address candidate
+ settingEngine.SetPrflxAcceptanceMinWait(0)
+ settingEngine.SetICETimeouts(
+ t.peerConnectionTimeouts.Disconnect,
+ t.peerConnectionTimeouts.Failed,
+ t.peerConnectionTimeouts.Keepalive,
+ )
+ // By default, webrtc will not collect candidates on the loopback address.
+ // This is disallowed in the ICE specification. However, implementations
+ // do not strictly follow this, for eg. Chrome gathers TCP loopback candidates.
+ // If you run pion on a system with only the loopback interface UP,
+ // it will not connect to anything.
+ settingEngine.SetIncludeLoopbackCandidate(true)
+
+ w, err = newWebRTCConnection(settingEngine, t.webrtcConfig)
+ if err != nil {
+ return nil, fmt.Errorf("instantiating peer connection failed: %w", err)
+ }
+
+ errC := addOnConnectionStateChangeCallback(w.PeerConnection)
+
+ // do offer-answer exchange
+ offer, err := w.PeerConnection.CreateOffer(nil)
+ if err != nil {
+ return nil, fmt.Errorf("create offer: %w", err)
+ }
+
+ err = w.PeerConnection.SetLocalDescription(offer)
+ if err != nil {
+ return nil, fmt.Errorf("set local description: %w", err)
+ }
+
+ answerSDPString, err := createServerSDP(raddr, ufrag, *remoteMultihash)
+ if err != nil {
+ return nil, fmt.Errorf("render server SDP: %w", err)
+ }
+
+ answer := webrtc.SessionDescription{SDP: answerSDPString, Type: webrtc.SDPTypeAnswer}
+ err = w.PeerConnection.SetRemoteDescription(answer)
+ if err != nil {
+ return nil, fmt.Errorf("set remote description: %w", err)
+ }
+
+ // await peerconnection opening
+ select {
+ case err := <-errC:
+ if err != nil {
+ return nil, err
+ }
+ case <-ctx.Done():
+ return nil, errors.New("peerconnection opening timed out")
+ }
+
+ // We are connected, run the noise handshake
+ detached, err := detachHandshakeDataChannel(ctx, w.HandshakeDataChannel)
+ if err != nil {
+ return nil, err
+ }
+ channel := newStream(w.HandshakeDataChannel, detached, func() {})
+
+ remotePubKey, err := t.noiseHandshake(ctx, w.PeerConnection, channel, p, remoteHashFunction, false)
+ if err != nil {
+ return nil, err
+ }
+
+ // Setup local and remote address for the connection
+ cp, err := w.HandshakeDataChannel.Transport().Transport().ICETransport().GetSelectedCandidatePair()
+ if cp == nil {
+ return nil, errors.New("ice connection did not have selected candidate pair: nil result")
+ }
+ if err != nil {
+ return nil, fmt.Errorf("ice connection did not have selected candidate pair: error: %w", err)
+ }
+ // the local address of the selected candidate pair should be the local address for the connection
+ localAddr, err := manet.FromNetAddr(&net.UDPAddr{IP: net.ParseIP(cp.Local.Address), Port: int(cp.Local.Port)})
+ if err != nil {
+ return nil, err
+ }
+ remoteMultiaddrWithoutCerthash, _ := ma.SplitFunc(remoteMultiaddr, func(c ma.Component) bool { return c.Protocol().Code == ma.P_CERTHASH })
+
+ conn, err := newConnection(
+ network.DirOutbound,
+ w.PeerConnection,
+ t,
+ scope,
+ t.localPeerId,
+ localAddr,
+ p,
+ remotePubKey,
+ remoteMultiaddrWithoutCerthash,
+ w.IncomingDataChannels,
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ if t.gater != nil && !t.gater.InterceptSecured(network.DirOutbound, p, conn) {
+ return nil, fmt.Errorf("secured connection gated")
+ }
+ return conn, nil
+}
+
+func genUfrag() string {
+ const (
+ uFragAlphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
+ uFragPrefix = "libp2p+webrtc+v1/"
+ uFragIdLength = 32
+ uFragIdOffset = len(uFragPrefix)
+ uFragLength = uFragIdOffset + uFragIdLength
+ )
+
+ seed := [8]byte{}
+ rand.Read(seed[:])
+ r := mrand.New(mrand.NewSource(binary.BigEndian.Uint64(seed[:])))
+ b := make([]byte, uFragLength)
+ for i := uFragIdOffset; i < uFragLength; i++ {
+ b[i] = uFragAlphabet[r.Intn(len(uFragAlphabet))]
+ }
+ return string(b)
+}
+
+func (t *WebRTCTransport) getCertificateFingerprint() (webrtc.DTLSFingerprint, error) {
+ fps, err := t.webrtcConfig.Certificates[0].GetFingerprints()
+ if err != nil {
+ return webrtc.DTLSFingerprint{}, err
+ }
+ return fps[0], nil
+}
+
+func (t *WebRTCTransport) generateNoisePrologue(pc *webrtc.PeerConnection, hash crypto.Hash, inbound bool) ([]byte, error) {
+ raw := pc.SCTP().Transport().GetRemoteCertificate()
+ cert, err := x509.ParseCertificate(raw)
+ if err != nil {
+ return nil, err
+ }
+
+ // NOTE: should we want we can fork the cert code as well to avoid
+ // all the extra allocations due to unneeded string interspersing (hex)
+ localFp, err := t.getCertificateFingerprint()
+ if err != nil {
+ return nil, err
+ }
+
+ remoteFpBytes, err := parseFingerprint(cert, hash)
+ if err != nil {
+ return nil, err
+ }
+
+ localFpBytes, err := decodeInterspersedHexFromASCIIString(localFp.Value)
+ if err != nil {
+ return nil, err
+ }
+
+ localEncoded, err := multihash.Encode(localFpBytes, multihash.SHA2_256)
+ if err != nil {
+ log.Debugf("could not encode multihash for local fingerprint")
+ return nil, err
+ }
+ remoteEncoded, err := multihash.Encode(remoteFpBytes, multihash.SHA2_256)
+ if err != nil {
+ log.Debugf("could not encode multihash for remote fingerprint")
+ return nil, err
+ }
+
+ result := []byte("libp2p-webrtc-noise:")
+ if inbound {
+ result = append(result, remoteEncoded...)
+ result = append(result, localEncoded...)
+ } else {
+ result = append(result, localEncoded...)
+ result = append(result, remoteEncoded...)
+ }
+ return result, nil
+}
+
+func (t *WebRTCTransport) noiseHandshake(ctx context.Context, pc *webrtc.PeerConnection, s *stream, peer peer.ID, hash crypto.Hash, inbound bool) (ic.PubKey, error) {
+ prologue, err := t.generateNoisePrologue(pc, hash, inbound)
+ if err != nil {
+ return nil, fmt.Errorf("generate prologue: %w", err)
+ }
+ opts := make([]noise.SessionOption, 0, 2)
+ opts = append(opts, noise.Prologue(prologue))
+ if peer == "" {
+ opts = append(opts, noise.DisablePeerIDCheck())
+ }
+ sessionTransport, err := t.noiseTpt.WithSessionOptions(opts...)
+ if err != nil {
+ return nil, fmt.Errorf("failed to instantiate Noise transport: %w", err)
+ }
+ var secureConn sec.SecureConn
+ if inbound {
+ secureConn, err = sessionTransport.SecureOutbound(ctx, netConnWrapper{s}, peer)
+ if err != nil {
+ return nil, fmt.Errorf("failed to secure inbound connection: %w", err)
+ }
+ } else {
+ secureConn, err = sessionTransport.SecureInbound(ctx, netConnWrapper{s}, peer)
+ if err != nil {
+ return nil, fmt.Errorf("failed to secure outbound connection: %w", err)
+ }
+ }
+ return secureConn.RemotePublicKey(), nil
+}
+
+type netConnWrapper struct {
+ *stream
+}
+
+func (netConnWrapper) LocalAddr() net.Addr { return nil }
+func (netConnWrapper) RemoteAddr() net.Addr { return nil }
+func (w netConnWrapper) Close() error {
+ // Close called while running the security handshake is an error and we should Reset the
+ // stream in that case rather than gracefully closing
+ w.stream.Reset()
+ return nil
+}
+
+// detachHandshakeDataChannel detaches the handshake data channel
+func detachHandshakeDataChannel(ctx context.Context, dc *webrtc.DataChannel) (datachannel.ReadWriteCloser, error) {
+ done := make(chan struct{})
+ var rwc datachannel.ReadWriteCloser
+ var err error
+ dc.OnOpen(func() {
+ defer close(done)
+ rwc, err = dc.Detach()
+ })
+ // this is safe since for detached datachannels, the peerconnection runs the onOpen
+ // callback immediately if the SCTP transport is also connected.
+ select {
+ case <-done:
+ return rwc, err
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+}
+
+// webRTCConnection holds the webrtc.PeerConnection with the handshake channel and the queue for
+// incoming data channels created by the peer.
+//
+// When creating a webrtc.PeerConnection, It is important to set the OnDataChannel handler upfront
+// before connecting with the peer. If the handler's set up after connecting with the peer, there's
+// a small window of time where datachannels created by the peer may not surface to us and cause a
+// memory leak.
+type webRTCConnection struct {
+ PeerConnection *webrtc.PeerConnection
+ HandshakeDataChannel *webrtc.DataChannel
+ IncomingDataChannels chan dataChannel
+}
+
+func newWebRTCConnection(settings webrtc.SettingEngine, config webrtc.Configuration) (webRTCConnection, error) {
+ api := webrtc.NewAPI(webrtc.WithSettingEngine(settings))
+ pc, err := api.NewPeerConnection(config)
+ if err != nil {
+ return webRTCConnection{}, fmt.Errorf("failed to create peer connection: %w", err)
+ }
+
+ negotiated, id := handshakeChannelNegotiated, handshakeChannelID
+ handshakeDataChannel, err := pc.CreateDataChannel("", &webrtc.DataChannelInit{
+ Negotiated: &negotiated,
+ ID: &id,
+ })
+ if err != nil {
+ pc.Close()
+ return webRTCConnection{}, fmt.Errorf("failed to create handshake channel: %w", err)
+ }
+
+ incomingDataChannels := make(chan dataChannel, maxAcceptQueueLen)
+ pc.OnDataChannel(func(dc *webrtc.DataChannel) {
+ dc.OnOpen(func() {
+ rwc, err := dc.Detach()
+ if err != nil {
+ log.Warnf("could not detach datachannel: id: %d", *dc.ID())
+ return
+ }
+ select {
+ case incomingDataChannels <- dataChannel{rwc, dc}:
+ default:
+ log.Warnf("connection busy, rejecting stream")
+ b, _ := proto.Marshal(&pb.Message{Flag: pb.Message_RESET.Enum()})
+ w := msgio.NewWriter(rwc)
+ w.WriteMsg(b)
+ rwc.Close()
+ }
+ })
+ })
+ return webRTCConnection{
+ PeerConnection: pc,
+ HandshakeDataChannel: handshakeDataChannel,
+ IncomingDataChannels: incomingDataChannels,
+ }, nil
+}
diff --git a/p2p/transport/webrtc/transport_test.go b/p2p/transport/webrtc/transport_test.go
new file mode 100644
index 0000000000..e5ef3ca1d0
--- /dev/null
+++ b/p2p/transport/webrtc/transport_test.go
@@ -0,0 +1,795 @@
+package libp2pwebrtc
+
+import (
+ "context"
+ "crypto/rand"
+ "encoding/hex"
+ "fmt"
+ "io"
+ "net"
+ "os"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "testing"
+ "time"
+
+ "github.com/libp2p/go-libp2p/core/crypto"
+ "github.com/libp2p/go-libp2p/core/network"
+ "github.com/libp2p/go-libp2p/core/peer"
+ ma "github.com/multiformats/go-multiaddr"
+ manet "github.com/multiformats/go-multiaddr/net"
+ "github.com/multiformats/go-multibase"
+ "github.com/multiformats/go-multihash"
+ quicproxy "github.com/quic-go/quic-go/integrationtests/tools/proxy"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "golang.org/x/crypto/sha3"
+)
+
+func getTransport(t *testing.T, opts ...Option) (*WebRTCTransport, peer.ID) {
+ t.Helper()
+ privKey, _, err := crypto.GenerateKeyPair(crypto.Ed25519, -1)
+ require.NoError(t, err)
+ rcmgr := &network.NullResourceManager{}
+ transport, err := New(privKey, nil, nil, rcmgr, opts...)
+ require.NoError(t, err)
+ peerID, err := peer.IDFromPrivateKey(privKey)
+ require.NoError(t, err)
+ t.Cleanup(func() { rcmgr.Close() })
+ return transport, peerID
+}
+
+func TestTransportWebRTC_CanDial(t *testing.T) {
+ tr, _ := getTransport(t)
+ invalid := []string{
+ "/ip4/1.2.3.4/udp/1234/webrtc-direct",
+ "/dns/test.test/udp/1234/webrtc-direct",
+ }
+
+ valid := []string{
+ "/ip4/1.2.3.4/udp/1234/webrtc-direct/certhash/uEiAsGPzpiPGQzSlVHRXrUCT5EkTV7YFrV4VZ3hpEKTd_zg",
+ "/ip6/0:0:0:0:0:0:0:1/udp/1234/webrtc-direct/certhash/uEiAsGPzpiPGQzSlVHRXrUCT5EkTV7YFrV4VZ3hpEKTd_zg",
+ "/ip6/::1/udp/1234/webrtc-direct/certhash/uEiAsGPzpiPGQzSlVHRXrUCT5EkTV7YFrV4VZ3hpEKTd_zg",
+ "/dns/test.test/udp/1234/webrtc-direct/certhash/uEiAsGPzpiPGQzSlVHRXrUCT5EkTV7YFrV4VZ3hpEKTd_zg",
+ }
+
+ for _, addr := range invalid {
+ a := ma.StringCast(addr)
+ require.False(t, tr.CanDial(a))
+ }
+
+ for _, addr := range valid {
+ a := ma.StringCast(addr)
+ require.True(t, tr.CanDial(a), addr)
+ }
+}
+
+func TestTransportWebRTC_ListenFailsOnNonWebRTCMultiaddr(t *testing.T) {
+ tr, _ := getTransport(t)
+ testAddrs := []string{
+ "/ip4/0.0.0.0/udp/0",
+ "/ip4/0.0.0.0/tcp/0/wss",
+ }
+ for _, addr := range testAddrs {
+ listenMultiaddr, err := ma.NewMultiaddr(addr)
+ require.NoError(t, err)
+ listener, err := tr.Listen(listenMultiaddr)
+ require.Error(t, err)
+ require.Nil(t, listener)
+ }
+}
+
+// using assert inside goroutines, refer: https://github.com/stretchr/testify/issues/772#issuecomment-945166599
+func TestTransportWebRTC_DialFailsOnUnsupportedHashFunction(t *testing.T) {
+ tr, _ := getTransport(t)
+ hash := sha3.New512()
+ certhash := func() string {
+ _, err := hash.Write([]byte("test-data"))
+ require.NoError(t, err)
+ mh, err := multihash.Encode(hash.Sum([]byte{}), multihash.SHA3_512)
+ require.NoError(t, err)
+ certhash, err := multibase.Encode(multibase.Base58BTC, mh)
+ require.NoError(t, err)
+ return certhash
+ }()
+ testaddr, err := ma.NewMultiaddr("/ip4/1.2.3.4/udp/1234/webrtc-direct/certhash/" + certhash)
+ require.NoError(t, err)
+ _, err = tr.Dial(context.Background(), testaddr, "")
+ require.ErrorContains(t, err, "unsupported hash function")
+}
+
+func TestTransportWebRTC_CanListenSingle(t *testing.T) {
+ tr, listeningPeer := getTransport(t)
+ tr1, connectingPeer := getTransport(t)
+ listenMultiaddr := ma.StringCast("/ip4/127.0.0.1/udp/0/webrtc-direct")
+
+ listener, err := tr.Listen(listenMultiaddr)
+ require.NoError(t, err)
+ defer listener.Close()
+
+ done := make(chan struct{})
+ go func() {
+ _, err := tr1.Dial(context.Background(), listener.Multiaddr(), listeningPeer)
+ assert.NoError(t, err)
+ close(done)
+ }()
+
+ conn, err := listener.Accept()
+ require.NoError(t, err)
+ require.NotNil(t, conn)
+
+ require.Equal(t, connectingPeer, conn.RemotePeer())
+ select {
+ case <-done:
+ case <-time.After(10 * time.Second):
+ t.FailNow()
+ }
+}
+
+// WithListenerMaxInFlightConnections sets the maximum number of connections that are in-flight, i.e
+// they are being negotiated, or are waiting to be accepted.
+func WithListenerMaxInFlightConnections(m uint32) Option {
+ return func(t *WebRTCTransport) error {
+ if m == 0 {
+ t.maxInFlightConnections = DefaultMaxInFlightConnections
+ } else {
+ t.maxInFlightConnections = m
+ }
+ return nil
+ }
+}
+
+func TestTransportWebRTC_CanListenMultiple(t *testing.T) {
+ count := 3
+ tr, listeningPeer := getTransport(t, WithListenerMaxInFlightConnections(uint32(count)))
+
+ listenMultiaddr := ma.StringCast("/ip4/127.0.0.1/udp/0/webrtc-direct")
+ listener, err := tr.Listen(listenMultiaddr)
+ require.NoError(t, err)
+ defer listener.Close()
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ var wg sync.WaitGroup
+ go func() {
+ for i := 0; i < count; i++ {
+ conn, err := listener.Accept()
+ assert.NoError(t, err)
+ assert.NotNil(t, conn)
+ defer conn.Close()
+ }
+ wg.Wait()
+ cancel()
+ }()
+
+ for i := 0; i < count; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ ctr, _ := getTransport(t)
+ conn, err := ctr.Dial(ctx, listener.Multiaddr(), listeningPeer)
+ select {
+ case <-ctx.Done():
+ default:
+ assert.NoError(t, err)
+ assert.NotNil(t, conn)
+ t.Cleanup(func() { conn.Close() })
+ }
+ }()
+ }
+
+ select {
+ case <-ctx.Done():
+ case <-time.After(30 * time.Second):
+ t.Fatalf("timed out")
+ }
+}
+
+func TestTransportWebRTC_CanCreateSuccessiveConnections(t *testing.T) {
+ tr, listeningPeer := getTransport(t)
+ listenMultiaddr := ma.StringCast("/ip4/127.0.0.1/udp/0/webrtc-direct")
+ listener, err := tr.Listen(listenMultiaddr)
+ require.NoError(t, err)
+ defer listener.Close()
+
+ count := 2
+
+ var wg sync.WaitGroup
+ wg.Add(count)
+ go func() {
+ for i := 0; i < count; i++ {
+ ctr, _ := getTransport(t)
+ conn, err := ctr.Dial(context.Background(), listener.Multiaddr(), listeningPeer)
+ require.NoError(t, err)
+ require.Equal(t, conn.RemotePeer(), listeningPeer)
+ t.Cleanup(func() { conn.Close() })
+ wg.Done()
+ }
+ }()
+
+ for i := 0; i < count; i++ {
+ conn, err := listener.Accept()
+ require.NoError(t, err)
+ defer conn.Close()
+ }
+ wg.Wait()
+}
+
+func TestTransportWebRTC_ListenerCanCreateStreams(t *testing.T) {
+ tr, listeningPeer := getTransport(t)
+ tr1, connectingPeer := getTransport(t)
+ listenMultiaddr := ma.StringCast("/ip4/127.0.0.1/udp/0/webrtc-direct")
+ listener, err := tr.Listen(listenMultiaddr)
+ require.NoError(t, err)
+ defer listener.Close()
+
+ streamChan := make(chan network.MuxedStream)
+ go func() {
+ conn, err := tr1.Dial(context.Background(), listener.Multiaddr(), listeningPeer)
+ require.NoError(t, err)
+ t.Cleanup(func() { conn.Close() })
+ t.Logf("connection opened by dialer")
+
+ stream, err := conn.AcceptStream()
+ require.NoError(t, err)
+ t.Logf("dialer accepted stream")
+ streamChan <- stream
+ }()
+
+ conn, err := listener.Accept()
+ require.NoError(t, err)
+ defer conn.Close()
+ require.Equal(t, connectingPeer, conn.RemotePeer())
+ t.Logf("listener accepted connection")
+
+ stream, err := conn.OpenStream(context.Background())
+ require.NoError(t, err)
+ t.Logf("listener opened stream")
+ _, err = stream.Write([]byte("test"))
+ require.NoError(t, err)
+
+ var str network.MuxedStream
+ select {
+ case str = <-streamChan:
+ case <-time.After(3 * time.Second):
+ t.Fatal("stream opening timed out")
+ }
+ buf := make([]byte, 100)
+ stream.SetReadDeadline(time.Now().Add(3 * time.Second))
+ n, err := str.Read(buf)
+ require.NoError(t, err)
+ require.Equal(t, "test", string(buf[:n]))
+}
+
+func TestTransportWebRTC_DialerCanCreateStreams(t *testing.T) {
+ tr, listeningPeer := getTransport(t)
+ listenMultiaddr := ma.StringCast("/ip4/127.0.0.1/udp/0/webrtc-direct")
+ listener, err := tr.Listen(listenMultiaddr)
+ require.NoError(t, err)
+ defer listener.Close()
+
+ tr1, connectingPeer := getTransport(t)
+ done := make(chan struct{})
+
+ go func() {
+ lconn, err := listener.Accept()
+ require.NoError(t, err)
+ require.Equal(t, connectingPeer, lconn.RemotePeer())
+ defer lconn.Close()
+
+ stream, err := lconn.AcceptStream()
+ require.NoError(t, err)
+ buf := make([]byte, 100)
+ n, err := stream.Read(buf)
+ require.NoError(t, err)
+ require.Equal(t, "test", string(buf[:n]))
+
+ close(done)
+ }()
+
+ go func() {
+ conn, err := tr1.Dial(context.Background(), listener.Multiaddr(), listeningPeer)
+ require.NoError(t, err)
+ defer conn.Close()
+ t.Logf("dialer opened connection")
+ stream, err := conn.OpenStream(context.Background())
+ require.NoError(t, err)
+ t.Logf("dialer opened stream")
+ _, err = stream.Write([]byte("test"))
+ require.NoError(t, err)
+ <-done
+ }()
+
+ select {
+ case <-done:
+ case <-time.After(10 * time.Second):
+ t.Fatal("timed out")
+ }
+}
+
+func TestTransportWebRTC_DialerCanCreateStreamsMultiple(t *testing.T) {
+ tr, listeningPeer := getTransport(t)
+ listenMultiaddr := ma.StringCast("/ip4/127.0.0.1/udp/0/webrtc-direct")
+ listener, err := tr.Listen(listenMultiaddr)
+ require.NoError(t, err)
+ defer listener.Close()
+
+ tr1, connectingPeer := getTransport(t)
+ readerDone := make(chan struct{})
+
+ const (
+ numListeners = 10
+ numStreams = 100
+ numWriters = 10
+ size = 20 << 10
+ )
+
+ go func() {
+ lconn, err := listener.Accept()
+ require.NoError(t, err)
+ require.Equal(t, connectingPeer, lconn.RemotePeer())
+ defer lconn.Close()
+ var wg sync.WaitGroup
+ var doneStreams atomic.Int32
+ for i := 0; i < numListeners; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ for {
+ var nn int32
+ if nn = doneStreams.Add(1); nn > int32(numStreams) {
+ return
+ }
+ s, err := lconn.AcceptStream()
+ require.NoError(t, err)
+ n, err := io.Copy(s, s)
+ require.Equal(t, n, int64(size))
+ require.NoError(t, err)
+ s.Close()
+ }
+ }()
+ }
+ wg.Wait()
+ readerDone <- struct{}{}
+ }()
+
+ conn, err := tr1.Dial(context.Background(), listener.Multiaddr(), listeningPeer)
+ require.NoError(t, err)
+ defer conn.Close()
+
+ var writerWG sync.WaitGroup
+ var cnt atomic.Int32
+ var streamsStarted atomic.Int32
+ for i := 0; i < numWriters; i++ {
+ writerWG.Add(1)
+ go func() {
+ defer writerWG.Done()
+ buf := make([]byte, size)
+ for {
+ var nn int32
+ if nn = streamsStarted.Add(1); nn > int32(numStreams) {
+ return
+ }
+ rand.Read(buf)
+
+ s, err := conn.OpenStream(context.Background())
+ require.NoError(t, err)
+ n, err := s.Write(buf)
+ require.Equal(t, n, size)
+ require.NoError(t, err)
+ s.CloseWrite()
+ resp := make([]byte, size+10)
+ n, err = io.ReadFull(s, resp)
+ require.ErrorIs(t, err, io.ErrUnexpectedEOF)
+ require.Equal(t, n, size)
+ if string(buf) != string(resp[:size]) {
+ t.Errorf("bytes not equal: %d %d", len(buf), len(resp))
+ }
+ s.Close()
+ t.Log("completed stream: ", cnt.Add(1), s.(*stream).id)
+ }
+ }()
+ }
+ writerWG.Wait()
+ select {
+ case <-readerDone:
+ case <-time.After(100 * time.Second):
+ t.Fatal("timed out")
+ }
+}
+
+func TestTransportWebRTC_Deadline(t *testing.T) {
+ tr, listeningPeer := getTransport(t)
+ listenMultiaddr := ma.StringCast("/ip4/127.0.0.1/udp/0/webrtc-direct")
+ listener, err := tr.Listen(listenMultiaddr)
+ require.NoError(t, err)
+ defer listener.Close()
+ tr1, connectingPeer := getTransport(t)
+
+ t.Run("SetReadDeadline", func(t *testing.T) {
+ go func() {
+ lconn, err := listener.Accept()
+ require.NoError(t, err)
+ t.Cleanup(func() { lconn.Close() })
+ require.Equal(t, connectingPeer, lconn.RemotePeer())
+ _, err = lconn.AcceptStream()
+ require.NoError(t, err)
+ }()
+
+ conn, err := tr1.Dial(context.Background(), listener.Multiaddr(), listeningPeer)
+ require.NoError(t, err)
+ defer conn.Close()
+ stream, err := conn.OpenStream(context.Background())
+ require.NoError(t, err)
+
+ // deadline set to the past
+ stream.SetReadDeadline(time.Now().Add(-200 * time.Millisecond))
+ _, err = stream.Read([]byte{0, 0})
+ require.ErrorIs(t, err, os.ErrDeadlineExceeded)
+
+ // future deadline exceeded
+ stream.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+ _, err = stream.Read([]byte{0, 0})
+ require.ErrorIs(t, err, os.ErrDeadlineExceeded)
+ })
+
+ t.Run("SetWriteDeadline", func(t *testing.T) {
+ go func() {
+ lconn, err := listener.Accept()
+ require.NoError(t, err)
+ t.Cleanup(func() { lconn.Close() })
+ require.Equal(t, connectingPeer, lconn.RemotePeer())
+ _, err = lconn.AcceptStream()
+ require.NoError(t, err)
+ }()
+
+ conn, err := tr1.Dial(context.Background(), listener.Multiaddr(), listeningPeer)
+ require.NoError(t, err)
+ defer conn.Close()
+ stream, err := conn.OpenStream(context.Background())
+ require.NoError(t, err)
+
+ stream.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
+ largeBuffer := make([]byte, 2*1024*1024)
+ _, err = stream.Write(largeBuffer)
+ require.ErrorIs(t, err, os.ErrDeadlineExceeded)
+
+ stream.SetWriteDeadline(time.Now().Add(-200 * time.Millisecond))
+ smallBuffer := make([]byte, 1024)
+ _, err = stream.Write(smallBuffer)
+ require.ErrorIs(t, err, os.ErrDeadlineExceeded)
+ })
+}
+
+func TestTransportWebRTC_StreamWriteBufferContention(t *testing.T) {
+ tr, listeningPeer := getTransport(t)
+ listenMultiaddr := ma.StringCast("/ip4/127.0.0.1/udp/0/webrtc-direct")
+ listener, err := tr.Listen(listenMultiaddr)
+ require.NoError(t, err)
+ defer listener.Close()
+
+ tr1, connectingPeer := getTransport(t)
+
+ var wg sync.WaitGroup
+ wg.Add(3)
+ go func() {
+ defer wg.Done()
+ lconn, err := listener.Accept()
+ require.NoError(t, err)
+ t.Cleanup(func() { lconn.Close() })
+ require.Equal(t, connectingPeer, lconn.RemotePeer())
+ for i := 0; i < 2; i++ {
+ go func() {
+ defer wg.Done()
+ _, err := lconn.AcceptStream()
+ require.NoError(t, err)
+ }()
+ }
+ }()
+
+ conn, err := tr1.Dial(context.Background(), listener.Multiaddr(), listeningPeer)
+ require.NoError(t, err)
+ defer conn.Close()
+
+ errC := make(chan error)
+ // writers
+ for i := 0; i < 2; i++ {
+ go func() {
+ stream, err := conn.OpenStream(context.Background())
+ require.NoError(t, err)
+
+ stream.SetWriteDeadline(time.Now().Add(200 * time.Millisecond))
+ largeBuffer := make([]byte, 2*1024*1024)
+ _, err = stream.Write(largeBuffer)
+ errC <- err
+ }()
+ }
+
+ require.ErrorIs(t, <-errC, os.ErrDeadlineExceeded)
+ require.ErrorIs(t, <-errC, os.ErrDeadlineExceeded)
+ wg.Wait()
+}
+
+func TestTransportWebRTC_RemoteReadsAfterClose(t *testing.T) {
+ tr, listeningPeer := getTransport(t)
+ listenMultiaddr := ma.StringCast("/ip4/127.0.0.1/udp/0/webrtc-direct")
+ listener, err := tr.Listen(listenMultiaddr)
+ require.NoError(t, err)
+ defer listener.Close()
+
+ tr1, _ := getTransport(t)
+
+ done := make(chan error)
+ go func() {
+ lconn, err := listener.Accept()
+ if err != nil {
+ done <- err
+ return
+ }
+ t.Cleanup(func() { lconn.Close() })
+
+ stream, err := lconn.AcceptStream()
+ if err != nil {
+ done <- err
+ return
+ }
+ _, err = stream.Write([]byte{1, 2, 3, 4})
+ if err != nil {
+ done <- err
+ return
+ }
+ err = stream.Close()
+ if err != nil {
+ done <- err
+ return
+ }
+ close(done)
+ }()
+
+ conn, err := tr1.Dial(context.Background(), listener.Multiaddr(), listeningPeer)
+ require.NoError(t, err)
+ defer conn.Close()
+ // create a stream
+ stream, err := conn.OpenStream(context.Background())
+
+ require.NoError(t, err)
+ // require write and close to complete
+ require.NoError(t, <-done)
+ stream.SetReadDeadline(time.Now().Add(5 * time.Second))
+
+ buf := make([]byte, 10)
+ n, err := stream.Read(buf)
+ require.NoError(t, err)
+ require.Equal(t, 4, n)
+}
+
+func TestTransportWebRTC_RemoteReadsAfterClose2(t *testing.T) {
+ tr, listeningPeer := getTransport(t)
+ listenMultiaddr := ma.StringCast("/ip4/127.0.0.1/udp/0/webrtc-direct")
+ listener, err := tr.Listen(listenMultiaddr)
+ require.NoError(t, err)
+ defer listener.Close()
+
+ tr1, _ := getTransport(t)
+
+ awaitStreamClosure := make(chan struct{})
+ readBytesResult := make(chan int)
+ done := make(chan error)
+ go func() {
+ lconn, err := listener.Accept()
+ if err != nil {
+ done <- err
+ return
+ }
+ defer lconn.Close()
+ stream, err := lconn.AcceptStream()
+ if err != nil {
+ done <- err
+ return
+ }
+
+ <-awaitStreamClosure
+ buf := make([]byte, 16)
+ n, err := stream.Read(buf)
+ if err != nil {
+ done <- err
+ return
+ }
+ readBytesResult <- n
+ close(done)
+ }()
+
+ conn, err := tr1.Dial(context.Background(), listener.Multiaddr(), listeningPeer)
+ require.NoError(t, err)
+ defer conn.Close()
+ // create a stream
+ stream, err := conn.OpenStream(context.Background())
+ require.NoError(t, err)
+ _, err = stream.Write([]byte{1, 2, 3, 4})
+ require.NoError(t, err)
+ err = stream.Close()
+ require.NoError(t, err)
+ // signal stream closure
+ close(awaitStreamClosure)
+ require.Equal(t, 4, <-readBytesResult)
+}
+
+func TestTransportWebRTC_Close(t *testing.T) {
+ tr, listeningPeer := getTransport(t)
+ listenMultiaddr := ma.StringCast("/ip4/127.0.0.1/udp/0/webrtc-direct")
+ listener, err := tr.Listen(listenMultiaddr)
+ require.NoError(t, err)
+ defer listener.Close()
+
+ tr1, connectingPeer := getTransport(t)
+
+ t.Run("RemoteClosesStream", func(t *testing.T) {
+ var wg sync.WaitGroup
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ lconn, err := listener.Accept()
+ require.NoError(t, err)
+ t.Cleanup(func() { lconn.Close() })
+ require.Equal(t, connectingPeer, lconn.RemotePeer())
+ stream, err := lconn.AcceptStream()
+ require.NoError(t, err)
+ time.Sleep(100 * time.Millisecond)
+ _ = stream.Close()
+ }()
+
+ buf := make([]byte, 2)
+
+ conn, err := tr1.Dial(context.Background(), listener.Multiaddr(), listeningPeer)
+ require.NoError(t, err)
+ defer conn.Close()
+ stream, err := conn.OpenStream(context.Background())
+ require.NoError(t, err)
+
+ err = stream.SetReadDeadline(time.Now().Add(2 * time.Second))
+ require.NoError(t, err)
+ _, err = stream.Read(buf)
+ require.ErrorIs(t, err, io.EOF)
+
+ wg.Wait()
+ })
+}
+
+func TestTransportWebRTC_PeerConnectionDTLSFailed(t *testing.T) {
+ tr, listeningPeer := getTransport(t)
+ listenMultiaddr := ma.StringCast("/ip4/127.0.0.1/udp/0/webrtc-direct")
+ ln, err := tr.Listen(listenMultiaddr)
+ require.NoError(t, err)
+ defer ln.Close()
+
+ encoded, err := hex.DecodeString("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
+ require.NoError(t, err)
+ encodedCerthash, err := multihash.Encode(encoded, multihash.SHA2_256)
+ require.NoError(t, err)
+ badEncodedCerthash, err := multibase.Encode(multibase.Base58BTC, encodedCerthash)
+ require.NoError(t, err)
+ badCerthash, err := ma.NewMultiaddr(fmt.Sprintf("/certhash/%s", badEncodedCerthash))
+ require.NoError(t, err)
+ badMultiaddr, _ := ma.SplitFunc(ln.Multiaddr(), func(c ma.Component) bool { return c.Protocol().Code == ma.P_CERTHASH })
+ badMultiaddr = badMultiaddr.Encapsulate(badCerthash)
+
+ tr1, _ := getTransport(t)
+ conn, err := tr1.Dial(context.Background(), badMultiaddr, listeningPeer)
+ require.Error(t, err)
+ require.ErrorContains(t, err, "failed")
+ require.Nil(t, conn)
+}
+
+func TestConnectionTimeoutOnListener(t *testing.T) {
+ tr, listeningPeer := getTransport(t)
+ tr.peerConnectionTimeouts.Disconnect = 100 * time.Millisecond
+ tr.peerConnectionTimeouts.Failed = 150 * time.Millisecond
+ tr.peerConnectionTimeouts.Keepalive = 50 * time.Millisecond
+
+ listenMultiaddr := ma.StringCast("/ip4/127.0.0.1/udp/0/webrtc-direct")
+ ln, err := tr.Listen(listenMultiaddr)
+ require.NoError(t, err)
+ defer ln.Close()
+
+ var drop atomic.Bool
+ proxy, err := quicproxy.NewQuicProxy("127.0.0.1:0", &quicproxy.Opts{
+ RemoteAddr: fmt.Sprintf("127.0.0.1:%d", ln.Addr().(*net.UDPAddr).Port),
+ DropPacket: func(quicproxy.Direction, []byte) bool { return drop.Load() },
+ })
+ require.NoError(t, err)
+ defer proxy.Close()
+
+ tr1, connectingPeer := getTransport(t)
+ go func() {
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancel()
+ addr, err := manet.FromNetAddr(proxy.LocalAddr())
+ require.NoError(t, err)
+ _, webrtcComponent := ma.SplitFunc(ln.Multiaddr(), func(c ma.Component) bool { return c.Protocol().Code == ma.P_WEBRTC_DIRECT })
+ addr = addr.Encapsulate(webrtcComponent)
+ conn, err := tr1.Dial(ctx, addr, listeningPeer)
+ require.NoError(t, err)
+ t.Cleanup(func() { conn.Close() })
+ str, err := conn.OpenStream(ctx)
+ require.NoError(t, err)
+ str.Write([]byte("foobar"))
+ }()
+
+ conn, err := ln.Accept()
+ require.NoError(t, err)
+ require.Equal(t, connectingPeer, conn.RemotePeer())
+ defer conn.Close()
+
+ str, err := conn.AcceptStream()
+ require.NoError(t, err)
+ _, err = str.Write([]byte("test"))
+ require.NoError(t, err)
+ // start dropping all packets
+ drop.Store(true)
+ start := time.Now()
+ for {
+ if _, err := str.Write([]byte("test")); err != nil {
+ if os.IsTimeout(err) {
+ break
+ }
+ // If we write when a connection timeout happens, sctp provides
+ // a "stream closed" error. This occurs concurrently with the
+ // callback we receive for connection timeout.
+ // Test once more after sleep that we provide the correct error.
+ if strings.Contains(err.Error(), "stream closed") {
+ time.Sleep(50 * time.Millisecond)
+ _, err = str.Write([]byte("test"))
+ require.True(t, os.IsTimeout(err), "invalid error type: %v", err)
+ } else {
+ t.Fatal("invalid error type", err)
+ }
+ break
+ }
+
+ if time.Since(start) > 5*time.Second {
+ t.Fatal("timeout")
+ }
+ // make sure to not write too often, we don't want to fill the flow control window
+ time.Sleep(20 * time.Millisecond)
+ }
+ // make sure that accepting a stream also returns an error...
+ _, err = conn.AcceptStream()
+ require.True(t, os.IsTimeout(err))
+ // ... as well as opening a new stream
+ _, err = conn.OpenStream(context.Background())
+ require.True(t, os.IsTimeout(err))
+}
+
+func TestMaxInFlightRequests(t *testing.T) {
+ const count = 3
+ tr, listeningPeer := getTransport(t,
+ WithListenerMaxInFlightConnections(count),
+ )
+ ln, err := tr.Listen(ma.StringCast("/ip4/127.0.0.1/udp/0/webrtc-direct"))
+ require.NoError(t, err)
+ defer ln.Close()
+
+ var wg sync.WaitGroup
+ var success, fails atomic.Int32
+ for i := 0; i < count+1; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ dialer, _ := getTransport(t)
+ ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+ defer cancel()
+ if conn, err := dialer.Dial(ctx, ln.Multiaddr(), listeningPeer); err == nil {
+ success.Add(1)
+ t.Cleanup(func() { conn.Close() })
+ } else {
+ t.Log("failed to dial:", err)
+ fails.Add(1)
+ }
+ }()
+ }
+ wg.Wait()
+ require.Equal(t, count, int(success.Load()), "expected exactly 3 dial successes")
+ require.Equal(t, 1, int(fails.Load()), "expected exactly 1 dial failure")
+}
diff --git a/p2p/transport/webrtc/udpmux/mux.go b/p2p/transport/webrtc/udpmux/mux.go
new file mode 100644
index 0000000000..98e60e3f19
--- /dev/null
+++ b/p2p/transport/webrtc/udpmux/mux.go
@@ -0,0 +1,298 @@
+package udpmux
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "io"
+ "net"
+ "strings"
+ "sync"
+
+ logging "github.com/ipfs/go-log/v2"
+ pool "github.com/libp2p/go-buffer-pool"
+ "github.com/pion/ice/v2"
+ "github.com/pion/stun"
+)
+
+var log = logging.Logger("webrtc-udpmux")
+
+// ReceiveBufSize is the size of the buffer used to receive packets from the PacketConn.
+// It is fine for this number to be higher than the actual path MTU as this value is not
+// used to decide the packet size on the write path.
+const ReceiveBufSize = 1500
+
+type Candidate struct {
+ Ufrag string
+ Addr *net.UDPAddr
+}
+
+// UDPMux multiplexes multiple ICE connections over a single net.PacketConn,
+// generally a UDP socket.
+//
+// The connections are indexed by (ufrag, IP address family) and by remote
+// address from which the connection has received valid STUN/RTC packets.
+//
+// When a new packet is received on the underlying net.PacketConn, we
+// first check the address map to see if there is a connection associated with the
+// remote address:
+// If found, we pass the packet to that connection.
+// Otherwise, we check to see if the packet is a STUN packet.
+// If it is, we read the ufrag from the STUN packet and use it to check if there
+// is a connection associated with the (ufrag, IP address family) pair.
+// If found we add the association to the address map.
+type UDPMux struct {
+ socket net.PacketConn
+
+ queue chan Candidate
+
+ mx sync.Mutex
+ // ufragMap allows us to multiplex incoming STUN packets based on ufrag
+ ufragMap map[ufragConnKey]*muxedConnection
+ // addrMap allows us to correctly direct incoming packets after the connection
+ // is established and ufrag isn't available on all packets
+ addrMap map[string]*muxedConnection
+ // ufragAddrMap allows cleaning up all addresses from the addrMap once the connection is closed
+ // During the ICE connectivity checks, the same ufrag might be used on multiple addresses.
+ ufragAddrMap map[ufragConnKey][]net.Addr
+
+ // the context controls the lifecycle of the mux
+ wg sync.WaitGroup
+ ctx context.Context
+ cancel context.CancelFunc
+}
+
+var _ ice.UDPMux = &UDPMux{}
+
+func NewUDPMux(socket net.PacketConn) *UDPMux {
+ ctx, cancel := context.WithCancel(context.Background())
+ mux := &UDPMux{
+ ctx: ctx,
+ cancel: cancel,
+ socket: socket,
+ ufragMap: make(map[ufragConnKey]*muxedConnection),
+ addrMap: make(map[string]*muxedConnection),
+ ufragAddrMap: make(map[ufragConnKey][]net.Addr),
+ queue: make(chan Candidate, 32),
+ }
+
+ return mux
+}
+
+func (mux *UDPMux) Start() {
+ mux.wg.Add(1)
+ go func() {
+ defer mux.wg.Done()
+ mux.readLoop()
+ }()
+}
+
+// GetListenAddresses implements ice.UDPMux
+func (mux *UDPMux) GetListenAddresses() []net.Addr {
+ return []net.Addr{mux.socket.LocalAddr()}
+}
+
+// GetConn implements ice.UDPMux
+// It creates a net.PacketConn for a given ufrag if an existing one cannot be found.
+// We differentiate IPv4 and IPv6 addresses, since a remote is can be reachable at multiple different
+// UDP addresses of the same IP address family (eg. server-reflexive addresses and peer-reflexive addresses).
+func (mux *UDPMux) GetConn(ufrag string, addr net.Addr) (net.PacketConn, error) {
+ a, ok := addr.(*net.UDPAddr)
+ if !ok {
+ return nil, fmt.Errorf("unexpected address type: %T", addr)
+ }
+ select {
+ case <-mux.ctx.Done():
+ return nil, io.ErrClosedPipe
+ default:
+ isIPv6 := ok && a.IP.To4() == nil
+ _, conn := mux.getOrCreateConn(ufrag, isIPv6, mux, addr)
+ return conn, nil
+ }
+}
+
+// Close implements ice.UDPMux
+func (mux *UDPMux) Close() error {
+ select {
+ case <-mux.ctx.Done():
+ return nil
+ default:
+ }
+ mux.cancel()
+ mux.socket.Close()
+ mux.wg.Wait()
+ return nil
+}
+
+// writeTo writes a packet to the underlying net.PacketConn
+func (mux *UDPMux) writeTo(buf []byte, addr net.Addr) (int, error) {
+ return mux.socket.WriteTo(buf, addr)
+}
+
+func (mux *UDPMux) readLoop() {
+ for {
+ select {
+ case <-mux.ctx.Done():
+ return
+ default:
+ }
+
+ buf := pool.Get(ReceiveBufSize)
+
+ n, addr, err := mux.socket.ReadFrom(buf)
+ if err != nil {
+ if strings.Contains(err.Error(), "use of closed network connection") {
+ log.Debugf("readLoop exiting: socket %s closed", mux.socket.LocalAddr())
+ } else {
+ log.Errorf("error reading from socket %s: %v", mux.socket.LocalAddr(), err)
+ }
+ pool.Put(buf)
+ return
+ }
+ buf = buf[:n]
+
+ if processed := mux.processPacket(buf, addr); !processed {
+ pool.Put(buf)
+ }
+ }
+}
+
+func (mux *UDPMux) processPacket(buf []byte, addr net.Addr) (processed bool) {
+ udpAddr, ok := addr.(*net.UDPAddr)
+ if !ok {
+ log.Errorf("received a non-UDP address: %s", addr)
+ return false
+ }
+ isIPv6 := udpAddr.IP.To4() == nil
+
+ // Connections are indexed by remote address. We first
+ // check if the remote address has a connection associated
+ // with it. If yes, we push the received packet to the connection
+ mux.mx.Lock()
+ conn, ok := mux.addrMap[addr.String()]
+ mux.mx.Unlock()
+ if ok {
+ if err := conn.Push(buf, addr); err != nil {
+ log.Debugf("could not push packet: %v", err)
+ return false
+ }
+ return true
+ }
+
+ if !stun.IsMessage(buf) {
+ log.Debug("incoming message is not a STUN message")
+ return false
+ }
+
+ msg := &stun.Message{Raw: buf}
+ if err := msg.Decode(); err != nil {
+ log.Debugf("failed to decode STUN message: %s", err)
+ return false
+ }
+ if msg.Type != stun.BindingRequest {
+ log.Debugf("incoming message should be a STUN binding request, got %s", msg.Type)
+ return false
+ }
+
+ ufrag, err := ufragFromSTUNMessage(msg)
+ if err != nil {
+ log.Debugf("could not find STUN username: %s", err)
+ return false
+ }
+
+ connCreated, conn := mux.getOrCreateConn(ufrag, isIPv6, mux, udpAddr)
+ if connCreated {
+ select {
+ case mux.queue <- Candidate{Addr: udpAddr, Ufrag: ufrag}:
+ default:
+ log.Debugw("queue full, dropping incoming candidate", "ufrag", ufrag, "addr", udpAddr)
+ conn.Close()
+ return false
+ }
+ }
+
+ if err := conn.Push(buf, addr); err != nil {
+ log.Debugf("could not push packet: %v", err)
+ return false
+ }
+ return true
+}
+
+func (mux *UDPMux) Accept(ctx context.Context) (Candidate, error) {
+ select {
+ case c := <-mux.queue:
+ return c, nil
+ case <-ctx.Done():
+ return Candidate{}, ctx.Err()
+ case <-mux.ctx.Done():
+ return Candidate{}, mux.ctx.Err()
+ }
+}
+
+type ufragConnKey struct {
+ ufrag string
+ isIPv6 bool
+}
+
+// ufragFromSTUNMessage returns the local or ufrag
+// from the STUN username attribute. Local ufrag is the ufrag of the
+// peer which initiated the connectivity check, e.g in a connectivity
+// check from A to B, the username attribute will be B_ufrag:A_ufrag
+// with the local ufrag value being A_ufrag. In case of ice-lite, the
+// localUfrag value will always be the remote peer's ufrag since ICE-lite
+// implementations do not generate connectivity checks. In our specific
+// case, since the local and remote ufrag is equal, we can return
+// either value.
+func ufragFromSTUNMessage(msg *stun.Message) (string, error) {
+ attr, err := msg.Get(stun.AttrUsername)
+ if err != nil {
+ return "", err
+ }
+ index := bytes.Index(attr, []byte{':'})
+ if index == -1 {
+ return "", fmt.Errorf("invalid STUN username attribute")
+ }
+ return string(attr[index+1:]), nil
+}
+
+// RemoveConnByUfrag removes the connection associated with the ufrag and all the
+// addresses associated with that connection. This method is called by pion when
+// a peerconnection is closed.
+func (mux *UDPMux) RemoveConnByUfrag(ufrag string) {
+ if ufrag == "" {
+ return
+ }
+
+ mux.mx.Lock()
+ defer mux.mx.Unlock()
+
+ for _, isIPv6 := range [...]bool{true, false} {
+ key := ufragConnKey{ufrag: ufrag, isIPv6: isIPv6}
+ if _, ok := mux.ufragMap[key]; ok {
+ delete(mux.ufragMap, key)
+ for _, addr := range mux.ufragAddrMap[key] {
+ delete(mux.addrMap, addr.String())
+ }
+ delete(mux.ufragAddrMap, key)
+ }
+ }
+}
+
+func (mux *UDPMux) getOrCreateConn(ufrag string, isIPv6 bool, _ *UDPMux, addr net.Addr) (created bool, _ *muxedConnection) {
+ key := ufragConnKey{ufrag: ufrag, isIPv6: isIPv6}
+
+ mux.mx.Lock()
+ defer mux.mx.Unlock()
+
+ if conn, ok := mux.ufragMap[key]; ok {
+ mux.addrMap[addr.String()] = conn
+ mux.ufragAddrMap[key] = append(mux.ufragAddrMap[key], addr)
+ return false, conn
+ }
+
+ conn := newMuxedConnection(mux, func() { mux.RemoveConnByUfrag(ufrag) })
+ mux.ufragMap[key] = conn
+ mux.addrMap[addr.String()] = conn
+ mux.ufragAddrMap[key] = append(mux.ufragAddrMap[key], addr)
+ return true, conn
+}
diff --git a/p2p/transport/webrtc/udpmux/mux_test.go b/p2p/transport/webrtc/udpmux/mux_test.go
new file mode 100644
index 0000000000..298e5c920f
--- /dev/null
+++ b/p2p/transport/webrtc/udpmux/mux_test.go
@@ -0,0 +1,248 @@
+package udpmux
+
+import (
+ "context"
+ "fmt"
+ "net"
+ "testing"
+ "time"
+
+ "github.com/pion/stun"
+ "github.com/stretchr/testify/require"
+)
+
+func getSTUNBindingRequest(ufrag string) *stun.Message {
+ msg := stun.New()
+ msg.SetType(stun.BindingRequest)
+ uattr := stun.RawAttribute{
+ Type: stun.AttrUsername,
+ Value: []byte(fmt.Sprintf("%s:%s", ufrag, ufrag)), // This is the format we expect in our connections
+ }
+ uattr.AddTo(msg)
+ msg.Encode()
+ return msg
+}
+
+func setupMapping(t *testing.T, ufrag string, from net.PacketConn, m *UDPMux) {
+ t.Helper()
+ msg := getSTUNBindingRequest(ufrag)
+ _, err := from.WriteTo(msg.Raw, m.GetListenAddresses()[0])
+ require.NoError(t, err)
+}
+
+func newPacketConn(t *testing.T) net.PacketConn {
+ t.Helper()
+ udpPort0 := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 0}
+ c, err := net.ListenUDP("udp", udpPort0)
+ require.NoError(t, err)
+ t.Cleanup(func() { c.Close() })
+ return c
+}
+
+func TestAccept(t *testing.T) {
+ c := newPacketConn(t)
+ defer c.Close()
+ m := NewUDPMux(c)
+ m.Start()
+ defer m.Close()
+
+ ufrags := []string{"a", "b", "c", "d"}
+ conns := make([]net.PacketConn, len(ufrags))
+ for i, ufrag := range ufrags {
+ conns[i] = newPacketConn(t)
+ setupMapping(t, ufrag, conns[i], m)
+ }
+ for i, ufrag := range ufrags {
+ c, err := m.Accept(context.Background())
+ require.NoError(t, err)
+ require.Equal(t, c.Ufrag, ufrag)
+ require.Equal(t, c.Addr, conns[i].LocalAddr())
+ }
+
+ for i, ufrag := range ufrags {
+ // should not be accepted
+ setupMapping(t, ufrag, conns[i], m)
+ ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
+ defer cancel()
+ _, err := m.Accept(ctx)
+ require.Error(t, err)
+
+ // should not be accepted
+ cc := newPacketConn(t)
+ setupMapping(t, ufrag, cc, m)
+ ctx, cancel = context.WithTimeout(context.Background(), 100*time.Millisecond)
+ defer cancel()
+ _, err = m.Accept(ctx)
+ require.Error(t, err)
+ }
+}
+
+func TestGetConn(t *testing.T) {
+ c := newPacketConn(t)
+ m := NewUDPMux(c)
+ m.Start()
+ defer m.Close()
+
+ ufrags := []string{"a", "b", "c", "d"}
+ conns := make([]net.PacketConn, len(ufrags))
+ for i, ufrag := range ufrags {
+ conns[i] = newPacketConn(t)
+ setupMapping(t, ufrag, conns[i], m)
+ }
+ for i, ufrag := range ufrags {
+ c, err := m.Accept(context.Background())
+ require.NoError(t, err)
+ require.Equal(t, c.Ufrag, ufrag)
+ require.Equal(t, c.Addr, conns[i].LocalAddr())
+ }
+
+ for i, ufrag := range ufrags {
+ c, err := m.GetConn(ufrag, conns[i].LocalAddr())
+ require.NoError(t, err)
+ msg := make([]byte, 100)
+ _, _, err = c.ReadFrom(msg)
+ require.NoError(t, err)
+ }
+
+ for i, ufrag := range ufrags {
+ cc := newPacketConn(t)
+ // setupMapping of cc to ufrags[0] and remove the stun binding request from the queue
+ setupMapping(t, ufrag, cc, m)
+ mc, err := m.GetConn(ufrag, cc.LocalAddr())
+ require.NoError(t, err)
+ msg := make([]byte, 100)
+ _, _, err = mc.ReadFrom(msg)
+ require.NoError(t, err)
+
+ // Write from new connection should provide the new address on ReadFrom
+ _, err = cc.WriteTo([]byte("test1"), c.LocalAddr())
+ require.NoError(t, err)
+ n, addr, err := mc.ReadFrom(msg)
+ require.NoError(t, err)
+ require.Equal(t, addr, cc.LocalAddr())
+ require.Equal(t, "test1", string(msg[:n]))
+
+ // Write from original connection should provide the original address
+ _, err = conns[i].WriteTo([]byte("test2"), c.LocalAddr())
+ require.NoError(t, err)
+ n, addr, err = mc.ReadFrom(msg)
+ require.NoError(t, err)
+ require.Equal(t, addr, conns[i].LocalAddr())
+ require.Equal(t, "test2", string(msg[:n]))
+ }
+}
+
+func TestRemoveConnByUfrag(t *testing.T) {
+ c := newPacketConn(t)
+ m := NewUDPMux(c)
+ m.Start()
+ defer m.Close()
+
+ // Map each ufrag to two addresses
+ ufrag := "a"
+ count := 10
+ conns := make([]net.PacketConn, count)
+ for i := 0; i < 10; i++ {
+ conns[i] = newPacketConn(t)
+ setupMapping(t, ufrag, conns[i], m)
+ }
+ mc, err := m.GetConn(ufrag, conns[0].LocalAddr())
+ require.NoError(t, err)
+ for i := 0; i < 10; i++ {
+ mc1, err := m.GetConn(ufrag, conns[i].LocalAddr())
+ require.NoError(t, err)
+ if mc1 != mc {
+ t.Fatalf("expected the two muxed connections to be same")
+ }
+ }
+
+ // Now remove the ufrag
+ m.RemoveConnByUfrag(ufrag)
+
+ // All connections should now be associated with b
+ ufrag = "b"
+ for i := 0; i < 10; i++ {
+ setupMapping(t, ufrag, conns[i], m)
+ }
+ mc, err = m.GetConn(ufrag, conns[0].LocalAddr())
+ require.NoError(t, err)
+ for i := 0; i < 10; i++ {
+ mc1, err := m.GetConn(ufrag, conns[i].LocalAddr())
+ require.NoError(t, err)
+ if mc1 != mc {
+ t.Fatalf("expected the two muxed connections to be same")
+ }
+ }
+
+ // Should be different even if the address is the same
+ mc1, err := m.GetConn("a", conns[0].LocalAddr())
+ require.NoError(t, err)
+ if mc1 == mc {
+ t.Fatalf("expected the two connections to be different")
+ }
+}
+
+func TestMuxedConnection(t *testing.T) {
+ c := newPacketConn(t)
+ m := NewUDPMux(c)
+ m.Start()
+ defer m.Close()
+
+ msgCount := 3
+ connCount := 3
+
+ ufrags := []string{"a", "b", "c"}
+ addrUfragMap := make(map[string]string)
+ ufragConnsMap := make(map[string][]net.PacketConn)
+ for _, ufrag := range ufrags {
+ for i := 0; i < connCount; i++ {
+ cc := newPacketConn(t)
+ addrUfragMap[cc.LocalAddr().String()] = ufrag
+ ufragConnsMap[ufrag] = append(ufragConnsMap[ufrag], cc)
+ }
+ }
+
+ done := make(chan bool, len(ufrags))
+ for _, ufrag := range ufrags {
+ go func(ufrag string) {
+ for _, cc := range ufragConnsMap[ufrag] {
+ setupMapping(t, ufrag, cc, m)
+ for j := 0; j < msgCount; j++ {
+ cc.WriteTo([]byte(ufrag), c.LocalAddr())
+ }
+ }
+ done <- true
+ }(ufrag)
+ }
+ for i := 0; i < len(ufrags); i++ {
+ <-done
+ }
+
+ for _, ufrag := range ufrags {
+ mc, err := m.GetConn(ufrag, c.LocalAddr()) // the address is irrelevant
+ require.NoError(t, err)
+ msgs := 0
+ stunRequests := 0
+ msg := make([]byte, 1500)
+ addrPacketCount := make(map[string]int)
+ for i := 0; i < connCount; i++ {
+ for j := 0; j < msgCount+1; j++ {
+ n, addr1, err := mc.ReadFrom(msg)
+ require.NoError(t, err)
+ require.Equal(t, addrUfragMap[addr1.String()], ufrag)
+ addrPacketCount[addr1.String()]++
+ if stun.IsMessage(msg[:n]) {
+ stunRequests++
+ } else {
+ msgs++
+ }
+ }
+ }
+ for addr, v := range addrPacketCount {
+ require.Equal(t, v, msgCount+1) // msgCount msgs + 1 STUN binding request
+ delete(addrUfragMap, addr)
+ }
+ require.Len(t, addrPacketCount, connCount)
+ }
+ require.Empty(t, addrUfragMap)
+}
diff --git a/p2p/transport/webrtc/udpmux/muxed_connection.go b/p2p/transport/webrtc/udpmux/muxed_connection.go
new file mode 100644
index 0000000000..2af5d33253
--- /dev/null
+++ b/p2p/transport/webrtc/udpmux/muxed_connection.go
@@ -0,0 +1,112 @@
+package udpmux
+
+import (
+ "context"
+ "errors"
+ "net"
+ "time"
+
+ pool "github.com/libp2p/go-buffer-pool"
+)
+
+type packet struct {
+ buf []byte
+ addr net.Addr
+}
+
+var _ net.PacketConn = &muxedConnection{}
+
+const queueLen = 128
+
+// muxedConnection provides a net.PacketConn abstraction
+// over packetQueue and adds the ability to store addresses
+// from which this connection (indexed by ufrag) received
+// data.
+type muxedConnection struct {
+ ctx context.Context
+ cancel context.CancelFunc
+ onClose func()
+ queue chan packet
+ mux *UDPMux
+}
+
+var _ net.PacketConn = &muxedConnection{}
+
+func newMuxedConnection(mux *UDPMux, onClose func()) *muxedConnection {
+ ctx, cancel := context.WithCancel(mux.ctx)
+ return &muxedConnection{
+ ctx: ctx,
+ cancel: cancel,
+ queue: make(chan packet, queueLen),
+ onClose: onClose,
+ mux: mux,
+ }
+}
+
+func (c *muxedConnection) Push(buf []byte, addr net.Addr) error {
+ select {
+ case <-c.ctx.Done():
+ return errors.New("closed")
+ default:
+ }
+ select {
+ case c.queue <- packet{buf: buf, addr: addr}:
+ return nil
+ default:
+ return errors.New("queue full")
+ }
+}
+
+func (c *muxedConnection) ReadFrom(buf []byte) (int, net.Addr, error) {
+ select {
+ case p := <-c.queue:
+ n := copy(buf, p.buf) // This might discard parts of the packet, if p is too short
+ if n < len(p.buf) {
+ log.Debugf("short read, had %d, read %d", len(p.buf), n)
+ }
+ pool.Put(p.buf)
+ return n, p.addr, nil
+ case <-c.ctx.Done():
+ return 0, nil, c.ctx.Err()
+ }
+}
+
+func (c *muxedConnection) WriteTo(p []byte, addr net.Addr) (n int, err error) {
+ return c.mux.writeTo(p, addr)
+}
+
+func (c *muxedConnection) Close() error {
+ select {
+ case <-c.ctx.Done():
+ return nil
+ default:
+ }
+ c.onClose()
+ c.cancel()
+ // drain the packet queue
+ for {
+ select {
+ case p := <-c.queue:
+ pool.Put(p.buf)
+ default:
+ return nil
+ }
+ }
+}
+
+func (c *muxedConnection) LocalAddr() net.Addr { return c.mux.socket.LocalAddr() }
+
+func (*muxedConnection) SetDeadline(t time.Time) error {
+ // no deadline is desired here
+ return nil
+}
+
+func (*muxedConnection) SetReadDeadline(t time.Time) error {
+ // no read deadline is desired here
+ return nil
+}
+
+func (*muxedConnection) SetWriteDeadline(t time.Time) error {
+ // no write deadline is desired here
+ return nil
+}
diff --git a/p2p/transport/websocket/addrs_test.go b/p2p/transport/websocket/addrs_test.go
index e2779fd462..3c5ba502a9 100644
--- a/p2p/transport/websocket/addrs_test.go
+++ b/p2p/transport/websocket/addrs_test.go
@@ -73,9 +73,9 @@ func TestListeningOnDNSAddr(t *testing.T) {
require.NoError(t, err)
addr := ln.Multiaddr()
first, rest := ma.SplitFirst(addr)
- require.Equal(t, first.Protocol().Code, ma.P_DNS)
- require.Equal(t, first.Value(), "localhost")
+ require.Equal(t, ma.P_DNS, first.Protocol().Code)
+ require.Equal(t, "localhost", first.Value())
next, _ := ma.SplitFirst(rest)
- require.Equal(t, next.Protocol().Code, ma.P_TCP)
- require.NotEqual(t, next.Value(), "0")
+ require.Equal(t, ma.P_TCP, next.Protocol().Code)
+ require.NotEqual(t, 0, next.Value())
}
diff --git a/p2p/transport/websocket/websocket.go b/p2p/transport/websocket/websocket.go
index e1965123d9..5142ca97a1 100644
--- a/p2p/transport/websocket/websocket.go
+++ b/p2p/transport/websocket/websocket.go
@@ -120,7 +120,7 @@ func (t *WebsocketTransport) Proxy() bool {
return false
}
-func (t *WebsocketTransport) Resolve(ctx context.Context, maddr ma.Multiaddr) ([]ma.Multiaddr, error) {
+func (t *WebsocketTransport) Resolve(_ context.Context, maddr ma.Multiaddr) ([]ma.Multiaddr, error) {
parsed, err := parseWebsocketMultiaddr(maddr)
if err != nil {
return nil, err
@@ -136,7 +136,7 @@ func (t *WebsocketTransport) Resolve(ctx context.Context, maddr ma.Multiaddr) ([
// We don't have an sni component, we'll use dns/dnsaddr
ma.ForEach(parsed.restMultiaddr, func(c ma.Component) bool {
switch c.Protocol().Code {
- case ma.P_DNS, ma.P_DNS4, ma.P_DNS6, ma.P_DNSADDR:
+ case ma.P_DNS, ma.P_DNS4, ma.P_DNS6:
// err shouldn't happen since this means we couldn't parse a dns hostname for an sni value.
parsed.sni, err = ma.NewComponent("sni", c.Value())
return false
diff --git a/p2p/transport/websocket/websocket_test.go b/p2p/transport/websocket/websocket_test.go
index aa06c62825..2023ee3528 100644
--- a/p2p/transport/websocket/websocket_test.go
+++ b/p2p/transport/websocket/websocket_test.go
@@ -525,12 +525,13 @@ func TestWriteZero(t *testing.T) {
func TestResolveMultiaddr(t *testing.T) {
// map[unresolved]resolved
testCases := map[string]string{
+ "/dns/example.com/tcp/1234/wss": "/dns/example.com/tcp/1234/tls/sni/example.com/ws",
"/dns4/example.com/tcp/1234/wss": "/dns4/example.com/tcp/1234/tls/sni/example.com/ws",
"/dns6/example.com/tcp/1234/wss": "/dns6/example.com/tcp/1234/tls/sni/example.com/ws",
- "/dnsaddr/example.com/tcp/1234/wss": "/dnsaddr/example.com/tcp/1234/tls/sni/example.com/ws",
+ "/dnsaddr/example.com/tcp/1234/wss": "/dnsaddr/example.com/tcp/1234/wss",
"/dns4/example.com/tcp/1234/tls/ws": "/dns4/example.com/tcp/1234/tls/sni/example.com/ws",
"/dns6/example.com/tcp/1234/tls/ws": "/dns6/example.com/tcp/1234/tls/sni/example.com/ws",
- "/dnsaddr/example.com/tcp/1234/tls/ws": "/dnsaddr/example.com/tcp/1234/tls/sni/example.com/ws",
+ "/dnsaddr/example.com/tcp/1234/tls/ws": "/dnsaddr/example.com/tcp/1234/tls/ws",
}
for unresolved, expectedMA := range testCases {
diff --git a/p2p/transport/webtransport/cert_manager_test.go b/p2p/transport/webtransport/cert_manager_test.go
index 29999a8fe0..942d47174e 100644
--- a/p2p/transport/webtransport/cert_manager_test.go
+++ b/p2p/transport/webtransport/cert_manager_test.go
@@ -166,7 +166,7 @@ func TestGetCurrentBucketStartTimeIsWithinBounds(t *testing.T) {
offset = offset % certValidity
// Bound this to 100 years
- timeSinceUnixEpoch = time.Duration(timeSinceUnixEpoch % (time.Hour * 24 * 365 * 100))
+ timeSinceUnixEpoch = timeSinceUnixEpoch % (time.Hour * 24 * 365 * 100)
// Start a bit further in the future to avoid edge cases around epoch
timeSinceUnixEpoch += time.Hour * 24 * 365
start := time.UnixMilli(timeSinceUnixEpoch.Milliseconds())
diff --git a/p2p/transport/webtransport/listener.go b/p2p/transport/webtransport/listener.go
index 337239fa8a..2a7c3546f2 100644
--- a/p2p/transport/webtransport/listener.go
+++ b/p2p/transport/webtransport/listener.go
@@ -212,5 +212,14 @@ func (l *listener) Close() error {
l.reuseListener.Close()
err := l.server.Close()
<-l.serverClosed
+loop:
+ for {
+ select {
+ case conn := <-l.queue:
+ conn.Close()
+ default:
+ break loop
+ }
+ }
return err
}
diff --git a/p2p/transport/webtransport/mock_connection_gater_test.go b/p2p/transport/webtransport/mock_connection_gater_test.go
index c6e7dbaad6..245d254fcb 100644
--- a/p2p/transport/webtransport/mock_connection_gater_test.go
+++ b/p2p/transport/webtransport/mock_connection_gater_test.go
@@ -1,5 +1,10 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/libp2p/go-libp2p/core/connmgr (interfaces: ConnectionGater)
+//
+// Generated by this command:
+//
+// mockgen -package libp2pwebtransport_test -destination mock_connection_gater_test.go github.com/libp2p/go-libp2p/core/connmgr ConnectionGater
+//
// Package libp2pwebtransport_test is a generated GoMock package.
package libp2pwebtransport_test
@@ -7,11 +12,11 @@ package libp2pwebtransport_test
import (
reflect "reflect"
- gomock "github.com/golang/mock/gomock"
control "github.com/libp2p/go-libp2p/core/control"
network "github.com/libp2p/go-libp2p/core/network"
peer "github.com/libp2p/go-libp2p/core/peer"
multiaddr "github.com/multiformats/go-multiaddr"
+ gomock "go.uber.org/mock/gomock"
)
// MockConnectionGater is a mock of ConnectionGater interface.
@@ -46,7 +51,7 @@ func (m *MockConnectionGater) InterceptAccept(arg0 network.ConnMultiaddrs) bool
}
// InterceptAccept indicates an expected call of InterceptAccept.
-func (mr *MockConnectionGaterMockRecorder) InterceptAccept(arg0 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptAccept(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptAccept", reflect.TypeOf((*MockConnectionGater)(nil).InterceptAccept), arg0)
}
@@ -60,7 +65,7 @@ func (m *MockConnectionGater) InterceptAddrDial(arg0 peer.ID, arg1 multiaddr.Mul
}
// InterceptAddrDial indicates an expected call of InterceptAddrDial.
-func (mr *MockConnectionGaterMockRecorder) InterceptAddrDial(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptAddrDial(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptAddrDial", reflect.TypeOf((*MockConnectionGater)(nil).InterceptAddrDial), arg0, arg1)
}
@@ -74,7 +79,7 @@ func (m *MockConnectionGater) InterceptPeerDial(arg0 peer.ID) bool {
}
// InterceptPeerDial indicates an expected call of InterceptPeerDial.
-func (mr *MockConnectionGaterMockRecorder) InterceptPeerDial(arg0 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptPeerDial(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptPeerDial", reflect.TypeOf((*MockConnectionGater)(nil).InterceptPeerDial), arg0)
}
@@ -88,7 +93,7 @@ func (m *MockConnectionGater) InterceptSecured(arg0 network.Direction, arg1 peer
}
// InterceptSecured indicates an expected call of InterceptSecured.
-func (mr *MockConnectionGaterMockRecorder) InterceptSecured(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptSecured(arg0, arg1, arg2 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptSecured", reflect.TypeOf((*MockConnectionGater)(nil).InterceptSecured), arg0, arg1, arg2)
}
@@ -103,7 +108,7 @@ func (m *MockConnectionGater) InterceptUpgraded(arg0 network.Conn) (bool, contro
}
// InterceptUpgraded indicates an expected call of InterceptUpgraded.
-func (mr *MockConnectionGaterMockRecorder) InterceptUpgraded(arg0 interface{}) *gomock.Call {
+func (mr *MockConnectionGaterMockRecorder) InterceptUpgraded(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InterceptUpgraded", reflect.TypeOf((*MockConnectionGater)(nil).InterceptUpgraded), arg0)
}
diff --git a/p2p/transport/webtransport/transport_test.go b/p2p/transport/webtransport/transport_test.go
index 6c666dc240..f6c850a2b9 100644
--- a/p2p/transport/webtransport/transport_test.go
+++ b/p2p/transport/webtransport/transport_test.go
@@ -28,7 +28,6 @@ import (
libp2pwebtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport"
"github.com/benbjohnson/clock"
- "github.com/golang/mock/gomock"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
"github.com/multiformats/go-multibase"
@@ -37,6 +36,7 @@ import (
"github.com/quic-go/quic-go/http3"
quicproxy "github.com/quic-go/quic-go/integrationtests/tools/proxy"
"github.com/stretchr/testify/require"
+ "go.uber.org/mock/gomock"
)
const clockSkewAllowance = time.Hour
@@ -97,7 +97,7 @@ func getCerthashComponent(t *testing.T, b []byte) ma.Multiaddr {
func newConnManager(t *testing.T, opts ...quicreuse.Option) *quicreuse.ConnManager {
t.Helper()
- cm, err := quicreuse.NewConnManager([32]byte{}, opts...)
+ cm, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}, opts...)
require.NoError(t, err)
t.Cleanup(func() { cm.Close() })
return cm
@@ -360,7 +360,7 @@ func TestResourceManagerListening(t *testing.T) {
}
// TODO: unify somehow. We do the same in libp2pquic.
-//go:generate sh -c "go run github.com/golang/mock/mockgen -package libp2pwebtransport_test -destination mock_connection_gater_test.go github.com/libp2p/go-libp2p/core/connmgr ConnectionGater && go run golang.org/x/tools/cmd/goimports -w mock_connection_gater_test.go"
+//go:generate sh -c "go run go.uber.org/mock/mockgen -package libp2pwebtransport_test -destination mock_connection_gater_test.go github.com/libp2p/go-libp2p/core/connmgr ConnectionGater && go run golang.org/x/tools/cmd/goimports -w mock_connection_gater_test.go"
func TestConnectionGaterDialing(t *testing.T) {
ctrl := gomock.NewController(t)
@@ -650,7 +650,7 @@ func serverSendsBackValidCert(t *testing.T, timeSinceUnixEpoch time.Duration, ke
}
// Bound this to 100 years
- timeSinceUnixEpoch = time.Duration(timeSinceUnixEpoch % (time.Hour * 24 * 365 * 100))
+ timeSinceUnixEpoch = timeSinceUnixEpoch % (time.Hour * 24 * 365 * 100)
// Start a bit further in the future to avoid edge cases around epoch
timeSinceUnixEpoch += time.Hour * 24 * 365
start := time.UnixMilli(timeSinceUnixEpoch.Milliseconds())
@@ -729,7 +729,7 @@ func TestServerRotatesCertCorrectly(t *testing.T) {
}
// Bound this to 100 years
- timeSinceUnixEpoch = time.Duration(timeSinceUnixEpoch % (time.Hour * 24 * 365 * 100))
+ timeSinceUnixEpoch = timeSinceUnixEpoch % (time.Hour * 24 * 365 * 100)
// Start a bit further in the future to avoid edge cases around epoch
timeSinceUnixEpoch += time.Hour * 24 * 365
start := time.UnixMilli(timeSinceUnixEpoch.Milliseconds())
diff --git a/test-plans/README.md b/test-plans/README.md
index 1d180aacd2..0606f85279 100644
--- a/test-plans/README.md
+++ b/test-plans/README.md
@@ -10,10 +10,10 @@ can dial/listen for ourselves we can do the following:
1. Start redis (needed by the tests): `docker run --rm -it -p 6379:6379
redis/redis-stack`.
-2. In one terminal run the dialer: `REDIS_ADDR=localhost:6379 ip="0.0.0.0"
+2. In one terminal run the dialer: `redis_addr=localhost:6379 ip="0.0.0.0"
transport=quic-v1 security=quic muxer=quic is_dialer="true" go run
./cmd/ping`
-3. In another terminal, run the listener: `REDIS_ADDR=localhost:6379
+3. In another terminal, run the listener: `redis_addr=localhost:6379
ip="0.0.0.0" transport=quic-v1 security=quic muxer=quic is_dialer="false" go
run ./cmd/ping`
@@ -29,9 +29,9 @@ the following (from the root directory of this repository):
1. Build the image: `docker build -t go-libp2p-head -f test-plans/PingDockerfile .`.
2. Build the images for all released versions in `libp2p/test-plans`: `(cd /libp2p/test-plans/multidim-interop/ && make)`.
+ to >/libp2p/test-plans/transport-interop/ && make)`.
3. Run the test:
```
-GO_LIBP2P="$PWD"; (cd /libp2p/test-plans/multidim-interop/ && npm run test -- --extra-version=$GO_LIBP2P/test-plans/ping-version.json --name-filter="go-libp2p-head")
+GO_LIBP2P="$PWD"; (cd /libp2p/test-plans/transport-interop/ && npm run test -- --extra-version=$GO_LIBP2P/test-plans/ping-version.json --name-filter="go-libp2p-head")
```
diff --git a/test-plans/cmd/ping/main.go b/test-plans/cmd/ping/main.go
index df90a4bf08..c836a72e72 100644
--- a/test-plans/cmd/ping/main.go
+++ b/test-plans/cmd/ping/main.go
@@ -15,6 +15,8 @@ import (
"strconv"
"time"
+ libp2pwebrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc"
+
"github.com/go-redis/redis/v8"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/peer"
@@ -103,6 +105,9 @@ func main() {
case "webtransport":
options = append(options, libp2p.Transport(libp2pwebtransport.New))
listenAddr = fmt.Sprintf("/ip4/%s/udp/0/quic-v1/webtransport", ip)
+ case "webrtc-direct":
+ options = append(options, libp2p.Transport(libp2pwebrtc.New))
+ listenAddr = fmt.Sprintf("/ip4/%s/udp/0/webrtc-direct", ip)
default:
log.Fatalf("Unsupported transport: %s", transport)
}
@@ -112,13 +117,11 @@ func main() {
var skipMuxer bool
var skipSecureChannel bool
switch transport {
- case "quic":
- fallthrough
case "quic-v1":
fallthrough
case "webtransport":
fallthrough
- case "webrtc":
+ case "webrtc-direct":
skipMuxer = true
skipSecureChannel = true
}
diff --git a/test-plans/go.mod b/test-plans/go.mod
index 03fb0bd08d..267a41349e 100644
--- a/test-plans/go.mod
+++ b/test-plans/go.mod
@@ -1,11 +1,11 @@
module github.com/libp2p/go-libp2p/test-plans/m/v2
-go 1.20
+go 1.21
require (
github.com/go-redis/redis/v8 v8.11.5
github.com/libp2p/go-libp2p v0.0.0
- github.com/multiformats/go-multiaddr v0.11.0
+ github.com/multiformats/go-multiaddr v0.12.2
)
require (
@@ -14,42 +14,40 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
- github.com/flynn/noise v1.0.0 // indirect
+ github.com/flynn/noise v1.1.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
- github.com/golang/mock v1.6.0 // indirect
- github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gopacket v1.1.19 // indirect
- github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect
- github.com/gorilla/websocket v1.5.0 // indirect
- github.com/huin/goupnp v1.2.0 // indirect
+ github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect
+ github.com/google/uuid v1.4.0 // indirect
+ github.com/gorilla/websocket v1.5.1 // indirect
+ github.com/huin/goupnp v1.3.0 // indirect
github.com/ipfs/go-cid v0.4.1 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
- github.com/klauspost/compress v1.16.7 // indirect
- github.com/klauspost/cpuid/v2 v2.2.5 // indirect
+ github.com/klauspost/compress v1.17.6 // indirect
+ github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
- github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.1.0 // indirect
- github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect
+ github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-nat v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect
github.com/libp2p/go-reuseport v0.4.0 // indirect
github.com/libp2p/go-yamux/v4 v4.0.1 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
- github.com/mattn/go-isatty v0.0.19 // indirect
- github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
- github.com/miekg/dns v1.1.55 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/miekg/dns v1.1.58 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
@@ -61,35 +59,54 @@ require (
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
- github.com/multiformats/go-multistream v0.4.1 // indirect
+ github.com/multiformats/go-multistream v0.5.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
- github.com/onsi/ginkgo/v2 v2.11.0 // indirect
- github.com/opencontainers/runtime-spec v1.1.0 // indirect
+ github.com/onsi/ginkgo/v2 v2.15.0 // indirect
+ github.com/opencontainers/runtime-spec v1.2.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
+ github.com/pion/datachannel v1.5.5 // indirect
+ github.com/pion/dtls/v2 v2.2.8 // indirect
+ github.com/pion/ice/v2 v2.3.11 // indirect
+ github.com/pion/interceptor v0.1.25 // indirect
+ github.com/pion/logging v0.2.2 // indirect
+ github.com/pion/mdns v0.0.9 // indirect
+ github.com/pion/randutil v0.1.0 // indirect
+ github.com/pion/rtcp v1.2.13 // indirect
+ github.com/pion/rtp v1.8.3 // indirect
+ github.com/pion/sctp v1.8.9 // indirect
+ github.com/pion/sdp/v3 v3.0.6 // indirect
+ github.com/pion/srtp/v2 v2.0.18 // indirect
+ github.com/pion/stun v0.6.1 // indirect
+ github.com/pion/transport/v2 v2.2.4 // indirect
+ github.com/pion/turn/v2 v2.1.4 // indirect
+ github.com/pion/webrtc/v3 v3.2.23 // indirect
github.com/pkg/errors v0.9.1 // indirect
- github.com/prometheus/client_golang v1.16.0 // indirect
- github.com/prometheus/client_model v0.4.0 // indirect
- github.com/prometheus/common v0.44.0 // indirect
- github.com/prometheus/procfs v0.11.1 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/prometheus/client_golang v1.18.0 // indirect
+ github.com/prometheus/client_model v0.6.0 // indirect
+ github.com/prometheus/common v0.47.0 // indirect
+ github.com/prometheus/procfs v0.12.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
- github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
- github.com/quic-go/quic-go v0.38.1 // indirect
- github.com/quic-go/webtransport-go v0.5.3 // indirect
+ github.com/quic-go/quic-go v0.41.0 // indirect
+ github.com/quic-go/webtransport-go v0.6.0 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
- go.uber.org/dig v1.17.0 // indirect
- go.uber.org/fx v1.20.0 // indirect
+ github.com/stretchr/testify v1.8.4 // indirect
+ go.uber.org/dig v1.17.1 // indirect
+ go.uber.org/fx v1.20.1 // indirect
+ go.uber.org/mock v0.4.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.25.0 // indirect
- golang.org/x/crypto v0.12.0 // indirect
- golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
- golang.org/x/mod v0.12.0 // indirect
- golang.org/x/net v0.14.0 // indirect
- golang.org/x/sync v0.3.0 // indirect
- golang.org/x/sys v0.11.0 // indirect
- golang.org/x/text v0.12.0 // indirect
- golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
- google.golang.org/protobuf v1.31.0 // indirect
+ go.uber.org/zap v1.27.0 // indirect
+ golang.org/x/crypto v0.19.0 // indirect
+ golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect
+ golang.org/x/mod v0.15.0 // indirect
+ golang.org/x/net v0.21.0 // indirect
+ golang.org/x/sync v0.6.0 // indirect
+ golang.org/x/sys v0.17.0 // indirect
+ golang.org/x/text v0.14.0 // indirect
+ golang.org/x/tools v0.18.0 // indirect
+ google.golang.org/protobuf v1.32.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
)
diff --git a/test-plans/go.sum b/test-plans/go.sum
index f14d5e5b9f..5ee58c6745 100644
--- a/test-plans/go.sum
+++ b/test-plans/go.sum
@@ -37,6 +37,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU=
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
+github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
@@ -49,18 +50,22 @@ github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0
github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4=
github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
-github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
-github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
+github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=
+github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
+github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
-github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
+github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
+github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
+github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -75,39 +80,50 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
-github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo=
-github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
+github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo=
+github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
+github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
+github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
-github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
-github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
+github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
-github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY=
-github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
+github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
-github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
-github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
@@ -120,28 +136,29 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
-github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
-github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
-github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
+github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
+github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
+github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
-github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c=
-github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro=
-github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s=
-github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w=
+github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
+github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
+github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg=
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk=
@@ -157,15 +174,13 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
-github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
-github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
-github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
-github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
+github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
+github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
@@ -187,8 +202,8 @@ github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
-github.com/multiformats/go-multiaddr v0.11.0 h1:XqGyJ8ufbCE0HmTDwx2kPdsrQ36AGPZNZX6s6xfJH10=
-github.com/multiformats/go-multiaddr v0.11.0/go.mod h1:gWUm0QLR4thQ6+ZF6SXUw8YjtwQSPapICM+NmCkxHSM=
+github.com/multiformats/go-multiaddr v0.12.2 h1:9G9sTY/wCYajKa9lyfWPmpZAwe6oV+Wb1zcmMS1HG24=
+github.com/multiformats/go-multiaddr v0.12.2/go.mod h1:GKyaTYjZRdcUhyOetrxTk9z0cW+jA/YrnqTOvKgi44M=
github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A=
github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
@@ -200,54 +215,111 @@ github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI1
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
-github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo=
-github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q=
+github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE=
+github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA=
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
+github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
+github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
-github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
-github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
-github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
+github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
+github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
+github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
+github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
+github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
-github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
+github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
+github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8=
+github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0=
+github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
+github.com/pion/dtls/v2 v2.2.8 h1:BUroldfiIbV9jSnC6cKOMnyiORRWrWWpV11JUyEu5OA=
+github.com/pion/dtls/v2 v2.2.8/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
+github.com/pion/ice/v2 v2.3.11 h1:rZjVmUwyT55cmN8ySMpL7rsS8KYsJERsrxJLLxpKhdw=
+github.com/pion/ice/v2 v2.3.11/go.mod h1:hPcLC3kxMa+JGRzMHqQzjoSj3xtE9F+eoncmXLlCL4E=
+github.com/pion/interceptor v0.1.25 h1:pwY9r7P6ToQ3+IF0bajN0xmk/fNw/suTgaTdlwTDmhc=
+github.com/pion/interceptor v0.1.25/go.mod h1:wkbPYAak5zKsfpVDYMtEfWEy8D4zL+rpxCxPImLOg3Y=
+github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
+github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
+github.com/pion/mdns v0.0.8/go.mod h1:hYE72WX8WDveIhg7fmXgMKivD3Puklk0Ymzog0lSyaI=
+github.com/pion/mdns v0.0.9 h1:7Ue5KZsqq8EuqStnpPWV33vYYEH0+skdDN5L7EiEsI4=
+github.com/pion/mdns v0.0.9/go.mod h1:2JA5exfxwzXiCihmxpTKgFUpiQws2MnipoPK09vecIc=
+github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
+github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
+github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I=
+github.com/pion/rtcp v1.2.12/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4=
+github.com/pion/rtcp v1.2.13 h1:+EQijuisKwm/8VBs8nWllr0bIndR7Lf7cZG200mpbNo=
+github.com/pion/rtcp v1.2.13/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4=
+github.com/pion/rtp v1.8.2/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
+github.com/pion/rtp v1.8.3 h1:VEHxqzSVQxCkKDSHro5/4IUUG1ea+MFdqR2R3xSpNU8=
+github.com/pion/rtp v1.8.3/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
+github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0=
+github.com/pion/sctp v1.8.8/go.mod h1:igF9nZBrjh5AtmKc7U30jXltsFHicFCXSmWA2GWRaWs=
+github.com/pion/sctp v1.8.9 h1:TP5ZVxV5J7rz7uZmbyvnUvsn7EJ2x/5q9uhsTtXbI3g=
+github.com/pion/sctp v1.8.9/go.mod h1:cMLT45jqw3+jiJCrtHVwfQLnfR0MGZ4rgOJwUOIqLkI=
+github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw=
+github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw=
+github.com/pion/srtp/v2 v2.0.18 h1:vKpAXfawO9RtTRKZJbG4y0v1b11NZxQnxRl85kGuUlo=
+github.com/pion/srtp/v2 v2.0.18/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA=
+github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
+github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
+github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40=
+github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI=
+github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
+github.com/pion/transport/v2 v2.2.2/go.mod h1:OJg3ojoBJopjEeECq2yJdXH9YVrUJ1uQ++NjXLOUorc=
+github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
+github.com/pion/transport/v2 v2.2.4 h1:41JJK6DZQYSeVLxILA2+F4ZkKb4Xd/tFJZRFZQ9QAlo=
+github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
+github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM=
+github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0=
+github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
+github.com/pion/turn/v2 v2.1.4 h1:2xn8rduI5W6sCZQkEnIUDAkrBQNl2eYIBCHMZ3QMmP8=
+github.com/pion/turn/v2 v2.1.4/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
+github.com/pion/webrtc/v3 v3.2.23 h1:GbqEuxBbVLFhXk0GwxKAoaIJYiEa9TyoZPEZC+2HZxM=
+github.com/pion/webrtc/v3 v3.2.23/go.mod h1:1CaT2fcZzZ6VZA+O1i9yK2DU4EOcXVvSbWG9pr5jefs=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
-github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
+github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
+github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
-github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
-github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
+github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
+github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
-github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
-github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
+github.com/prometheus/common v0.47.0 h1:p5Cz0FNHo7SnWOmWmoRozVcjEp0bIVU8cV7OShpjL1k=
+github.com/prometheus/common v0.47.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
-github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
+github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
+github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
-github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=
-github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
-github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE=
-github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4=
-github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU=
-github.com/quic-go/webtransport-go v0.5.3/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU=
+github.com/quic-go/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
+github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
+github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY=
+github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc=
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
+github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
@@ -278,12 +350,20 @@ github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
@@ -291,21 +371,26 @@ github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMI
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
-go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI=
-go.uber.org/dig v1.17.0/go.mod h1:rTxpf7l5I0eBTlE6/9RL+lDybC7WFwY2QH55ZSjy1mU=
-go.uber.org/fx v1.20.0 h1:ZMC/pnRvhsthOZh9MZjMq5U8Or3mA9zBSPaLnzs3ihQ=
-go.uber.org/fx v1.20.0/go.mod h1:qCUj0btiR3/JnanEr1TYEePfSw6o/4qYJscgvzQ5Ub0=
+go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
+go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc=
+go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
+go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk=
+go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
-go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
+go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
-go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
-go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -316,11 +401,17 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
+golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
+golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
+golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
+golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
+golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
-golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
+golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE=
+golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -330,8 +421,10 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
+golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -344,12 +437,23 @@ golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
+golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
+golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
+golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
+golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
+golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -363,8 +467,10 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
+golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -372,25 +478,60 @@ golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
+golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
+golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
+golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
+golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -403,11 +544,13 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
-golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
+golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -428,22 +571,35 @@ google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmE
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
-google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
+google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/test-plans/ping-version.json b/test-plans/ping-version.json
index 311cb58e5b..705934f2b7 100644
--- a/test-plans/ping-version.json
+++ b/test-plans/ping-version.json
@@ -6,7 +6,8 @@
"ws",
"wss",
"quic-v1",
- "webtransport"
+ "webtransport",
+ "webrtc-direct"
],
"secureChannels": [
"tls",
diff --git a/tools.go b/tools.go
index 46a8037df7..7a650d9c19 100644
--- a/tools.go
+++ b/tools.go
@@ -3,7 +3,7 @@
package libp2p
import (
- _ "github.com/golang/mock/mockgen"
+ _ "go.uber.org/mock/mockgen"
_ "golang.org/x/tools/cmd/goimports"
_ "google.golang.org/protobuf/cmd/protoc-gen-go"
)
diff --git a/version.json b/version.json
index 2074057d9d..74b45c8ce4 100644
--- a/version.json
+++ b/version.json
@@ -1,3 +1,3 @@
{
- "version": "v0.31.0"
+ "version": "v0.33.0"
}