diff --git a/README.md b/README.md index f5ef7959..a79467c0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ -go-libp2p-swarm +# DEPRECATION NOTICE + +This package has moved into go-libp2p as a sub-package, github.com/libp2p/go-libp2p/p2p/net/swarm. + +# go-libp2p-swarm ================== [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](https://protocol.ai) diff --git a/addrs.go b/addrs.go deleted file mode 100644 index 09f8df76..00000000 --- a/addrs.go +++ /dev/null @@ -1,35 +0,0 @@ -package swarm - -import ( - ma "github.com/multiformats/go-multiaddr" - mamask "github.com/whyrusleeping/multiaddr-filter" -) - -// 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 := mamask.NewMask(p) - if err != nil { - panic("error in lowTimeoutFilters init: " + err.Error()) - } - lowTimeoutFilters.AddFilter(*f, ma.ActionDeny) - } -} diff --git a/dial_error.go b/dial_error.go index f2986348..4370a993 100644 --- a/dial_error.go +++ b/dial_error.go @@ -1,71 +1,13 @@ package swarm import ( - "fmt" - "os" - "strings" - - "github.com/libp2p/go-libp2p-core/peer" - - ma "github.com/multiformats/go-multiaddr" + "github.com/libp2p/go-libp2p/p2p/net/swarm" ) -// maxDialDialErrors is the maximum number of dial errors we record -const maxDialDialErrors = 16 - // DialError is the error type returned when dialing. -type DialError struct { - Peer peer.ID - DialErrors []TransportError - Cause error - Skipped int -} - -func (e *DialError) Timeout() bool { - return os.IsTimeout(e.Cause) -} - -func (e *DialError) recordErr(addr ma.Multiaddr, err error) { - if len(e.DialErrors) >= maxDialDialErrors { - e.Skipped++ - return - } - e.DialErrors = append(e.DialErrors, TransportError{ - Address: addr, - Cause: err, - }) -} - -func (e *DialError) Error() string { - var builder strings.Builder - fmt.Fprintf(&builder, "failed to dial %s:", e.Peer) - if e.Cause != nil { - fmt.Fprintf(&builder, " %s", e.Cause) - } - for _, te := range e.DialErrors { - fmt.Fprintf(&builder, "\n * [%s] %s", te.Address, te.Cause) - } - if e.Skipped > 0 { - fmt.Fprintf(&builder, "\n ... skipping %d errors ...", e.Skipped) - } - return builder.String() -} - -// Unwrap implements https://godoc.org/golang.org/x/xerrors#Wrapper. -func (e *DialError) Unwrap() error { - return e.Cause -} - -var _ error = (*DialError)(nil) +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.DialError instead. +type DialError = swarm.DialError // TransportError is the error returned when dialing a specific address. -type TransportError struct { - Address ma.Multiaddr - Cause error -} - -func (e *TransportError) Error() string { - return fmt.Sprintf("failed to dial %s: %s", e.Address, e.Cause) -} - -var _ error = (*TransportError)(nil) +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.TransportError instead. +type TransportError = swarm.TransportError diff --git a/dial_sync.go b/dial_sync.go deleted file mode 100644 index f24ecd3c..00000000 --- a/dial_sync.go +++ /dev/null @@ -1,109 +0,0 @@ -package swarm - -import ( - "context" - "sync" - - "github.com/libp2p/go-libp2p-core/network" - "github.com/libp2p/go-libp2p-core/peer" -) - -// dialWorkerFunc is used by dialSync to spawn a new dial worker -type dialWorkerFunc func(peer.ID, <-chan dialRequest) - -// newDialSync constructs a new dialSync -func newDialSync(worker dialWorkerFunc) *dialSync { - return &dialSync{ - dials: make(map[peer.ID]*activeDial), - dialWorker: worker, - } -} - -// dialSync is a dial synchronization helper that ensures that at most one dial -// to any given peer is active at any given time. -type dialSync struct { - mutex sync.Mutex - dials map[peer.ID]*activeDial - dialWorker dialWorkerFunc -} - -type activeDial struct { - refCnt int - - ctx context.Context - cancel func() - - reqch chan dialRequest -} - -func (ad *activeDial) close() { - ad.cancel() - close(ad.reqch) -} - -func (ad *activeDial) dial(ctx context.Context) (*Conn, error) { - dialCtx := ad.ctx - - if forceDirect, reason := network.GetForceDirectDial(ctx); forceDirect { - dialCtx = network.WithForceDirectDial(dialCtx, reason) - } - if simConnect, isClient, reason := network.GetSimultaneousConnect(ctx); simConnect { - dialCtx = network.WithSimultaneousConnect(dialCtx, isClient, reason) - } - - resch := make(chan dialResponse, 1) - select { - case ad.reqch <- dialRequest{ctx: dialCtx, resch: resch}: - case <-ctx.Done(): - return nil, ctx.Err() - } - - select { - case res := <-resch: - return res.conn, res.err - case <-ctx.Done(): - return nil, ctx.Err() - } -} - -func (ds *dialSync) getActiveDial(p peer.ID) (*activeDial, error) { - ds.mutex.Lock() - defer ds.mutex.Unlock() - - actd, ok := ds.dials[p] - if !ok { - // This code intentionally uses the background context. Otherwise, if the first call - // to Dial is canceled, subsequent dial calls will also be canceled. - ctx, cancel := context.WithCancel(context.Background()) - actd = &activeDial{ - ctx: ctx, - cancel: cancel, - reqch: make(chan dialRequest), - } - go ds.dialWorker(p, actd.reqch) - ds.dials[p] = actd - } - // increase ref count before dropping mutex - actd.refCnt++ - return actd, nil -} - -// Dial initiates a dial to the given peer if there are none in progress -// then waits for the dial to that peer to complete. -func (ds *dialSync) Dial(ctx context.Context, p peer.ID) (*Conn, error) { - ad, err := ds.getActiveDial(p) - if err != nil { - return nil, err - } - - defer func() { - ds.mutex.Lock() - defer ds.mutex.Unlock() - ad.refCnt-- - if ad.refCnt == 0 { - ad.close() - delete(ds.dials, p) - } - }() - return ad.dial(ctx) -} diff --git a/dial_sync_test.go b/dial_sync_test.go deleted file mode 100644 index 0d9c6ca4..00000000 --- a/dial_sync_test.go +++ /dev/null @@ -1,231 +0,0 @@ -package swarm - -import ( - "context" - "fmt" - "sync" - "sync/atomic" - "testing" - "time" - - "github.com/libp2p/go-libp2p-core/peer" -) - -func getMockDialFunc() (dialWorkerFunc, func(), context.Context, <-chan struct{}) { - dfcalls := make(chan struct{}, 512) // buffer it large enough that we won't care - dialctx, cancel := context.WithCancel(context.Background()) - ch := make(chan struct{}) - f := func(p peer.ID, reqch <-chan dialRequest) { - defer cancel() - dfcalls <- struct{}{} - go func() { - for req := range reqch { - <-ch - req.resch <- dialResponse{conn: new(Conn)} - } - }() - } - - var once sync.Once - return f, func() { once.Do(func() { close(ch) }) }, dialctx, dfcalls -} - -func TestBasicDialSync(t *testing.T) { - df, done, _, callsch := getMockDialFunc() - dsync := newDialSync(df) - p := peer.ID("testpeer") - - finished := make(chan struct{}, 2) - go func() { - if _, err := dsync.Dial(context.Background(), p); err != nil { - t.Error(err) - } - finished <- struct{}{} - }() - - go func() { - if _, err := dsync.Dial(context.Background(), p); err != nil { - t.Error(err) - } - finished <- struct{}{} - }() - - // short sleep just to make sure we've moved around in the scheduler - time.Sleep(time.Millisecond * 20) - done() - - <-finished - <-finished - - if len(callsch) > 1 { - t.Fatal("should only have called dial func once!") - } -} - -func TestDialSyncCancel(t *testing.T) { - df, done, _, dcall := getMockDialFunc() - - dsync := newDialSync(df) - - p := peer.ID("testpeer") - - ctx1, cancel1 := context.WithCancel(context.Background()) - - finished := make(chan struct{}) - go func() { - _, err := dsync.Dial(ctx1, p) - if err != ctx1.Err() { - t.Error("should have gotten context error") - } - finished <- struct{}{} - }() - - // make sure the above makes it through the wait code first - select { - case <-dcall: - case <-time.After(time.Second): - t.Fatal("timed out waiting for dial to start") - } - - // Add a second dialwait in so two actors are waiting on the same dial - go func() { - _, err := dsync.Dial(context.Background(), p) - if err != nil { - t.Error(err) - } - finished <- struct{}{} - }() - - time.Sleep(time.Millisecond * 20) - - // cancel the first dialwait, it should not affect the second at all - cancel1() - select { - case <-finished: - case <-time.After(time.Second): - t.Fatal("timed out waiting for wait to exit") - } - - // short sleep just to make sure we've moved around in the scheduler - time.Sleep(time.Millisecond * 20) - done() - - <-finished -} - -func TestDialSyncAllCancel(t *testing.T) { - df, done, dctx, _ := getMockDialFunc() - - dsync := newDialSync(df) - p := peer.ID("testpeer") - ctx, cancel := context.WithCancel(context.Background()) - - finished := make(chan struct{}) - go func() { - if _, err := dsync.Dial(ctx, p); err != ctx.Err() { - t.Error("should have gotten context error") - } - finished <- struct{}{} - }() - - // Add a second dialwait in so two actors are waiting on the same dial - go func() { - if _, err := dsync.Dial(ctx, p); err != ctx.Err() { - t.Error("should have gotten context error") - } - finished <- struct{}{} - }() - - cancel() - for i := 0; i < 2; i++ { - select { - case <-finished: - case <-time.After(time.Second): - t.Fatal("timed out waiting for wait to exit") - } - } - - // the dial should have exited now - select { - case <-dctx.Done(): - case <-time.After(time.Second): - t.Fatal("timed out waiting for dial to return") - } - - // should be able to successfully dial that peer again - done() - if _, err := dsync.Dial(context.Background(), p); err != nil { - t.Fatal(err) - } -} - -func TestFailFirst(t *testing.T) { - var count int32 - f := func(p peer.ID, reqch <-chan dialRequest) { - go func() { - for { - req, ok := <-reqch - if !ok { - return - } - - if atomic.LoadInt32(&count) > 0 { - req.resch <- dialResponse{conn: new(Conn)} - } else { - req.resch <- dialResponse{err: fmt.Errorf("gophers ate the modem")} - } - atomic.AddInt32(&count, 1) - } - }() - } - - ds := newDialSync(f) - p := peer.ID("testing") - - ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - - if _, err := ds.Dial(ctx, p); err == nil { - t.Fatal("expected gophers to have eaten the modem") - } - - c, err := ds.Dial(ctx, p) - if err != nil { - t.Fatal(err) - } - if c == nil { - t.Fatal("should have gotten a 'real' conn back") - } -} - -func TestStressActiveDial(t *testing.T) { - ds := newDialSync(func(p peer.ID, reqch <-chan dialRequest) { - go func() { - for { - req, ok := <-reqch - if !ok { - return - } - req.resch <- dialResponse{} - } - }() - }) - - wg := sync.WaitGroup{} - - pid := peer.ID("foo") - - makeDials := func() { - for i := 0; i < 10000; i++ { - ds.Dial(context.Background(), pid) - } - wg.Done() - } - - for i := 0; i < 100; i++ { - wg.Add(1) - go makeDials() - } - - wg.Wait() -} diff --git a/dial_test.go b/dial_test.go deleted file mode 100644 index 48fd30bb..00000000 --- a/dial_test.go +++ /dev/null @@ -1,616 +0,0 @@ -package swarm_test - -import ( - "context" - "net" - "sync" - "testing" - "time" - - . "github.com/libp2p/go-libp2p-swarm" - - "github.com/libp2p/go-libp2p-core/network" - "github.com/libp2p/go-libp2p-core/peer" - "github.com/libp2p/go-libp2p-core/peerstore" - testutil "github.com/libp2p/go-libp2p-core/test" - swarmt "github.com/libp2p/go-libp2p-swarm/testing" - "github.com/libp2p/go-libp2p-testing/ci" - - ma "github.com/multiformats/go-multiaddr" - manet "github.com/multiformats/go-multiaddr/net" - - "github.com/stretchr/testify/require" -) - -func closeSwarms(swarms []*Swarm) { - for _, s := range swarms { - s.Close() - } -} - -func TestBasicDialPeer(t *testing.T) { - t.Parallel() - - swarms := makeSwarms(t, 2) - defer closeSwarms(swarms) - s1 := swarms[0] - s2 := swarms[1] - - s1.Peerstore().AddAddrs(s2.LocalPeer(), s2.ListenAddresses(), peerstore.PermanentAddrTTL) - - c, err := s1.DialPeer(context.Background(), s2.LocalPeer()) - require.NoError(t, err) - - s, err := c.NewStream(context.Background()) - require.NoError(t, err) - s.Close() -} - -func TestDialWithNoListeners(t *testing.T) { - t.Parallel() - - s1 := makeDialOnlySwarm(t) - swarms := makeSwarms(t, 1) - defer closeSwarms(swarms) - s2 := swarms[0] - - s1.Peerstore().AddAddrs(s2.LocalPeer(), s2.ListenAddresses(), peerstore.PermanentAddrTTL) - - c, err := s1.DialPeer(context.Background(), s2.LocalPeer()) - require.NoError(t, err) - - s, err := c.NewStream(context.Background()) - require.NoError(t, err) - s.Close() -} - -func acceptAndHang(l net.Listener) { - conns := make([]net.Conn, 0, 10) - for { - c, err := l.Accept() - if err != nil { - break - } - if c != nil { - conns = append(conns, c) - } - } - for _, c := range conns { - c.Close() - } -} - -func TestSimultDials(t *testing.T) { - t.Parallel() - - ctx := context.Background() - swarms := makeSwarms(t, 2, swarmt.OptDisableReuseport) - defer closeSwarms(swarms) - - // connect everyone - { - var wg sync.WaitGroup - errs := make(chan error, 20) // 2 connect calls in each of the 10 for-loop iterations - connect := func(s *Swarm, dst peer.ID, addr ma.Multiaddr) { - // copy for other peer - log.Debugf("TestSimultOpen: connecting: %s --> %s (%s)", s.LocalPeer(), dst, addr) - s.Peerstore().AddAddr(dst, addr, peerstore.TempAddrTTL) - if _, err := s.DialPeer(ctx, dst); err != nil { - errs <- err - } - wg.Done() - } - - ifaceAddrs0, err := swarms[0].InterfaceListenAddresses() - if err != nil { - t.Fatal(err) - } - ifaceAddrs1, err := swarms[1].InterfaceListenAddresses() - if err != nil { - t.Fatal(err) - } - - log.Info("Connecting swarms simultaneously.") - for i := 0; i < 10; i++ { // connect 10x for each. - wg.Add(2) - go connect(swarms[0], swarms[1].LocalPeer(), ifaceAddrs1[0]) - go connect(swarms[1], swarms[0].LocalPeer(), ifaceAddrs0[0]) - } - wg.Wait() - close(errs) - - for err := range errs { - if err != nil { - t.Fatal("error swarm dialing to peer", err) - } - } - } - - // should still just have 1, at most 2 connections :) - c01l := len(swarms[0].ConnsToPeer(swarms[1].LocalPeer())) - if c01l > 2 { - t.Error("0->1 has", c01l) - } - c10l := len(swarms[1].ConnsToPeer(swarms[0].LocalPeer())) - if c10l > 2 { - t.Error("1->0 has", c10l) - } -} - -func newSilentPeer(t *testing.T) (peer.ID, ma.Multiaddr, net.Listener) { - dst := testutil.RandPeerIDFatal(t) - lst, err := net.Listen("tcp4", "localhost:0") - if err != nil { - t.Fatal(err) - } - addr, err := manet.FromNetAddr(lst.Addr()) - if err != nil { - t.Fatal(err) - } - addrs, err := manet.ResolveUnspecifiedAddresses([]ma.Multiaddr{addr}, nil) - if err != nil { - t.Fatal(err) - } - t.Log("new silent peer:", dst, addrs[0]) - return dst, addrs[0], lst -} - -func TestDialWait(t *testing.T) { - const dialTimeout = 250 * time.Millisecond - - swarms := makeSwarms(t, 1, swarmt.DialTimeout(dialTimeout)) - s1 := swarms[0] - defer s1.Close() - - // dial to a non-existent peer. - s2p, s2addr, s2l := newSilentPeer(t) - go acceptAndHang(s2l) - defer s2l.Close() - s1.Peerstore().AddAddr(s2p, s2addr, peerstore.PermanentAddrTTL) - - before := time.Now() - if c, err := s1.DialPeer(context.Background(), s2p); err == nil { - defer c.Close() - t.Fatal("error swarm dialing to unknown peer worked...", err) - } else { - t.Log("correctly got error:", err) - } - duration := time.Since(before) - - if duration < dialTimeout*DialAttempts { - t.Error("< dialTimeout * DialAttempts not being respected", duration, dialTimeout*DialAttempts) - } - if duration > 2*dialTimeout*DialAttempts { - t.Error("> 2*dialTimeout * DialAttempts not being respected", duration, 2*dialTimeout*DialAttempts) - } - - if !s1.Backoff().Backoff(s2p, s2addr) { - t.Error("s2 should now be on backoff") - } -} - -func TestDialBackoff(t *testing.T) { - if ci.IsRunning() { - t.Skip("travis will never have fun with this test") - } - t.Parallel() - - const dialTimeout = 100 * time.Millisecond - - ctx := context.Background() - swarms := makeSwarms(t, 2, swarmt.DialTimeout(dialTimeout)) - defer closeSwarms(swarms) - s1 := swarms[0] - s2 := swarms[1] - - s2addrs, err := s2.InterfaceListenAddresses() - require.NoError(t, err) - s1.Peerstore().AddAddrs(s2.LocalPeer(), s2addrs, peerstore.PermanentAddrTTL) - - // dial to a non-existent peer. - s3p, s3addr, s3l := newSilentPeer(t) - go acceptAndHang(s3l) - defer s3l.Close() - s1.Peerstore().AddAddr(s3p, s3addr, peerstore.PermanentAddrTTL) - - // in this test we will: - // 1) dial 10x to each node. - // 2) all dials should hang - // 3) s1->s2 should succeed. - // 4) s1->s3 should not (and should place s3 on backoff) - // 5) disconnect entirely - // 6) dial 10x to each node again - // 7) s3 dials should all return immediately (except 1) - // 8) s2 dials should all hang, and succeed - // 9) last s3 dial ends, unsuccessful - - dialOnlineNode := func(dst peer.ID, times int) <-chan bool { - ch := make(chan bool) - for i := 0; i < times; i++ { - go func() { - if _, err := s1.DialPeer(ctx, dst); err != nil { - t.Error("error dialing", dst, err) - ch <- false - } else { - ch <- true - } - }() - } - return ch - } - - dialOfflineNode := func(dst peer.ID, times int) <-chan bool { - ch := make(chan bool) - for i := 0; i < times; i++ { - go func() { - if c, err := s1.DialPeer(ctx, dst); err != nil { - ch <- false - } else { - t.Error("succeeded in dialing", dst) - ch <- true - c.Close() - } - }() - } - return ch - } - - { - // 1) dial 10x to each node. - N := 10 - s2done := dialOnlineNode(s2.LocalPeer(), N) - s3done := dialOfflineNode(s3p, N) - - // when all dials should be done by: - dialTimeout1x := time.After(dialTimeout) - dialTimeout10Ax := time.After(dialTimeout * 2 * 10) // DialAttempts * 10) - - // 2) all dials should hang - select { - case <-s2done: - t.Error("s2 should not happen immediately") - case <-s3done: - t.Error("s3 should not happen yet") - case <-time.After(time.Millisecond): - // s2 may finish very quickly, so let's get out. - } - - // 3) s1->s2 should succeed. - for i := 0; i < N; i++ { - select { - case r := <-s2done: - if !r { - t.Error("s2 should not fail") - } - case <-s3done: - t.Error("s3 should not happen yet") - case <-dialTimeout1x: - t.Error("s2 took too long") - } - } - - select { - case <-s2done: - t.Error("s2 should have no more") - case <-s3done: - t.Error("s3 should not happen yet") - case <-dialTimeout1x: // let it pass - } - - // 4) s1->s3 should not (and should place s3 on backoff) - // N-1 should finish before dialTimeout1x * 2 - for i := 0; i < N; i++ { - select { - case <-s2done: - t.Error("s2 should have no more") - case r := <-s3done: - if r { - t.Error("s3 should not succeed") - } - case <-(dialTimeout1x): - if i < (N - 1) { - t.Fatal("s3 took too long") - } - t.Log("dialTimeout1x * 1.3 hit for last peer") - case <-dialTimeout10Ax: - t.Fatal("s3 took too long") - } - } - - // check backoff state - if s1.Backoff().Backoff(s2.LocalPeer(), s2addrs[0]) { - t.Error("s2 should not be on backoff") - } - if !s1.Backoff().Backoff(s3p, s3addr) { - t.Error("s3 should be on backoff") - } - - // 5) disconnect entirely - - for _, c := range s1.Conns() { - c.Close() - } - for i := 0; i < 100 && len(s1.Conns()) > 0; i++ { - <-time.After(time.Millisecond) - } - if len(s1.Conns()) > 0 { - t.Fatal("s1 conns must exit") - } - } - - { - // 6) dial 10x to each node again - N := 10 - s2done := dialOnlineNode(s2.LocalPeer(), N) - s3done := dialOfflineNode(s3p, N) - - // when all dials should be done by: - dialTimeout1x := time.After(dialTimeout) - dialTimeout10Ax := time.After(dialTimeout * 2 * 10) // DialAttempts * 10) - - // 7) s3 dials should all return immediately (except 1) - for i := 0; i < N-1; i++ { - select { - case <-s2done: - t.Error("s2 should not succeed yet") - case r := <-s3done: - if r { - t.Error("s3 should not succeed") - } - case <-dialTimeout1x: - t.Fatal("s3 took too long") - } - } - - // 8) s2 dials should all hang, and succeed - for i := 0; i < N; i++ { - select { - case r := <-s2done: - if !r { - t.Error("s2 should succeed") - } - // case <-s3done: - case <-(dialTimeout1x): - t.Fatal("s3 took too long") - } - } - - // 9) the last s3 should return, failed. - select { - case <-s2done: - t.Error("s2 should have no more") - case r := <-s3done: - if r { - t.Error("s3 should not succeed") - } - case <-dialTimeout10Ax: - t.Fatal("s3 took too long") - } - - // check backoff state (the same) - if s1.Backoff().Backoff(s2.LocalPeer(), s2addrs[0]) { - t.Error("s2 should not be on backoff") - } - if !s1.Backoff().Backoff(s3p, s3addr) { - t.Error("s3 should be on backoff") - } - } -} - -func TestDialBackoffClears(t *testing.T) { - t.Parallel() - - const dialTimeout = 250 * time.Millisecond - swarms := makeSwarms(t, 2, swarmt.DialTimeout(dialTimeout)) - defer closeSwarms(swarms) - s1 := swarms[0] - s2 := swarms[1] - - // use another address first, that accept and hang on conns - _, s2bad, s2l := newSilentPeer(t) - go acceptAndHang(s2l) - defer s2l.Close() - - // phase 1 -- dial to non-operational addresses - s1.Peerstore().AddAddr(s2.LocalPeer(), s2bad, peerstore.PermanentAddrTTL) - - before := time.Now() - _, err := s1.DialPeer(context.Background(), s2.LocalPeer()) - require.Error(t, err, "dialing to broken addr worked...") - duration := time.Since(before) - - if duration < dialTimeout*DialAttempts { - t.Error("< dialTimeout * DialAttempts not being respected", duration, dialTimeout*DialAttempts) - } - if duration > 2*dialTimeout*DialAttempts { - t.Error("> 2*dialTimeout * DialAttempts not being respected", duration, 2*dialTimeout*DialAttempts) - } - require.True(t, s1.Backoff().Backoff(s2.LocalPeer(), s2bad), "s2 should now be on backoff") - - // phase 2 -- add the working address. dial should succeed. - ifaceAddrs1, err := s2.InterfaceListenAddresses() - require.NoError(t, err) - s1.Peerstore().AddAddrs(s2.LocalPeer(), ifaceAddrs1, peerstore.PermanentAddrTTL) - - // backoffs are per address, not peer - c, err := s1.DialPeer(context.Background(), s2.LocalPeer()) - require.NoError(t, err) - defer c.Close() - require.False(t, s1.Backoff().Backoff(s2.LocalPeer(), s2bad), "s2 should no longer be on backoff") -} - -func TestDialPeerFailed(t *testing.T) { - t.Parallel() - - swarms := makeSwarms(t, 2, swarmt.DialTimeout(100*time.Millisecond)) - defer closeSwarms(swarms) - testedSwarm, targetSwarm := swarms[0], swarms[1] - - const expectedErrorsCount = 5 - for i := 0; i < expectedErrorsCount; i++ { - _, silentPeerAddress, silentPeerListener := newSilentPeer(t) - go acceptAndHang(silentPeerListener) - defer silentPeerListener.Close() - - testedSwarm.Peerstore().AddAddr(targetSwarm.LocalPeer(), silentPeerAddress, peerstore.PermanentAddrTTL) - } - - _, err := testedSwarm.DialPeer(context.Background(), targetSwarm.LocalPeer()) - require.Error(t, err) - - // dial_test.go:508: correctly get a combined error: failed to dial PEER: all dials failed - // * [/ip4/127.0.0.1/tcp/46485] failed to negotiate security protocol: context deadline exceeded - // * [/ip4/127.0.0.1/tcp/34881] failed to negotiate security protocol: context deadline exceeded - // ... - - dialErr, ok := err.(*DialError) - if !ok { - t.Fatalf("expected *DialError, got %T", err) - } - - if len(dialErr.DialErrors) != expectedErrorsCount { - t.Errorf("expected %d errors, got %d", expectedErrorsCount, len(dialErr.DialErrors)) - } -} - -func TestDialExistingConnection(t *testing.T) { - swarms := makeSwarms(t, 2) - defer closeSwarms(swarms) - s1 := swarms[0] - s2 := swarms[1] - - s1.Peerstore().AddAddrs(s2.LocalPeer(), s2.ListenAddresses(), peerstore.PermanentAddrTTL) - - c1, err := s1.DialPeer(context.Background(), s2.LocalPeer()) - require.NoError(t, err) - - c2, err := s1.DialPeer(context.Background(), s2.LocalPeer()) - require.NoError(t, err) - - require.Equal(t, c1, c2, "expecting the same connection from both dials") -} - -func newSilentListener(t *testing.T) ([]ma.Multiaddr, net.Listener) { - lst, err := net.Listen("tcp4", "localhost:0") - if err != nil { - t.Fatal(err) - } - addr, err := manet.FromNetAddr(lst.Addr()) - if err != nil { - t.Fatal(err) - } - addrs, err := manet.ResolveUnspecifiedAddresses([]ma.Multiaddr{addr}, nil) - if err != nil { - t.Fatal(err) - } - return addrs, lst - -} - -func TestDialSimultaneousJoin(t *testing.T) { - const dialTimeout = 250 * time.Millisecond - - swarms := makeSwarms(t, 2, swarmt.DialTimeout(dialTimeout)) - defer closeSwarms(swarms) - s1 := swarms[0] - s2 := swarms[1] - - s2silentAddrs, s2silentListener := newSilentListener(t) - go acceptAndHang(s2silentListener) - - connch := make(chan network.Conn, 512) - errs := make(chan error, 2) - - // start a dial to s2 through the silent addr - go func() { - s1.Peerstore().AddAddrs(s2.LocalPeer(), s2silentAddrs, peerstore.PermanentAddrTTL) - - c, err := s1.DialPeer(context.Background(), s2.LocalPeer()) - if err != nil { - errs <- err - connch <- nil - return - } - - t.Logf("first dial succedded; conn: %+v", c) - - connch <- c - errs <- nil - }() - - // wait a bit for the dial to take hold - time.Sleep(100 * time.Millisecond) - - // start a second dial to s2 that uses the real s2 addrs - go func() { - s2addrs, err := s2.InterfaceListenAddresses() - if err != nil { - errs <- err - return - } - s1.Peerstore().AddAddrs(s2.LocalPeer(), s2addrs[:1], peerstore.PermanentAddrTTL) - - c, err := s1.DialPeer(context.Background(), s2.LocalPeer()) - if err != nil { - errs <- err - connch <- nil - return - } - - t.Logf("second dial succedded; conn: %+v", c) - - connch <- c - errs <- nil - }() - - // wait for the second dial to finish - c2 := <-connch - - // start a third dial to s2, this should get the existing connection from the successful dial - go func() { - c, err := s1.DialPeer(context.Background(), s2.LocalPeer()) - if err != nil { - errs <- err - connch <- nil - return - } - - t.Logf("third dial succedded; conn: %+v", c) - - connch <- c - errs <- nil - }() - - c3 := <-connch - - // raise any errors from the previous goroutines - for i := 0; i < 3; i++ { - require.NoError(t, <-errs) - } - - if c2 != c3 { - t.Fatal("expected c2 and c3 to be the same") - } - - // next, the first dial to s2, using the silent addr should timeout; at this point the dial - // will error but the last chance check will see the existing connection and return it - select { - case c1 := <-connch: - if c1 != c2 { - t.Fatal("expected c1 and c2 to be the same") - } - case <-time.After(2 * dialTimeout): - t.Fatal("no connection from first dial") - } -} - -func TestDialSelf(t *testing.T) { - t.Parallel() - - swarms := makeSwarms(t, 2) - defer closeSwarms(swarms) - s1 := swarms[0] - - _, err := s1.DialPeer(context.Background(), s1.LocalPeer()) - require.ErrorIs(t, err, ErrDialToSelf, "expected error from self dial") -} diff --git a/dial_worker.go b/dial_worker.go deleted file mode 100644 index 8d5d4341..00000000 --- a/dial_worker.go +++ /dev/null @@ -1,316 +0,0 @@ -package swarm - -import ( - "context" - "sync" - - "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" -) - -// ///////////////////////////////////////////////////////////////////////////////// -// lo and behold, The Dialer -// TODO explain how all this works -// //////////////////////////////////////////////////////////////////////////////// - -type dialRequest struct { - ctx context.Context - resch chan dialResponse -} - -type dialResponse struct { - conn *Conn - err error -} - -type pendRequest struct { - req dialRequest // the original request - err *DialError // dial error accumulator - addrs map[ma.Multiaddr]struct{} // pending addr dials -} - -type addrDial struct { - addr ma.Multiaddr - ctx context.Context - conn *Conn - err error - requests []int - dialed bool -} - -type dialWorker struct { - s *Swarm - peer peer.ID - reqch <-chan dialRequest - reqno int - requests map[int]*pendRequest - pending map[ma.Multiaddr]*addrDial - resch chan dialResult - - connected bool // true when a connection has been successfully established - - nextDial []ma.Multiaddr - - // ready when we have more addresses to dial (nextDial is not empty) - triggerDial <-chan struct{} - - // for testing - wg sync.WaitGroup -} - -func newDialWorker(s *Swarm, p peer.ID, reqch <-chan dialRequest) *dialWorker { - return &dialWorker{ - s: s, - peer: p, - reqch: reqch, - requests: make(map[int]*pendRequest), - pending: make(map[ma.Multiaddr]*addrDial), - resch: make(chan dialResult), - } -} - -func (w *dialWorker) loop() { - w.wg.Add(1) - defer w.wg.Done() - defer w.s.limiter.clearAllPeerDials(w.peer) - - // used to signal readiness to dial and completion of the dial - ready := make(chan struct{}) - close(ready) - -loop: - for { - select { - case req, ok := <-w.reqch: - if !ok { - return - } - - c := w.s.bestAcceptableConnToPeer(req.ctx, w.peer) - if c != nil { - req.resch <- dialResponse{conn: c} - continue loop - } - - addrs, err := w.s.addrsForDial(req.ctx, w.peer) - if err != nil { - req.resch <- dialResponse{err: err} - continue loop - } - - // at this point, len(addrs) > 0 or else it would be error from addrsForDial - // ranke them to process in order - addrs = w.rankAddrs(addrs) - - // create the pending request object - pr := &pendRequest{ - req: req, - err: &DialError{Peer: w.peer}, - addrs: make(map[ma.Multiaddr]struct{}), - } - for _, a := range addrs { - pr.addrs[a] = struct{}{} - } - - // check if any of the addrs has been successfully dialed and accumulate - // errors from complete dials while collecting new addrs to dial/join - var todial []ma.Multiaddr - var tojoin []*addrDial - - for _, a := range addrs { - ad, ok := w.pending[a] - if !ok { - todial = append(todial, a) - continue - } - - if ad.conn != nil { - // dial to this addr was successful, complete the request - req.resch <- dialResponse{conn: ad.conn} - continue loop - } - - if ad.err != nil { - // dial to this addr errored, accumulate the error - pr.err.recordErr(a, ad.err) - delete(pr.addrs, a) - continue - } - - // dial is still pending, add to the join list - tojoin = append(tojoin, ad) - } - - if len(todial) == 0 && len(tojoin) == 0 { - // all request applicable addrs have been dialed, we must have errored - req.resch <- dialResponse{err: pr.err} - continue loop - } - - // the request has some pending or new dials, track it and schedule new dials - w.reqno++ - w.requests[w.reqno] = pr - - for _, ad := range tojoin { - if !ad.dialed { - if simConnect, isClient, reason := network.GetSimultaneousConnect(req.ctx); simConnect { - if simConnect, _, _ := network.GetSimultaneousConnect(ad.ctx); !simConnect { - ad.ctx = network.WithSimultaneousConnect(ad.ctx, isClient, reason) - } - } - } - ad.requests = append(ad.requests, w.reqno) - } - - if len(todial) > 0 { - for _, a := range todial { - w.pending[a] = &addrDial{addr: a, ctx: req.ctx, requests: []int{w.reqno}} - } - - w.nextDial = append(w.nextDial, todial...) - w.nextDial = w.rankAddrs(w.nextDial) - - // trigger a new dial now to account for the new addrs we added - w.triggerDial = ready - } - - case <-w.triggerDial: - for _, addr := range w.nextDial { - // spawn the dial - ad := w.pending[addr] - err := w.s.dialNextAddr(ad.ctx, w.peer, addr, w.resch) - if err != nil { - w.dispatchError(ad, err) - } - } - - w.nextDial = nil - w.triggerDial = nil - - case res := <-w.resch: - if res.Conn != nil { - w.connected = true - } - - ad := w.pending[res.Addr] - - if res.Conn != nil { - // we got a connection, add it to the swarm - conn, err := w.s.addConn(res.Conn, network.DirOutbound) - if err != nil { - // oops no, we failed to add it to the swarm - res.Conn.Close() - w.dispatchError(ad, err) - continue loop - } - - // dispatch to still pending requests - for _, reqno := range ad.requests { - pr, ok := w.requests[reqno] - if !ok { - // it has already dispatched a connection - continue - } - - pr.req.resch <- dialResponse{conn: conn} - delete(w.requests, reqno) - } - - ad.conn = conn - ad.requests = nil - - continue loop - } - - // it must be an error -- add backoff if applicable and dispatch - if res.Err != context.Canceled && !w.connected { - // we only add backoff if there has not been a successful connection - // for consistency with the old dialer behavior. - w.s.backf.AddBackoff(w.peer, res.Addr) - } - - w.dispatchError(ad, res.Err) - } - } -} - -// dispatches an error to a specific addr dial -func (w *dialWorker) dispatchError(ad *addrDial, err error) { - ad.err = err - for _, reqno := range ad.requests { - pr, ok := w.requests[reqno] - if !ok { - // has already been dispatched - continue - } - - // accumulate the error - pr.err.recordErr(ad.addr, err) - - delete(pr.addrs, ad.addr) - if len(pr.addrs) == 0 { - // 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) - if c != nil { - pr.req.resch <- dialResponse{conn: c} - } else { - pr.req.resch <- dialResponse{err: pr.err} - } - delete(w.requests, reqno) - } - } - - ad.requests = nil - - // if it was a backoff, clear the address dial so that it doesn't inhibit new dial requests. - // this is necessary to support active listen scenarios, where a new dial comes in while - // another dial is in progress, and needs to do a direct connection without inhibitions from - // dial backoff. - // it is also necessary to preserve consisent behaviour with the old dialer -- TestDialBackoff - // regresses without this. - if err == ErrDialBackoff { - delete(w.pending, ad.addr) - } -} - -// ranks addresses in descending order of preference for dialing, with the following rules: -// NonRelay > Relay -// NonWS > WS -// Private > Public -// UDP > TCP -func (w *dialWorker) rankAddrs(addrs []ma.Multiaddr) []ma.Multiaddr { - addrTier := func(a ma.Multiaddr) (tier int) { - if isRelayAddr(a) { - tier |= 0b1000 - } - if isExpensiveAddr(a) { - tier |= 0b0100 - } - if !manet.IsPrivateAddr(a) { - tier |= 0b0010 - } - if isFdConsumingAddr(a) { - tier |= 0b0001 - } - - return tier - } - - tiers := make([][]ma.Multiaddr, 16) - for _, a := range addrs { - tier := addrTier(a) - tiers[tier] = append(tiers[tier], a) - } - - result := make([]ma.Multiaddr, 0, len(addrs)) - for _, tier := range tiers { - result = append(result, tier...) - } - - return result -} diff --git a/dial_worker_test.go b/dial_worker_test.go deleted file mode 100644 index d9aa115e..00000000 --- a/dial_worker_test.go +++ /dev/null @@ -1,327 +0,0 @@ -package swarm - -import ( - "context" - "errors" - "fmt" - "sync" - "testing" - "time" - - "github.com/stretchr/testify/require" - - csms "github.com/libp2p/go-conn-security-multistream" - "github.com/libp2p/go-libp2p-core/peerstore" - "github.com/libp2p/go-libp2p-core/sec/insecure" - "github.com/libp2p/go-libp2p-core/transport" - "github.com/libp2p/go-libp2p-peerstore/pstoremem" - quic "github.com/libp2p/go-libp2p-quic-transport" - tnet "github.com/libp2p/go-libp2p-testing/net" - tptu "github.com/libp2p/go-libp2p-transport-upgrader" - yamux "github.com/libp2p/go-libp2p-yamux" - msmux "github.com/libp2p/go-stream-muxer-multistream" - tcp "github.com/libp2p/go-tcp-transport" - ma "github.com/multiformats/go-multiaddr" -) - -func makeSwarm(t *testing.T) *Swarm { - p := tnet.RandPeerNetParamsOrFatal(t) - - ps, err := pstoremem.NewPeerstore() - require.NoError(t, err) - ps.AddPubKey(p.ID, p.PubKey) - ps.AddPrivKey(p.ID, p.PrivKey) - t.Cleanup(func() { ps.Close() }) - - s, err := NewSwarm(p.ID, ps, WithDialTimeout(time.Second)) - require.NoError(t, err) - - upgrader := makeUpgrader(t, s) - - var tcpOpts []tcp.Option - tcpOpts = append(tcpOpts, tcp.DisableReuseport()) - tcpTransport, err := tcp.NewTCPTransport(upgrader, nil, tcpOpts...) - require.NoError(t, err) - if err := s.AddTransport(tcpTransport); err != nil { - t.Fatal(err) - } - if err := s.Listen(p.Addr); err != nil { - t.Fatal(err) - } - - quicTransport, err := quic.NewTransport(p.PrivKey, nil, nil, nil) - if err != nil { - t.Fatal(err) - } - if err := s.AddTransport(quicTransport); err != nil { - t.Fatal(err) - } - if err := s.Listen(ma.StringCast("/ip4/127.0.0.1/udp/0/quic")); err != nil { - t.Fatal(err) - } - - return s -} - -func makeUpgrader(t *testing.T, n *Swarm) transport.Upgrader { - id := n.LocalPeer() - pk := n.Peerstore().PrivKey(id) - secMuxer := new(csms.SSMuxer) - secMuxer.AddTransport(insecure.ID, insecure.NewWithIdentity(id, pk)) - - stMuxer := msmux.NewBlankTransport() - stMuxer.AddTransport("/yamux/1.0.0", yamux.DefaultTransport) - u, err := tptu.New(secMuxer, stMuxer) - require.NoError(t, err) - return u -} - -func TestDialWorkerLoopBasic(t *testing.T) { - s1 := makeSwarm(t) - s2 := makeSwarm(t) - defer s1.Close() - defer s2.Close() - - s1.Peerstore().AddAddrs(s2.LocalPeer(), s2.ListenAddresses(), peerstore.PermanentAddrTTL) - - reqch := make(chan dialRequest) - resch := make(chan dialResponse) - worker := newDialWorker(s1, s2.LocalPeer(), reqch) - go worker.loop() - - var conn *Conn - reqch <- dialRequest{ctx: context.Background(), resch: resch} - select { - case res := <-resch: - require.NoError(t, res.err) - conn = res.conn - case <-time.After(time.Minute): - t.Fatal("dial didn't complete") - } - - s, err := conn.NewStream(context.Background()) - require.NoError(t, err) - s.Close() - - var conn2 *Conn - reqch <- dialRequest{ctx: context.Background(), resch: resch} - select { - case res := <-resch: - require.NoError(t, res.err) - conn2 = res.conn - case <-time.After(time.Minute): - t.Fatal("dial didn't complete") - } - - require.Equal(t, conn, conn2) - - close(reqch) - worker.wg.Wait() -} - -func TestDialWorkerLoopConcurrent(t *testing.T) { - s1 := makeSwarm(t) - s2 := makeSwarm(t) - defer s1.Close() - defer s2.Close() - - s1.Peerstore().AddAddrs(s2.LocalPeer(), s2.ListenAddresses(), peerstore.PermanentAddrTTL) - - reqch := make(chan dialRequest) - worker := newDialWorker(s1, s2.LocalPeer(), reqch) - go worker.loop() - - const dials = 100 - var wg sync.WaitGroup - resch := make(chan dialResponse, dials) - for i := 0; i < dials; i++ { - wg.Add(1) - go func() { - defer wg.Done() - reschgo := make(chan dialResponse, 1) - reqch <- dialRequest{ctx: context.Background(), resch: reschgo} - select { - case res := <-reschgo: - resch <- res - case <-time.After(time.Minute): - resch <- dialResponse{err: errors.New("timed out!")} - } - }() - } - wg.Wait() - - for i := 0; i < dials; i++ { - res := <-resch - require.NoError(t, res.err) - } - - t.Log("all concurrent dials done") - - close(reqch) - worker.wg.Wait() -} - -func TestDialWorkerLoopFailure(t *testing.T) { - s1 := makeSwarm(t) - defer s1.Close() - - p2 := tnet.RandPeerNetParamsOrFatal(t) - - s1.Peerstore().AddAddrs(p2.ID, []ma.Multiaddr{ma.StringCast("/ip4/11.0.0.1/tcp/1234"), ma.StringCast("/ip4/11.0.0.1/udp/1234/quic")}, peerstore.PermanentAddrTTL) - - reqch := make(chan dialRequest) - resch := make(chan dialResponse) - worker := newDialWorker(s1, p2.ID, reqch) - go worker.loop() - - reqch <- dialRequest{ctx: context.Background(), resch: resch} - select { - case res := <-resch: - require.Error(t, res.err) - case <-time.After(time.Minute): - t.Fatal("dial didn't complete") - } - - close(reqch) - worker.wg.Wait() -} - -func TestDialWorkerLoopConcurrentFailure(t *testing.T) { - s1 := makeSwarm(t) - defer s1.Close() - - p2 := tnet.RandPeerNetParamsOrFatal(t) - - s1.Peerstore().AddAddrs(p2.ID, []ma.Multiaddr{ma.StringCast("/ip4/11.0.0.1/tcp/1234"), ma.StringCast("/ip4/11.0.0.1/udp/1234/quic")}, peerstore.PermanentAddrTTL) - - reqch := make(chan dialRequest) - worker := newDialWorker(s1, p2.ID, reqch) - go worker.loop() - - const dials = 100 - var errTimeout = errors.New("timed out!") - var wg sync.WaitGroup - resch := make(chan dialResponse, dials) - for i := 0; i < dials; i++ { - wg.Add(1) - go func() { - defer wg.Done() - reschgo := make(chan dialResponse, 1) - reqch <- dialRequest{ctx: context.Background(), resch: reschgo} - - select { - case res := <-reschgo: - resch <- res - case <-time.After(time.Minute): - resch <- dialResponse{err: errTimeout} - } - }() - } - wg.Wait() - - for i := 0; i < dials; i++ { - res := <-resch - require.Error(t, res.err) - if res.err == errTimeout { - t.Fatal("dial response timed out") - } - } - - t.Log("all concurrent dials done") - - close(reqch) - worker.wg.Wait() -} - -func TestDialWorkerLoopConcurrentMix(t *testing.T) { - s1 := makeSwarm(t) - s2 := makeSwarm(t) - defer s1.Close() - defer s2.Close() - - s1.Peerstore().AddAddrs(s2.LocalPeer(), s2.ListenAddresses(), peerstore.PermanentAddrTTL) - s1.Peerstore().AddAddrs(s2.LocalPeer(), []ma.Multiaddr{ma.StringCast("/ip4/11.0.0.1/tcp/1234"), ma.StringCast("/ip4/11.0.0.1/udp/1234/quic")}, peerstore.PermanentAddrTTL) - - reqch := make(chan dialRequest) - worker := newDialWorker(s1, s2.LocalPeer(), reqch) - go worker.loop() - - const dials = 100 - var wg sync.WaitGroup - resch := make(chan dialResponse, dials) - for i := 0; i < dials; i++ { - wg.Add(1) - go func() { - defer wg.Done() - reschgo := make(chan dialResponse, 1) - reqch <- dialRequest{ctx: context.Background(), resch: reschgo} - select { - case res := <-reschgo: - resch <- res - case <-time.After(time.Minute): - resch <- dialResponse{err: errors.New("timed out!")} - } - }() - } - wg.Wait() - - for i := 0; i < dials; i++ { - res := <-resch - require.NoError(t, res.err) - } - - t.Log("all concurrent dials done") - - close(reqch) - worker.wg.Wait() -} - -func TestDialWorkerLoopConcurrentFailureStress(t *testing.T) { - s1 := makeSwarm(t) - defer s1.Close() - - p2 := tnet.RandPeerNetParamsOrFatal(t) - - var addrs []ma.Multiaddr - for i := 0; i < 200; i++ { - addrs = append(addrs, ma.StringCast(fmt.Sprintf("/ip4/11.0.0.%d/tcp/%d", i%256, 1234+i))) - } - s1.Peerstore().AddAddrs(p2.ID, addrs, peerstore.PermanentAddrTTL) - - reqch := make(chan dialRequest) - worker := newDialWorker(s1, p2.ID, reqch) - go worker.loop() - - const dials = 100 - var errTimeout = errors.New("timed out!") - var wg sync.WaitGroup - resch := make(chan dialResponse, dials) - for i := 0; i < dials; i++ { - wg.Add(1) - go func() { - defer wg.Done() - reschgo := make(chan dialResponse, 1) - reqch <- dialRequest{ctx: context.Background(), resch: reschgo} - select { - case res := <-reschgo: - resch <- res - case <-time.After(5 * time.Minute): - resch <- dialResponse{err: errTimeout} - } - }() - } - wg.Wait() - - for i := 0; i < dials; i++ { - res := <-resch - require.Error(t, res.err) - if res.err == errTimeout { - t.Fatal("dial response timed out") - } - } - - t.Log("all concurrent dials done") - - close(reqch) - worker.wg.Wait() -} diff --git a/go.mod b/go.mod index 3b6e872c..bfbf2492 100644 --- a/go.mod +++ b/go.mod @@ -3,54 +3,44 @@ module github.com/libp2p/go-libp2p-swarm go 1.17 require ( - github.com/golang/mock v1.6.0 - github.com/ipfs/go-log/v2 v2.5.0 - github.com/libp2p/go-conn-security-multistream v0.3.0 - github.com/libp2p/go-libp2p-core v0.14.0 - github.com/libp2p/go-libp2p-peerstore v0.6.0 - github.com/libp2p/go-libp2p-quic-transport v0.16.0 - github.com/libp2p/go-libp2p-testing v0.7.0 - github.com/libp2p/go-libp2p-transport-upgrader v0.7.0 - github.com/libp2p/go-libp2p-yamux v0.8.1 - github.com/libp2p/go-stream-muxer-multistream v0.4.0 - github.com/libp2p/go-tcp-transport v0.5.0 - github.com/multiformats/go-multiaddr v0.5.0 - github.com/multiformats/go-multiaddr-fmt v0.1.0 - github.com/stretchr/testify v1.7.0 - github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 + github.com/libp2p/go-libp2p v0.20.0 + github.com/libp2p/go-libp2p-core v0.16.1 ) require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/btcsuite/btcd v0.20.1-beta // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/btcsuite/btcd v0.22.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cheekybits/genny v1.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 // indirect + github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/gopacket v1.1.19 // indirect - github.com/ipfs/go-cid v0.0.7 // indirect + github.com/ipfs/go-cid v0.1.0 // indirect + github.com/ipfs/go-log/v2 v2.5.1 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect - github.com/klauspost/compress v1.13.6 // indirect - github.com/klauspost/cpuid/v2 v2.0.4 // indirect + github.com/klauspost/compress v1.15.1 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/libp2p/go-buffer-pool v0.0.2 // indirect github.com/libp2p/go-flow-metrics v0.0.3 // indirect - github.com/libp2p/go-libp2p-pnet v0.2.0 // indirect - github.com/libp2p/go-libp2p-tls v0.3.0 // indirect - github.com/libp2p/go-msgio v0.0.6 // indirect + github.com/libp2p/go-libp2p-peerstore v0.6.0 // indirect + github.com/libp2p/go-libp2p-testing v0.9.2 // indirect + github.com/libp2p/go-msgio v0.2.0 // indirect github.com/libp2p/go-netroute v0.2.0 // indirect github.com/libp2p/go-openssl v0.0.7 // indirect - github.com/libp2p/go-reuseport v0.1.0 // indirect - github.com/libp2p/go-reuseport-transport v0.1.0 // indirect - github.com/libp2p/go-yamux/v3 v3.0.2 // indirect - github.com/lucas-clemente/quic-go v0.25.0 // indirect - github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect - github.com/marten-seemann/qtls-go1-17 v0.1.0 // indirect - github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 // indirect + github.com/libp2p/go-reuseport v0.2.0 // indirect + github.com/libp2p/go-yamux/v3 v3.1.1 // indirect + github.com/lucas-clemente/quic-go v0.27.1 // indirect + github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect + github.com/marten-seemann/qtls-go1-17 v0.1.1 // indirect + github.com/marten-seemann/qtls-go1-18 v0.1.1 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect @@ -61,29 +51,37 @@ require ( github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.0.3 // indirect github.com/multiformats/go-base36 v0.1.0 // indirect + github.com/multiformats/go-multiaddr v0.5.0 // indirect + github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect github.com/multiformats/go-multibase v0.0.3 // indirect - github.com/multiformats/go-multihash v0.0.15 // indirect - github.com/multiformats/go-multistream v0.2.1 // indirect + github.com/multiformats/go-multicodec v0.4.1 // indirect + github.com/multiformats/go-multihash v0.1.0 // indirect + github.com/multiformats/go-multistream v0.3.1 // indirect github.com/multiformats/go-varint v0.0.6 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/onsi/ginkgo v1.16.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.10.0 // indirect + github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.18.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/stretchr/testify v1.7.0 // indirect + github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.19.1 // indirect - golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf // indirect + golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect golang.org/x/mod v0.4.2 // indirect - golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect - golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect + golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect + golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect golang.org/x/tools v0.1.5 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/grpc v1.31.1 // indirect google.golang.org/protobuf v1.26.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + lukechampine.com/blake3 v1.1.6 // indirect ) diff --git a/go.sum b/go.sum index 1f26da9f..11d94643 100644 --- a/go.sum +++ b/go.sum @@ -2,13 +2,45 @@ 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= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= 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/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= @@ -32,21 +64,32 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= +github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= @@ -55,41 +98,57 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH 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 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +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/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= 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/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 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.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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= -github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC5IlbaIF5Q7JNieBoACT7iW0YTxQHR0in0= github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= +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.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= 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= @@ -97,6 +156,7 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +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/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -107,9 +167,13 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 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/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= 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= @@ -117,6 +181,7 @@ github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -127,9 +192,15 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 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= @@ -137,11 +208,14 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y 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= @@ -154,6 +228,10 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a 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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -164,17 +242,27 @@ github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8v 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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/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/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +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= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= @@ -206,21 +294,32 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= -github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY= github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= +github.com/ipfs/go-cid v0.1.0 h1:YN33LQulcRHjfom/i25yoOZR4Telp1Hr/2RU3d0PnC0= +github.com/ipfs/go-cid v0.1.0/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o= github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= +github.com/ipfs/go-datastore v0.5.1/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= +github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= +github.com/ipfs/go-log v1.0.4 h1:6nLQdX4W8P9yZZFH7mO+X/PzjN8Laozm/lMJ6esdgzY= +github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g= -github.com/ipfs/go-log/v2 v2.5.0 h1:+MhAooFd9XZNvR0i9FriKW6HB0ql7HNXUuflWtc0dd4= github.com/ipfs/go-log/v2 v2.5.0/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= +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/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= @@ -237,7 +336,10 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= @@ -247,78 +349,98 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL 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/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/cpuid/v2 v2.0.4 h1:g0I61F2K2DjRHz1cnxlkNSBIaePVoJIjjnHui8QHbiw= +github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A= +github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 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/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= 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 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= 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/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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= -github.com/libp2p/go-conn-security-multistream v0.3.0 h1:9UCIKlBL1hC9u7nkMXpD1nkc/T53PKMAn3/k9ivBAVc= +github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= github.com/libp2p/go-conn-security-multistream v0.3.0/go.mod h1:EEP47t4fw/bTelVmEzIDqSe69hO/ip52xBEhZMLWAHM= +github.com/libp2p/go-eventbus v0.2.1/go.mod h1:jc2S4SoEVPP48H9Wpzm5aiGwUCBMfGhVhhBjyhhCJs8= +github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM= github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= +github.com/libp2p/go-libp2p v0.20.0 h1:FpwrR9l3ZVsL9ArwgENHYn1I32OogiCAFS6abxdUVH4= +github.com/libp2p/go-libp2p v0.20.0/go.mod h1:g0C5Fu+aXXbCXkusCzLycuBowEih3ElmDqtbo61Em7k= +github.com/libp2p/go-libp2p-asn-util v0.2.0/go.mod h1:WoaWxbHKBymSN41hWSq/lGKJEca7TNm58+gGJi2WsLI= +github.com/libp2p/go-libp2p-blankhost v0.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= +github.com/libp2p/go-libp2p-circuit v0.6.0/go.mod h1:kB8hY+zCpMeScyvFrKrGicRdid6vNXbunKE4rXATZ0M= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= +github.com/libp2p/go-libp2p-core v0.5.7/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.6.0/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= github.com/libp2p/go-libp2p-core v0.10.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= github.com/libp2p/go-libp2p-core v0.12.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= -github.com/libp2p/go-libp2p-core v0.14.0 h1:0kYSgiK/D7Eo28GTuRXo5YHsWwAisVpFCqCVPUd/vJs= github.com/libp2p/go-libp2p-core v0.14.0/go.mod h1:tLasfcVdTXnixsLB0QYaT1syJOhsbrhG7q6pGrHtBg8= -github.com/libp2p/go-libp2p-mplex v0.5.0 h1:vt3k4E4HSND9XH4Z8rUpacPJFSAgLOv6HDvG8W9Ks9E= +github.com/libp2p/go-libp2p-core v0.16.1 h1:bWoiEBqVkpJ13hbv/f69tHODp86t6mvc4fBN4DkK73M= +github.com/libp2p/go-libp2p-core v0.16.1/go.mod h1:O3i/7y+LqUb0N+qhzXjBjjpchgptWAVMG1Voegk7b4c= github.com/libp2p/go-libp2p-mplex v0.5.0/go.mod h1:eLImPJLkj3iG5t5lq68w3Vm5NAQ5BcKwrrb2VmOYb3M= github.com/libp2p/go-libp2p-peerstore v0.6.0 h1:HJminhQSGISBIRb93N6WK3t6Fa8OOTnHd/VBjL4mY5A= github.com/libp2p/go-libp2p-peerstore v0.6.0/go.mod h1:DGEmKdXrcYpK9Jha3sS7MhqYdInxJy84bIPtSu65bKc= -github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= -github.com/libp2p/go-libp2p-quic-transport v0.16.0 h1:aVg9/jr+R2esov5sH7wkXrmYmqJiUjtLMLYX3L9KYdY= github.com/libp2p/go-libp2p-quic-transport v0.16.0/go.mod h1:1BXjVMzr+w7EkPfiHkKnwsWjPjtfaNT0q8RS3tGDvEQ= +github.com/libp2p/go-libp2p-resource-manager v0.3.0/go.mod h1:K+eCkiapf+ey/LADO4TaMpMTP9/Qde/uLlrnRqV4PLQ= +github.com/libp2p/go-libp2p-swarm v0.10.0/go.mod h1:71ceMcV6Rg/0rIQ97rsZWMzto1l9LnNquef+efcRbmA= +github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc= github.com/libp2p/go-libp2p-testing v0.5.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= -github.com/libp2p/go-libp2p-testing v0.7.0 h1:9bfyhNINizxuLrKsenzGaZalXRXIaAEmx1BP/PzF1gM= github.com/libp2p/go-libp2p-testing v0.7.0/go.mod h1:OLbdn9DbgdMwv00v+tlp1l3oe2Cl+FAjoWIA2pa0X6E= -github.com/libp2p/go-libp2p-tls v0.3.0 h1:8BgvUJiOTcj0Gp6XvEicF0rL5aUtRg/UzEdeZDmDlC8= +github.com/libp2p/go-libp2p-testing v0.9.2 h1:dCpODRtRaDZKF8HXT9qqqgON+OMEB423Knrgeod8j84= +github.com/libp2p/go-libp2p-testing v0.9.2/go.mod h1:Td7kbdkWqYTJYQGTwzlgXwaqldraIanyjuRiAbK/XQU= github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= -github.com/libp2p/go-libp2p-transport-upgrader v0.7.0 h1:ADnLrL7fC4Vy7HPjk9oGof7nDeTqGXuof85Ar6kin9Q= github.com/libp2p/go-libp2p-transport-upgrader v0.7.0/go.mod h1:GIR2aTRp1J5yjVlkUoFqMkdobfob6RnAwYg/RZPhrzg= -github.com/libp2p/go-libp2p-yamux v0.8.1 h1:pi7zUeZ4Z9TpbUMntvSvoP3dFD4SEw/VPybxBcOZGzg= -github.com/libp2p/go-libp2p-yamux v0.8.1/go.mod h1:rUozF8Jah2dL9LLGyBaBeTQeARdwhefMCTQVQt6QobE= +github.com/libp2p/go-libp2p-yamux v0.8.0/go.mod h1:yTkPgN2ib8FHyU1ZcVD7aelzyAqXXwEPbyx+aSKm9h8= github.com/libp2p/go-maddr-filter v0.1.0/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= -github.com/libp2p/go-mplex v0.4.0 h1:Ukkez9/4EOX5rTw4sHefNJp10dksftAA05ZgyjplUbM= github.com/libp2p/go-mplex v0.4.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= -github.com/libp2p/go-msgio v0.0.6 h1:lQ7Uc0kS1wb1EfRxO2Eir/RJoHkHn7t6o+EiwsYIKJA= +github.com/libp2p/go-mplex v0.7.0/go.mod h1:rW8ThnRcYWft/Jb2jeORBmPd6xuG3dGxWN/W168L9EU= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.6/go.mod h1:4ecVB6d9f4BDSL5fqvPiC4A3KivjWn+Venn/1ALLMWA= +github.com/libp2p/go-msgio v0.2.0 h1:W6shmB+FeynDrUVl2dgFQvzfBZcXiyqY4VmpQLu9FqU= +github.com/libp2p/go-msgio v0.2.0/go.mod h1:dBVM1gW3Jk9XqHkU4eKdGvVHdLa51hoGfll6jMJMSlY= +github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC3uRBM= +github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= github.com/libp2p/go-netroute v0.1.3/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= github.com/libp2p/go-netroute v0.1.5/go.mod h1:V1SR3AaECRkEQCoFFzYwVYWvYIEtlxx89+O3qcpCl4A= github.com/libp2p/go-netroute v0.2.0 h1:0FpsbsvuSnAhXFnCY0VLFbJOzaK0VnP0r1QT/o4nWRE= github.com/libp2p/go-netroute v0.2.0/go.mod h1:Vio7LTzZ+6hoT4CMZi5/6CpY3Snzh2vgZhWgxMNwlQI= github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.5/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= github.com/libp2p/go-openssl v0.0.7 h1:eCAzdLejcNVBzP/iZM9vqHnQm+XyCEbSSIheIPRGNsw= github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= -github.com/libp2p/go-reuseport v0.1.0 h1:0ooKOx2iwyIkf339WCZ2HN3ujTDbkK0PjC7JVoP1AiM= github.com/libp2p/go-reuseport v0.1.0/go.mod h1:bQVn9hmfcTaoo0c9v5pBhOarsU1eNOBZdaAd2hzXRKU= -github.com/libp2p/go-reuseport-transport v0.1.0 h1:C3PHeHjmnz8m6f0uydObj02tMEoi7CyD1zuN7xQT8gc= +github.com/libp2p/go-reuseport v0.2.0 h1:18PRvIMlpY6ZK85nIAicSBuXXvrYoSw3dsBAR7zc560= +github.com/libp2p/go-reuseport v0.2.0/go.mod h1:bvVho6eLMm6Bz5hmU0LYN3ixd3nPPvtIlaURZZgOY4k= github.com/libp2p/go-reuseport-transport v0.1.0/go.mod h1:vev0C0uMkzriDY59yFHD9v+ujJvYmDQVLowvAjEOmfw= github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= github.com/libp2p/go-sockaddr v0.1.0/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-stream-muxer-multistream v0.4.0 h1:HsM/9OdtqnIzjVXcxTXjmqKrj3gJ8kacaOJwJS1ipaY= github.com/libp2p/go-stream-muxer-multistream v0.4.0/go.mod h1:nb+dGViZleRP4XcyHuZSVrJCBl55nRBOMmiSL/dyziw= -github.com/libp2p/go-tcp-transport v0.5.0 h1:3ZPW8HAuyRAuFzyabE0hSrCXKKSWzROnZZX7DtcIatY= github.com/libp2p/go-tcp-transport v0.5.0/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= -github.com/libp2p/go-yamux/v3 v3.0.2 h1:LW0q5+A1Wy0npEsPJP9wmare2NH4ohNluN5EWVwv2mE= -github.com/libp2p/go-yamux/v3 v3.0.2/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= +github.com/libp2p/go-yamux/v3 v3.0.1/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= +github.com/libp2p/go-yamux/v3 v3.1.1 h1:X0qSVodCZciOu/f4KTp9V+O0LAqcqP2tdaUGB0+0lng= +github.com/libp2p/go-yamux/v3 v3.1.1/go.mod h1:jeLEQgLXqE2YqX1ilAClIfCMDY+0uXQUKmmb/qp0gT4= +github.com/libp2p/zeroconf/v2 v2.1.1/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc= github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg= +github.com/lucas-clemente/quic-go v0.27.1 h1:sOw+4kFSVrdWOYmUjufQ9GBVPqZ+tu+jMtXxXNmRJyk= +github.com/lucas-clemente/quic-go v0.27.1/go.mod h1:AzgQoPda7N+3IqMMMkywBKggIFo2KT6pfnlrQ2QieeI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -326,12 +448,15 @@ github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= -github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco= github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= -github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= +github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ= +github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= -github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM= +github.com/marten-seemann/qtls-go1-17 v0.1.1 h1:DQjHPq+aOzUeh9/lixAGunn6rIOQyWChPSI4+hgW7jc= +github.com/marten-seemann/qtls-go1-17 v0.1.1/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s= github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI= +github.com/marten-seemann/qtls-go1-18 v0.1.1 h1:qp7p7XXUFL7fpBvSS1sWD+uSqPvzNQK43DH+/qEkj0Y= +github.com/marten-seemann/qtls-go1-18 v0.1.1/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= 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-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -346,6 +471,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +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/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= @@ -355,6 +482,8 @@ github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4S github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= @@ -371,6 +500,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ 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.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= @@ -380,6 +510,7 @@ github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= +github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= 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.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= @@ -391,22 +522,28 @@ github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/o github.com/multiformats/go-multiaddr v0.4.1/go.mod h1:3afI9HfVW8csiF8UZqtpYRiDyew8pRX7qLIGHu9FLuM= github.com/multiformats/go-multiaddr v0.5.0 h1:i/JuOoVg4szYQ4YEzDGtb2h0o8M7CG/Yq6cGlcjWZpM= github.com/multiformats/go-multiaddr v0.5.0/go.mod h1:3KAxNkUqLTJ20AAwN4XVX4kZar+bR+gh4zgbfr3SNug= +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-multiaddr-net v0.2.0/go.mod h1:gGdH3UXny6U3cKKYCvpXI5rnK7YaOIEOPVDI9tsJbEA= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= +github.com/multiformats/go-multicodec v0.4.1 h1:BSJbf+zpghcZMZrwTYBGwy0CPcVZGWiC72Cp8bBd4R4= +github.com/multiformats/go-multicodec v0.4.1/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= +github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= 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.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= -github.com/multiformats/go-multihash v0.0.15 h1:hWOPdrNqDjwHDx82vsYGSDZNyktOJJ2dzZJzFkOV1jM= github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= +github.com/multiformats/go-multihash v0.1.0 h1:CgAgwqk3//SVEw3T+6DqI4mWMyRuDwZtOWcJT0q9+EA= +github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84= github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= -github.com/multiformats/go-multistream v0.2.1 h1:R5exp4cKvGlePuxg/bn4cnV53K4DxCe+uldxs7QzfrE= github.com/multiformats/go-multistream v0.2.1/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= +github.com/multiformats/go-multistream v0.3.1 h1:GQM84yyQ5EZB9l0p5+5eDwFoQgwHI2tLmYGpaWlLF/U= +github.com/multiformats/go-multistream v0.3.1/go.mod h1:ODRoqamLUsETKS9BNcII4gcRsJBU5VAwRIv7O39cEXg= github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= @@ -437,6 +574,7 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 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.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= @@ -444,6 +582,7 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -455,6 +594,7 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= @@ -475,8 +615,10 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= -github.com/prometheus/client_golang v1.10.0 h1:/o0BDeWzLWXNZ+4q5gXltUvaMpJqckTa+jTNoB+z4cg= github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -490,8 +632,10 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.18.0 h1:WCVKW7aL6LEe1uryfI9dnEc2ZqNB1Fn0ok930v0iL1Y= github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= 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.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -499,8 +643,11 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/raulk/clock v1.1.0/go.mod h1:3MpVxdZ/ODBQDxbN+kzshf5OSZwPjtMDx6BBXBmOeY0= +github.com/raulk/go-watchdog v1.2.0/go.mod h1:lzSbAl5sh4rtI8tYHU01BWIDzgzqaQLj6RcA1i4mlqI= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -536,6 +683,7 @@ github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5k 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/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= @@ -543,9 +691,11 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= 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/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -573,14 +723,18 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +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= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 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= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -588,8 +742,11 @@ go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mI go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +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.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -620,32 +777,61 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/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-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +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-20210506145944-38f3c27a63bf h1:B2n+Zi5QeYRDAEodEu72OS36gmTWjgpXr2+cWcBW90o= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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/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/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/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 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/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= @@ -658,26 +844,47 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r 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-20190813141303-74dc4d7220e7/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-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= 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-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/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-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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/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= @@ -685,9 +892,12 @@ 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/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/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= @@ -701,32 +911,53 @@ golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/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-20190405154228-4b34438f7a67/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-20190826190057-c7b8b68b1456/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-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/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-20200116001909-b77594299b42/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-20200519105757-fe76b779f299/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-20201214210602-f9fddec55a1e/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-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -734,10 +965,15 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +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-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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= @@ -746,6 +982,7 @@ golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -756,18 +993,48 @@ golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/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-20190328211700-ab21143f2384/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-20191108193012-7d206e10da11/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-20200103221440-774c71fcf114/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= @@ -782,19 +1049,64 @@ google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+ 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.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +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-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +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= @@ -802,12 +1114,19 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/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.28.1/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/grpc v1.31.1 h1:SfXqXS5hkufcdZ/mHtYCh53P2b+92WQq/DZcKLgsFRs= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -815,15 +1134,20 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ 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 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 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 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -851,8 +1175,16 @@ 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.1.6 h1:H3cROdztr7RCfoaTpGZFQsrqvweFLrqS73j7L7cmR5c= +lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= +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= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= diff --git a/limiter.go b/limiter.go deleted file mode 100644 index 6b49d8ec..00000000 --- a/limiter.go +++ /dev/null @@ -1,227 +0,0 @@ -package swarm - -import ( - "context" - "os" - "strconv" - "sync" - "time" - - "github.com/libp2p/go-libp2p-core/peer" - "github.com/libp2p/go-libp2p-core/transport" - - 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 - timeout time.Duration -} - -func (dj *dialJob) cancelled() bool { - return dj.ctx.Err() != nil -} - -type dialLimiter struct { - lk sync.Mutex - - fdConsuming int - fdLimit int - waitingOnFd []*dialJob - - dialFunc dialfunc - - activePerPeer map[peer.ID]int - perPeerLimit int - waitingOnPeerLimit map[peer.ID][]*dialJob -} - -type dialfunc func(context.Context, peer.ID, ma.Multiaddr) (transport.CapableConn, error) - -func newDialLimiter(df dialfunc) *dialLimiter { - fd := ConcurrentFdDials - if env := os.Getenv("LIBP2P_SWARM_FD_LIMIT"); env != "" { - if n, err := strconv.ParseInt(env, 10, 32); err == nil { - fd = int(n) - } - } - return newDialLimiterWithParams(df, fd, DefaultPerPeerRateLimit) -} - -func newDialLimiterWithParams(df dialfunc, fdLimit, perPeerLimit int) *dialLimiter { - return &dialLimiter{ - fdLimit: fdLimit, - perPeerLimit: perPeerLimit, - waitingOnPeerLimit: make(map[peer.ID][]*dialJob), - activePerPeer: make(map[peer.ID]int), - dialFunc: df, - } -} - -// freeFDToken frees FD token and if there are any schedules another waiting dialJob -// in it's place -func (dl *dialLimiter) freeFDToken() { - log.Debugf("[limiter] freeing FD token; waiting: %d; consuming: %d", len(dl.waitingOnFd), dl.fdConsuming) - dl.fdConsuming-- - - for len(dl.waitingOnFd) > 0 { - next := dl.waitingOnFd[0] - dl.waitingOnFd[0] = nil // clear out memory - dl.waitingOnFd = dl.waitingOnFd[1:] - - if len(dl.waitingOnFd) == 0 { - // clear out memory. - dl.waitingOnFd = nil - } - - // Skip over canceled dials instead of queuing up a goroutine. - if next.cancelled() { - dl.freePeerToken(next) - continue - } - dl.fdConsuming++ - - // we already have activePerPeer token at this point so we can just dial - go dl.executeDial(next) - return - } -} - -func (dl *dialLimiter) freePeerToken(dj *dialJob) { - log.Debugf("[limiter] freeing peer token; peer %s; addr: %s; active for peer: %d; waiting on peer limit: %d", - dj.peer, dj.addr, dl.activePerPeer[dj.peer], len(dl.waitingOnPeerLimit[dj.peer])) - // release tokens in reverse order than we take them - dl.activePerPeer[dj.peer]-- - if dl.activePerPeer[dj.peer] == 0 { - delete(dl.activePerPeer, dj.peer) - } - - waitlist := dl.waitingOnPeerLimit[dj.peer] - for len(waitlist) > 0 { - next := waitlist[0] - waitlist[0] = nil // clear out memory - waitlist = waitlist[1:] - - if len(waitlist) == 0 { - delete(dl.waitingOnPeerLimit, next.peer) - } else { - dl.waitingOnPeerLimit[next.peer] = waitlist - } - - if next.cancelled() { - continue - } - - dl.activePerPeer[next.peer]++ // just kidding, we still want this token - - dl.addCheckFdLimit(next) - return - } -} - -func (dl *dialLimiter) finishedDial(dj *dialJob) { - dl.lk.Lock() - defer dl.lk.Unlock() - if dl.shouldConsumeFd(dj.addr) { - dl.freeFDToken() - } - - dl.freePeerToken(dj) -} - -func (dl *dialLimiter) shouldConsumeFd(addr ma.Multiaddr) bool { - // we don't consume FD's for relay addresses for now as they will be consumed when the Relay Transport - // actually dials the Relay server. That dial call will also pass through this limiter with - // the address of the relay server i.e. non-relay address. - _, err := addr.ValueForProtocol(ma.P_CIRCUIT) - - isRelay := err == nil - - return !isRelay && isFdConsumingAddr(addr) -} - -func (dl *dialLimiter) addCheckFdLimit(dj *dialJob) { - if dl.shouldConsumeFd(dj.addr) { - if dl.fdConsuming >= dl.fdLimit { - log.Debugf("[limiter] blocked dial waiting on FD token; peer: %s; addr: %s; consuming: %d; "+ - "limit: %d; waiting: %d", dj.peer, dj.addr, dl.fdConsuming, dl.fdLimit, len(dl.waitingOnFd)) - dl.waitingOnFd = append(dl.waitingOnFd, dj) - return - } - - log.Debugf("[limiter] taking FD token: peer: %s; addr: %s; prev consuming: %d", - dj.peer, dj.addr, dl.fdConsuming) - // take token - dl.fdConsuming++ - } - - log.Debugf("[limiter] executing dial; peer: %s; addr: %s; FD consuming: %d; waiting: %d", - dj.peer, dj.addr, dl.fdConsuming, len(dl.waitingOnFd)) - go dl.executeDial(dj) -} - -func (dl *dialLimiter) addCheckPeerLimit(dj *dialJob) { - if dl.activePerPeer[dj.peer] >= dl.perPeerLimit { - log.Debugf("[limiter] blocked dial waiting on peer limit; peer: %s; addr: %s; active: %d; "+ - "peer limit: %d; waiting: %d", dj.peer, dj.addr, dl.activePerPeer[dj.peer], dl.perPeerLimit, - len(dl.waitingOnPeerLimit[dj.peer])) - wlist := dl.waitingOnPeerLimit[dj.peer] - dl.waitingOnPeerLimit[dj.peer] = append(wlist, dj) - return - } - dl.activePerPeer[dj.peer]++ - - dl.addCheckFdLimit(dj) -} - -// AddDialJob tries to take the needed tokens for starting the given dial job. -// If it acquires all needed tokens, it immediately starts the dial, otherwise -// it will put it on the waitlist for the requested token. -func (dl *dialLimiter) AddDialJob(dj *dialJob) { - dl.lk.Lock() - defer dl.lk.Unlock() - - log.Debugf("[limiter] adding a dial job through limiter: %v", dj.addr) - dl.addCheckPeerLimit(dj) -} - -func (dl *dialLimiter) clearAllPeerDials(p peer.ID) { - dl.lk.Lock() - defer dl.lk.Unlock() - delete(dl.waitingOnPeerLimit, p) - log.Debugf("[limiter] clearing all peer dials: %v", p) - // NB: the waitingOnFd list doesn't need to be cleaned out here, we will - // remove them as we encounter them because they are 'cancelled' at this - // point -} - -// executeDial calls the dialFunc, and reports the result through the response -// channel when finished. Once the response is sent it also releases all tokens -// it held during the dial. -func (dl *dialLimiter) executeDial(j *dialJob) { - defer dl.finishedDial(j) - if j.cancelled() { - return - } - - dctx, cancel := context.WithTimeout(j.ctx, j.timeout) - defer cancel() - - con, err := dl.dialFunc(dctx, j.peer, j.addr) - select { - case j.resp <- dialResult{Conn: con, Addr: j.addr, Err: err}: - case <-j.ctx.Done(): - if con != nil { - con.Close() - } - } -} diff --git a/limiter_test.go b/limiter_test.go deleted file mode 100644 index 47918ce5..00000000 --- a/limiter_test.go +++ /dev/null @@ -1,397 +0,0 @@ -package swarm - -import ( - "context" - "errors" - "fmt" - "math/rand" - "strconv" - "sync" - "testing" - "time" - - "github.com/libp2p/go-libp2p-core/peer" - "github.com/libp2p/go-libp2p-core/test" - "github.com/libp2p/go-libp2p-core/transport" - - ma "github.com/multiformats/go-multiaddr" - mafmt "github.com/multiformats/go-multiaddr-fmt" -) - -func addrWithPort(p int) ma.Multiaddr { - return ma.StringCast(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", p)) -} - -// in these tests I use addresses with tcp ports over a certain number to -// signify 'good' addresses that will succeed, and addresses below that number -// will fail. This lets us more easily test these different scenarios. -func tcpPortOver(a ma.Multiaddr, n int) bool { - port, err := a.ValueForProtocol(ma.P_TCP) - if err != nil { - panic(err) - } - - pnum, err := strconv.Atoi(port) - if err != nil { - panic(err) - } - - return pnum > n -} - -func tryDialAddrs(ctx context.Context, l *dialLimiter, p peer.ID, addrs []ma.Multiaddr, res chan dialResult) { - for _, a := range addrs { - l.AddDialJob(&dialJob{ - ctx: ctx, - peer: p, - addr: a, - resp: res, - }) - } -} - -func hangDialFunc(hang chan struct{}) dialfunc { - return func(ctx context.Context, p peer.ID, a ma.Multiaddr) (transport.CapableConn, error) { - if mafmt.UTP.Matches(a) { - return transport.CapableConn(nil), nil - } - - _, err := a.ValueForProtocol(ma.P_CIRCUIT) - if err == nil { - return transport.CapableConn(nil), nil - } - - if tcpPortOver(a, 10) { - return transport.CapableConn(nil), nil - } - - <-hang - return nil, fmt.Errorf("test bad dial") - } -} - -func TestLimiterBasicDials(t *testing.T) { - hang := make(chan struct{}) - defer close(hang) - - l := newDialLimiterWithParams(hangDialFunc(hang), ConcurrentFdDials, 4) - - bads := []ma.Multiaddr{addrWithPort(1), addrWithPort(2), addrWithPort(3), addrWithPort(4)} - good := addrWithPort(20) - - resch := make(chan dialResult) - pid := peer.ID("testpeer") - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - tryDialAddrs(ctx, l, pid, bads, resch) - - l.AddDialJob(&dialJob{ - ctx: ctx, - peer: pid, - addr: good, - resp: resch, - }) - - select { - case <-resch: - t.Fatal("no dials should have completed!") - case <-time.After(time.Millisecond * 100): - } - - // complete a single hung dial - hang <- struct{}{} - - select { - case r := <-resch: - if r.Err == nil { - t.Fatal("should have gotten failed dial result") - } - case <-time.After(time.Second): - t.Fatal("timed out waiting for dial completion") - } - - select { - case r := <-resch: - if r.Err != nil { - t.Fatal("expected second result to be success!") - } - case <-time.After(time.Second): - } -} - -func TestFDLimiting(t *testing.T) { - hang := make(chan struct{}) - defer close(hang) - l := newDialLimiterWithParams(hangDialFunc(hang), 16, 5) - - bads := []ma.Multiaddr{addrWithPort(1), addrWithPort(2), addrWithPort(3), addrWithPort(4)} - pids := []peer.ID{"testpeer1", "testpeer2", "testpeer3", "testpeer4"} - goodTCP := addrWithPort(20) - - ctx := context.Background() - resch := make(chan dialResult) - - // take all fd limit tokens with hang dials - for _, pid := range pids { - tryDialAddrs(ctx, l, pid, bads, resch) - } - - // these dials should work normally, but will hang because we have taken - // up all the fd limiting - for _, pid := range pids { - l.AddDialJob(&dialJob{ - ctx: ctx, - peer: pid, - addr: goodTCP, - resp: resch, - }) - } - - select { - case <-resch: - t.Fatal("no dials should have completed!") - case <-time.After(time.Millisecond * 100): - } - - pid5 := peer.ID("testpeer5") - utpaddr := ma.StringCast("/ip4/127.0.0.1/udp/7777/utp") - - // This should complete immediately since utp addresses arent blocked by fd rate limiting - l.AddDialJob(&dialJob{ctx: ctx, peer: pid5, addr: utpaddr, resp: resch}) - - select { - case res := <-resch: - if res.Err != nil { - t.Fatal("should have gotten successful response") - } - case <-time.After(time.Second * 5): - t.Fatal("timeout waiting for utp addr success") - } - - // A relay address with tcp transport will complete because we do not consume fds for dials - // with relay addresses as the fd will be consumed when we actually dial the relay server. - pid6 := test.RandPeerIDFatal(t) - relayAddr := ma.StringCast(fmt.Sprintf("/ip4/127.0.0.1/tcp/20/p2p-circuit/p2p/%s", pid6)) - l.AddDialJob(&dialJob{ctx: ctx, peer: pid6, addr: relayAddr, resp: resch}) - - select { - case res := <-resch: - if res.Err != nil { - t.Fatal("should have gotten successful response") - } - case <-time.After(time.Second * 5): - t.Fatal("timeout waiting for relay addr success") - } -} - -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) { - if tcpPortOver(a, 10) { - return (transport.CapableConn)(nil), nil - } - - lk.Lock() - ch := hangchs[p] - lk.Unlock() - <-ch - return nil, fmt.Errorf("test bad dial") - } - l := newDialLimiterWithParams(df, 8, 4) - - bads := []ma.Multiaddr{addrWithPort(1), addrWithPort(2), addrWithPort(3), addrWithPort(4)} - pids := []peer.ID{"testpeer1", "testpeer2"} - - ctx := context.Background() - resch := make(chan dialResult) - - // take all fd limit tokens with hang dials - for _, pid := range pids { - hangchs[pid] = make(chan struct{}) - } - - for _, pid := range pids { - tryDialAddrs(ctx, l, pid, bads, resch) - } - - // add a good dial job for peer 1 - l.AddDialJob(&dialJob{ - ctx: ctx, - peer: pids[1], - addr: ma.StringCast("/ip4/127.0.0.1/tcp/1001"), - resp: resch, - }) - - select { - case <-resch: - t.Fatal("no dials should have completed!") - case <-time.After(time.Millisecond * 100): - } - - // unblock one dial for peer 0 - hangchs[pids[0]] <- struct{}{} - - select { - case res := <-resch: - if res.Err == nil { - t.Fatal("should have only been a failure here") - } - case <-time.After(time.Millisecond * 100): - t.Fatal("expected a dial failure here") - } - - select { - case <-resch: - t.Fatal("no more dials should have completed!") - case <-time.After(time.Millisecond * 100): - } - - // add a bad dial job to peer 0 to fill their rate limiter - // and test that more dials for this peer won't interfere with peer 1's successful dial incoming - l.AddDialJob(&dialJob{ - ctx: ctx, - peer: pids[0], - addr: addrWithPort(7), - resp: resch, - }) - - hangchs[pids[1]] <- struct{}{} - - // now one failed dial from peer 1 should get through and fail - // which will in turn unblock the successful dial on peer 1 - select { - case res := <-resch: - if res.Err == nil { - t.Fatal("should have only been a failure here") - } - case <-time.After(time.Millisecond * 100): - t.Fatal("expected a dial failure here") - } - - select { - case res := <-resch: - if res.Err != nil { - t.Fatal("should have succeeded!") - } - case <-time.After(time.Millisecond * 100): - t.Fatal("should have gotten successful dial") - } -} - -func TestStressLimiter(t *testing.T) { - df := func(ctx context.Context, p peer.ID, a ma.Multiaddr) (transport.CapableConn, error) { - if tcpPortOver(a, 1000) { - return transport.CapableConn(nil), nil - } - - time.Sleep(time.Millisecond * time.Duration(5+rand.Intn(100))) - return nil, fmt.Errorf("test bad dial") - } - - l := newDialLimiterWithParams(df, 20, 5) - - var bads []ma.Multiaddr - for i := 0; i < 100; i++ { - bads = append(bads, addrWithPort(i)) - } - - addresses := append(bads, addrWithPort(2000)) - success := make(chan struct{}) - - for i := 0; i < 20; i++ { - go func(id peer.ID) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - resp := make(chan dialResult) - time.Sleep(time.Duration(rand.Intn(10)) * time.Millisecond) - for _, i := range rand.Perm(len(addresses)) { - l.AddDialJob(&dialJob{ - addr: addresses[i], - ctx: ctx, - peer: id, - resp: resp, - }) - } - - for res := range resp { - if res.Err == nil { - success <- struct{}{} - return - } - } - }(peer.ID(fmt.Sprintf("testpeer%d", i))) - } - - for i := 0; i < 20; i++ { - select { - case <-success: - case <-time.After(time.Minute): - t.Fatal("expected a success within five seconds") - } - } -} - -func TestFDLimitUnderflow(t *testing.T) { - df := func(ctx context.Context, p peer.ID, addr ma.Multiaddr) (transport.CapableConn, error) { - select { - case <-ctx.Done(): - case <-time.After(5 * time.Second): - } - return nil, fmt.Errorf("df timed out") - } - - const fdLimit = 20 - l := newDialLimiterWithParams(df, fdLimit, 3) - - var addrs []ma.Multiaddr - for i := 0; i <= 1000; i++ { - addrs = append(addrs, addrWithPort(i)) - } - - wg := sync.WaitGroup{} - const num = 3 * fdLimit - wg.Add(num) - errs := make(chan error, num) - for i := 0; i < num; i++ { - go func(id peer.ID, i int) { - defer wg.Done() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - resp := make(chan dialResult) - l.AddDialJob(&dialJob{ - addr: addrs[i], - ctx: ctx, - peer: id, - resp: resp, - }) - - for res := range resp { - if res.Err != nil { - return - } - errs <- errors.New("got dial res, but shouldn't") - } - }(peer.ID(fmt.Sprintf("testpeer%d", i%20)), i) - } - - go func() { - wg.Wait() - close(errs) - }() - - for err := range errs { - t.Fatal(err) - } - - l.lk.Lock() - fdConsuming := l.fdConsuming - l.lk.Unlock() - - if fdConsuming < 0 { - t.Fatalf("l.fdConsuming < 0") - } -} diff --git a/peers_test.go b/peers_test.go deleted file mode 100644 index d7c19b4f..00000000 --- a/peers_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package swarm_test - -import ( - "context" - "testing" - "time" - - . "github.com/libp2p/go-libp2p-swarm" - - "github.com/libp2p/go-libp2p-core/peer" - "github.com/libp2p/go-libp2p-core/peerstore" - - ma "github.com/multiformats/go-multiaddr" - - "github.com/stretchr/testify/require" -) - -func TestPeers(t *testing.T) { - ctx := context.Background() - swarms := makeSwarms(t, 2) - s1 := swarms[0] - s2 := swarms[1] - - connect := func(s *Swarm, dst peer.ID, addr ma.Multiaddr) { - // TODO: make a DialAddr func. - s.Peerstore().AddAddr(dst, addr, peerstore.PermanentAddrTTL) - // t.Logf("connections from %s", s.LocalPeer()) - // for _, c := range s.ConnsToPeer(dst) { - // t.Logf("connection from %s to %s: %v", s.LocalPeer(), dst, c) - // } - // t.Logf("") - if _, err := s.DialPeer(ctx, dst); err != nil { - t.Fatal("error swarm dialing to peer", err) - } - // t.Log(s.swarm.Dump()) - } - - connect(s1, s2.LocalPeer(), s2.ListenAddresses()[0]) - require.Eventually(t, func() bool { return len(s2.Peers()) > 0 }, 3*time.Second, 50*time.Millisecond) - connect(s2, s1.LocalPeer(), s1.ListenAddresses()[0]) - - for i := 0; i < 100; i++ { - connect(s1, s2.LocalPeer(), s2.ListenAddresses()[0]) - connect(s2, s1.LocalPeer(), s1.ListenAddresses()[0]) - } - - for _, s := range swarms { - log.Infof("%s swarm routing table: %s", s.LocalPeer(), s.Peers()) - } - - test := func(s *Swarm) { - expect := 1 - actual := len(s.Peers()) - if actual != expect { - t.Errorf("%s has %d peers, not %d: %v", s.LocalPeer(), actual, expect, s.Peers()) - } - actual = len(s.Conns()) - if actual != expect { - t.Errorf("%s has %d conns, not %d: %v", s.LocalPeer(), actual, expect, s.Conns()) - } - } - - test(s1) - test(s2) -} diff --git a/simul_test.go b/simul_test.go deleted file mode 100644 index 0e7d6da7..00000000 --- a/simul_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package swarm_test - -import ( - "context" - "runtime" - "sync" - "testing" - "time" - - "github.com/libp2p/go-libp2p-core/peer" - "github.com/libp2p/go-libp2p-core/peerstore" - - ma "github.com/multiformats/go-multiaddr" - - . "github.com/libp2p/go-libp2p-swarm" - swarmt "github.com/libp2p/go-libp2p-swarm/testing" - "github.com/libp2p/go-libp2p-testing/ci" -) - -func TestSimultOpen(t *testing.T) { - t.Parallel() - swarms := makeSwarms(t, 2, swarmt.OptDisableReuseport) - - // connect everyone - { - var wg sync.WaitGroup - connect := func(s *Swarm, dst peer.ID, addr ma.Multiaddr) { - defer wg.Done() - // copy for other peer - log.Debugf("TestSimultOpen: connecting: %s --> %s (%s)", s.LocalPeer(), dst, addr) - s.Peerstore().AddAddr(dst, addr, peerstore.PermanentAddrTTL) - if _, err := s.DialPeer(context.Background(), dst); err != nil { - t.Error("error swarm dialing to peer", err) - } - } - - log.Info("Connecting swarms simultaneously.") - wg.Add(2) - go connect(swarms[0], swarms[1].LocalPeer(), swarms[1].ListenAddresses()[0]) - go connect(swarms[1], swarms[0].LocalPeer(), swarms[0].ListenAddresses()[0]) - wg.Wait() - } - - for _, s := range swarms { - s.Close() - } -} - -func TestSimultOpenMany(t *testing.T) { - // t.Skip("very very slow") - - addrs := 20 - rounds := 10 - if ci.IsRunning() || runtime.GOOS == "darwin" { - // osx has a limit of 256 file descriptors - addrs = 10 - rounds = 5 - } - subtestSwarm(t, addrs, rounds) -} - -func TestSimultOpenFewStress(t *testing.T) { - if testing.Short() { - t.SkipNow() - } - // t.Skip("skipping for another test") - t.Parallel() - - msgs := 40 - swarms := 2 - rounds := 10 - // rounds := 100 - - for i := 0; i < rounds; i++ { - subtestSwarm(t, swarms, msgs) - <-time.After(10 * time.Millisecond) - } -} diff --git a/swarm.go b/swarm.go index 9df18403..92abe4b9 100644 --- a/swarm.go +++ b/swarm.go @@ -1,607 +1,71 @@ +// Deprecated: This package has moved into go-libp2p as a sub-package: github.com/libp2p/go-libp2p/p2p/net/swarm. package swarm import ( - "context" - "errors" - "fmt" - "io" - "strings" - "sync" - "sync/atomic" "time" + "github.com/libp2p/go-libp2p/p2p/net/swarm" + "github.com/libp2p/go-libp2p-core/connmgr" "github.com/libp2p/go-libp2p-core/metrics" "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-core/transport" - - logging "github.com/ipfs/go-log/v2" - ma "github.com/multiformats/go-multiaddr" ) -const ( - defaultDialTimeout = 15 * time.Second - - // defaultDialTimeoutLocal is the maximum duration a Dial to local network address - // is allowed to take. - // This includes the time between dialing the raw network connection, - // protocol selection as well the handshake, if applicable. - defaultDialTimeoutLocal = 5 * time.Second -) - -var log = logging.Logger("swarm2") - // ErrSwarmClosed is returned when one attempts to operate on a closed swarm. -var ErrSwarmClosed = errors.New("swarm closed") +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.ErrSwarmClosed instead. +var ErrSwarmClosed = swarm.ErrSwarmClosed // ErrAddrFiltered is returned when trying to register a connection to a // filtered address. You shouldn't see this error unless some underlying // transport is misbehaving. -var ErrAddrFiltered = errors.New("address filtered") +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.ErrAddrFiltered instead. +var ErrAddrFiltered = swarm.ErrAddrFiltered // ErrDialTimeout is returned when one a dial times out due to the global timeout -var ErrDialTimeout = errors.New("dial timed out") +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.ErrDialTimeout instead. +var ErrDialTimeout = swarm.ErrDialTimeout -type Option func(*Swarm) error +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.Option instead. +type Option = swarm.Option // WithConnectionGater sets a connection gater +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.WithConnectionGater instead. func WithConnectionGater(gater connmgr.ConnectionGater) Option { - return func(s *Swarm) error { - s.gater = gater - return nil - } + return swarm.WithConnectionGater(gater) } // WithMetrics sets a metrics reporter +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.WithMetrics instead. func WithMetrics(reporter metrics.Reporter) Option { - return func(s *Swarm) error { - s.bwc = reporter - return nil - } + return swarm.WithMetrics(reporter) } +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.WithDialTimeout instead. func WithDialTimeout(t time.Duration) Option { - return func(s *Swarm) error { - s.dialTimeout = t - return nil - } + return swarm.WithDialTimeout(t) } +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.WithDialTimeoutLocal instead. func WithDialTimeoutLocal(t time.Duration) Option { - return func(s *Swarm) error { - s.dialTimeoutLocal = t - return nil - } + return swarm.WithDialTimeoutLocal(t) } +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.WithResourceManager instead. func WithResourceManager(m network.ResourceManager) Option { - return func(s *Swarm) error { - s.rcmgr = m - return nil - } + return swarm.WithResourceManager(m) } // Swarm is a connection muxer, allowing connections to other peers to // be opened and closed, while still using the same Chan for all // 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 - - // Close refcount. This allows us to fully wait for the swarm to be torn - // down before continuing. - refs sync.WaitGroup - - rcmgr network.ResourceManager - - local peer.ID - peers peerstore.Peerstore - - dialTimeout time.Duration - dialTimeoutLocal time.Duration - - conns struct { - sync.RWMutex - m map[peer.ID][]*Conn - } - - listeners struct { - sync.RWMutex - - ifaceListenAddres []ma.Multiaddr - cacheEOL time.Time - - m map[transport.Listener]struct{} - } - - notifs struct { - sync.RWMutex - m map[network.Notifiee]struct{} - } - - transports struct { - sync.RWMutex - m map[int]transport.Transport - } - - // stream handlers - streamh atomic.Value - - // dialing helpers - dsync *dialSync - backf DialBackoff - limiter *dialLimiter - gater connmgr.ConnectionGater - - closeOnce sync.Once - ctx context.Context // is canceled when Close is called - ctxCancel context.CancelFunc - - bwc metrics.Reporter -} +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.Swarm instead. +type Swarm = swarm.Swarm // NewSwarm constructs a Swarm. +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.NewSwarm instead. func NewSwarm(local peer.ID, peers peerstore.Peerstore, opts ...Option) (*Swarm, error) { - ctx, cancel := context.WithCancel(context.Background()) - s := &Swarm{ - local: local, - peers: peers, - ctx: ctx, - ctxCancel: cancel, - dialTimeout: defaultDialTimeout, - dialTimeoutLocal: defaultDialTimeoutLocal, - } - - s.conns.m = make(map[peer.ID][]*Conn) - s.listeners.m = make(map[transport.Listener]struct{}) - s.transports.m = make(map[int]transport.Transport) - s.notifs.m = make(map[network.Notifiee]struct{}) - - for _, opt := range opts { - if err := opt(s); err != nil { - return nil, err - } - } - if s.rcmgr == nil { - s.rcmgr = network.NullResourceManager - } - - s.dsync = newDialSync(s.dialWorkerLoop) - s.limiter = newDialLimiter(s.dialAddr) - s.backf.init(s.ctx) - return s, nil -} - -func (s *Swarm) Close() error { - s.closeOnce.Do(s.close) - return nil -} - -func (s *Swarm) close() { - s.ctxCancel() - - // Prevents new connections and/or listeners from being added to the swarm. - s.listeners.Lock() - listeners := s.listeners.m - s.listeners.m = nil - s.listeners.Unlock() - - s.conns.Lock() - conns := s.conns.m - s.conns.m = nil - s.conns.Unlock() - - // Lots of goroutines but we might as well do this in parallel. We want to shut down as fast as - // possible. - - for l := range listeners { - go func(l transport.Listener) { - if err := l.Close(); err != nil { - log.Errorf("error when shutting down listener: %s", err) - } - }(l) - } - - for _, cs := range conns { - for _, c := range cs { - go func(c *Conn) { - if err := c.Close(); err != nil { - log.Errorf("error when shutting down connection: %s", err) - } - }(c) - } - } - - // Wait for everything to finish. - s.refs.Wait() - - // Now close out any transports (if necessary). Do this after closing - // all connections/listeners. - s.transports.Lock() - transports := s.transports.m - s.transports.m = nil - s.transports.Unlock() - - var wg sync.WaitGroup - for _, t := range transports { - if closer, ok := t.(io.Closer); ok { - wg.Add(1) - go func(c io.Closer) { - defer wg.Done() - if err := closer.Close(); err != nil { - log.Errorf("error when closing down transport %T: %s", c, err) - } - }(closer) - } - } - wg.Wait() -} - -func (s *Swarm) addConn(tc transport.CapableConn, dir network.Direction) (*Conn, error) { - var ( - p = tc.RemotePeer() - addr = tc.RemoteMultiaddr() - ) - - // create the Stat object, initializing with the underlying connection Stat if available - var stat network.ConnStats - if cs, ok := tc.(network.ConnStat); ok { - stat = cs.Stat() - } - stat.Direction = dir - stat.Opened = time.Now() - - // Wrap and register the connection. - c := &Conn{ - conn: tc, - swarm: s, - stat: stat, - id: atomic.AddUint64(&s.nextConnID, 1), - } - - // we ONLY check upgraded connections here so we can send them a Disconnect message. - // If we do this in the Upgrader, we will not be able to do this. - if s.gater != nil { - if allow, _ := s.gater.InterceptUpgraded(c); !allow { - // 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) - } - return nil, ErrGaterDisallowedConnection - } - } - - // Add the public key. - if pk := tc.RemotePublicKey(); pk != nil { - s.peers.AddPubKey(p, pk) - } - - // Clear any backoffs - s.backf.Clear(p) - - // Finally, add the peer. - s.conns.Lock() - // Check if we're still online - if s.conns.m == nil { - s.conns.Unlock() - tc.Close() - return nil, ErrSwarmClosed - } - - c.streams.m = make(map[*Stream]struct{}) - s.conns.m[p] = append(s.conns.m[p], c) - - // Add two swarm refs: - // * One will be decremented after the close notifications fire in Conn.doClose - // * The other will be decremented when Conn.start exits. - s.refs.Add(2) - - // Take the notification lock before releasing the conns lock to block - // Disconnect notifications until after the Connect notifications done. - c.notifyLk.Lock() - s.conns.Unlock() - - s.notifyAll(func(f network.Notifiee) { - f.Connected(s, c) - }) - c.notifyLk.Unlock() - - c.start() - return c, nil -} - -// Peerstore returns this swarms internal Peerstore. -func (s *Swarm) Peerstore() peerstore.Peerstore { - return s.peers -} - -// SetStreamHandler assigns the handler for new streams. -func (s *Swarm) SetStreamHandler(handler network.StreamHandler) { - s.streamh.Store(handler) -} - -// StreamHandler gets the handler for new streams. -func (s *Swarm) StreamHandler() network.StreamHandler { - handler, _ := s.streamh.Load().(network.StreamHandler) - return handler + return swarm.NewSwarm(local, peers, opts...) } - -// NewStream creates a new stream on any available connection to peer, dialing -// if necessary. -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 - // 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 - for { - // will prefer direct connections over relayed connections for opening streams - c := s.bestConnToPeer(p) - if c == nil { - if nodial, _ := network.GetNoDial(ctx); nodial { - return nil, network.ErrNoConn - } - - if dials >= DialAttempts { - return nil, errors.New("max dial attempts exceeded") - } - dials++ - - var err error - c, err = s.dialPeer(ctx, p) - if err != nil { - return nil, err - } - } - - s, err := c.NewStream(ctx) - if err != nil { - if c.conn.IsClosed() { - continue - } - return nil, err - } - return s, nil - } -} - -// ConnsToPeer returns all the live connections to peer. -func (s *Swarm) ConnsToPeer(p peer.ID) []network.Conn { - // TODO: Consider sorting the connection list best to worst. Currently, - // it's sorted oldest to newest. - s.conns.RLock() - defer s.conns.RUnlock() - conns := s.conns.m[p] - output := make([]network.Conn, len(conns)) - for i, c := range conns { - output[i] = c - } - return output -} - -func isBetterConn(a, b *Conn) bool { - // If one is transient and not the other, prefer the non-transient connection. - aTransient := a.Stat().Transient - bTransient := b.Stat().Transient - if aTransient != bTransient { - return !aTransient - } - - // If one is direct and not the other, prefer the direct connection. - aDirect := isDirectConn(a) - bDirect := isDirectConn(b) - if aDirect != bDirect { - return aDirect - } - - // Otherwise, prefer the connection with more open streams. - a.streams.Lock() - aLen := len(a.streams.m) - a.streams.Unlock() - - b.streams.Lock() - bLen := len(b.streams.m) - b.streams.Unlock() - - if aLen != bLen { - return aLen > bLen - } - - // finally, pick the last connection. - return true -} - -// bestConnToPeer returns the best connection to peer. -func (s *Swarm) bestConnToPeer(p peer.ID) *Conn { - - // TODO: Prefer some transports over others. - // For now, prefers direct connections over Relayed connections. - // For tie-breaking, select the newest non-closed connection with the most streams. - s.conns.RLock() - defer s.conns.RUnlock() - - var best *Conn - for _, c := range s.conns.m[p] { - if c.conn.IsClosed() { - // We *will* garbage collect this soon anyways. - continue - } - if best == nil || isBetterConn(c, best) { - best = c - } - } - return best -} - -func (s *Swarm) bestAcceptableConnToPeer(ctx context.Context, p peer.ID) *Conn { - conn := s.bestConnToPeer(p) - if conn != nil { - forceDirect, _ := network.GetForceDirectDial(ctx) - if !forceDirect || isDirectConn(conn) { - return conn - } - } - return nil -} - -func isDirectConn(c *Conn) bool { - return c != nil && !c.conn.Transport().Proxy() -} - -// Connectedness returns our "connectedness" state with the given peer. -// -// To check if we have an open connection, use `s.Connectedness(p) == -// network.Connected`. -func (s *Swarm) Connectedness(p peer.ID) network.Connectedness { - if s.bestConnToPeer(p) != nil { - return network.Connected - } - return network.NotConnected -} - -// Conns returns a slice of all connections. -func (s *Swarm) Conns() []network.Conn { - s.conns.RLock() - defer s.conns.RUnlock() - - conns := make([]network.Conn, 0, len(s.conns.m)) - for _, cs := range s.conns.m { - for _, c := range cs { - conns = append(conns, c) - } - } - return conns -} - -// ClosePeer closes all connections to the given peer. -func (s *Swarm) ClosePeer(p peer.ID) error { - conns := s.ConnsToPeer(p) - switch len(conns) { - case 0: - return nil - case 1: - return conns[0].Close() - default: - errCh := make(chan error) - for _, c := range conns { - go func(c network.Conn) { - errCh <- c.Close() - }(c) - } - - var errs []string - for range conns { - err := <-errCh - if err != nil { - errs = append(errs, err.Error()) - } - } - if len(errs) > 0 { - return fmt.Errorf("when disconnecting from peer %s: %s", p, strings.Join(errs, ", ")) - } - return nil - } -} - -// Peers returns a copy of the set of peers swarm is connected to. -func (s *Swarm) Peers() []peer.ID { - s.conns.RLock() - defer s.conns.RUnlock() - peers := make([]peer.ID, 0, len(s.conns.m)) - for p := range s.conns.m { - peers = append(peers, p) - } - - return peers -} - -// LocalPeer returns the local peer swarm is associated to. -func (s *Swarm) LocalPeer() peer.ID { - return s.local -} - -// Backoff returns the DialBackoff object for this swarm. -func (s *Swarm) Backoff() *DialBackoff { - return &s.backf -} - -// notifyAll sends a signal to all Notifiees -func (s *Swarm) notifyAll(notify func(network.Notifiee)) { - var wg sync.WaitGroup - - s.notifs.RLock() - wg.Add(len(s.notifs.m)) - for f := range s.notifs.m { - go func(f network.Notifiee) { - defer wg.Done() - notify(f) - }(f) - } - - wg.Wait() - s.notifs.RUnlock() -} - -// Notify signs up Notifiee to receive signals when events happen -func (s *Swarm) Notify(f network.Notifiee) { - s.notifs.Lock() - s.notifs.m[f] = struct{}{} - s.notifs.Unlock() -} - -// StopNotify unregisters Notifiee fromr receiving signals -func (s *Swarm) StopNotify(f network.Notifiee) { - s.notifs.Lock() - delete(s.notifs.m, f) - s.notifs.Unlock() -} - -func (s *Swarm) removeConn(c *Conn) { - p := c.RemotePeer() - - s.conns.Lock() - defer s.conns.Unlock() - cs := s.conns.m[p] - for i, ci := range cs { - if ci == c { - if len(cs) == 1 { - delete(s.conns.m, p) - } else { - // NOTE: We're intentionally preserving order. - // This way, connections to a peer are always - // sorted oldest to newest. - copy(cs[i:], cs[i+1:]) - cs[len(cs)-1] = nil - s.conns.m[p] = cs[:len(cs)-1] - } - return - } - } -} - -// String returns a string representation of Network. -func (s *Swarm) String() string { - return fmt.Sprintf("", s.LocalPeer()) -} - -func (s *Swarm) ResourceManager() network.ResourceManager { - return s.rcmgr -} - -// Swarm is a Network. -var _ network.Network = (*Swarm)(nil) -var _ transport.TransportNetwork = (*Swarm)(nil) diff --git a/swarm_addr.go b/swarm_addr.go deleted file mode 100644 index 8d088e76..00000000 --- a/swarm_addr.go +++ /dev/null @@ -1,72 +0,0 @@ -package swarm - -import ( - "time" - - manet "github.com/multiformats/go-multiaddr/net" - - ma "github.com/multiformats/go-multiaddr" -) - -// ListenAddresses returns a list of addresses at which this swarm listens. -func (s *Swarm) ListenAddresses() []ma.Multiaddr { - s.listeners.RLock() - defer s.listeners.RUnlock() - return s.listenAddressesNoLock() -} - -func (s *Swarm) listenAddressesNoLock() []ma.Multiaddr { - addrs := make([]ma.Multiaddr, 0, len(s.listeners.m)) - for l := range s.listeners.m { - addrs = append(addrs, l.Multiaddr()) - } - return addrs -} - -const ifaceAddrsCacheDuration = 1 * time.Minute - -// InterfaceListenAddresses returns a list of addresses at which this swarm -// listens. It expands "any interface" addresses (/ip4/0.0.0.0, /ip6/::) to -// use the known local interfaces. -func (s *Swarm) InterfaceListenAddresses() ([]ma.Multiaddr, error) { - s.listeners.RLock() // RLock start - - ifaceListenAddres := s.listeners.ifaceListenAddres - isEOL := time.Now().After(s.listeners.cacheEOL) - s.listeners.RUnlock() // RLock end - - if !isEOL { - // Cache is valid, clone the slice - return append(ifaceListenAddres[:0:0], ifaceListenAddres...), nil - } - - // Cache is not valid - // Perfrom double checked locking - - s.listeners.Lock() // Lock start - - ifaceListenAddres = s.listeners.ifaceListenAddres - isEOL = time.Now().After(s.listeners.cacheEOL) - if isEOL { - // Cache is still invalid - listenAddres := s.listenAddressesNoLock() - if len(listenAddres) > 0 { - // We're actually listening on addresses. - var err error - ifaceListenAddres, err = manet.ResolveUnspecifiedAddresses(listenAddres, nil) - if err != nil { - s.listeners.Unlock() // Lock early exit - return nil, err - } - } else { - ifaceListenAddres = nil - } - - s.listeners.ifaceListenAddres = ifaceListenAddres - s.listeners.cacheEOL = time.Now().Add(ifaceAddrsCacheDuration) - } - - s.listeners.Unlock() // Lock end - - return append(ifaceListenAddres[:0:0], ifaceListenAddres...), nil -} diff --git a/swarm_addr_test.go b/swarm_addr_test.go deleted file mode 100644 index 21ecafa2..00000000 --- a/swarm_addr_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package swarm_test - -import ( - "context" - "testing" - - "github.com/libp2p/go-libp2p-core/peerstore" - "github.com/libp2p/go-libp2p-core/test" - "github.com/stretchr/testify/require" - - ma "github.com/multiformats/go-multiaddr" - - swarmt "github.com/libp2p/go-libp2p-swarm/testing" -) - -func TestDialBadAddrs(t *testing.T) { - m := func(s string) ma.Multiaddr { - maddr, err := ma.NewMultiaddr(s) - if err != nil { - t.Fatal(err) - } - return maddr - } - - s := makeSwarms(t, 1)[0] - - test := func(a ma.Multiaddr) { - p := test.RandPeerIDFatal(t) - s.Peerstore().AddAddr(p, a, peerstore.PermanentAddrTTL) - if _, err := s.DialPeer(context.Background(), p); err == nil { - t.Errorf("swarm should not dial: %s", p) - } - } - - test(m("/ip6/fe80::1")) // link local - test(m("/ip6/fe80::100")) // link local - test(m("/ip4/127.0.0.1/udp/1234/utp")) // utp -} - -func TestAddrRace(t *testing.T) { - s := makeSwarms(t, 1)[0] - defer s.Close() - - a1, err := s.InterfaceListenAddresses() - require.NoError(t, err) - a2, err := s.InterfaceListenAddresses() - require.NoError(t, err) - - if len(a1) > 0 && len(a2) > 0 && &a1[0] == &a2[0] { - t.Fatal("got the exact same address set twice; this could lead to data races") - } -} - -func TestAddressesWithoutListening(t *testing.T) { - s := swarmt.GenSwarm(t, swarmt.OptDialOnly) - a1, err := s.InterfaceListenAddresses() - require.NoError(t, err) - require.Empty(t, a1, "expected to be listening on no addresses") -} diff --git a/swarm_conn.go b/swarm_conn.go index 77b2defb..3be3eda8 100644 --- a/swarm_conn.go +++ b/swarm_conn.go @@ -1,263 +1,14 @@ package swarm import ( - "context" - "errors" - "fmt" - "sync" - "sync/atomic" - "time" - - 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/transport" - - ma "github.com/multiformats/go-multiaddr" + "github.com/libp2p/go-libp2p/p2p/net/swarm" ) -// TODO: Put this elsewhere. - // ErrConnClosed is returned when operating on a closed connection. -var ErrConnClosed = errors.New("connection closed") +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.ErrConnClosed instead. +var ErrConnClosed = swarm.ErrConnClosed // Conn is the connection type used by swarm. In general, you won't use this // type directly. -type Conn struct { - id uint64 - conn transport.CapableConn - swarm *Swarm - - closeOnce sync.Once - err error - - notifyLk sync.Mutex - - streams struct { - sync.Mutex - m map[*Stream]struct{} - } - - stat network.ConnStats -} - -var _ network.Conn = &Conn{} - -func (c *Conn) ID() string { - // format: - - return fmt.Sprintf("%s-%d", c.RemotePeer().Pretty()[0:10], c.id) -} - -// Close closes this connection. -// -// Note: This method won't wait for the close notifications to finish as that -// would create a deadlock when called from an open notification (because all -// open notifications must finish before we can fire off the close -// notifications). -func (c *Conn) Close() error { - c.closeOnce.Do(c.doClose) - return c.err -} - -func (c *Conn) doClose() { - c.swarm.removeConn(c) - - // Prevent new streams from opening. - c.streams.Lock() - streams := c.streams.m - c.streams.m = nil - c.streams.Unlock() - - c.err = c.conn.Close() - - // This is just for cleaning up state. The connection has already been closed. - // We *could* optimize this but it really isn't worth it. - for s := range streams { - s.Reset() - } - - // do this in a goroutine to avoid deadlocking if we call close in an open notification. - go func() { - // prevents us from issuing close notifications before finishing the open notifications - c.notifyLk.Lock() - defer c.notifyLk.Unlock() - - c.swarm.notifyAll(func(f network.Notifiee) { - f.Disconnected(c.swarm, c) - }) - c.swarm.refs.Done() // taken in Swarm.addConn - }() -} - -func (c *Conn) removeStream(s *Stream) { - c.streams.Lock() - c.stat.NumStreams-- - delete(c.streams.m, s) - c.streams.Unlock() - s.scope.Done() -} - -// listens for new streams. -// -// The caller must take a swarm ref before calling. This function decrements the -// swarm ref count. -func (c *Conn) start() { - go func() { - defer c.swarm.refs.Done() - defer c.Close() - - for { - ts, err := c.conn.AcceptStream() - if err != nil { - return - } - scope, err := c.swarm.ResourceManager().OpenStream(c.RemotePeer(), network.DirInbound) - if err != nil { - ts.Reset() - continue - } - c.swarm.refs.Add(1) - go func() { - s, err := c.addStream(ts, network.DirInbound, scope) - - // Don't defer this. We don't want to block - // swarm shutdown on the connection handler. - c.swarm.refs.Done() - - // We only get an error here when the swarm is closed or closing. - if err != nil { - return - } - - if h := c.swarm.StreamHandler(); h != nil { - h(s) - } - }() - } - }() -} - -func (c *Conn) String() string { - return fmt.Sprintf( - " %s (%s)>", - c.conn.Transport(), - c.conn.LocalMultiaddr(), - c.conn.LocalPeer().Pretty(), - c.conn.RemoteMultiaddr(), - c.conn.RemotePeer().Pretty(), - ) -} - -// LocalMultiaddr is the Multiaddr on this side -func (c *Conn) LocalMultiaddr() ma.Multiaddr { - return c.conn.LocalMultiaddr() -} - -// LocalPeer is the Peer on our side of the connection -func (c *Conn) LocalPeer() peer.ID { - return c.conn.LocalPeer() -} - -// RemoteMultiaddr is the Multiaddr on the remote side -func (c *Conn) RemoteMultiaddr() ma.Multiaddr { - return c.conn.RemoteMultiaddr() -} - -// RemotePeer is the Peer on the remote side -func (c *Conn) RemotePeer() peer.ID { - return c.conn.RemotePeer() -} - -// LocalPrivateKey is the public key of the peer on this side -func (c *Conn) LocalPrivateKey() ic.PrivKey { - return c.conn.LocalPrivateKey() -} - -// RemotePublicKey is the public key of the peer on the remote side -func (c *Conn) RemotePublicKey() ic.PubKey { - return c.conn.RemotePublicKey() -} - -// Stat returns metadata pertaining to this connection -func (c *Conn) Stat() network.ConnStats { - c.streams.Lock() - defer c.streams.Unlock() - return c.stat -} - -// NewStream returns a new Stream from this connection -func (c *Conn) NewStream(ctx context.Context) (network.Stream, error) { - if c.Stat().Transient { - if useTransient, _ := network.GetUseTransient(ctx); !useTransient { - return nil, network.ErrTransientConn - } - } - - scope, err := c.swarm.ResourceManager().OpenStream(c.RemotePeer(), network.DirOutbound) - if err != nil { - return nil, err - } - ts, err := c.conn.OpenStream(ctx) - if err != nil { - scope.Done() - return nil, err - } - return c.addStream(ts, network.DirOutbound, scope) -} - -func (c *Conn) addStream(ts network.MuxedStream, dir network.Direction, scope network.StreamManagementScope) (*Stream, error) { - c.streams.Lock() - // Are we still online? - if c.streams.m == nil { - c.streams.Unlock() - scope.Done() - ts.Reset() - return nil, ErrConnClosed - } - - // Wrap and register the stream. - s := &Stream{ - stream: ts, - conn: c, - scope: scope, - stat: network.Stats{ - Direction: dir, - Opened: time.Now(), - }, - id: atomic.AddUint64(&c.swarm.nextStreamID, 1), - } - c.stat.NumStreams++ - c.streams.m[s] = struct{}{} - - // Released once the stream disconnect notifications have finished - // firing (in Swarm.remove). - c.swarm.refs.Add(1) - - // Take the notification lock before releasing the streams lock to block - // StreamClose notifications until after the StreamOpen notifications - // done. - s.notifyLk.Lock() - c.streams.Unlock() - - c.swarm.notifyAll(func(f network.Notifiee) { - f.OpenedStream(c.swarm, s) - }) - s.notifyLk.Unlock() - - return s, nil -} - -// GetStreams returns the streams associated with this connection. -func (c *Conn) GetStreams() []network.Stream { - c.streams.Lock() - defer c.streams.Unlock() - streams := make([]network.Stream, 0, len(c.streams.m)) - for s := range c.streams.m { - streams = append(streams, s) - } - return streams -} - -func (c *Conn) Scope() network.ConnScope { - return c.conn.Scope() -} +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.Conn instead. +type Conn = swarm.Conn diff --git a/swarm_dial.go b/swarm_dial.go index ca11d732..719f54a0 100644 --- a/swarm_dial.go +++ b/swarm_dial.go @@ -1,18 +1,7 @@ package swarm import ( - "context" - "errors" - "fmt" - "sync" - "time" - - "github.com/libp2p/go-libp2p-core/network" - "github.com/libp2p/go-libp2p-core/peer" - "github.com/libp2p/go-libp2p-core/transport" - - ma "github.com/multiformats/go-multiaddr" - manet "github.com/multiformats/go-multiaddr/net" + "github.com/libp2p/go-libp2p/p2p/net/swarm" ) // Diagram of dial sync: @@ -29,412 +18,70 @@ import ( var ( // ErrDialBackoff is returned by the backoff code when a given peer has // been dialed too frequently - ErrDialBackoff = errors.New("dial backoff") + // Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.ErrDialBackoff instead. + ErrDialBackoff = swarm.ErrDialBackoff // ErrDialToSelf is returned if we attempt to dial our own peer - ErrDialToSelf = errors.New("dial to self attempted") + // Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.ErrDialToSelf instead. + ErrDialToSelf = swarm.ErrDialToSelf // ErrNoTransport is returned when we don't know a transport for the // given multiaddr. - ErrNoTransport = errors.New("no transport for protocol") + // Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.ErrNoTransport instead. + ErrNoTransport = swarm.ErrNoTransport // ErrAllDialsFailed is returned when connecting to a peer has ultimately failed - ErrAllDialsFailed = errors.New("all dials failed") + // Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.ErrAllDialsFailed instead. + ErrAllDialsFailed = swarm.ErrAllDialsFailed // ErrNoAddresses is returned when we fail to find any addresses for a // peer we're trying to dial. - ErrNoAddresses = errors.New("no addresses") + // Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.ErrNoAddresses instead. + ErrNoAddresses = swarm.ErrNoAddresses // ErrNoGoodAddresses is returned when we find addresses for a peer but // can't use any of them. - ErrNoGoodAddresses = errors.New("no good addresses") + // Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.ErrNoGoodAddresses instead. + ErrNoGoodAddresses = swarm.ErrNoGoodAddresses // ErrGaterDisallowedConnection is returned when the gater prevents us from // forming a connection with a peer. - ErrGaterDisallowedConnection = errors.New("gater disallows connection to peer") + // Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.ErrGaterDisallowedConnection instead. + ErrGaterDisallowedConnection = swarm.ErrGaterDisallowedConnection ) // DialAttempts governs how many times a goroutine will try to dial a given peer. // Note: this is down to one, as we have _too many dials_ atm. To add back in, // add loop back in Dial(.) -const DialAttempts = 1 +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.DialAttempts instead. +const DialAttempts = swarm.DialAttempts // ConcurrentFdDials is the number of concurrent outbound dials over transports // that consume file descriptors -const ConcurrentFdDials = 160 +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.ConcurrentFdDials instead. +const ConcurrentFdDials = swarm.ConcurrentFdDials // DefaultPerPeerRateLimit is the number of concurrent outbound dials to make // per peer -const DefaultPerPeerRateLimit = 8 - -// dialbackoff is a struct used to avoid over-dialing the same, dead peers. -// Whenever we totally time out on a peer (all three attempts), we add them -// to dialbackoff. Then, whenevers goroutines would _wait_ (dialsync), they -// check dialbackoff. If it's there, they don't wait and exit promptly with -// an error. (the single goroutine that is actually dialing continues to -// dial). If a dial is successful, the peer is removed from backoff. -// Example: -// -// for { -// if ok, wait := dialsync.Lock(p); !ok { -// if backoff.Backoff(p) { -// return errDialFailed -// } -// <-wait -// continue -// } -// defer dialsync.Unlock(p) -// c, err := actuallyDial(p) -// if err != nil { -// dialbackoff.AddBackoff(p) -// continue -// } -// dialbackoff.Clear(p) -// } -// +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.DefaultPerPeerRateLimit instead. +const DefaultPerPeerRateLimit = swarm.DefaultPerPeerRateLimit // DialBackoff is a type for tracking peer dial backoffs. // // * It's safe to use its zero value. // * It's thread-safe. // * It's *not* safe to move this type after using. -type DialBackoff struct { - entries map[peer.ID]map[string]*backoffAddr - lock sync.RWMutex -} - -type backoffAddr struct { - tries int - until time.Time -} - -func (db *DialBackoff) init(ctx context.Context) { - if db.entries == nil { - db.entries = make(map[peer.ID]map[string]*backoffAddr) - } - go db.background(ctx) -} - -func (db *DialBackoff) background(ctx context.Context) { - ticker := time.NewTicker(BackoffMax) - defer ticker.Stop() - for { - select { - case <-ctx.Done(): - return - case <-ticker.C: - db.cleanup() - } - } -} - -// Backoff returns whether the client should backoff from dialing -// peer p at address addr -func (db *DialBackoff) Backoff(p peer.ID, addr ma.Multiaddr) (backoff bool) { - db.lock.Lock() - defer db.lock.Unlock() - - ap, found := db.entries[p][string(addr.Bytes())] - return found && time.Now().Before(ap.until) -} +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.DialBackoff instead. +type DialBackoff = swarm.DialBackoff // BackoffBase is the base amount of time to backoff (default: 5s). -var BackoffBase = time.Second * 5 +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.BackoffBase instead. +var BackoffBase = swarm.BackoffBase // BackoffCoef is the backoff coefficient (default: 1s). -var BackoffCoef = time.Second +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.BackoffCoef instead. +var BackoffCoef = swarm.BackoffCoef // BackoffMax is the maximum backoff time (default: 5m). -var BackoffMax = time.Minute * 5 - -// AddBackoff lets other nodes know that we've entered backoff with -// peer p, so dialers should not wait unnecessarily. We still will -// attempt to dial with one goroutine, in case we get through. -// -// Backoff is not exponential, it's quadratic and computed according to the -// following formula: -// -// BackoffBase + BakoffCoef * PriorBackoffs^2 -// -// Where PriorBackoffs is the number of previous backoffs. -func (db *DialBackoff) AddBackoff(p peer.ID, addr ma.Multiaddr) { - saddr := string(addr.Bytes()) - db.lock.Lock() - defer db.lock.Unlock() - bp, ok := db.entries[p] - if !ok { - bp = make(map[string]*backoffAddr, 1) - db.entries[p] = bp - } - ba, ok := bp[saddr] - if !ok { - bp[saddr] = &backoffAddr{ - tries: 1, - until: time.Now().Add(BackoffBase), - } - return - } - - backoffTime := BackoffBase + BackoffCoef*time.Duration(ba.tries*ba.tries) - if backoffTime > BackoffMax { - backoffTime = BackoffMax - } - ba.until = time.Now().Add(backoffTime) - ba.tries++ -} - -// Clear removes a backoff record. Clients should call this after a -// successful Dial. -func (db *DialBackoff) Clear(p peer.ID) { - db.lock.Lock() - defer db.lock.Unlock() - delete(db.entries, p) -} - -func (db *DialBackoff) cleanup() { - db.lock.Lock() - defer db.lock.Unlock() - now := time.Now() - for p, e := range db.entries { - good := false - for _, backoff := range e { - backoffTime := BackoffBase + BackoffCoef*time.Duration(backoff.tries*backoff.tries) - if backoffTime > BackoffMax { - backoffTime = BackoffMax - } - if now.Before(backoff.until.Add(backoffTime)) { - good = true - break - } - } - if !good { - delete(db.entries, p) - } - } -} - -// DialPeer connects to a peer. -// -// 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. -// This allows us to use various transport protocols, do NAT traversal/relay, -// etc. to achieve connection. -func (s *Swarm) DialPeer(ctx context.Context, p peer.ID) (network.Conn, error) { - if s.gater != nil && !s.gater.InterceptPeerDial(p) { - log.Debugf("gater disallowed outbound connection to peer %s", p.Pretty()) - return nil, &DialError{Peer: p, Cause: ErrGaterDisallowedConnection} - } - - // Avoid typed nil issues. - c, err := s.dialPeer(ctx, p) - if err != nil { - return nil, err - } - return c, nil -} - -// internal dial method that returns an unwrapped conn -// -// It is gated by the swarm's dial synchronization systems: dialsync and -// dialbackoff. -func (s *Swarm) dialPeer(ctx context.Context, p peer.ID) (*Conn, error) { - log.Debugw("dialing peer", "from", s.local, "to", p) - err := p.Validate() - if err != nil { - return nil, err - } - - if p == s.local { - return nil, ErrDialToSelf - } - - // check if we already have an open (usable) connection first - conn := s.bestAcceptableConnToPeer(ctx, p) - if conn != nil { - return conn, nil - } - - // apply the DialPeer timeout - ctx, cancel := context.WithTimeout(ctx, network.GetDialPeerTimeout(ctx)) - defer cancel() - - conn, err = s.dsync.Dial(ctx, p) - if err == nil { - return conn, nil - } - - log.Debugf("network for %s finished dialing %s", s.local, p) - - if ctx.Err() != nil { - // Context error trumps any dial errors as it was likely the ultimate cause. - return nil, ctx.Err() - } - - if s.ctx.Err() != nil { - // Ok, so the swarm is shutting down. - return nil, ErrSwarmClosed - } - - return nil, err -} - -// dialWorkerLoop synchronizes and executes concurrent dials to a single peer -func (s *Swarm) dialWorkerLoop(p peer.ID, reqch <-chan dialRequest) { - w := newDialWorker(s, p, reqch) - w.loop() -} - -func (s *Swarm) addrsForDial(ctx context.Context, p peer.ID) ([]ma.Multiaddr, error) { - peerAddrs := s.peers.Addrs(p) - if len(peerAddrs) == 0 { - return nil, ErrNoAddresses - } - - goodAddrs := s.filterKnownUndialables(p, peerAddrs) - if forceDirect, _ := network.GetForceDirectDial(ctx); forceDirect { - goodAddrs = ma.FilterAddrs(goodAddrs, s.nonProxyAddr) - } - - if len(goodAddrs) == 0 { - return nil, ErrNoGoodAddresses - } - - return goodAddrs, nil -} - -func (s *Swarm) dialNextAddr(ctx context.Context, p peer.ID, addr ma.Multiaddr, resch chan dialResult) error { - // check the dial backoff - if forceDirect, _ := network.GetForceDirectDial(ctx); !forceDirect { - if s.backf.Backoff(p, addr) { - return ErrDialBackoff - } - } - - // start the dial - s.limitedDial(ctx, p, addr, resch) - - return nil -} - -func (s *Swarm) canDial(addr ma.Multiaddr) bool { - t := s.TransportForDialing(addr) - return t != nil && t.CanDial(addr) -} - -func (s *Swarm) nonProxyAddr(addr ma.Multiaddr) bool { - t := s.TransportForDialing(addr) - return !t.Proxy() -} - -// 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, -// and addresses that we know to be our own. -// This is an optimization to avoid wasting time on dials that we know are going to fail. -func (s *Swarm) filterKnownUndialables(p peer.ID, addrs []ma.Multiaddr) []ma.Multiaddr { - lisAddrs, _ := s.InterfaceListenAddresses() - var ourAddrs []ma.Multiaddr - for _, addr := range lisAddrs { - protos := addr.Protocols() - // we're only sure about filtering out /ip4 and /ip6 addresses, so far - if protos[0].Code == ma.P_IP4 || protos[0].Code == ma.P_IP6 { - ourAddrs = append(ourAddrs, addr) - } - } - - return ma.FilterAddrs(addrs, - func(addr ma.Multiaddr) bool { - for _, a := range ourAddrs { - if a.Equal(addr) { - return false - } - } - return true - }, - s.canDial, - // TODO: Consider allowing link-local addresses - func(addr ma.Multiaddr) bool { return !manet.IsIP6LinkLocal(addr) }, - func(addr ma.Multiaddr) bool { - return s.gater == nil || s.gater.InterceptAddrDial(p, addr) - }, - ) -} - -// 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) { - timeout := s.dialTimeout - if lowTimeoutFilters.AddrBlocked(a) && s.dialTimeoutLocal < s.dialTimeout { - timeout = s.dialTimeoutLocal - } - s.limiter.AddDialJob(&dialJob{ - addr: a, - peer: p, - resp: resp, - ctx: ctx, - timeout: timeout, - }) -} - -// 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) { - // Just to double check. Costs nothing. - if s.local == p { - return nil, ErrDialToSelf - } - log.Debugf("%s swarm dialing %s %s", s.local, p, addr) - - tpt := s.TransportForDialing(addr) - if tpt == nil { - return nil, ErrNoTransport - } - - connC, err := tpt.Dial(ctx, addr, p) - if err != nil { - return nil, err - } - - // Trust the transport? Yeah... right. - if connC.RemotePeer() != p { - connC.Close() - err = fmt.Errorf("BUG in transport %T: tried to dial %s, dialed %s", p, connC.RemotePeer(), tpt) - log.Error(err) - return nil, err - } - - // success! we got one! - return connC, nil -} - -// TODO We should have a `IsFdConsuming() bool` method on the `Transport` interface in go-libp2p-core/transport. -// This function checks if any of the transport protocols in the address requires a file descriptor. -// For now: -// A Non-circuit address which has the TCP/UNIX protocol is deemed FD consuming. -// For a circuit-relay address, we look at the address of the relay server/proxy -// and use the same logic as above to decide. -func isFdConsumingAddr(addr ma.Multiaddr) bool { - first, _ := ma.SplitFunc(addr, func(c ma.Component) bool { - return c.Protocol().Code == ma.P_CIRCUIT - }) - - // for safety - if first == nil { - return true - } - - _, err1 := first.ValueForProtocol(ma.P_TCP) - _, err2 := first.ValueForProtocol(ma.P_UNIX) - return err1 == nil || err2 == nil -} - -func isExpensiveAddr(addr ma.Multiaddr) bool { - _, err1 := addr.ValueForProtocol(ma.P_WS) - _, err2 := addr.ValueForProtocol(ma.P_WSS) - return err1 == nil || err2 == nil -} - -func isRelayAddr(addr ma.Multiaddr) bool { - _, err := addr.ValueForProtocol(ma.P_CIRCUIT) - return err == nil -} +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.BackoffMax instead. +var BackoffMax = swarm.BackoffMax diff --git a/swarm_listen.go b/swarm_listen.go deleted file mode 100644 index ca54280c..00000000 --- a/swarm_listen.go +++ /dev/null @@ -1,121 +0,0 @@ -package swarm - -import ( - "fmt" - "time" - - "github.com/libp2p/go-libp2p-core/network" - - ma "github.com/multiformats/go-multiaddr" -) - -// Listen sets up listeners for all of the given addresses. -// It returns as long as we successfully listen on at least *one* address. -func (s *Swarm) Listen(addrs ...ma.Multiaddr) error { - errs := make([]error, len(addrs)) - var succeeded int - for i, a := range addrs { - if err := s.AddListenAddr(a); err != nil { - errs[i] = err - } else { - succeeded++ - } - } - - for i, e := range errs { - if e != nil { - log.Warnw("listening failed", "on", addrs[i], "error", errs[i]) - } - } - - if succeeded == 0 && len(addrs) > 0 { - return fmt.Errorf("failed to listen on any addresses: %s", errs) - } - - return nil -} - -// AddListenAddr tells the swarm to listen on a single address. Unlike Listen, -// this method does not attempt to filter out bad addresses. -func (s *Swarm) AddListenAddr(a ma.Multiaddr) error { - tpt := s.TransportForListening(a) - if tpt == nil { - // TransportForListening will return nil if either: - // 1. No transport has been registered. - // 2. We're closed (so we've nulled out the transport map. - // - // Distinguish between these two cases to avoid confusing users. - select { - case <-s.ctx.Done(): - return ErrSwarmClosed - default: - return ErrNoTransport - } - } - - list, err := tpt.Listen(a) - if err != nil { - return err - } - - s.listeners.Lock() - if s.listeners.m == nil { - s.listeners.Unlock() - list.Close() - return ErrSwarmClosed - } - s.refs.Add(1) - s.listeners.m[list] = struct{}{} - s.listeners.cacheEOL = time.Time{} - s.listeners.Unlock() - - maddr := list.Multiaddr() - - // signal to our notifiees on listen. - s.notifyAll(func(n network.Notifiee) { - n.Listen(s, maddr) - }) - - go func() { - defer func() { - list.Close() - s.listeners.Lock() - delete(s.listeners.m, list) - s.listeners.cacheEOL = time.Time{} - s.listeners.Unlock() - - // signal to our notifiees on listen close. - s.notifyAll(func(n network.Notifiee) { - n.ListenClose(s, maddr) - }) - s.refs.Done() - }() - for { - c, err := list.Accept() - if err != nil { - if s.ctx.Err() == nil { - // only log if the swarm is still running. - log.Errorf("swarm listener accept error: %s", err) - } - return - } - - log.Debugf("swarm listener accepted connection: %s", c) - s.refs.Add(1) - go func() { - defer s.refs.Done() - _, err := s.addConn(c, network.DirInbound) - switch err { - case nil: - case ErrSwarmClosed: - // ignore. - return - default: - log.Warnw("adding connection failed", "to", a, "error", err) - return - } - }() - } - }() - return nil -} diff --git a/swarm_net_test.go b/swarm_net_test.go deleted file mode 100644 index 3096574d..00000000 --- a/swarm_net_test.go +++ /dev/null @@ -1,164 +0,0 @@ -package swarm_test - -import ( - "context" - "fmt" - "io/ioutil" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/libp2p/go-libp2p-core/network" - - . "github.com/libp2p/go-libp2p-swarm/testing" -) - -// TestConnectednessCorrect starts a few networks, connects a few -// and tests Connectedness value is correct. -func TestConnectednessCorrect(t *testing.T) { - nets := make([]network.Network, 4) - for i := 0; i < 4; i++ { - nets[i] = GenSwarm(t) - } - - // connect 0-1, 0-2, 0-3, 1-2, 2-3 - - dial := func(a, b network.Network) { - DivulgeAddresses(b, a) - if _, err := a.DialPeer(context.Background(), b.LocalPeer()); err != nil { - t.Fatalf("Failed to dial: %s", err) - } - } - - dial(nets[0], nets[1]) - dial(nets[0], nets[3]) - dial(nets[1], nets[2]) - dial(nets[3], nets[2]) - - // The notifications for new connections get sent out asynchronously. - // There is the potential for a race condition here, so we sleep to ensure - // that they have been received. - time.Sleep(time.Millisecond * 100) - - // test those connected show up correctly - - // test connected - expectConnectedness(t, nets[0], nets[1], network.Connected) - expectConnectedness(t, nets[0], nets[3], network.Connected) - expectConnectedness(t, nets[1], nets[2], network.Connected) - expectConnectedness(t, nets[3], nets[2], network.Connected) - - // test not connected - expectConnectedness(t, nets[0], nets[2], network.NotConnected) - expectConnectedness(t, nets[1], nets[3], network.NotConnected) - - require.Len(t, nets[0].Peers(), 2, "expected net 0 to have two peers") - require.Len(t, nets[2].Peers(), 2, "expected net 2 to have two peers") - require.NotZerof(t, nets[1].ConnsToPeer(nets[3].LocalPeer()), "net 1 should have no connections to net 3") - require.NoError(t, nets[2].ClosePeer(nets[1].LocalPeer())) - - time.Sleep(time.Millisecond * 50) - expectConnectedness(t, nets[2], nets[1], network.NotConnected) - - for _, n := range nets { - n.Close() - } -} - -func expectConnectedness(t *testing.T, a, b network.Network, expected network.Connectedness) { - es := "%s is connected to %s, but Connectedness incorrect. %s %s %s" - atob := a.Connectedness(b.LocalPeer()) - btoa := b.Connectedness(a.LocalPeer()) - if atob != expected { - t.Errorf(es, a, b, printConns(a), printConns(b), atob) - } - - // test symmetric case - if btoa != expected { - t.Errorf(es, b, a, printConns(b), printConns(a), btoa) - } -} - -func printConns(n network.Network) string { - s := fmt.Sprintf("Connections in %s:\n", n) - for _, c := range n.Conns() { - s = s + fmt.Sprintf("- %s\n", c) - } - return s -} - -func TestNetworkOpenStream(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - testString := "hello ipfs" - - nets := make([]network.Network, 4) - for i := 0; i < 4; i++ { - nets[i] = GenSwarm(t) - } - - dial := func(a, b network.Network) { - DivulgeAddresses(b, a) - if _, err := a.DialPeer(ctx, b.LocalPeer()); err != nil { - t.Fatalf("Failed to dial: %s", err) - } - } - - dial(nets[0], nets[1]) - dial(nets[0], nets[3]) - dial(nets[1], nets[2]) - - done := make(chan bool) - nets[1].SetStreamHandler(func(s network.Stream) { - defer close(done) - defer s.Close() - - buf, err := ioutil.ReadAll(s) - if err != nil { - t.Error(err) - return - } - if string(buf) != testString { - t.Error("got wrong message") - } - }) - - s, err := nets[0].NewStream(ctx, nets[1].LocalPeer()) - if err != nil { - t.Fatal(err) - } - - var numStreams int - for _, conn := range nets[0].ConnsToPeer(nets[1].LocalPeer()) { - numStreams += conn.Stat().NumStreams - } - - if numStreams != 1 { - t.Fatal("should only have one stream there") - } - - n, err := s.Write([]byte(testString)) - if err != nil { - t.Fatal(err) - } else if n != len(testString) { - t.Errorf("expected to write %d bytes, wrote %d", len(testString), n) - } - - err = s.Close() - if err != nil { - t.Fatal(err) - } - - select { - case <-done: - case <-time.After(time.Millisecond * 100): - t.Fatal("timed out waiting on stream") - } - - _, err = nets[1].NewStream(ctx, nets[3].LocalPeer()) - if err == nil { - t.Fatal("expected stream open 1->3 to fail") - } -} diff --git a/swarm_notif_test.go b/swarm_notif_test.go deleted file mode 100644 index c0c6f82d..00000000 --- a/swarm_notif_test.go +++ /dev/null @@ -1,226 +0,0 @@ -package swarm_test - -import ( - "context" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/libp2p/go-libp2p-core/network" - "github.com/libp2p/go-libp2p-core/peer" - - ma "github.com/multiformats/go-multiaddr" - - . "github.com/libp2p/go-libp2p-swarm" -) - -func TestNotifications(t *testing.T) { - const swarmSize = 5 - - notifiees := make([]*netNotifiee, swarmSize) - - swarms := makeSwarms(t, swarmSize) - defer func() { - for i, s := range swarms { - select { - case <-notifiees[i].listenClose: - t.Error("should not have been closed") - default: - } - require.NoError(t, s.Close()) - select { - case <-notifiees[i].listenClose: - default: - t.Error("expected a listen close notification") - } - } - }() - - const timeout = 5 * time.Second - - // signup notifs - for i, swarm := range swarms { - n := newNetNotifiee(swarmSize) - swarm.Notify(n) - notifiees[i] = n - } - - connectSwarms(t, context.Background(), swarms) - - time.Sleep(50 * time.Millisecond) - // should've gotten 5 by now. - - // test everyone got the correct connection opened calls - for i, s := range swarms { - n := notifiees[i] - notifs := make(map[peer.ID][]network.Conn) - for j, s2 := range swarms { - if i == j { - continue - } - - // this feels a little sketchy, but its probably okay - for len(s.ConnsToPeer(s2.LocalPeer())) != len(notifs[s2.LocalPeer()]) { - select { - case c := <-n.connected: - nfp := notifs[c.RemotePeer()] - notifs[c.RemotePeer()] = append(nfp, c) - case <-time.After(timeout): - t.Fatal("timeout") - } - } - } - - for p, cons := range notifs { - expect := s.ConnsToPeer(p) - if len(expect) != len(cons) { - t.Fatal("got different number of connections") - } - - for _, c := range cons { - var found bool - for _, c2 := range expect { - if c == c2 { - found = true - break - } - } - - if !found { - t.Fatal("connection not found!") - } - } - } - } - - complement := func(c network.Conn) (*Swarm, *netNotifiee, *Conn) { - for i, s := range swarms { - for _, c2 := range s.Conns() { - if c.LocalMultiaddr().Equal(c2.RemoteMultiaddr()) && - c2.LocalMultiaddr().Equal(c.RemoteMultiaddr()) { - return s, notifiees[i], c2.(*Conn) - } - } - } - t.Fatal("complementary conn not found", c) - return nil, nil, nil - } - - testOCStream := func(n *netNotifiee, s network.Stream) { - var s2 network.Stream - select { - case s2 = <-n.openedStream: - t.Log("got notif for opened stream") - case <-time.After(timeout): - t.Fatal("timeout") - } - if s != s2 { - t.Fatal("got incorrect stream", s.Conn(), s2.Conn()) - } - - select { - case s2 = <-n.closedStream: - t.Log("got notif for closed stream") - case <-time.After(timeout): - t.Fatal("timeout") - } - if s != s2 { - t.Fatal("got incorrect stream", s.Conn(), s2.Conn()) - } - } - - streams := make(chan network.Stream) - for _, s := range swarms { - s.SetStreamHandler(func(s network.Stream) { - streams <- s - s.Reset() - }) - } - - // open a streams in each conn - for i, s := range swarms { - for _, c := range s.Conns() { - _, n2, _ := complement(c) - - st1, err := c.NewStream(context.Background()) - if err != nil { - t.Error(err) - } else { - st1.Write([]byte("hello")) - st1.Reset() - testOCStream(notifiees[i], st1) - st2 := <-streams - testOCStream(n2, st2) - } - } - } - - // close conns - for i, s := range swarms { - n := notifiees[i] - for _, c := range s.Conns() { - _, n2, c2 := complement(c) - c.Close() - c2.Close() - - var c3, c4 network.Conn - select { - case c3 = <-n.disconnected: - case <-time.After(timeout): - t.Fatal("timeout") - } - if c != c3 { - t.Fatal("got incorrect conn", c, c3) - } - - select { - case c4 = <-n2.disconnected: - case <-time.After(timeout): - t.Fatal("timeout") - } - if c2 != c4 { - t.Fatal("got incorrect conn", c, c2) - } - } - } -} - -type netNotifiee struct { - listen chan ma.Multiaddr - listenClose chan ma.Multiaddr - connected chan network.Conn - disconnected chan network.Conn - openedStream chan network.Stream - closedStream chan network.Stream -} - -func newNetNotifiee(buffer int) *netNotifiee { - return &netNotifiee{ - listen: make(chan ma.Multiaddr, buffer), - listenClose: make(chan ma.Multiaddr, buffer), - connected: make(chan network.Conn, buffer), - disconnected: make(chan network.Conn, buffer), - openedStream: make(chan network.Stream, buffer), - closedStream: make(chan network.Stream, buffer), - } -} - -func (nn *netNotifiee) Listen(n network.Network, a ma.Multiaddr) { - nn.listen <- a -} -func (nn *netNotifiee) ListenClose(n network.Network, a ma.Multiaddr) { - nn.listenClose <- a -} -func (nn *netNotifiee) Connected(n network.Network, v network.Conn) { - nn.connected <- v -} -func (nn *netNotifiee) Disconnected(n network.Network, v network.Conn) { - nn.disconnected <- v -} -func (nn *netNotifiee) OpenedStream(n network.Network, v network.Stream) { - nn.openedStream <- v -} -func (nn *netNotifiee) ClosedStream(n network.Network, v network.Stream) { - nn.closedStream <- v -} diff --git a/swarm_stream.go b/swarm_stream.go index 5e5c9653..bf91088f 100644 --- a/swarm_stream.go +++ b/swarm_stream.go @@ -1,165 +1,10 @@ package swarm import ( - "fmt" - "sync" - "sync/atomic" - "time" - - "github.com/libp2p/go-libp2p-core/network" - "github.com/libp2p/go-libp2p-core/protocol" + "github.com/libp2p/go-libp2p/p2p/net/swarm" ) -// Validate Stream conforms to the go-libp2p-net Stream interface -var _ network.Stream = &Stream{} - // Stream is the stream type used by swarm. In general, you won't use this type // directly. -type Stream struct { - id uint64 - - stream network.MuxedStream - conn *Conn - scope network.StreamManagementScope - - closeOnce sync.Once - - notifyLk sync.Mutex - - protocol atomic.Value - - stat network.Stats -} - -func (s *Stream) ID() string { - // format: -- - return fmt.Sprintf("%s-%d", s.conn.ID(), s.id) -} - -func (s *Stream) String() string { - return fmt.Sprintf( - " %s (%s)>", - s.conn.conn.Transport(), - s.conn.LocalMultiaddr(), - s.conn.LocalPeer(), - s.conn.RemoteMultiaddr(), - s.conn.RemotePeer(), - ) -} - -// Conn returns the Conn associated with this stream, as an network.Conn -func (s *Stream) Conn() network.Conn { - return s.conn -} - -// Read reads bytes from a stream. -func (s *Stream) Read(p []byte) (int, error) { - n, err := s.stream.Read(p) - // TODO: push this down to a lower level for better accuracy. - if s.conn.swarm.bwc != nil { - s.conn.swarm.bwc.LogRecvMessage(int64(n)) - s.conn.swarm.bwc.LogRecvMessageStream(int64(n), s.Protocol(), s.Conn().RemotePeer()) - } - return n, err -} - -// Write writes bytes to a stream, flushing for each call. -func (s *Stream) Write(p []byte) (int, error) { - n, err := s.stream.Write(p) - // TODO: push this down to a lower level for better accuracy. - if s.conn.swarm.bwc != nil { - s.conn.swarm.bwc.LogSentMessage(int64(n)) - s.conn.swarm.bwc.LogSentMessageStream(int64(n), s.Protocol(), s.Conn().RemotePeer()) - } - return n, err -} - -// Close closes the stream, closing both ends and freeing all associated -// resources. -func (s *Stream) Close() error { - err := s.stream.Close() - s.closeOnce.Do(s.remove) - return err -} - -// Reset resets the stream, signaling an error on both ends and freeing all -// associated resources. -func (s *Stream) Reset() error { - err := s.stream.Reset() - s.closeOnce.Do(s.remove) - return err -} - -// Close 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. -func (s *Stream) CloseWrite() error { - return s.stream.CloseWrite() -} - -// Close closes the stream for reading. This function does not free resources, -// call Close or Reset when done with the stream. -func (s *Stream) CloseRead() error { - return s.stream.CloseRead() -} - -func (s *Stream) remove() { - s.conn.removeStream(s) - - // We *must* do this in a goroutine. This can be called during a - // an open notification and will block until that notification is done. - go func() { - s.notifyLk.Lock() - defer s.notifyLk.Unlock() - - s.conn.swarm.notifyAll(func(f network.Notifiee) { - f.ClosedStream(s.conn.swarm, s) - }) - s.conn.swarm.refs.Done() - }() -} - -// Protocol returns the protocol negotiated on this stream (if set). -func (s *Stream) Protocol() protocol.ID { - // Ignore type error. It means that the protocol is unset. - p, _ := s.protocol.Load().(protocol.ID) - return p -} - -// SetProtocol sets the protocol for this stream. -// -// This doesn't actually *do* anything other than record the fact that we're -// speaking the given protocol over this stream. It's still up to the user to -// negotiate the protocol. This is usually done by the Host. -func (s *Stream) SetProtocol(p protocol.ID) error { - if err := s.scope.SetProtocol(p); err != nil { - return err - } - - s.protocol.Store(p) - return nil -} - -// SetDeadline sets the read and write deadlines for this stream. -func (s *Stream) SetDeadline(t time.Time) error { - return s.stream.SetDeadline(t) -} - -// SetReadDeadline sets the read deadline for this stream. -func (s *Stream) SetReadDeadline(t time.Time) error { - return s.stream.SetReadDeadline(t) -} - -// SetWriteDeadline sets the write deadline for this stream. -func (s *Stream) SetWriteDeadline(t time.Time) error { - return s.stream.SetWriteDeadline(t) -} - -// Stat returns metadata information for this stream. -func (s *Stream) Stat() network.Stats { - return s.stat -} - -func (s *Stream) Scope() network.StreamScope { - return s.scope -} +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm.Stream instead. +type Stream = swarm.Stream diff --git a/swarm_test.go b/swarm_test.go deleted file mode 100644 index 714941f5..00000000 --- a/swarm_test.go +++ /dev/null @@ -1,541 +0,0 @@ -package swarm_test - -import ( - "bytes" - "context" - "errors" - "fmt" - "io" - "strings" - "sync" - "testing" - "time" - - "github.com/libp2p/go-libp2p-core/protocol" - - swarm "github.com/libp2p/go-libp2p-swarm" - . "github.com/libp2p/go-libp2p-swarm/testing" - - "github.com/libp2p/go-libp2p-core/control" - "github.com/libp2p/go-libp2p-core/network" - "github.com/libp2p/go-libp2p-core/peer" - "github.com/libp2p/go-libp2p-core/peerstore" - - logging "github.com/ipfs/go-log/v2" - mocknetwork "github.com/libp2p/go-libp2p-testing/mocks/network" - ma "github.com/multiformats/go-multiaddr" - manet "github.com/multiformats/go-multiaddr/net" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/require" -) - -var log = logging.Logger("swarm_test") - -func EchoStreamHandler(stream network.Stream) { - go func() { - defer stream.Close() - - // pull out the ipfs conn - c := stream.Conn() - log.Infof("%s ponging to %s", c.LocalPeer(), c.RemotePeer()) - - buf := make([]byte, 4) - - for { - if _, err := stream.Read(buf); err != nil { - if err != io.EOF { - log.Error("ping receive error:", err) - } - return - } - - if !bytes.Equal(buf, []byte("ping")) { - log.Errorf("ping receive error: ping != %s %v", buf, buf) - return - } - - if _, err := stream.Write([]byte("pong")); err != nil { - log.Error("pond send error:", err) - return - } - } - }() -} - -func makeDialOnlySwarm(t *testing.T) *swarm.Swarm { - swarm := GenSwarm(t, OptDialOnly) - swarm.SetStreamHandler(EchoStreamHandler) - return swarm -} - -func makeSwarms(t *testing.T, num int, opts ...Option) []*swarm.Swarm { - swarms := make([]*swarm.Swarm, 0, num) - for i := 0; i < num; i++ { - swarm := GenSwarm(t, opts...) - swarm.SetStreamHandler(EchoStreamHandler) - swarms = append(swarms, swarm) - } - return swarms -} - -func connectSwarms(t *testing.T, ctx context.Context, swarms []*swarm.Swarm) { - var wg sync.WaitGroup - connect := func(s *swarm.Swarm, dst peer.ID, addr ma.Multiaddr) { - // TODO: make a DialAddr func. - s.Peerstore().AddAddr(dst, addr, peerstore.PermanentAddrTTL) - if _, err := s.DialPeer(ctx, dst); err != nil { - t.Fatal("error swarm dialing to peer", err) - } - wg.Done() - } - - log.Info("Connecting swarms simultaneously.") - for i, s1 := range swarms { - for _, s2 := range swarms[i+1:] { - wg.Add(1) - connect(s1, s2.LocalPeer(), s2.ListenAddresses()[0]) // try the first. - } - } - wg.Wait() - - for _, s := range swarms { - log.Infof("%s swarm routing table: %s", s.LocalPeer(), s.Peers()) - } -} - -func subtestSwarm(t *testing.T, SwarmNum int, MsgNum int) { - swarms := makeSwarms(t, SwarmNum, OptDisableReuseport) - - // connect everyone - connectSwarms(t, context.Background(), swarms) - - // ping/pong - for _, s1 := range swarms { - log.Debugf("-------------------------------------------------------") - log.Debugf("%s ping pong round", s1.LocalPeer()) - log.Debugf("-------------------------------------------------------") - - _, cancel := context.WithCancel(context.Background()) - got := map[peer.ID]int{} - errChan := make(chan error, MsgNum*len(swarms)) - streamChan := make(chan network.Stream, MsgNum) - - // send out "ping" x MsgNum to every peer - go func() { - defer close(streamChan) - - var wg sync.WaitGroup - send := func(p peer.ID) { - defer wg.Done() - - // first, one stream per peer (nice) - stream, err := s1.NewStream(context.Background(), p) - if err != nil { - errChan <- err - return - } - - // send out ping! - for k := 0; k < MsgNum; k++ { // with k messages - msg := "ping" - log.Debugf("%s %s %s (%d)", s1.LocalPeer(), msg, p, k) - if _, err := stream.Write([]byte(msg)); err != nil { - errChan <- err - continue - } - } - - // read it later - streamChan <- stream - } - - for _, s2 := range swarms { - if s2.LocalPeer() == s1.LocalPeer() { - continue // dont send to self... - } - - wg.Add(1) - go send(s2.LocalPeer()) - } - wg.Wait() - }() - - // receive "pong" x MsgNum from every peer - go func() { - defer close(errChan) - count := 0 - countShouldBe := MsgNum * (len(swarms) - 1) - for stream := range streamChan { // one per peer - // get peer on the other side - p := stream.Conn().RemotePeer() - - // receive pings - msgCount := 0 - msg := make([]byte, 4) - for k := 0; k < MsgNum; k++ { // with k messages - - // read from the stream - if _, err := stream.Read(msg); err != nil { - errChan <- err - continue - } - - if string(msg) != "pong" { - errChan <- fmt.Errorf("unexpected message: %s", msg) - continue - } - - log.Debugf("%s %s %s (%d)", s1.LocalPeer(), msg, p, k) - msgCount++ - } - - got[p] = msgCount - count += msgCount - stream.Close() - } - - if count != countShouldBe { - errChan <- fmt.Errorf("count mismatch: %d != %d", count, countShouldBe) - } - }() - - // check any errors (blocks till consumer is done) - for err := range errChan { - if err != nil { - t.Error(err.Error()) - } - } - - log.Debugf("%s got pongs", s1.LocalPeer()) - if (len(swarms) - 1) != len(got) { - t.Errorf("got (%d) less messages than sent (%d).", len(got), len(swarms)) - } - - for p, n := range got { - if n != MsgNum { - t.Error("peer did not get all msgs", p, n, "/", MsgNum) - } - } - - cancel() - <-time.After(10 * time.Millisecond) - } -} - -func TestSwarm(t *testing.T) { - t.Parallel() - subtestSwarm(t, 5, 100) -} - -func TestBasicSwarm(t *testing.T) { - // t.Skip("skipping for another test") - t.Parallel() - subtestSwarm(t, 2, 1) -} - -func TestConnectionGating(t *testing.T) { - ctx := context.Background() - tcs := map[string]struct { - p1Gater func(gater *MockConnectionGater) *MockConnectionGater - p2Gater func(gater *MockConnectionGater) *MockConnectionGater - - p1ConnectednessToP2 network.Connectedness - p2ConnectednessToP1 network.Connectedness - isP1OutboundErr bool - disableOnQUIC bool - }{ - "no gating": { - p1ConnectednessToP2: network.Connected, - p2ConnectednessToP1: network.Connected, - isP1OutboundErr: false, - }, - "p1 gates outbound peer dial": { - p1Gater: func(c *MockConnectionGater) *MockConnectionGater { - c.PeerDial = func(p peer.ID) bool { return false } - return c - }, - p1ConnectednessToP2: network.NotConnected, - p2ConnectednessToP1: network.NotConnected, - isP1OutboundErr: true, - }, - "p1 gates outbound addr dialing": { - p1Gater: func(c *MockConnectionGater) *MockConnectionGater { - c.Dial = func(p peer.ID, addr ma.Multiaddr) bool { return false } - return c - }, - p1ConnectednessToP2: network.NotConnected, - p2ConnectednessToP1: network.NotConnected, - isP1OutboundErr: true, - }, - "p2 accepts inbound peer dial if outgoing dial is gated": { - p2Gater: func(c *MockConnectionGater) *MockConnectionGater { - c.Dial = func(peer.ID, ma.Multiaddr) bool { return false } - return c - }, - p1ConnectednessToP2: network.Connected, - p2ConnectednessToP1: network.Connected, - isP1OutboundErr: false, - }, - "p2 gates inbound peer dial before securing": { - p2Gater: func(c *MockConnectionGater) *MockConnectionGater { - c.Accept = func(c network.ConnMultiaddrs) bool { return false } - return c - }, - p1ConnectednessToP2: network.NotConnected, - p2ConnectednessToP1: network.NotConnected, - isP1OutboundErr: true, - // QUIC gates the connection after completion of the handshake - disableOnQUIC: true, - }, - "p2 gates inbound peer dial before multiplexing": { - p1Gater: func(c *MockConnectionGater) *MockConnectionGater { - c.Secured = func(network.Direction, peer.ID, network.ConnMultiaddrs) bool { return false } - return c - }, - p1ConnectednessToP2: network.NotConnected, - p2ConnectednessToP1: network.NotConnected, - isP1OutboundErr: true, - }, - "p2 gates inbound peer dial after upgrading": { - p1Gater: func(c *MockConnectionGater) *MockConnectionGater { - c.Upgraded = func(c network.Conn) (bool, control.DisconnectReason) { return false, 0 } - return c - }, - p1ConnectednessToP2: network.NotConnected, - p2ConnectednessToP1: network.NotConnected, - isP1OutboundErr: true, - }, - "p2 gates outbound dials": { - p2Gater: func(c *MockConnectionGater) *MockConnectionGater { - c.PeerDial = func(p peer.ID) bool { return false } - return c - }, - p1ConnectednessToP2: network.Connected, - p2ConnectednessToP1: network.Connected, - isP1OutboundErr: false, - }, - } - - for n, tc := range tcs { - for _, useQuic := range []bool{false, true} { - trString := "TCP" - optTransport := OptDisableQUIC - if useQuic { - if tc.disableOnQUIC { - continue - } - trString = "QUIC" - optTransport = OptDisableTCP - } - t.Run(fmt.Sprintf("%s %s", n, trString), func(t *testing.T) { - p1Gater := DefaultMockConnectionGater() - p2Gater := DefaultMockConnectionGater() - if tc.p1Gater != nil { - p1Gater = tc.p1Gater(p1Gater) - } - if tc.p2Gater != nil { - p2Gater = tc.p2Gater(p2Gater) - } - - sw1 := GenSwarm(t, OptConnGater(p1Gater), optTransport) - sw2 := GenSwarm(t, OptConnGater(p2Gater), optTransport) - - p1 := sw1.LocalPeer() - p2 := sw2.LocalPeer() - sw1.Peerstore().AddAddr(p2, sw2.ListenAddresses()[0], peerstore.PermanentAddrTTL) - // 1 -> 2 - _, err := sw1.DialPeer(ctx, p2) - - require.Equal(t, tc.isP1OutboundErr, err != nil, n) - require.Equal(t, tc.p1ConnectednessToP2, sw1.Connectedness(p2), n) - - require.Eventually(t, func() bool { - return tc.p2ConnectednessToP1 == sw2.Connectedness(p1) - }, 2*time.Second, 100*time.Millisecond, n) - }) - } - } -} - -func TestNoDial(t *testing.T) { - swarms := makeSwarms(t, 2) - - _, err := swarms[0].NewStream(network.WithNoDial(context.Background(), "swarm test"), swarms[1].LocalPeer()) - if err != network.ErrNoConn { - t.Fatal("should have failed with ErrNoConn") - } -} - -func TestCloseWithOpenStreams(t *testing.T) { - ctx := context.Background() - swarms := makeSwarms(t, 2) - connectSwarms(t, ctx, swarms) - - s, err := swarms[0].NewStream(ctx, swarms[1].LocalPeer()) - require.NoError(t, err) - defer s.Close() - // close swarm before stream. - require.NoError(t, swarms[0].Close()) -} - -func TestTypedNilConn(t *testing.T) { - s := GenSwarm(t) - defer s.Close() - - // We can't dial ourselves. - c, err := s.DialPeer(context.Background(), s.LocalPeer()) - require.Error(t, err) - // If we fail to dial, the connection should be nil. - require.Nil(t, c) -} - -func TestPreventDialListenAddr(t *testing.T) { - s := GenSwarm(t, OptDialOnly) - if err := s.Listen(ma.StringCast("/ip4/0.0.0.0/udp/0/quic")); err != nil { - t.Fatal(err) - } - addrs, err := s.InterfaceListenAddresses() - if err != nil { - t.Fatal(err) - } - var addr ma.Multiaddr - for _, a := range addrs { - _, s, err := manet.DialArgs(a) - if err != nil { - t.Fatal(err) - } - if strings.Split(s, ":")[0] == "127.0.0.1" { - addr = a - break - } - } - remote := peer.ID("foobar") - s.Peerstore().AddAddr(remote, addr, time.Hour) - _, err = s.DialPeer(context.Background(), remote) - if !errors.Is(err, swarm.ErrNoGoodAddresses) { - t.Fatal("expected dial to fail: %w", err) - } -} - -func TestStreamCount(t *testing.T) { - s1 := GenSwarm(t) - s2 := GenSwarm(t) - connectSwarms(t, context.Background(), []*swarm.Swarm{s2, s1}) - - countStreams := func() (n int) { - var num int - for _, c := range s1.ConnsToPeer(s2.LocalPeer()) { - n += c.Stat().NumStreams - num += len(c.GetStreams()) - } - require.Equal(t, n, num, "inconsistent stream count") - return - } - - streams := make(chan network.Stream, 20) - streamAccepted := make(chan struct{}, 1) - s1.SetStreamHandler(func(str network.Stream) { - streams <- str - streamAccepted <- struct{}{} - }) - - for i := 0; i < 10; i++ { - str, err := s2.NewStream(context.Background(), s1.LocalPeer()) - require.NoError(t, err) - str.Write([]byte("foobar")) - <-streamAccepted - } - require.Eventually(t, func() bool { return len(streams) == 10 }, 5*time.Second, 10*time.Millisecond) - require.Equal(t, countStreams(), 10) - (<-streams).Reset() - (<-streams).Close() - require.Equal(t, countStreams(), 8) - - str, err := s1.NewStream(context.Background(), s2.LocalPeer()) - require.NoError(t, err) - require.Equal(t, countStreams(), 9) - str.Close() - require.Equal(t, countStreams(), 8) -} - -func TestResourceManager(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - rcmgr1 := mocknetwork.NewMockResourceManager(ctrl) - s1 := GenSwarm(t, OptResourceManager(rcmgr1)) - defer s1.Close() - - rcmgr2 := mocknetwork.NewMockResourceManager(ctrl) - s2 := GenSwarm(t, OptResourceManager(rcmgr2)) - defer s2.Close() - connectSwarms(t, context.Background(), []*swarm.Swarm{s1, s2}) - - strChan := make(chan network.Stream) - s2.SetStreamHandler(func(str network.Stream) { strChan <- str }) - - streamScope1 := mocknetwork.NewMockStreamManagementScope(ctrl) - rcmgr1.EXPECT().OpenStream(s2.LocalPeer(), network.DirOutbound).Return(streamScope1, nil) - streamScope2 := mocknetwork.NewMockStreamManagementScope(ctrl) - rcmgr2.EXPECT().OpenStream(s1.LocalPeer(), network.DirInbound).Return(streamScope2, nil) - str, err := s1.NewStream(context.Background(), s2.LocalPeer()) - require.NoError(t, err) - str.Write([]byte("foobar")) - - p := protocol.ID("proto") - streamScope1.EXPECT().SetProtocol(p) - require.NoError(t, str.SetProtocol(p)) - - sstr := <-strChan - streamScope2.EXPECT().Done() - require.NoError(t, sstr.Close()) - streamScope1.EXPECT().Done() - require.NoError(t, str.Close()) -} - -func TestResourceManagerNewStream(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - rcmgr1 := mocknetwork.NewMockResourceManager(ctrl) - s1 := GenSwarm(t, OptResourceManager(rcmgr1)) - defer s1.Close() - - s2 := GenSwarm(t) - defer s2.Close() - - connectSwarms(t, context.Background(), []*swarm.Swarm{s1, s2}) - - rerr := errors.New("denied") - rcmgr1.EXPECT().OpenStream(s2.LocalPeer(), network.DirOutbound).Return(nil, rerr) - _, err := s1.NewStream(context.Background(), s2.LocalPeer()) - require.ErrorIs(t, err, rerr) -} - -func TestResourceManagerAcceptStream(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - rcmgr1 := mocknetwork.NewMockResourceManager(ctrl) - s1 := GenSwarm(t, OptResourceManager(rcmgr1)) - defer s1.Close() - - rcmgr2 := mocknetwork.NewMockResourceManager(ctrl) - s2 := GenSwarm(t, OptResourceManager(rcmgr2)) - defer s2.Close() - s2.SetStreamHandler(func(str network.Stream) { t.Fatal("didn't expect to accept a stream") }) - - connectSwarms(t, context.Background(), []*swarm.Swarm{s1, s2}) - - streamScope := mocknetwork.NewMockStreamManagementScope(ctrl) - rcmgr1.EXPECT().OpenStream(s2.LocalPeer(), network.DirOutbound).Return(streamScope, nil) - streamScope.EXPECT().Done() - rcmgr2.EXPECT().OpenStream(s1.LocalPeer(), network.DirInbound).Return(nil, errors.New("nope")) - str, err := s1.NewStream(context.Background(), s2.LocalPeer()) - require.NoError(t, err) - _, err = str.Write([]byte("foobar")) - require.NoError(t, err) - _, err = str.Read([]byte{0}) - require.EqualError(t, err, "stream reset") -} diff --git a/swarm_transport.go b/swarm_transport.go deleted file mode 100644 index 21728ac3..00000000 --- a/swarm_transport.go +++ /dev/null @@ -1,111 +0,0 @@ -package swarm - -import ( - "fmt" - "strings" - - "github.com/libp2p/go-libp2p-core/transport" - - ma "github.com/multiformats/go-multiaddr" -) - -// TransportForDialing retrieves the appropriate transport for dialing the given -// multiaddr. -func (s *Swarm) TransportForDialing(a ma.Multiaddr) transport.Transport { - protocols := a.Protocols() - if len(protocols) == 0 { - return nil - } - - s.transports.RLock() - defer s.transports.RUnlock() - if len(s.transports.m) == 0 { - // make sure we're not just shutting down. - if s.transports.m != nil { - log.Error("you have no transports configured") - } - return nil - } - - for _, p := range protocols { - transport, ok := s.transports.m[p.Code] - if !ok { - continue - } - if transport.Proxy() { - return transport - } - } - - return s.transports.m[protocols[len(protocols)-1].Code] -} - -// TransportForListening retrieves the appropriate transport for listening on -// the given multiaddr. -func (s *Swarm) TransportForListening(a ma.Multiaddr) transport.Transport { - protocols := a.Protocols() - if len(protocols) == 0 { - return nil - } - - s.transports.RLock() - defer s.transports.RUnlock() - if len(s.transports.m) == 0 { - // make sure we're not just shutting down. - if s.transports.m != nil { - log.Error("you have no transports configured") - } - return nil - } - - selected := s.transports.m[protocols[len(protocols)-1].Code] - for _, p := range protocols { - transport, ok := s.transports.m[p.Code] - if !ok { - continue - } - if transport.Proxy() { - selected = transport - } - } - return selected -} - -// AddTransport adds a transport to this swarm. -// -// Satisfies the Network interface from go-libp2p-transport. -func (s *Swarm) AddTransport(t transport.Transport) error { - protocols := t.Protocols() - - if len(protocols) == 0 { - return fmt.Errorf("useless transport handles no protocols: %T", t) - } - - s.transports.Lock() - defer s.transports.Unlock() - if s.transports.m == nil { - return ErrSwarmClosed - } - var registered []string - for _, p := range protocols { - if _, ok := s.transports.m[p]; ok { - proto := ma.ProtocolWithCode(p) - name := proto.Name - if name == "" { - name = fmt.Sprintf("unknown (%d)", p) - } - registered = append(registered, name) - } - } - if len(registered) > 0 { - return fmt.Errorf( - "transports already registered for protocol(s): %s", - strings.Join(registered, ", "), - ) - } - - for _, p := range protocols { - s.transports.m[p] = t - } - return nil -} diff --git a/testing/testing.go b/testing/testing.go index e1ab9913..dd1330fd 100644 --- a/testing/testing.go +++ b/testing/testing.go @@ -1,242 +1,80 @@ +// Deprecated: This package has moved into go-libp2p as a sub-package: github.com/libp2p/go-libp2p/p2p/net/swarm/testing. package testing import ( "testing" "time" + "github.com/libp2p/go-libp2p/p2p/net/swarm" + swarm_testing "github.com/libp2p/go-libp2p/p2p/net/swarm/testing" + tptu "github.com/libp2p/go-libp2p/p2p/net/upgrader" + "github.com/libp2p/go-libp2p-core/connmgr" - "github.com/libp2p/go-libp2p-core/control" "github.com/libp2p/go-libp2p-core/crypto" - "github.com/libp2p/go-libp2p-core/metrics" "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-core/sec/insecure" "github.com/libp2p/go-libp2p-core/transport" - "github.com/libp2p/go-tcp-transport" - - csms "github.com/libp2p/go-conn-security-multistream" - "github.com/libp2p/go-libp2p-peerstore/pstoremem" - quic "github.com/libp2p/go-libp2p-quic-transport" - swarm "github.com/libp2p/go-libp2p-swarm" - tnet "github.com/libp2p/go-libp2p-testing/net" - tptu "github.com/libp2p/go-libp2p-transport-upgrader" - yamux "github.com/libp2p/go-libp2p-yamux" - msmux "github.com/libp2p/go-stream-muxer-multistream" - ma "github.com/multiformats/go-multiaddr" - "github.com/stretchr/testify/require" ) -type config struct { - disableReuseport bool - dialOnly bool - disableTCP bool - disableQUIC bool - dialTimeout time.Duration - connectionGater connmgr.ConnectionGater - rcmgr network.ResourceManager - sk crypto.PrivKey -} - // Option is an option that can be passed when constructing a test swarm. -type Option func(*testing.T, *config) +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm/testing.Option instead. +type Option = swarm_testing.Option // OptDisableReuseport disables reuseport in this test swarm. -var OptDisableReuseport Option = func(_ *testing.T, c *config) { - c.disableReuseport = true -} +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm/testing.OptDisableReuseport instead. +var OptDisableReuseport Option = swarm_testing.OptDisableReuseport // OptDialOnly prevents the test swarm from listening. -var OptDialOnly Option = func(_ *testing.T, c *config) { - c.dialOnly = true -} +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm/testing.OptDialOnly instead. +var OptDialOnly Option = swarm_testing.OptDialOnly // OptDisableTCP disables TCP. -var OptDisableTCP Option = func(_ *testing.T, c *config) { - c.disableTCP = true -} +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm/testing.OptDisableTCP instead. +var OptDisableTCP Option = swarm_testing.OptDisableTCP // OptDisableQUIC disables QUIC. -var OptDisableQUIC Option = func(_ *testing.T, c *config) { - c.disableQUIC = true -} +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm/testing.OptDisableQUIC instead. +var OptDisableQUIC Option = swarm_testing.OptDisableQUIC // OptConnGater configures the given connection gater on the test +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm/testing.OptConnGater instead. func OptConnGater(cg connmgr.ConnectionGater) Option { - return func(_ *testing.T, c *config) { - c.connectionGater = cg - } + return swarm_testing.OptConnGater(cg) } +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm/testing.OptResourceManager instead. func OptResourceManager(rcmgr network.ResourceManager) Option { - return func(_ *testing.T, c *config) { - c.rcmgr = rcmgr - } + return swarm_testing.OptResourceManager(rcmgr) } // OptPeerPrivateKey configures the peer private key which is then used to derive the public key and peer ID. +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm/testing.OptPeerPrivateKey instead. func OptPeerPrivateKey(sk crypto.PrivKey) Option { - return func(_ *testing.T, c *config) { - c.sk = sk - } + return swarm_testing.OptPeerPrivateKey(sk) } +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm/testing.DialTimeout instead. func DialTimeout(t time.Duration) Option { - return func(_ *testing.T, c *config) { - c.dialTimeout = t - } + return swarm_testing.DialTimeout(t) } // GenUpgrader creates a new connection upgrader for use with this swarm. +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm/testing.GenUpgrader instead. func GenUpgrader(t *testing.T, n *swarm.Swarm, opts ...tptu.Option) transport.Upgrader { - id := n.LocalPeer() - pk := n.Peerstore().PrivKey(id) - secMuxer := new(csms.SSMuxer) - secMuxer.AddTransport(insecure.ID, insecure.NewWithIdentity(id, pk)) - - stMuxer := msmux.NewBlankTransport() - stMuxer.AddTransport("/yamux/1.0.0", yamux.DefaultTransport) - u, err := tptu.New(secMuxer, stMuxer, opts...) - require.NoError(t, err) - return u + return swarm_testing.GenUpgrader(t, n, opts...) } // GenSwarm generates a new test swarm. +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm/testing.GenSwarm instead. func GenSwarm(t *testing.T, opts ...Option) *swarm.Swarm { - var cfg config - for _, o := range opts { - o(t, &cfg) - } - - var p tnet.PeerNetParams - if cfg.sk == nil { - p = tnet.RandPeerNetParamsOrFatal(t) - } else { - pk := cfg.sk.GetPublic() - id, err := peer.IDFromPublicKey(pk) - if err != nil { - t.Fatal(err) - } - p.PrivKey = cfg.sk - p.PubKey = pk - p.ID = id - p.Addr = tnet.ZeroLocalTCPAddress - } - - ps, err := pstoremem.NewPeerstore() - require.NoError(t, err) - ps.AddPubKey(p.ID, p.PubKey) - ps.AddPrivKey(p.ID, p.PrivKey) - t.Cleanup(func() { ps.Close() }) - - swarmOpts := []swarm.Option{swarm.WithMetrics(metrics.NewBandwidthCounter())} - if cfg.connectionGater != nil { - swarmOpts = append(swarmOpts, swarm.WithConnectionGater(cfg.connectionGater)) - } - if cfg.rcmgr != nil { - swarmOpts = append(swarmOpts, swarm.WithResourceManager(cfg.rcmgr)) - } - if cfg.dialTimeout != 0 { - swarmOpts = append(swarmOpts, swarm.WithDialTimeout(cfg.dialTimeout)) - } - s, err := swarm.NewSwarm(p.ID, ps, swarmOpts...) - require.NoError(t, err) - - upgrader := GenUpgrader(t, s, tptu.WithConnectionGater(cfg.connectionGater)) - - if !cfg.disableTCP { - var tcpOpts []tcp.Option - if cfg.disableReuseport { - tcpOpts = append(tcpOpts, tcp.DisableReuseport()) - } - tcpTransport, err := tcp.NewTCPTransport(upgrader, nil, tcpOpts...) - require.NoError(t, err) - if err := s.AddTransport(tcpTransport); err != nil { - t.Fatal(err) - } - if !cfg.dialOnly { - if err := s.Listen(p.Addr); err != nil { - t.Fatal(err) - } - } - } - if !cfg.disableQUIC { - quicTransport, err := quic.NewTransport(p.PrivKey, nil, cfg.connectionGater, nil) - if err != nil { - t.Fatal(err) - } - if err := s.AddTransport(quicTransport); err != nil { - t.Fatal(err) - } - if !cfg.dialOnly { - if err := s.Listen(ma.StringCast("/ip4/127.0.0.1/udp/0/quic")); err != nil { - t.Fatal(err) - } - } - } - if !cfg.dialOnly { - s.Peerstore().AddAddrs(p.ID, s.ListenAddresses(), peerstore.PermanentAddrTTL) - } - return s + return swarm_testing.GenSwarm(t, opts...) } // DivulgeAddresses adds swarm a's addresses to swarm b's peerstore. +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm/testing.DivulgeAddresses instead. func DivulgeAddresses(a, b network.Network) { - id := a.LocalPeer() - addrs := a.Peerstore().Addrs(id) - b.Peerstore().AddAddrs(id, addrs, peerstore.PermanentAddrTTL) + swarm_testing.DivulgeAddresses(a, b) } // MockConnectionGater is a mock connection gater to be used by the tests. -type MockConnectionGater struct { - Dial func(p peer.ID, addr ma.Multiaddr) bool - PeerDial func(p peer.ID) bool - Accept func(c network.ConnMultiaddrs) bool - Secured func(network.Direction, peer.ID, network.ConnMultiaddrs) bool - Upgraded func(c network.Conn) (bool, control.DisconnectReason) -} - -func DefaultMockConnectionGater() *MockConnectionGater { - m := &MockConnectionGater{} - m.Dial = func(p peer.ID, addr ma.Multiaddr) bool { - return true - } - - m.PeerDial = func(p peer.ID) bool { - return true - } - - m.Accept = func(c network.ConnMultiaddrs) bool { - return true - } - - m.Secured = func(network.Direction, peer.ID, network.ConnMultiaddrs) bool { - return true - } - - m.Upgraded = func(c network.Conn) (bool, control.DisconnectReason) { - return true, 0 - } - - return m -} - -func (m *MockConnectionGater) InterceptAddrDial(p peer.ID, addr ma.Multiaddr) (allow bool) { - return m.Dial(p, addr) -} - -func (m *MockConnectionGater) InterceptPeerDial(p peer.ID) (allow bool) { - return m.PeerDial(p) -} - -func (m *MockConnectionGater) InterceptAccept(c network.ConnMultiaddrs) (allow bool) { - return m.Accept(c) -} - -func (m *MockConnectionGater) InterceptSecured(d network.Direction, p peer.ID, c network.ConnMultiaddrs) (allow bool) { - return m.Secured(d, p, c) -} - -func (m *MockConnectionGater) InterceptUpgraded(tc network.Conn) (allow bool, reason control.DisconnectReason) { - return m.Upgraded(tc) -} +// Deprecated: use github.com/libp2p/go-libp2p/p2p/net/swarm/testing.MockConnectionGater instead. +type MockConnectionGater = swarm_testing.MockConnectionGater diff --git a/testing/testing_test.go b/testing/testing_test.go deleted file mode 100644 index ef625702..00000000 --- a/testing/testing_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package testing - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestGenSwarm(t *testing.T) { - swarm := GenSwarm(t) - require.NoError(t, swarm.Close()) - GenUpgrader(t, swarm) -} diff --git a/transport_test.go b/transport_test.go deleted file mode 100644 index 6d5913cf..00000000 --- a/transport_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package swarm_test - -import ( - "context" - "testing" - - swarm "github.com/libp2p/go-libp2p-swarm" - swarmt "github.com/libp2p/go-libp2p-swarm/testing" - - "github.com/libp2p/go-libp2p-core/peer" - "github.com/libp2p/go-libp2p-core/transport" - - ma "github.com/multiformats/go-multiaddr" - - "github.com/stretchr/testify/require" -) - -type dummyTransport struct { - protocols []int - proxy bool - closed bool -} - -func (dt *dummyTransport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID) (transport.CapableConn, error) { - panic("unimplemented") -} - -func (dt *dummyTransport) CanDial(addr ma.Multiaddr) bool { - panic("unimplemented") -} - -func (dt *dummyTransport) Listen(laddr ma.Multiaddr) (transport.Listener, error) { - panic("unimplemented") -} - -func (dt *dummyTransport) Proxy() bool { - return dt.proxy -} - -func (dt *dummyTransport) Protocols() []int { - return dt.protocols -} -func (dt *dummyTransport) Close() error { - dt.closed = true - return nil -} - -func TestUselessTransport(t *testing.T) { - s := swarmt.GenSwarm(t) - require.Error(t, s.AddTransport(new(dummyTransport)), "adding a transport that supports no protocols should have failed") -} - -func TestTransportClose(t *testing.T) { - s := swarmt.GenSwarm(t) - tpt := &dummyTransport{protocols: []int{1}} - require.NoError(t, s.AddTransport(tpt)) - _ = s.Close() - if !tpt.closed { - t.Fatal("expected transport to be closed") - } -} - -func TestTransportAfterClose(t *testing.T) { - s := swarmt.GenSwarm(t) - s.Close() - - tpt := &dummyTransport{protocols: []int{1}} - if err := s.AddTransport(tpt); err != swarm.ErrSwarmClosed { - t.Fatal("expected swarm closed error, got: ", err) - } -} diff --git a/util_test.go b/util_test.go deleted file mode 100644 index 11124adb..00000000 --- a/util_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package swarm - -import ( - "fmt" - "testing" - - "github.com/libp2p/go-libp2p-core/test" - ma "github.com/multiformats/go-multiaddr" - - "github.com/stretchr/testify/require" -) - -func TestIsFdConsuming(t *testing.T) { - tcs := map[string]struct { - addr string - isFdConsuming bool - }{ - "tcp": { - addr: "/ip4/127.0.0.1/tcp/20", - isFdConsuming: true, - }, - "quic": { - addr: "/ip4/127.0.0.1/udp/0/quic", - isFdConsuming: false, - }, - "addr-without-registered-transport": { - addr: "/ip4/127.0.0.1/tcp/20/ws", - isFdConsuming: true, - }, - "relay-tcp": { - addr: fmt.Sprintf("/ip4/127.0.0.1/tcp/20/p2p-circuit/p2p/%s", test.RandPeerIDFatal(t)), - isFdConsuming: true, - }, - "relay-quic": { - addr: fmt.Sprintf("/ip4/127.0.0.1/udp/20/quic/p2p-circuit/p2p/%s", test.RandPeerIDFatal(t)), - isFdConsuming: false, - }, - "relay-without-serveraddr": { - addr: fmt.Sprintf("/p2p-circuit/p2p/%s", test.RandPeerIDFatal(t)), - isFdConsuming: true, - }, - "relay-without-registered-transport-server": { - addr: fmt.Sprintf("/ip4/127.0.0.1/tcp/20/ws/p2p-circuit/p2p/%s", test.RandPeerIDFatal(t)), - isFdConsuming: true, - }, - } - - for name := range tcs { - maddr, err := ma.NewMultiaddr(tcs[name].addr) - require.NoError(t, err, name) - require.Equal(t, tcs[name].isFdConsuming, isFdConsumingAddr(maddr), name) - } -} diff --git a/version.json b/version.json index 9186b8ee..ea22ea59 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "v0.10.2" + "version": "v0.11.0" }