├── .github └── workflows │ ├── automerge.yml │ ├── go-check.yml │ ├── go-test.yml │ ├── release-check.yml │ ├── releaser.yml │ └── tagpush.yml ├── LICENSE ├── README.md ├── codecov.yml ├── conn.go ├── dial.go ├── go.mod ├── go.sum ├── listen.go ├── pb ├── Makefile ├── relay.pb.go └── relay.proto ├── relay.go ├── relay_test.go ├── transport.go ├── transport_test.go ├── util.go └── version.json /.github/workflows/automerge.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | name: Automerge 5 | on: [ pull_request ] 6 | 7 | jobs: 8 | automerge: 9 | uses: protocol/.github/.github/workflows/automerge.yml@master 10 | with: 11 | job: 'automerge' 12 | -------------------------------------------------------------------------------- /.github/workflows/go-check.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | on: [push, pull_request] 5 | name: Go Checks 6 | 7 | jobs: 8 | unit: 9 | runs-on: ubuntu-latest 10 | name: All 11 | env: 12 | RUNGOGENERATE: false 13 | steps: 14 | - uses: actions/checkout@v2 15 | with: 16 | submodules: recursive 17 | - uses: actions/setup-go@v2 18 | with: 19 | go-version: "1.18.x" 20 | - name: Run repo-specific setup 21 | uses: ./.github/actions/go-check-setup 22 | if: hashFiles('./.github/actions/go-check-setup') != '' 23 | - name: Read config 24 | if: hashFiles('./.github/workflows/go-check-config.json') != '' 25 | run: | 26 | if jq -re .gogenerate ./.github/workflows/go-check-config.json; then 27 | echo "RUNGOGENERATE=true" >> $GITHUB_ENV 28 | fi 29 | - name: Install staticcheck 30 | run: go install honnef.co/go/tools/cmd/staticcheck@d7e217c1ff411395475b2971c0824e1e7cc1af98 # 2022.1 (v0.3.0) 31 | - name: Check that go.mod is tidy 32 | uses: protocol/multiple-go-modules@v1.2 33 | with: 34 | run: | 35 | go mod tidy 36 | if [[ -n $(git ls-files --other --exclude-standard --directory -- go.sum) ]]; then 37 | echo "go.sum was added by go mod tidy" 38 | exit 1 39 | fi 40 | git diff --exit-code -- go.sum go.mod 41 | - name: gofmt 42 | if: ${{ success() || failure() }} # run this step even if the previous one failed 43 | run: | 44 | out=$(gofmt -s -l .) 45 | if [[ -n "$out" ]]; then 46 | echo $out | awk '{print "::error file=" $0 ",line=0,col=0::File is not gofmt-ed."}' 47 | exit 1 48 | fi 49 | - name: go vet 50 | if: ${{ success() || failure() }} # run this step even if the previous one failed 51 | uses: protocol/multiple-go-modules@v1.2 52 | with: 53 | run: go vet ./... 54 | - name: staticcheck 55 | if: ${{ success() || failure() }} # run this step even if the previous one failed 56 | uses: protocol/multiple-go-modules@v1.2 57 | with: 58 | run: | 59 | set -o pipefail 60 | staticcheck ./... | sed -e 's@\(.*\)\.go@./\1.go@g' 61 | - name: go generate 62 | uses: protocol/multiple-go-modules@v1.2 63 | if: (success() || failure()) && env.RUNGOGENERATE == 'true' 64 | with: 65 | run: | 66 | git clean -fd # make sure there aren't untracked files / directories 67 | go generate ./... 68 | # check if go generate modified or added any files 69 | if ! $(git add . && git diff-index HEAD --exit-code --quiet); then 70 | echo "go generated caused changes to the repository:" 71 | git status --short 72 | exit 1 73 | fi 74 | -------------------------------------------------------------------------------- /.github/workflows/go-test.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | on: [push, pull_request] 5 | name: Go Test 6 | 7 | jobs: 8 | unit: 9 | strategy: 10 | fail-fast: false 11 | matrix: 12 | os: [ "ubuntu", "windows", "macos" ] 13 | go: [ "1.17.x", "1.18.x" ] 14 | env: 15 | COVERAGES: "" 16 | runs-on: ${{ format('{0}-latest', matrix.os) }} 17 | name: ${{ matrix.os }} (go ${{ matrix.go }}) 18 | steps: 19 | - uses: actions/checkout@v2 20 | with: 21 | submodules: recursive 22 | - uses: actions/setup-go@v2 23 | with: 24 | go-version: ${{ matrix.go }} 25 | - name: Go information 26 | run: | 27 | go version 28 | go env 29 | - name: Use msys2 on windows 30 | if: ${{ matrix.os == 'windows' }} 31 | shell: bash 32 | # The executable for msys2 is also called bash.cmd 33 | # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md#shells 34 | # If we prepend its location to the PATH 35 | # subsequent 'shell: bash' steps will use msys2 instead of gitbash 36 | run: echo "C:/msys64/usr/bin" >> $GITHUB_PATH 37 | - name: Run repo-specific setup 38 | uses: ./.github/actions/go-test-setup 39 | if: hashFiles('./.github/actions/go-test-setup') != '' 40 | - name: Run tests 41 | uses: protocol/multiple-go-modules@v1.2 42 | with: 43 | # Use -coverpkg=./..., so that we include cross-package coverage. 44 | # If package ./A imports ./B, and ./A's tests also cover ./B, 45 | # this means ./B's coverage will be significantly higher than 0%. 46 | run: go test -v -coverprofile=module-coverage.txt -coverpkg=./... ./... 47 | - name: Run tests (32 bit) 48 | if: ${{ matrix.os != 'macos' }} # can't run 32 bit tests on OSX. 49 | uses: protocol/multiple-go-modules@v1.2 50 | env: 51 | GOARCH: 386 52 | with: 53 | run: | 54 | export "PATH=${{ env.PATH_386 }}:$PATH" 55 | go test -v ./... 56 | - name: Run tests with race detector 57 | if: ${{ matrix.os == 'ubuntu' }} # speed things up. Windows and OSX VMs are slow 58 | uses: protocol/multiple-go-modules@v1.2 59 | with: 60 | run: go test -v -race ./... 61 | - name: Collect coverage files 62 | shell: bash 63 | run: echo "COVERAGES=$(find . -type f -name 'module-coverage.txt' | tr -s '\n' ',' | sed 's/,$//')" >> $GITHUB_ENV 64 | - name: Upload coverage to Codecov 65 | uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 66 | with: 67 | files: '${{ env.COVERAGES }}' 68 | env_vars: OS=${{ matrix.os }}, GO=${{ matrix.go }} 69 | -------------------------------------------------------------------------------- /.github/workflows/release-check.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | name: Release Checker 5 | on: 6 | pull_request: 7 | paths: [ 'version.json' ] 8 | 9 | jobs: 10 | release-check: 11 | uses: protocol/.github/.github/workflows/release-check.yml@master 12 | -------------------------------------------------------------------------------- /.github/workflows/releaser.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | name: Releaser 5 | on: 6 | push: 7 | paths: [ 'version.json' ] 8 | 9 | jobs: 10 | releaser: 11 | uses: protocol/.github/.github/workflows/releaser.yml@master 12 | -------------------------------------------------------------------------------- /.github/workflows/tagpush.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | name: Tag Push Checker 5 | on: 6 | push: 7 | tags: 8 | - v* 9 | 10 | jobs: 11 | releaser: 12 | uses: protocol/.github/.github/workflows/tagpush.yml@master 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Jeromy Johnson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DEPRECATION NOTICE 2 | 3 | This package has moved into go-libp2p as a sub-package, `github.com/libp2p/go-libp2p/p2p/protocol/internal/circuitv1-deprecated`. 4 | 5 | go-libp2p-circuit 6 | ================== 7 | 8 | [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](https://protocol.ai) 9 | [![](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](https://libp2p.io/) 10 | [![](https://img.shields.io/badge/freenode-%23libp2p-yellow.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23libp2p) 11 | [![Coverage Status](https://img.shields.io/codecov/c/github/libp2p/go-libp2p-circuit.svg?style=flat-square&branch=master)](https://codecov.io/github/libp2p/go-libp2p-circuit?branch=master) 12 | [![Travis CI](https://travis-ci.org/libp2p/go-libp2p-circuit.svg?branch=master)](https://travis-ci.org/libp2p/go-libp2p-circuit) 13 | [![Discourse posts](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg)](https://discuss.libp2p.io) 14 | 15 | 16 | > The libp2p relay allows peers to relay connections on behalf of others. 17 | 18 | 19 | ## Table of Contents 20 | 21 | - [Install](#install) 22 | - [Contribute](#contribute) 23 | - [License](#license) 24 | 25 | ## Install 26 | 27 | ```sh 28 | go get -u github.com/libp2p/go-libp2p-circuit 29 | ``` 30 | 31 | ## Usage 32 | 33 | Refer to the [relay example](https://github.com/libp2p/go-libp2p/tree/master/examples/relay) in the `go-libp2p-examples` repository for usage instructions. 34 | 35 | ## Contribute 36 | 37 | PRs are welcome! 38 | 39 | Small note: If editing the Readme, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification. 40 | 41 | ## License 42 | 43 | MIT © Jeromy Johnson 44 | 45 | --- 46 | 47 | The last gx published version of this module was: 2.3.15: QmRTkLxADQRbgnhpt2zzQQJr8Ri764b7dujoDkZw33b3iE 48 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | range: "50...100" 3 | comment: off 4 | -------------------------------------------------------------------------------- /conn.go: -------------------------------------------------------------------------------- 1 | package relay 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "time" 7 | 8 | "github.com/libp2p/go-libp2p-core/host" 9 | "github.com/libp2p/go-libp2p-core/network" 10 | "github.com/libp2p/go-libp2p-core/peer" 11 | 12 | ma "github.com/multiformats/go-multiaddr" 13 | manet "github.com/multiformats/go-multiaddr/net" 14 | ) 15 | 16 | // HopTagWeight is the connection manager weight for connections carrying relay hop streams 17 | var HopTagWeight = 5 18 | 19 | type Conn struct { 20 | stream network.Stream 21 | remote peer.AddrInfo 22 | host host.Host 23 | relay *Relay 24 | } 25 | 26 | type NetAddr struct { 27 | Relay string 28 | Remote string 29 | } 30 | 31 | func (n *NetAddr) Network() string { 32 | return "libp2p-circuit-relay" 33 | } 34 | 35 | func (n *NetAddr) String() string { 36 | return fmt.Sprintf("relay[%s-%s]", n.Remote, n.Relay) 37 | } 38 | 39 | func (c *Conn) Close() error { 40 | c.untagHop() 41 | return c.stream.Reset() 42 | } 43 | 44 | func (c *Conn) Read(buf []byte) (int, error) { 45 | return c.stream.Read(buf) 46 | } 47 | 48 | func (c *Conn) Write(buf []byte) (int, error) { 49 | return c.stream.Write(buf) 50 | } 51 | 52 | func (c *Conn) SetDeadline(t time.Time) error { 53 | return c.stream.SetDeadline(t) 54 | } 55 | 56 | func (c *Conn) SetReadDeadline(t time.Time) error { 57 | return c.stream.SetReadDeadline(t) 58 | } 59 | 60 | func (c *Conn) SetWriteDeadline(t time.Time) error { 61 | return c.stream.SetWriteDeadline(t) 62 | } 63 | 64 | func (c *Conn) RemoteAddr() net.Addr { 65 | return &NetAddr{ 66 | Relay: c.stream.Conn().RemotePeer().Pretty(), 67 | Remote: c.remote.ID.Pretty(), 68 | } 69 | } 70 | 71 | // Increment the underlying relay connection tag by 1, thus increasing its protection from 72 | // connection pruning. This ensures that connections to relays are not accidentally closed, 73 | // by the connection manager, taking with them all the relayed connections (that may themselves 74 | // be protected). 75 | func (c *Conn) tagHop() { 76 | c.relay.mx.Lock() 77 | defer c.relay.mx.Unlock() 78 | 79 | p := c.stream.Conn().RemotePeer() 80 | c.relay.hopCount[p]++ 81 | if c.relay.hopCount[p] == 1 { 82 | c.host.ConnManager().TagPeer(p, "relay-hop-stream", HopTagWeight) 83 | } 84 | } 85 | 86 | // Decrement the underlying relay connection tag by 1; this is performed when we close the 87 | // relayed connection. 88 | func (c *Conn) untagHop() { 89 | c.relay.mx.Lock() 90 | defer c.relay.mx.Unlock() 91 | 92 | p := c.stream.Conn().RemotePeer() 93 | c.relay.hopCount[p]-- 94 | if c.relay.hopCount[p] == 0 { 95 | c.host.ConnManager().UntagPeer(p, "relay-hop-stream") 96 | delete(c.relay.hopCount, p) 97 | } 98 | } 99 | 100 | // TODO: is it okay to cast c.Conn().RemotePeer() into a multiaddr? might be "user input" 101 | func (c *Conn) RemoteMultiaddr() ma.Multiaddr { 102 | // TODO: We should be able to do this directly without converting to/from a string. 103 | relayAddr, err := ma.NewComponent( 104 | ma.ProtocolWithCode(ma.P_P2P).Name, 105 | c.stream.Conn().RemotePeer().Pretty(), 106 | ) 107 | if err != nil { 108 | panic(err) 109 | } 110 | return ma.Join(c.stream.Conn().RemoteMultiaddr(), relayAddr, circuitAddr) 111 | } 112 | 113 | func (c *Conn) LocalMultiaddr() ma.Multiaddr { 114 | return c.stream.Conn().LocalMultiaddr() 115 | } 116 | 117 | func (c *Conn) LocalAddr() net.Addr { 118 | na, err := manet.ToNetAddr(c.stream.Conn().LocalMultiaddr()) 119 | if err != nil { 120 | log.Error("failed to convert local multiaddr to net addr:", err) 121 | return nil 122 | } 123 | return na 124 | } 125 | -------------------------------------------------------------------------------- /dial.go: -------------------------------------------------------------------------------- 1 | package relay 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/libp2p/go-libp2p-core/network" 8 | 9 | "github.com/libp2p/go-libp2p-core/peer" 10 | "github.com/libp2p/go-libp2p-core/transport" 11 | ma "github.com/multiformats/go-multiaddr" 12 | ) 13 | 14 | func (d *RelayTransport) Dial(ctx context.Context, a ma.Multiaddr, p peer.ID) (transport.CapableConn, error) { 15 | c, err := d.Relay().Dial(ctx, a, p) 16 | if err != nil { 17 | return nil, err 18 | } 19 | c.tagHop() 20 | scope, _ := network.NullResourceManager.OpenConnection(network.DirOutbound, false) 21 | return d.upgrader.Upgrade(ctx, d, c, network.DirOutbound, p, scope) 22 | } 23 | 24 | func (r *Relay) Dial(ctx context.Context, a ma.Multiaddr, p peer.ID) (*Conn, error) { 25 | // split /a/p2p-circuit/b into (/a, /p2p-circuit/b) 26 | relayaddr, destaddr := ma.SplitFunc(a, func(c ma.Component) bool { 27 | return c.Protocol().Code == ma.P_CIRCUIT 28 | }) 29 | 30 | // If the address contained no /p2p-circuit part, the second part is nil. 31 | if destaddr == nil { 32 | return nil, fmt.Errorf("%s is not a relay address", a) 33 | } 34 | 35 | if relayaddr == nil { 36 | return nil, fmt.Errorf( 37 | "can't dial a p2p-circuit without specifying a relay: %s", 38 | a, 39 | ) 40 | } 41 | 42 | // Strip the /p2p-circuit prefix from the destaddr. 43 | _, destaddr = ma.SplitFirst(destaddr) 44 | 45 | dinfo := &peer.AddrInfo{ID: p, Addrs: []ma.Multiaddr{}} 46 | if destaddr != nil { 47 | dinfo.Addrs = append(dinfo.Addrs, destaddr) 48 | } 49 | 50 | var rinfo *peer.AddrInfo 51 | rinfo, err := peer.AddrInfoFromP2pAddr(relayaddr) 52 | if err != nil { 53 | return nil, fmt.Errorf("error parsing multiaddr '%s': %s", relayaddr.String(), err) 54 | } 55 | 56 | return r.DialPeer(ctx, *rinfo, *dinfo) 57 | } 58 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/libp2p/go-libp2p-circuit 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/gogo/protobuf v1.3.2 7 | github.com/ipfs/go-log/v2 v2.5.0 8 | github.com/libp2p/go-buffer-pool v0.0.2 9 | github.com/libp2p/go-libp2p-blankhost v0.2.0 10 | github.com/libp2p/go-libp2p-core v0.14.0 11 | github.com/libp2p/go-libp2p-swarm v0.10.0 12 | github.com/libp2p/go-msgio v0.0.6 13 | github.com/multiformats/go-multiaddr v0.5.0 14 | github.com/multiformats/go-varint v0.0.6 15 | ) 16 | 17 | require ( 18 | github.com/beorn7/perks v1.0.1 // indirect 19 | github.com/btcsuite/btcd v0.20.1-beta // indirect 20 | github.com/cespare/xxhash/v2 v2.1.1 // indirect 21 | github.com/cheekybits/genny v1.0.0 // indirect 22 | github.com/davecgh/go-spew v1.1.1 // indirect 23 | github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 // indirect 24 | github.com/francoispqt/gojay v1.2.13 // indirect 25 | github.com/fsnotify/fsnotify v1.4.9 // indirect 26 | github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect 27 | github.com/golang/protobuf v1.5.2 // indirect 28 | github.com/google/gopacket v1.1.19 // indirect 29 | github.com/ipfs/go-cid v0.0.7 // indirect 30 | github.com/ipfs/go-log v1.0.4 // indirect 31 | github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect 32 | github.com/klauspost/compress v1.13.6 // indirect 33 | github.com/klauspost/cpuid/v2 v2.0.4 // indirect 34 | github.com/libp2p/go-conn-security-multistream v0.3.0 // indirect 35 | github.com/libp2p/go-eventbus v0.2.1 // indirect 36 | github.com/libp2p/go-flow-metrics v0.0.3 // indirect 37 | github.com/libp2p/go-libp2p-peerstore v0.6.0 // indirect 38 | github.com/libp2p/go-libp2p-pnet v0.2.0 // indirect 39 | github.com/libp2p/go-libp2p-quic-transport v0.16.0 // indirect 40 | github.com/libp2p/go-libp2p-testing v0.7.0 // indirect 41 | github.com/libp2p/go-libp2p-tls v0.3.0 // indirect 42 | github.com/libp2p/go-libp2p-transport-upgrader v0.7.0 // indirect 43 | github.com/libp2p/go-libp2p-yamux v0.8.0 // indirect 44 | github.com/libp2p/go-netroute v0.2.0 // indirect 45 | github.com/libp2p/go-openssl v0.0.7 // indirect 46 | github.com/libp2p/go-reuseport v0.1.0 // indirect 47 | github.com/libp2p/go-reuseport-transport v0.1.0 // indirect 48 | github.com/libp2p/go-stream-muxer-multistream v0.4.0 // indirect 49 | github.com/libp2p/go-tcp-transport v0.5.0 // indirect 50 | github.com/libp2p/go-yamux/v3 v3.0.1 // indirect 51 | github.com/lucas-clemente/quic-go v0.25.0 // indirect 52 | github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect 53 | github.com/marten-seemann/qtls-go1-17 v0.1.0 // indirect 54 | github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 // indirect 55 | github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect 56 | github.com/mattn/go-isatty v0.0.14 // indirect 57 | github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect 58 | github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect 59 | github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect 60 | github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect 61 | github.com/minio/sha256-simd v1.0.0 // indirect 62 | github.com/mr-tron/base58 v1.2.0 // indirect 63 | github.com/multiformats/go-base32 v0.0.3 // indirect 64 | github.com/multiformats/go-base36 v0.1.0 // indirect 65 | github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect 66 | github.com/multiformats/go-multibase v0.0.3 // indirect 67 | github.com/multiformats/go-multihash v0.0.15 // indirect 68 | github.com/multiformats/go-multistream v0.2.1 // indirect 69 | github.com/nxadm/tail v1.4.8 // indirect 70 | github.com/onsi/ginkgo v1.16.4 // indirect 71 | github.com/opentracing/opentracing-go v1.1.0 // indirect 72 | github.com/pmezard/go-difflib v1.0.0 // indirect 73 | github.com/prometheus/client_golang v1.10.0 // indirect 74 | github.com/prometheus/client_model v0.2.0 // indirect 75 | github.com/prometheus/common v0.18.0 // indirect 76 | github.com/prometheus/procfs v0.6.0 // indirect 77 | github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect 78 | github.com/stretchr/testify v1.7.0 // indirect 79 | github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect 80 | go.uber.org/atomic v1.7.0 // indirect 81 | go.uber.org/multierr v1.6.0 // indirect 82 | go.uber.org/zap v1.19.1 // indirect 83 | golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf // indirect 84 | golang.org/x/mod v0.4.2 // indirect 85 | golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect 86 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect 87 | golang.org/x/tools v0.1.5 // indirect 88 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect 89 | google.golang.org/grpc v1.31.1 // indirect 90 | google.golang.org/protobuf v1.26.0 // indirect 91 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect 92 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 93 | ) 94 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 4 | cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= 5 | dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= 6 | dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= 7 | dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= 8 | dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= 9 | git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= 10 | github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= 11 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 12 | github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= 13 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 14 | github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= 15 | github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= 16 | github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= 17 | github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= 18 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= 19 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 20 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 21 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 22 | github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 23 | github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= 24 | github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= 25 | github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= 26 | github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= 27 | github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= 28 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 29 | github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= 30 | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 31 | github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= 32 | github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= 33 | github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 34 | github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= 35 | github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= 36 | github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 37 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 38 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 39 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 40 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 41 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 42 | github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= 43 | github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= 44 | github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= 45 | github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= 46 | github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= 47 | github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= 48 | github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= 49 | github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= 50 | github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= 51 | github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= 52 | github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= 53 | github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= 54 | github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= 55 | github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= 56 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 57 | github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 58 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 59 | github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 60 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 61 | github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= 62 | github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= 63 | github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= 64 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 65 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 66 | github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= 67 | github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= 68 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 69 | github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 70 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 71 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 72 | github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 73 | github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 74 | github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 75 | github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 76 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 77 | github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 78 | github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 79 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 80 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 81 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 82 | github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC5IlbaIF5Q7JNieBoACT7iW0YTxQHR0in0= 83 | github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= 84 | github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= 85 | github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= 86 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 87 | github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= 88 | github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 89 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 90 | github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= 91 | github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= 92 | github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= 93 | github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= 94 | github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= 95 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 96 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 97 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 98 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 99 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 100 | github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= 101 | github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= 102 | github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= 103 | github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= 104 | github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= 105 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 106 | github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= 107 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 108 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 109 | github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= 110 | github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 111 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 112 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 113 | github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= 114 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 115 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 116 | github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= 117 | github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 118 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 119 | github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= 120 | github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= 121 | github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= 122 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 123 | github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 124 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 125 | github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 126 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 127 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 128 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 129 | github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 130 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 131 | github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= 132 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 133 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 134 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 135 | github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= 136 | github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= 137 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 138 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 139 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 140 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 141 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 142 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 143 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 144 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 145 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 146 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 147 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 148 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 149 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 150 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 151 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 152 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 153 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 154 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 155 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 156 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 157 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 158 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 159 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 160 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 161 | github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= 162 | github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= 163 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 164 | github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= 165 | github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= 166 | github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 167 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 168 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 169 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 170 | github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 171 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 172 | github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= 173 | github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= 174 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 175 | github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= 176 | github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 177 | github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 178 | github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 179 | github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 180 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 181 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 182 | github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= 183 | github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 184 | github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= 185 | github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= 186 | github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= 187 | github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= 188 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 189 | github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 190 | github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= 191 | github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= 192 | github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= 193 | github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= 194 | github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= 195 | github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= 196 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 197 | github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 198 | github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 199 | github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= 200 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 201 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 202 | github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 203 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 204 | github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= 205 | github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= 206 | github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= 207 | github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= 208 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 209 | github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= 210 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 211 | github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= 212 | github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= 213 | github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= 214 | github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= 215 | github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY= 216 | github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= 217 | github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= 218 | github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= 219 | github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= 220 | github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q= 221 | github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= 222 | github.com/ipfs/go-log v1.0.4 h1:6nLQdX4W8P9yZZFH7mO+X/PzjN8Laozm/lMJ6esdgzY= 223 | github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= 224 | github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= 225 | github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g= 226 | github.com/ipfs/go-log/v2 v2.5.0 h1:+MhAooFd9XZNvR0i9FriKW6HB0ql7HNXUuflWtc0dd4= 227 | github.com/ipfs/go-log/v2 v2.5.0/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= 228 | github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= 229 | github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= 230 | github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= 231 | github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= 232 | github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= 233 | github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= 234 | github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 235 | github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 236 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 237 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 238 | github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= 239 | github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= 240 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 241 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 242 | github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 243 | github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 244 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 245 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 246 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 247 | github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= 248 | github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= 249 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 250 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 251 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 252 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 253 | github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= 254 | github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= 255 | github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 256 | github.com/klauspost/cpuid/v2 v2.0.4 h1:g0I61F2K2DjRHz1cnxlkNSBIaePVoJIjjnHui8QHbiw= 257 | github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 258 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 259 | github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 260 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 261 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 262 | github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= 263 | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 264 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 265 | github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 266 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 267 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 268 | github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= 269 | github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= 270 | github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= 271 | github.com/libp2p/go-conn-security-multistream v0.3.0 h1:9UCIKlBL1hC9u7nkMXpD1nkc/T53PKMAn3/k9ivBAVc= 272 | github.com/libp2p/go-conn-security-multistream v0.3.0/go.mod h1:EEP47t4fw/bTelVmEzIDqSe69hO/ip52xBEhZMLWAHM= 273 | github.com/libp2p/go-eventbus v0.2.1 h1:VanAdErQnpTioN2TowqNcOijf6YwhuODe4pPKSDpxGc= 274 | github.com/libp2p/go-eventbus v0.2.1/go.mod h1:jc2S4SoEVPP48H9Wpzm5aiGwUCBMfGhVhhBjyhhCJs8= 275 | github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= 276 | github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM= 277 | github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= 278 | github.com/libp2p/go-libp2p-blankhost v0.2.0 h1:3EsGAi0CBGcZ33GwRuXEYJLLPoVWyXJ1bcJzAJjINkk= 279 | github.com/libp2p/go-libp2p-blankhost v0.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= 280 | github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= 281 | github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= 282 | github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= 283 | github.com/libp2p/go-libp2p-core v0.5.7/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= 284 | github.com/libp2p/go-libp2p-core v0.6.0/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= 285 | github.com/libp2p/go-libp2p-core v0.10.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= 286 | github.com/libp2p/go-libp2p-core v0.12.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= 287 | github.com/libp2p/go-libp2p-core v0.14.0 h1:0kYSgiK/D7Eo28GTuRXo5YHsWwAisVpFCqCVPUd/vJs= 288 | github.com/libp2p/go-libp2p-core v0.14.0/go.mod h1:tLasfcVdTXnixsLB0QYaT1syJOhsbrhG7q6pGrHtBg8= 289 | github.com/libp2p/go-libp2p-mplex v0.5.0 h1:vt3k4E4HSND9XH4Z8rUpacPJFSAgLOv6HDvG8W9Ks9E= 290 | github.com/libp2p/go-libp2p-mplex v0.5.0/go.mod h1:eLImPJLkj3iG5t5lq68w3Vm5NAQ5BcKwrrb2VmOYb3M= 291 | github.com/libp2p/go-libp2p-peerstore v0.6.0 h1:HJminhQSGISBIRb93N6WK3t6Fa8OOTnHd/VBjL4mY5A= 292 | github.com/libp2p/go-libp2p-peerstore v0.6.0/go.mod h1:DGEmKdXrcYpK9Jha3sS7MhqYdInxJy84bIPtSu65bKc= 293 | github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= 294 | github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= 295 | github.com/libp2p/go-libp2p-quic-transport v0.16.0 h1:aVg9/jr+R2esov5sH7wkXrmYmqJiUjtLMLYX3L9KYdY= 296 | github.com/libp2p/go-libp2p-quic-transport v0.16.0/go.mod h1:1BXjVMzr+w7EkPfiHkKnwsWjPjtfaNT0q8RS3tGDvEQ= 297 | github.com/libp2p/go-libp2p-swarm v0.10.0 h1:1yr7UCwxCN92cw9g9Q+fnJSlk7lOB1RetoEewxhGVL0= 298 | github.com/libp2p/go-libp2p-swarm v0.10.0/go.mod h1:71ceMcV6Rg/0rIQ97rsZWMzto1l9LnNquef+efcRbmA= 299 | github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= 300 | github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc= 301 | github.com/libp2p/go-libp2p-testing v0.5.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= 302 | github.com/libp2p/go-libp2p-testing v0.7.0 h1:9bfyhNINizxuLrKsenzGaZalXRXIaAEmx1BP/PzF1gM= 303 | github.com/libp2p/go-libp2p-testing v0.7.0/go.mod h1:OLbdn9DbgdMwv00v+tlp1l3oe2Cl+FAjoWIA2pa0X6E= 304 | github.com/libp2p/go-libp2p-tls v0.3.0 h1:8BgvUJiOTcj0Gp6XvEicF0rL5aUtRg/UzEdeZDmDlC8= 305 | github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= 306 | github.com/libp2p/go-libp2p-transport-upgrader v0.7.0 h1:ADnLrL7fC4Vy7HPjk9oGof7nDeTqGXuof85Ar6kin9Q= 307 | github.com/libp2p/go-libp2p-transport-upgrader v0.7.0/go.mod h1:GIR2aTRp1J5yjVlkUoFqMkdobfob6RnAwYg/RZPhrzg= 308 | github.com/libp2p/go-libp2p-yamux v0.8.0 h1:APQYlttIj+Rr5sfa6siojwsi0ZwcIh/exHIUl9hZr6o= 309 | github.com/libp2p/go-libp2p-yamux v0.8.0/go.mod h1:yTkPgN2ib8FHyU1ZcVD7aelzyAqXXwEPbyx+aSKm9h8= 310 | github.com/libp2p/go-maddr-filter v0.1.0/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= 311 | github.com/libp2p/go-mplex v0.4.0 h1:Ukkez9/4EOX5rTw4sHefNJp10dksftAA05ZgyjplUbM= 312 | github.com/libp2p/go-mplex v0.4.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= 313 | github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= 314 | github.com/libp2p/go-msgio v0.0.6 h1:lQ7Uc0kS1wb1EfRxO2Eir/RJoHkHn7t6o+EiwsYIKJA= 315 | github.com/libp2p/go-msgio v0.0.6/go.mod h1:4ecVB6d9f4BDSL5fqvPiC4A3KivjWn+Venn/1ALLMWA= 316 | github.com/libp2p/go-netroute v0.1.3/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= 317 | github.com/libp2p/go-netroute v0.1.5/go.mod h1:V1SR3AaECRkEQCoFFzYwVYWvYIEtlxx89+O3qcpCl4A= 318 | github.com/libp2p/go-netroute v0.2.0 h1:0FpsbsvuSnAhXFnCY0VLFbJOzaK0VnP0r1QT/o4nWRE= 319 | github.com/libp2p/go-netroute v0.2.0/go.mod h1:Vio7LTzZ+6hoT4CMZi5/6CpY3Snzh2vgZhWgxMNwlQI= 320 | github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= 321 | github.com/libp2p/go-openssl v0.0.5/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= 322 | github.com/libp2p/go-openssl v0.0.7 h1:eCAzdLejcNVBzP/iZM9vqHnQm+XyCEbSSIheIPRGNsw= 323 | github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= 324 | github.com/libp2p/go-reuseport v0.1.0 h1:0ooKOx2iwyIkf339WCZ2HN3ujTDbkK0PjC7JVoP1AiM= 325 | github.com/libp2p/go-reuseport v0.1.0/go.mod h1:bQVn9hmfcTaoo0c9v5pBhOarsU1eNOBZdaAd2hzXRKU= 326 | github.com/libp2p/go-reuseport-transport v0.1.0 h1:C3PHeHjmnz8m6f0uydObj02tMEoi7CyD1zuN7xQT8gc= 327 | github.com/libp2p/go-reuseport-transport v0.1.0/go.mod h1:vev0C0uMkzriDY59yFHD9v+ujJvYmDQVLowvAjEOmfw= 328 | github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= 329 | github.com/libp2p/go-sockaddr v0.1.0/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= 330 | github.com/libp2p/go-stream-muxer-multistream v0.4.0 h1:HsM/9OdtqnIzjVXcxTXjmqKrj3gJ8kacaOJwJS1ipaY= 331 | github.com/libp2p/go-stream-muxer-multistream v0.4.0/go.mod h1:nb+dGViZleRP4XcyHuZSVrJCBl55nRBOMmiSL/dyziw= 332 | github.com/libp2p/go-tcp-transport v0.5.0 h1:3ZPW8HAuyRAuFzyabE0hSrCXKKSWzROnZZX7DtcIatY= 333 | github.com/libp2p/go-tcp-transport v0.5.0/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= 334 | github.com/libp2p/go-yamux/v3 v3.0.1 h1:lIdxHGVZ+y/EHgCrqGNt4Q+Mk9qu26MbOWH/yRw+Ihk= 335 | github.com/libp2p/go-yamux/v3 v3.0.1/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= 336 | github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= 337 | github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= 338 | github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc= 339 | github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg= 340 | github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= 341 | github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= 342 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 343 | github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 344 | github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 345 | github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= 346 | github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= 347 | github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco= 348 | github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= 349 | github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= 350 | github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= 351 | github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM= 352 | github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI= 353 | github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= 354 | github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= 355 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 356 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 357 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 358 | github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 359 | github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= 360 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 361 | github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 362 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= 363 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 364 | github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= 365 | github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= 366 | github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 367 | github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= 368 | github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= 369 | github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= 370 | github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= 371 | github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= 372 | github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= 373 | github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= 374 | github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= 375 | github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= 376 | github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= 377 | github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= 378 | github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= 379 | github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= 380 | github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= 381 | github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= 382 | github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= 383 | github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 384 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 385 | github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 386 | github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= 387 | github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= 388 | github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 389 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 390 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 391 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 392 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 393 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 394 | github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= 395 | github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 396 | github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 397 | github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= 398 | github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 399 | github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= 400 | github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= 401 | github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= 402 | github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= 403 | github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= 404 | github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= 405 | github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= 406 | github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= 407 | github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y= 408 | github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= 409 | github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= 410 | github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= 411 | github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/oCXAT8Z4mzFpyoPyRc= 412 | github.com/multiformats/go-multiaddr v0.4.1/go.mod h1:3afI9HfVW8csiF8UZqtpYRiDyew8pRX7qLIGHu9FLuM= 413 | github.com/multiformats/go-multiaddr v0.5.0 h1:i/JuOoVg4szYQ4YEzDGtb2h0o8M7CG/Yq6cGlcjWZpM= 414 | github.com/multiformats/go-multiaddr v0.5.0/go.mod h1:3KAxNkUqLTJ20AAwN4XVX4kZar+bR+gh4zgbfr3SNug= 415 | github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= 416 | github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= 417 | github.com/multiformats/go-multiaddr-net v0.2.0/go.mod h1:gGdH3UXny6U3cKKYCvpXI5rnK7YaOIEOPVDI9tsJbEA= 418 | github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= 419 | github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= 420 | github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= 421 | github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= 422 | github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= 423 | github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= 424 | github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= 425 | github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= 426 | github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= 427 | github.com/multiformats/go-multihash v0.0.15 h1:hWOPdrNqDjwHDx82vsYGSDZNyktOJJ2dzZJzFkOV1jM= 428 | github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= 429 | github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= 430 | github.com/multiformats/go-multistream v0.2.1 h1:R5exp4cKvGlePuxg/bn4cnV53K4DxCe+uldxs7QzfrE= 431 | github.com/multiformats/go-multistream v0.2.1/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= 432 | github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 433 | github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 434 | github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 435 | github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= 436 | github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 437 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 438 | github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 439 | github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= 440 | github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= 441 | github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= 442 | github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= 443 | github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= 444 | github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= 445 | github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= 446 | github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= 447 | github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= 448 | github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= 449 | github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= 450 | github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= 451 | github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= 452 | github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= 453 | github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= 454 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 455 | github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 456 | github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= 457 | github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= 458 | github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= 459 | github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= 460 | github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= 461 | github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= 462 | github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 463 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 464 | github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= 465 | github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= 466 | github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= 467 | github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= 468 | github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= 469 | github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= 470 | github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= 471 | github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 472 | github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= 473 | github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 474 | github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= 475 | github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= 476 | github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= 477 | github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= 478 | github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= 479 | github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= 480 | github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= 481 | github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= 482 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 483 | github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= 484 | github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= 485 | github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= 486 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 487 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 488 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 489 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 490 | github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= 491 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 492 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 493 | github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= 494 | github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 495 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 496 | github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= 497 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 498 | github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= 499 | github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= 500 | github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= 501 | github.com/prometheus/client_golang v1.10.0 h1:/o0BDeWzLWXNZ+4q5gXltUvaMpJqckTa+jTNoB+z4cg= 502 | github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= 503 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 504 | github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 505 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 506 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 507 | github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 508 | github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= 509 | github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 510 | github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 511 | github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 512 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 513 | github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= 514 | github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= 515 | github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= 516 | github.com/prometheus/common v0.18.0 h1:WCVKW7aL6LEe1uryfI9dnEc2ZqNB1Fn0ok930v0iL1Y= 517 | github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= 518 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 519 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 520 | github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 521 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 522 | github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= 523 | github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= 524 | github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= 525 | github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= 526 | github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= 527 | github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= 528 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 529 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 530 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 531 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 532 | github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 533 | github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= 534 | github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= 535 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 536 | github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= 537 | github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= 538 | github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= 539 | github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= 540 | github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= 541 | github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= 542 | github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= 543 | github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= 544 | github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= 545 | github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= 546 | github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= 547 | github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= 548 | github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= 549 | github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= 550 | github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= 551 | github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= 552 | github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= 553 | github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= 554 | github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= 555 | github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 556 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 557 | github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= 558 | github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= 559 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 560 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 561 | github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= 562 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 563 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 564 | github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= 565 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 566 | github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= 567 | github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= 568 | github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= 569 | github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= 570 | github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= 571 | github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= 572 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 573 | github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 574 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 575 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 576 | github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 577 | github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= 578 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 579 | github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 580 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 581 | github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= 582 | github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= 583 | github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= 584 | github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= 585 | github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= 586 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 587 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 588 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 589 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 590 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 591 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 592 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 593 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 594 | github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= 595 | github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= 596 | github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 597 | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 598 | github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= 599 | github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 600 | github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= 601 | github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= 602 | github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= 603 | github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= 604 | github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= 605 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 606 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 607 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 608 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 609 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 610 | go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 611 | go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= 612 | go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= 613 | go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 614 | go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 615 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 616 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 617 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 618 | go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 619 | go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 620 | go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 621 | go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= 622 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 623 | go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= 624 | go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4= 625 | go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= 626 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 627 | go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= 628 | go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= 629 | go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= 630 | go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 631 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 632 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 633 | go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= 634 | go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= 635 | go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= 636 | go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= 637 | go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= 638 | go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= 639 | golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= 640 | golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 641 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 642 | golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 643 | golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 644 | golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 645 | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 646 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 647 | golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 648 | golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 649 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 650 | golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 651 | golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 652 | golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 653 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 654 | golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 655 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 656 | golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= 657 | golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf h1:B2n+Zi5QeYRDAEodEu72OS36gmTWjgpXr2+cWcBW90o= 658 | golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= 659 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 660 | golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 661 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 662 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 663 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 664 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 665 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 666 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 667 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 668 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 669 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 670 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 671 | golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= 672 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 673 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 674 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 675 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 676 | golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 677 | golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 678 | golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 679 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 680 | golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 681 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 682 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 683 | golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 684 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 685 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 686 | golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 687 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 688 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 689 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 690 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 691 | golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 692 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 693 | golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 694 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 695 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 696 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 697 | golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 698 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 699 | golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= 700 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 701 | golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= 702 | golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= 703 | golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= 704 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 705 | golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 706 | golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 707 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 708 | golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= 709 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 710 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 711 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 712 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 713 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 714 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 715 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 716 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 717 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 718 | golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 719 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 720 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 721 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 722 | golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 723 | golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 724 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 725 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 726 | golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 727 | golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 728 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 729 | golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 730 | golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 731 | golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 732 | golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 733 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 734 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 735 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 736 | golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 737 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 738 | golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 739 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 740 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 741 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 742 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 743 | golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 744 | golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 745 | golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 746 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 747 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 748 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 749 | golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 750 | golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 751 | golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 752 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 753 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 754 | golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 755 | golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 756 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 757 | golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 758 | golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 759 | golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 760 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 761 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 762 | golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 763 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 764 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= 765 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 766 | golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 767 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 768 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 769 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 770 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 771 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 772 | golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= 773 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 774 | golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 775 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 776 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 777 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 778 | golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 779 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 780 | golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 781 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 782 | golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 783 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 784 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 785 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 786 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 787 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 788 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 789 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 790 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 791 | golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 792 | golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 793 | golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 794 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 795 | golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 796 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 797 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 798 | golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 799 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 800 | golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 801 | golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= 802 | golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 803 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 804 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 805 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 806 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 807 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 808 | google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= 809 | google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= 810 | google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= 811 | google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= 812 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 813 | google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 814 | google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 815 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 816 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 817 | google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 818 | google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 819 | google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= 820 | google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 821 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 822 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 823 | google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= 824 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 825 | google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 826 | google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= 827 | google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= 828 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 829 | google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= 830 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 831 | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 832 | google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 833 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 834 | google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 835 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 836 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 837 | google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 838 | google.golang.org/grpc v1.31.1 h1:SfXqXS5hkufcdZ/mHtYCh53P2b+92WQq/DZcKLgsFRs= 839 | google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 840 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 841 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 842 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 843 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 844 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 845 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 846 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 847 | google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= 848 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 849 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 850 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 851 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 852 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 853 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 854 | gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 855 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 856 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 857 | gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= 858 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 859 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 860 | gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= 861 | gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= 862 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 863 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 864 | gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 865 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 866 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 867 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 868 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 869 | gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 870 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 871 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 872 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 873 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 874 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 875 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= 876 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 877 | grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= 878 | honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 879 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 880 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 881 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 882 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 883 | sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= 884 | sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= 885 | sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= 886 | sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= 887 | -------------------------------------------------------------------------------- /listen.go: -------------------------------------------------------------------------------- 1 | package relay 2 | 3 | import ( 4 | "net" 5 | 6 | pb "github.com/libp2p/go-libp2p-circuit/pb" 7 | 8 | ma "github.com/multiformats/go-multiaddr" 9 | manet "github.com/multiformats/go-multiaddr/net" 10 | ) 11 | 12 | var _ manet.Listener = (*RelayListener)(nil) 13 | 14 | type RelayListener Relay 15 | 16 | func (l *RelayListener) Relay() *Relay { 17 | return (*Relay)(l) 18 | } 19 | 20 | func (r *Relay) Listener() *RelayListener { 21 | // TODO: Only allow one! 22 | return (*RelayListener)(r) 23 | } 24 | 25 | func (l *RelayListener) Accept() (manet.Conn, error) { 26 | for { 27 | select { 28 | case c := <-l.incoming: 29 | err := l.Relay().writeResponse(c.stream, pb.CircuitRelay_SUCCESS) 30 | if err != nil { 31 | log.Debugf("error writing relay response: %s", err.Error()) 32 | c.stream.Reset() 33 | continue 34 | } 35 | 36 | // TODO: Pretty print. 37 | log.Infof("accepted relay connection: %q", c) 38 | 39 | c.tagHop() 40 | return c, nil 41 | case <-l.ctx.Done(): 42 | return nil, l.ctx.Err() 43 | } 44 | } 45 | } 46 | 47 | func (l *RelayListener) Addr() net.Addr { 48 | return &NetAddr{ 49 | Relay: "any", 50 | Remote: "any", 51 | } 52 | } 53 | 54 | func (l *RelayListener) Multiaddr() ma.Multiaddr { 55 | return circuitAddr 56 | } 57 | 58 | func (l *RelayListener) Close() error { 59 | // TODO: noop? 60 | return nil 61 | } 62 | -------------------------------------------------------------------------------- /pb/Makefile: -------------------------------------------------------------------------------- 1 | PB = $(wildcard *.proto) 2 | GO = $(PB:.proto=.pb.go) 3 | 4 | all: $(GO) 5 | 6 | %.pb.go: %.proto 7 | protoc --proto_path=$(GOPATH)/src:. --gogofast_out=. $< 8 | 9 | clean: 10 | rm -f *.pb.go 11 | rm -f *.go 12 | -------------------------------------------------------------------------------- /pb/relay.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-gogo. DO NOT EDIT. 2 | // source: relay.proto 3 | 4 | package relay_pb 5 | 6 | import ( 7 | fmt "fmt" 8 | github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto" 9 | proto "github.com/gogo/protobuf/proto" 10 | io "io" 11 | math "math" 12 | math_bits "math/bits" 13 | ) 14 | 15 | // Reference imports to suppress errors if they are not otherwise used. 16 | var _ = proto.Marshal 17 | var _ = fmt.Errorf 18 | var _ = math.Inf 19 | 20 | // This is a compile-time assertion to ensure that this generated file 21 | // is compatible with the proto package it is being compiled against. 22 | // A compilation error at this line likely means your copy of the 23 | // proto package needs to be updated. 24 | const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package 25 | 26 | type CircuitRelay_Status int32 27 | 28 | const ( 29 | CircuitRelay_SUCCESS CircuitRelay_Status = 100 30 | CircuitRelay_HOP_SRC_ADDR_TOO_LONG CircuitRelay_Status = 220 31 | CircuitRelay_HOP_DST_ADDR_TOO_LONG CircuitRelay_Status = 221 32 | CircuitRelay_HOP_SRC_MULTIADDR_INVALID CircuitRelay_Status = 250 33 | CircuitRelay_HOP_DST_MULTIADDR_INVALID CircuitRelay_Status = 251 34 | CircuitRelay_HOP_NO_CONN_TO_DST CircuitRelay_Status = 260 35 | CircuitRelay_HOP_CANT_DIAL_DST CircuitRelay_Status = 261 36 | CircuitRelay_HOP_CANT_OPEN_DST_STREAM CircuitRelay_Status = 262 37 | CircuitRelay_HOP_CANT_SPEAK_RELAY CircuitRelay_Status = 270 38 | CircuitRelay_HOP_CANT_RELAY_TO_SELF CircuitRelay_Status = 280 39 | CircuitRelay_STOP_SRC_ADDR_TOO_LONG CircuitRelay_Status = 320 40 | CircuitRelay_STOP_DST_ADDR_TOO_LONG CircuitRelay_Status = 321 41 | CircuitRelay_STOP_SRC_MULTIADDR_INVALID CircuitRelay_Status = 350 42 | CircuitRelay_STOP_DST_MULTIADDR_INVALID CircuitRelay_Status = 351 43 | CircuitRelay_STOP_RELAY_REFUSED CircuitRelay_Status = 390 44 | CircuitRelay_MALFORMED_MESSAGE CircuitRelay_Status = 400 45 | ) 46 | 47 | var CircuitRelay_Status_name = map[int32]string{ 48 | 100: "SUCCESS", 49 | 220: "HOP_SRC_ADDR_TOO_LONG", 50 | 221: "HOP_DST_ADDR_TOO_LONG", 51 | 250: "HOP_SRC_MULTIADDR_INVALID", 52 | 251: "HOP_DST_MULTIADDR_INVALID", 53 | 260: "HOP_NO_CONN_TO_DST", 54 | 261: "HOP_CANT_DIAL_DST", 55 | 262: "HOP_CANT_OPEN_DST_STREAM", 56 | 270: "HOP_CANT_SPEAK_RELAY", 57 | 280: "HOP_CANT_RELAY_TO_SELF", 58 | 320: "STOP_SRC_ADDR_TOO_LONG", 59 | 321: "STOP_DST_ADDR_TOO_LONG", 60 | 350: "STOP_SRC_MULTIADDR_INVALID", 61 | 351: "STOP_DST_MULTIADDR_INVALID", 62 | 390: "STOP_RELAY_REFUSED", 63 | 400: "MALFORMED_MESSAGE", 64 | } 65 | 66 | var CircuitRelay_Status_value = map[string]int32{ 67 | "SUCCESS": 100, 68 | "HOP_SRC_ADDR_TOO_LONG": 220, 69 | "HOP_DST_ADDR_TOO_LONG": 221, 70 | "HOP_SRC_MULTIADDR_INVALID": 250, 71 | "HOP_DST_MULTIADDR_INVALID": 251, 72 | "HOP_NO_CONN_TO_DST": 260, 73 | "HOP_CANT_DIAL_DST": 261, 74 | "HOP_CANT_OPEN_DST_STREAM": 262, 75 | "HOP_CANT_SPEAK_RELAY": 270, 76 | "HOP_CANT_RELAY_TO_SELF": 280, 77 | "STOP_SRC_ADDR_TOO_LONG": 320, 78 | "STOP_DST_ADDR_TOO_LONG": 321, 79 | "STOP_SRC_MULTIADDR_INVALID": 350, 80 | "STOP_DST_MULTIADDR_INVALID": 351, 81 | "STOP_RELAY_REFUSED": 390, 82 | "MALFORMED_MESSAGE": 400, 83 | } 84 | 85 | func (x CircuitRelay_Status) Enum() *CircuitRelay_Status { 86 | p := new(CircuitRelay_Status) 87 | *p = x 88 | return p 89 | } 90 | 91 | func (x CircuitRelay_Status) String() string { 92 | return proto.EnumName(CircuitRelay_Status_name, int32(x)) 93 | } 94 | 95 | func (x *CircuitRelay_Status) UnmarshalJSON(data []byte) error { 96 | value, err := proto.UnmarshalJSONEnum(CircuitRelay_Status_value, data, "CircuitRelay_Status") 97 | if err != nil { 98 | return err 99 | } 100 | *x = CircuitRelay_Status(value) 101 | return nil 102 | } 103 | 104 | func (CircuitRelay_Status) EnumDescriptor() ([]byte, []int) { 105 | return fileDescriptor_9f69a7d5a802d584, []int{0, 0} 106 | } 107 | 108 | type CircuitRelay_Type int32 109 | 110 | const ( 111 | CircuitRelay_HOP CircuitRelay_Type = 1 112 | CircuitRelay_STOP CircuitRelay_Type = 2 113 | CircuitRelay_STATUS CircuitRelay_Type = 3 114 | CircuitRelay_CAN_HOP CircuitRelay_Type = 4 115 | ) 116 | 117 | var CircuitRelay_Type_name = map[int32]string{ 118 | 1: "HOP", 119 | 2: "STOP", 120 | 3: "STATUS", 121 | 4: "CAN_HOP", 122 | } 123 | 124 | var CircuitRelay_Type_value = map[string]int32{ 125 | "HOP": 1, 126 | "STOP": 2, 127 | "STATUS": 3, 128 | "CAN_HOP": 4, 129 | } 130 | 131 | func (x CircuitRelay_Type) Enum() *CircuitRelay_Type { 132 | p := new(CircuitRelay_Type) 133 | *p = x 134 | return p 135 | } 136 | 137 | func (x CircuitRelay_Type) String() string { 138 | return proto.EnumName(CircuitRelay_Type_name, int32(x)) 139 | } 140 | 141 | func (x *CircuitRelay_Type) UnmarshalJSON(data []byte) error { 142 | value, err := proto.UnmarshalJSONEnum(CircuitRelay_Type_value, data, "CircuitRelay_Type") 143 | if err != nil { 144 | return err 145 | } 146 | *x = CircuitRelay_Type(value) 147 | return nil 148 | } 149 | 150 | func (CircuitRelay_Type) EnumDescriptor() ([]byte, []int) { 151 | return fileDescriptor_9f69a7d5a802d584, []int{0, 1} 152 | } 153 | 154 | type CircuitRelay struct { 155 | Type *CircuitRelay_Type `protobuf:"varint,1,opt,name=type,enum=relay.pb.CircuitRelay_Type" json:"type,omitempty"` 156 | SrcPeer *CircuitRelay_Peer `protobuf:"bytes,2,opt,name=srcPeer" json:"srcPeer,omitempty"` 157 | DstPeer *CircuitRelay_Peer `protobuf:"bytes,3,opt,name=dstPeer" json:"dstPeer,omitempty"` 158 | Code *CircuitRelay_Status `protobuf:"varint,4,opt,name=code,enum=relay.pb.CircuitRelay_Status" json:"code,omitempty"` 159 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 160 | XXX_unrecognized []byte `json:"-"` 161 | XXX_sizecache int32 `json:"-"` 162 | } 163 | 164 | func (m *CircuitRelay) Reset() { *m = CircuitRelay{} } 165 | func (m *CircuitRelay) String() string { return proto.CompactTextString(m) } 166 | func (*CircuitRelay) ProtoMessage() {} 167 | func (*CircuitRelay) Descriptor() ([]byte, []int) { 168 | return fileDescriptor_9f69a7d5a802d584, []int{0} 169 | } 170 | func (m *CircuitRelay) XXX_Unmarshal(b []byte) error { 171 | return m.Unmarshal(b) 172 | } 173 | func (m *CircuitRelay) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 174 | if deterministic { 175 | return xxx_messageInfo_CircuitRelay.Marshal(b, m, deterministic) 176 | } else { 177 | b = b[:cap(b)] 178 | n, err := m.MarshalToSizedBuffer(b) 179 | if err != nil { 180 | return nil, err 181 | } 182 | return b[:n], nil 183 | } 184 | } 185 | func (m *CircuitRelay) XXX_Merge(src proto.Message) { 186 | xxx_messageInfo_CircuitRelay.Merge(m, src) 187 | } 188 | func (m *CircuitRelay) XXX_Size() int { 189 | return m.Size() 190 | } 191 | func (m *CircuitRelay) XXX_DiscardUnknown() { 192 | xxx_messageInfo_CircuitRelay.DiscardUnknown(m) 193 | } 194 | 195 | var xxx_messageInfo_CircuitRelay proto.InternalMessageInfo 196 | 197 | func (m *CircuitRelay) GetType() CircuitRelay_Type { 198 | if m != nil && m.Type != nil { 199 | return *m.Type 200 | } 201 | return CircuitRelay_HOP 202 | } 203 | 204 | func (m *CircuitRelay) GetSrcPeer() *CircuitRelay_Peer { 205 | if m != nil { 206 | return m.SrcPeer 207 | } 208 | return nil 209 | } 210 | 211 | func (m *CircuitRelay) GetDstPeer() *CircuitRelay_Peer { 212 | if m != nil { 213 | return m.DstPeer 214 | } 215 | return nil 216 | } 217 | 218 | func (m *CircuitRelay) GetCode() CircuitRelay_Status { 219 | if m != nil && m.Code != nil { 220 | return *m.Code 221 | } 222 | return CircuitRelay_SUCCESS 223 | } 224 | 225 | type CircuitRelay_Peer struct { 226 | Id []byte `protobuf:"bytes,1,req,name=id" json:"id,omitempty"` 227 | Addrs [][]byte `protobuf:"bytes,2,rep,name=addrs" json:"addrs,omitempty"` 228 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 229 | XXX_unrecognized []byte `json:"-"` 230 | XXX_sizecache int32 `json:"-"` 231 | } 232 | 233 | func (m *CircuitRelay_Peer) Reset() { *m = CircuitRelay_Peer{} } 234 | func (m *CircuitRelay_Peer) String() string { return proto.CompactTextString(m) } 235 | func (*CircuitRelay_Peer) ProtoMessage() {} 236 | func (*CircuitRelay_Peer) Descriptor() ([]byte, []int) { 237 | return fileDescriptor_9f69a7d5a802d584, []int{0, 0} 238 | } 239 | func (m *CircuitRelay_Peer) XXX_Unmarshal(b []byte) error { 240 | return m.Unmarshal(b) 241 | } 242 | func (m *CircuitRelay_Peer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 243 | if deterministic { 244 | return xxx_messageInfo_CircuitRelay_Peer.Marshal(b, m, deterministic) 245 | } else { 246 | b = b[:cap(b)] 247 | n, err := m.MarshalToSizedBuffer(b) 248 | if err != nil { 249 | return nil, err 250 | } 251 | return b[:n], nil 252 | } 253 | } 254 | func (m *CircuitRelay_Peer) XXX_Merge(src proto.Message) { 255 | xxx_messageInfo_CircuitRelay_Peer.Merge(m, src) 256 | } 257 | func (m *CircuitRelay_Peer) XXX_Size() int { 258 | return m.Size() 259 | } 260 | func (m *CircuitRelay_Peer) XXX_DiscardUnknown() { 261 | xxx_messageInfo_CircuitRelay_Peer.DiscardUnknown(m) 262 | } 263 | 264 | var xxx_messageInfo_CircuitRelay_Peer proto.InternalMessageInfo 265 | 266 | func (m *CircuitRelay_Peer) GetId() []byte { 267 | if m != nil { 268 | return m.Id 269 | } 270 | return nil 271 | } 272 | 273 | func (m *CircuitRelay_Peer) GetAddrs() [][]byte { 274 | if m != nil { 275 | return m.Addrs 276 | } 277 | return nil 278 | } 279 | 280 | func init() { 281 | proto.RegisterEnum("relay.pb.CircuitRelay_Status", CircuitRelay_Status_name, CircuitRelay_Status_value) 282 | proto.RegisterEnum("relay.pb.CircuitRelay_Type", CircuitRelay_Type_name, CircuitRelay_Type_value) 283 | proto.RegisterType((*CircuitRelay)(nil), "relay.pb.CircuitRelay") 284 | proto.RegisterType((*CircuitRelay_Peer)(nil), "relay.pb.CircuitRelay.Peer") 285 | } 286 | 287 | func init() { proto.RegisterFile("relay.proto", fileDescriptor_9f69a7d5a802d584) } 288 | 289 | var fileDescriptor_9f69a7d5a802d584 = []byte{ 290 | // 473 bytes of a gzipped FileDescriptorProto 291 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x4f, 0x6f, 0xd3, 0x3e, 292 | 0x18, 0xc7, 0x65, 0x27, 0xbf, 0x76, 0x7a, 0x5a, 0x4d, 0xfe, 0x59, 0x63, 0x64, 0x9d, 0x56, 0xaa, 293 | 0x9e, 0x7a, 0x40, 0x45, 0x4c, 0xe2, 0x05, 0x98, 0xc4, 0xdd, 0x2a, 0xd2, 0x38, 0xb2, 0x5d, 0x24, 294 | 0x4e, 0x56, 0x69, 0x72, 0xa8, 0x84, 0xd4, 0x2a, 0xcd, 0x0e, 0xbd, 0xc3, 0xb8, 0x21, 0x8e, 0xbc, 295 | 0x1c, 0xe0, 0xc4, 0x91, 0x17, 0xc0, 0x3f, 0xf5, 0x65, 0xc0, 0x05, 0xd9, 0x5d, 0x33, 0x44, 0x37, 296 | 0x89, 0xa3, 0x9f, 0xef, 0xe7, 0xe3, 0x3c, 0xf9, 0x26, 0xd0, 0x28, 0xf2, 0x17, 0x93, 0x55, 0x7f, 297 | 0x51, 0xcc, 0xcb, 0x39, 0xdd, 0xbb, 0x3a, 0x3c, 0xef, 0xbe, 0xae, 0x41, 0x33, 0x9c, 0x15, 0xd3, 298 | 0x8b, 0x59, 0x29, 0xed, 0x8c, 0x3e, 0x00, 0xbf, 0x5c, 0x2d, 0xf2, 0x00, 0x75, 0x50, 0x6f, 0xff, 299 | 0xf4, 0xb8, 0xbf, 0x25, 0xfb, 0x7f, 0x52, 0x7d, 0xbd, 0x5a, 0xe4, 0xd2, 0x81, 0xf4, 0x11, 0xd4, 300 | 0x97, 0xc5, 0x34, 0xcd, 0xf3, 0x22, 0xc0, 0x1d, 0xd4, 0x6b, 0xdc, 0xea, 0x58, 0x44, 0x6e, 0x59, 301 | 0xab, 0x65, 0xcb, 0xd2, 0x69, 0xde, 0x3f, 0x68, 0x57, 0x2c, 0x7d, 0x08, 0xfe, 0x74, 0x9e, 0xe5, 302 | 0x81, 0xef, 0xd6, 0x3b, 0xb9, 0xc5, 0x51, 0xe5, 0xa4, 0xbc, 0x58, 0x4a, 0x87, 0xb6, 0xee, 0x83, 303 | 0xef, 0xd4, 0x7d, 0xc0, 0xb3, 0x2c, 0x40, 0x1d, 0xdc, 0x6b, 0x4a, 0x3c, 0xcb, 0xe8, 0x01, 0xfc, 304 | 0x37, 0xc9, 0xb2, 0x62, 0x19, 0xe0, 0x8e, 0xd7, 0x6b, 0xca, 0xcd, 0xa1, 0xfb, 0xd1, 0x83, 0xda, 305 | 0x46, 0xa7, 0x0d, 0xa8, 0xab, 0x71, 0x18, 0x72, 0xa5, 0x48, 0x46, 0x5b, 0x70, 0xe7, 0x5c, 0xa4, 306 | 0x46, 0xc9, 0xd0, 0xb0, 0x28, 0x92, 0x46, 0x0b, 0x61, 0x62, 0x91, 0x9c, 0x91, 0x2f, 0x68, 0x9b, 307 | 0x45, 0x4a, 0xff, 0x95, 0x7d, 0x45, 0xb4, 0x0d, 0x47, 0x5b, 0x6f, 0x34, 0x8e, 0xf5, 0xd0, 0x01, 308 | 0xc3, 0xe4, 0x29, 0x8b, 0x87, 0x11, 0xf9, 0x59, 0xe5, 0xd6, 0xdd, 0xcd, 0x7f, 0x21, 0x7a, 0x17, 309 | 0xa8, 0xcd, 0x13, 0x61, 0x42, 0x91, 0x24, 0x46, 0x0b, 0x8b, 0x92, 0x97, 0x98, 0x1e, 0xc2, 0xff, 310 | 0x36, 0x08, 0x59, 0xa2, 0x4d, 0x34, 0x64, 0xb1, 0x9b, 0xbf, 0xc2, 0xf4, 0x04, 0x82, 0x6a, 0x2e, 311 | 0x52, 0x9e, 0xb8, 0xab, 0x95, 0x96, 0x9c, 0x8d, 0xc8, 0x25, 0xa6, 0x47, 0x70, 0x50, 0xc5, 0x2a, 312 | 0xe5, 0xec, 0x89, 0x91, 0x3c, 0x66, 0xcf, 0xc8, 0x1b, 0x4c, 0x8f, 0xe1, 0xb0, 0x8a, 0xdc, 0xd0, 313 | 0x3e, 0x4d, 0xf1, 0x78, 0x40, 0xde, 0xb9, 0x50, 0xe9, 0x1b, 0x0b, 0x78, 0x7f, 0x1d, 0xee, 0x36, 314 | 0xf0, 0x01, 0xd3, 0x7b, 0xd0, 0xaa, 0xcc, 0xdd, 0x57, 0xfc, 0x76, 0x0d, 0xdc, 0xdc, 0xc1, 0x77, 315 | 0x6c, 0x3b, 0x70, 0xc0, 0x66, 0x29, 0xc9, 0x07, 0x63, 0xc5, 0x23, 0x72, 0xe9, 0xd9, 0x0e, 0x46, 316 | 0x2c, 0x1e, 0x08, 0x39, 0xe2, 0x91, 0x19, 0x71, 0xa5, 0xd8, 0x19, 0x27, 0x6f, 0xbd, 0xee, 0x29, 317 | 0xf8, 0xf6, 0x0f, 0xa5, 0x75, 0xf0, 0xce, 0x45, 0x4a, 0x10, 0xdd, 0x03, 0xdf, 0xde, 0x40, 0x30, 318 | 0x05, 0xa8, 0x29, 0xcd, 0xf4, 0x58, 0x11, 0xcf, 0x7e, 0xe0, 0x90, 0x25, 0xc6, 0x22, 0xfe, 0xe3, 319 | 0xe6, 0xa7, 0x75, 0x1b, 0x7d, 0x5e, 0xb7, 0xd1, 0x8f, 0x75, 0x1b, 0xfd, 0x0e, 0x00, 0x00, 0xff, 320 | 0xff, 0x6b, 0x22, 0x33, 0xbb, 0x2f, 0x03, 0x00, 0x00, 321 | } 322 | 323 | func (m *CircuitRelay) Marshal() (dAtA []byte, err error) { 324 | size := m.Size() 325 | dAtA = make([]byte, size) 326 | n, err := m.MarshalToSizedBuffer(dAtA[:size]) 327 | if err != nil { 328 | return nil, err 329 | } 330 | return dAtA[:n], nil 331 | } 332 | 333 | func (m *CircuitRelay) MarshalTo(dAtA []byte) (int, error) { 334 | size := m.Size() 335 | return m.MarshalToSizedBuffer(dAtA[:size]) 336 | } 337 | 338 | func (m *CircuitRelay) MarshalToSizedBuffer(dAtA []byte) (int, error) { 339 | i := len(dAtA) 340 | _ = i 341 | var l int 342 | _ = l 343 | if m.XXX_unrecognized != nil { 344 | i -= len(m.XXX_unrecognized) 345 | copy(dAtA[i:], m.XXX_unrecognized) 346 | } 347 | if m.Code != nil { 348 | i = encodeVarintRelay(dAtA, i, uint64(*m.Code)) 349 | i-- 350 | dAtA[i] = 0x20 351 | } 352 | if m.DstPeer != nil { 353 | { 354 | size, err := m.DstPeer.MarshalToSizedBuffer(dAtA[:i]) 355 | if err != nil { 356 | return 0, err 357 | } 358 | i -= size 359 | i = encodeVarintRelay(dAtA, i, uint64(size)) 360 | } 361 | i-- 362 | dAtA[i] = 0x1a 363 | } 364 | if m.SrcPeer != nil { 365 | { 366 | size, err := m.SrcPeer.MarshalToSizedBuffer(dAtA[:i]) 367 | if err != nil { 368 | return 0, err 369 | } 370 | i -= size 371 | i = encodeVarintRelay(dAtA, i, uint64(size)) 372 | } 373 | i-- 374 | dAtA[i] = 0x12 375 | } 376 | if m.Type != nil { 377 | i = encodeVarintRelay(dAtA, i, uint64(*m.Type)) 378 | i-- 379 | dAtA[i] = 0x8 380 | } 381 | return len(dAtA) - i, nil 382 | } 383 | 384 | func (m *CircuitRelay_Peer) Marshal() (dAtA []byte, err error) { 385 | size := m.Size() 386 | dAtA = make([]byte, size) 387 | n, err := m.MarshalToSizedBuffer(dAtA[:size]) 388 | if err != nil { 389 | return nil, err 390 | } 391 | return dAtA[:n], nil 392 | } 393 | 394 | func (m *CircuitRelay_Peer) MarshalTo(dAtA []byte) (int, error) { 395 | size := m.Size() 396 | return m.MarshalToSizedBuffer(dAtA[:size]) 397 | } 398 | 399 | func (m *CircuitRelay_Peer) MarshalToSizedBuffer(dAtA []byte) (int, error) { 400 | i := len(dAtA) 401 | _ = i 402 | var l int 403 | _ = l 404 | if m.XXX_unrecognized != nil { 405 | i -= len(m.XXX_unrecognized) 406 | copy(dAtA[i:], m.XXX_unrecognized) 407 | } 408 | if len(m.Addrs) > 0 { 409 | for iNdEx := len(m.Addrs) - 1; iNdEx >= 0; iNdEx-- { 410 | i -= len(m.Addrs[iNdEx]) 411 | copy(dAtA[i:], m.Addrs[iNdEx]) 412 | i = encodeVarintRelay(dAtA, i, uint64(len(m.Addrs[iNdEx]))) 413 | i-- 414 | dAtA[i] = 0x12 415 | } 416 | } 417 | if m.Id == nil { 418 | return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("id") 419 | } else { 420 | i -= len(m.Id) 421 | copy(dAtA[i:], m.Id) 422 | i = encodeVarintRelay(dAtA, i, uint64(len(m.Id))) 423 | i-- 424 | dAtA[i] = 0xa 425 | } 426 | return len(dAtA) - i, nil 427 | } 428 | 429 | func encodeVarintRelay(dAtA []byte, offset int, v uint64) int { 430 | offset -= sovRelay(v) 431 | base := offset 432 | for v >= 1<<7 { 433 | dAtA[offset] = uint8(v&0x7f | 0x80) 434 | v >>= 7 435 | offset++ 436 | } 437 | dAtA[offset] = uint8(v) 438 | return base 439 | } 440 | func (m *CircuitRelay) Size() (n int) { 441 | if m == nil { 442 | return 0 443 | } 444 | var l int 445 | _ = l 446 | if m.Type != nil { 447 | n += 1 + sovRelay(uint64(*m.Type)) 448 | } 449 | if m.SrcPeer != nil { 450 | l = m.SrcPeer.Size() 451 | n += 1 + l + sovRelay(uint64(l)) 452 | } 453 | if m.DstPeer != nil { 454 | l = m.DstPeer.Size() 455 | n += 1 + l + sovRelay(uint64(l)) 456 | } 457 | if m.Code != nil { 458 | n += 1 + sovRelay(uint64(*m.Code)) 459 | } 460 | if m.XXX_unrecognized != nil { 461 | n += len(m.XXX_unrecognized) 462 | } 463 | return n 464 | } 465 | 466 | func (m *CircuitRelay_Peer) Size() (n int) { 467 | if m == nil { 468 | return 0 469 | } 470 | var l int 471 | _ = l 472 | if m.Id != nil { 473 | l = len(m.Id) 474 | n += 1 + l + sovRelay(uint64(l)) 475 | } 476 | if len(m.Addrs) > 0 { 477 | for _, b := range m.Addrs { 478 | l = len(b) 479 | n += 1 + l + sovRelay(uint64(l)) 480 | } 481 | } 482 | if m.XXX_unrecognized != nil { 483 | n += len(m.XXX_unrecognized) 484 | } 485 | return n 486 | } 487 | 488 | func sovRelay(x uint64) (n int) { 489 | return (math_bits.Len64(x|1) + 6) / 7 490 | } 491 | func sozRelay(x uint64) (n int) { 492 | return sovRelay(uint64((x << 1) ^ uint64((int64(x) >> 63)))) 493 | } 494 | func (m *CircuitRelay) Unmarshal(dAtA []byte) error { 495 | l := len(dAtA) 496 | iNdEx := 0 497 | for iNdEx < l { 498 | preIndex := iNdEx 499 | var wire uint64 500 | for shift := uint(0); ; shift += 7 { 501 | if shift >= 64 { 502 | return ErrIntOverflowRelay 503 | } 504 | if iNdEx >= l { 505 | return io.ErrUnexpectedEOF 506 | } 507 | b := dAtA[iNdEx] 508 | iNdEx++ 509 | wire |= uint64(b&0x7F) << shift 510 | if b < 0x80 { 511 | break 512 | } 513 | } 514 | fieldNum := int32(wire >> 3) 515 | wireType := int(wire & 0x7) 516 | if wireType == 4 { 517 | return fmt.Errorf("proto: CircuitRelay: wiretype end group for non-group") 518 | } 519 | if fieldNum <= 0 { 520 | return fmt.Errorf("proto: CircuitRelay: illegal tag %d (wire type %d)", fieldNum, wire) 521 | } 522 | switch fieldNum { 523 | case 1: 524 | if wireType != 0 { 525 | return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) 526 | } 527 | var v CircuitRelay_Type 528 | for shift := uint(0); ; shift += 7 { 529 | if shift >= 64 { 530 | return ErrIntOverflowRelay 531 | } 532 | if iNdEx >= l { 533 | return io.ErrUnexpectedEOF 534 | } 535 | b := dAtA[iNdEx] 536 | iNdEx++ 537 | v |= CircuitRelay_Type(b&0x7F) << shift 538 | if b < 0x80 { 539 | break 540 | } 541 | } 542 | m.Type = &v 543 | case 2: 544 | if wireType != 2 { 545 | return fmt.Errorf("proto: wrong wireType = %d for field SrcPeer", wireType) 546 | } 547 | var msglen int 548 | for shift := uint(0); ; shift += 7 { 549 | if shift >= 64 { 550 | return ErrIntOverflowRelay 551 | } 552 | if iNdEx >= l { 553 | return io.ErrUnexpectedEOF 554 | } 555 | b := dAtA[iNdEx] 556 | iNdEx++ 557 | msglen |= int(b&0x7F) << shift 558 | if b < 0x80 { 559 | break 560 | } 561 | } 562 | if msglen < 0 { 563 | return ErrInvalidLengthRelay 564 | } 565 | postIndex := iNdEx + msglen 566 | if postIndex < 0 { 567 | return ErrInvalidLengthRelay 568 | } 569 | if postIndex > l { 570 | return io.ErrUnexpectedEOF 571 | } 572 | if m.SrcPeer == nil { 573 | m.SrcPeer = &CircuitRelay_Peer{} 574 | } 575 | if err := m.SrcPeer.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { 576 | return err 577 | } 578 | iNdEx = postIndex 579 | case 3: 580 | if wireType != 2 { 581 | return fmt.Errorf("proto: wrong wireType = %d for field DstPeer", wireType) 582 | } 583 | var msglen int 584 | for shift := uint(0); ; shift += 7 { 585 | if shift >= 64 { 586 | return ErrIntOverflowRelay 587 | } 588 | if iNdEx >= l { 589 | return io.ErrUnexpectedEOF 590 | } 591 | b := dAtA[iNdEx] 592 | iNdEx++ 593 | msglen |= int(b&0x7F) << shift 594 | if b < 0x80 { 595 | break 596 | } 597 | } 598 | if msglen < 0 { 599 | return ErrInvalidLengthRelay 600 | } 601 | postIndex := iNdEx + msglen 602 | if postIndex < 0 { 603 | return ErrInvalidLengthRelay 604 | } 605 | if postIndex > l { 606 | return io.ErrUnexpectedEOF 607 | } 608 | if m.DstPeer == nil { 609 | m.DstPeer = &CircuitRelay_Peer{} 610 | } 611 | if err := m.DstPeer.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { 612 | return err 613 | } 614 | iNdEx = postIndex 615 | case 4: 616 | if wireType != 0 { 617 | return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) 618 | } 619 | var v CircuitRelay_Status 620 | for shift := uint(0); ; shift += 7 { 621 | if shift >= 64 { 622 | return ErrIntOverflowRelay 623 | } 624 | if iNdEx >= l { 625 | return io.ErrUnexpectedEOF 626 | } 627 | b := dAtA[iNdEx] 628 | iNdEx++ 629 | v |= CircuitRelay_Status(b&0x7F) << shift 630 | if b < 0x80 { 631 | break 632 | } 633 | } 634 | m.Code = &v 635 | default: 636 | iNdEx = preIndex 637 | skippy, err := skipRelay(dAtA[iNdEx:]) 638 | if err != nil { 639 | return err 640 | } 641 | if skippy < 0 { 642 | return ErrInvalidLengthRelay 643 | } 644 | if (iNdEx + skippy) < 0 { 645 | return ErrInvalidLengthRelay 646 | } 647 | if (iNdEx + skippy) > l { 648 | return io.ErrUnexpectedEOF 649 | } 650 | m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) 651 | iNdEx += skippy 652 | } 653 | } 654 | 655 | if iNdEx > l { 656 | return io.ErrUnexpectedEOF 657 | } 658 | return nil 659 | } 660 | func (m *CircuitRelay_Peer) Unmarshal(dAtA []byte) error { 661 | var hasFields [1]uint64 662 | l := len(dAtA) 663 | iNdEx := 0 664 | for iNdEx < l { 665 | preIndex := iNdEx 666 | var wire uint64 667 | for shift := uint(0); ; shift += 7 { 668 | if shift >= 64 { 669 | return ErrIntOverflowRelay 670 | } 671 | if iNdEx >= l { 672 | return io.ErrUnexpectedEOF 673 | } 674 | b := dAtA[iNdEx] 675 | iNdEx++ 676 | wire |= uint64(b&0x7F) << shift 677 | if b < 0x80 { 678 | break 679 | } 680 | } 681 | fieldNum := int32(wire >> 3) 682 | wireType := int(wire & 0x7) 683 | if wireType == 4 { 684 | return fmt.Errorf("proto: Peer: wiretype end group for non-group") 685 | } 686 | if fieldNum <= 0 { 687 | return fmt.Errorf("proto: Peer: illegal tag %d (wire type %d)", fieldNum, wire) 688 | } 689 | switch fieldNum { 690 | case 1: 691 | if wireType != 2 { 692 | return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) 693 | } 694 | var byteLen int 695 | for shift := uint(0); ; shift += 7 { 696 | if shift >= 64 { 697 | return ErrIntOverflowRelay 698 | } 699 | if iNdEx >= l { 700 | return io.ErrUnexpectedEOF 701 | } 702 | b := dAtA[iNdEx] 703 | iNdEx++ 704 | byteLen |= int(b&0x7F) << shift 705 | if b < 0x80 { 706 | break 707 | } 708 | } 709 | if byteLen < 0 { 710 | return ErrInvalidLengthRelay 711 | } 712 | postIndex := iNdEx + byteLen 713 | if postIndex < 0 { 714 | return ErrInvalidLengthRelay 715 | } 716 | if postIndex > l { 717 | return io.ErrUnexpectedEOF 718 | } 719 | m.Id = append(m.Id[:0], dAtA[iNdEx:postIndex]...) 720 | if m.Id == nil { 721 | m.Id = []byte{} 722 | } 723 | iNdEx = postIndex 724 | hasFields[0] |= uint64(0x00000001) 725 | case 2: 726 | if wireType != 2 { 727 | return fmt.Errorf("proto: wrong wireType = %d for field Addrs", wireType) 728 | } 729 | var byteLen int 730 | for shift := uint(0); ; shift += 7 { 731 | if shift >= 64 { 732 | return ErrIntOverflowRelay 733 | } 734 | if iNdEx >= l { 735 | return io.ErrUnexpectedEOF 736 | } 737 | b := dAtA[iNdEx] 738 | iNdEx++ 739 | byteLen |= int(b&0x7F) << shift 740 | if b < 0x80 { 741 | break 742 | } 743 | } 744 | if byteLen < 0 { 745 | return ErrInvalidLengthRelay 746 | } 747 | postIndex := iNdEx + byteLen 748 | if postIndex < 0 { 749 | return ErrInvalidLengthRelay 750 | } 751 | if postIndex > l { 752 | return io.ErrUnexpectedEOF 753 | } 754 | m.Addrs = append(m.Addrs, make([]byte, postIndex-iNdEx)) 755 | copy(m.Addrs[len(m.Addrs)-1], dAtA[iNdEx:postIndex]) 756 | iNdEx = postIndex 757 | default: 758 | iNdEx = preIndex 759 | skippy, err := skipRelay(dAtA[iNdEx:]) 760 | if err != nil { 761 | return err 762 | } 763 | if skippy < 0 { 764 | return ErrInvalidLengthRelay 765 | } 766 | if (iNdEx + skippy) < 0 { 767 | return ErrInvalidLengthRelay 768 | } 769 | if (iNdEx + skippy) > l { 770 | return io.ErrUnexpectedEOF 771 | } 772 | m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) 773 | iNdEx += skippy 774 | } 775 | } 776 | if hasFields[0]&uint64(0x00000001) == 0 { 777 | return github_com_gogo_protobuf_proto.NewRequiredNotSetError("id") 778 | } 779 | 780 | if iNdEx > l { 781 | return io.ErrUnexpectedEOF 782 | } 783 | return nil 784 | } 785 | func skipRelay(dAtA []byte) (n int, err error) { 786 | l := len(dAtA) 787 | iNdEx := 0 788 | depth := 0 789 | for iNdEx < l { 790 | var wire uint64 791 | for shift := uint(0); ; shift += 7 { 792 | if shift >= 64 { 793 | return 0, ErrIntOverflowRelay 794 | } 795 | if iNdEx >= l { 796 | return 0, io.ErrUnexpectedEOF 797 | } 798 | b := dAtA[iNdEx] 799 | iNdEx++ 800 | wire |= (uint64(b) & 0x7F) << shift 801 | if b < 0x80 { 802 | break 803 | } 804 | } 805 | wireType := int(wire & 0x7) 806 | switch wireType { 807 | case 0: 808 | for shift := uint(0); ; shift += 7 { 809 | if shift >= 64 { 810 | return 0, ErrIntOverflowRelay 811 | } 812 | if iNdEx >= l { 813 | return 0, io.ErrUnexpectedEOF 814 | } 815 | iNdEx++ 816 | if dAtA[iNdEx-1] < 0x80 { 817 | break 818 | } 819 | } 820 | case 1: 821 | iNdEx += 8 822 | case 2: 823 | var length int 824 | for shift := uint(0); ; shift += 7 { 825 | if shift >= 64 { 826 | return 0, ErrIntOverflowRelay 827 | } 828 | if iNdEx >= l { 829 | return 0, io.ErrUnexpectedEOF 830 | } 831 | b := dAtA[iNdEx] 832 | iNdEx++ 833 | length |= (int(b) & 0x7F) << shift 834 | if b < 0x80 { 835 | break 836 | } 837 | } 838 | if length < 0 { 839 | return 0, ErrInvalidLengthRelay 840 | } 841 | iNdEx += length 842 | if iNdEx < 0 { 843 | return 0, ErrInvalidLengthRelay 844 | } 845 | case 3: 846 | depth++ 847 | case 4: 848 | if depth == 0 { 849 | return 0, ErrUnexpectedEndOfGroupRelay 850 | } 851 | depth-- 852 | case 5: 853 | iNdEx += 4 854 | default: 855 | return 0, fmt.Errorf("proto: illegal wireType %d", wireType) 856 | } 857 | if depth == 0 { 858 | return iNdEx, nil 859 | } 860 | } 861 | return 0, io.ErrUnexpectedEOF 862 | } 863 | 864 | var ( 865 | ErrInvalidLengthRelay = fmt.Errorf("proto: negative length found during unmarshaling") 866 | ErrIntOverflowRelay = fmt.Errorf("proto: integer overflow") 867 | ErrUnexpectedEndOfGroupRelay = fmt.Errorf("proto: unexpected end of group") 868 | ) 869 | -------------------------------------------------------------------------------- /pb/relay.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | package relay.pb; 4 | 5 | message CircuitRelay { 6 | 7 | enum Status { 8 | SUCCESS = 100; 9 | HOP_SRC_ADDR_TOO_LONG = 220; 10 | HOP_DST_ADDR_TOO_LONG = 221; 11 | HOP_SRC_MULTIADDR_INVALID = 250; 12 | HOP_DST_MULTIADDR_INVALID = 251; 13 | HOP_NO_CONN_TO_DST = 260; 14 | HOP_CANT_DIAL_DST = 261; 15 | HOP_CANT_OPEN_DST_STREAM = 262; 16 | HOP_CANT_SPEAK_RELAY = 270; 17 | HOP_CANT_RELAY_TO_SELF = 280; 18 | STOP_SRC_ADDR_TOO_LONG = 320; 19 | STOP_DST_ADDR_TOO_LONG = 321; 20 | STOP_SRC_MULTIADDR_INVALID = 350; 21 | STOP_DST_MULTIADDR_INVALID = 351; 22 | STOP_RELAY_REFUSED = 390; 23 | MALFORMED_MESSAGE = 400; 24 | } 25 | 26 | enum Type { // RPC identifier, either HOP, STOP or STATUS 27 | HOP = 1; 28 | STOP = 2; 29 | STATUS = 3; 30 | CAN_HOP = 4; 31 | } 32 | 33 | message Peer { 34 | required bytes id = 1; // peer id 35 | repeated bytes addrs = 2; // peer's known addresses 36 | } 37 | 38 | optional Type type = 1; // Type of the message 39 | 40 | optional Peer srcPeer = 2; // srcPeer and dstPeer are used when Type is HOP or STOP 41 | optional Peer dstPeer = 3; 42 | 43 | optional Status code = 4; // Status code, used when Type is STATUS 44 | } 45 | -------------------------------------------------------------------------------- /relay.go: -------------------------------------------------------------------------------- 1 | package relay 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "sync" 8 | "sync/atomic" 9 | "time" 10 | 11 | pb "github.com/libp2p/go-libp2p-circuit/pb" 12 | 13 | "github.com/libp2p/go-libp2p-core/host" 14 | "github.com/libp2p/go-libp2p-core/network" 15 | "github.com/libp2p/go-libp2p-core/peer" 16 | "github.com/libp2p/go-libp2p-core/peerstore" 17 | "github.com/libp2p/go-libp2p-core/transport" 18 | 19 | pool "github.com/libp2p/go-buffer-pool" 20 | 21 | logging "github.com/ipfs/go-log/v2" 22 | 23 | ma "github.com/multiformats/go-multiaddr" 24 | ) 25 | 26 | var log = logging.Logger("relay") 27 | 28 | const ProtoID = "/libp2p/circuit/relay/0.1.0" 29 | 30 | const maxMessageSize = 4096 31 | 32 | var ( 33 | RelayAcceptTimeout = 10 * time.Second 34 | HopConnectTimeout = 30 * time.Second 35 | StopHandshakeTimeout = 1 * time.Minute 36 | 37 | HopStreamBufferSize = 4096 38 | HopStreamLimit = 1 << 19 // 512K hops for 1M goroutines 39 | 40 | streamTimeout = 1 * time.Minute 41 | ) 42 | 43 | // Relay is the relay transport and service. 44 | type Relay struct { 45 | host host.Host 46 | upgrader transport.Upgrader 47 | ctx context.Context 48 | ctxCancel context.CancelFunc 49 | self peer.ID 50 | 51 | active bool 52 | hop bool 53 | 54 | incoming chan *Conn 55 | 56 | // atomic counters 57 | streamCount int32 58 | liveHopCount int32 59 | 60 | // per peer hop counters 61 | mx sync.Mutex 62 | hopCount map[peer.ID]int 63 | } 64 | 65 | // RelayOpts are options for configuring the relay transport. 66 | type RelayOpt int 67 | 68 | var ( 69 | // OptActive configures the relay transport to actively establish 70 | // outbound connections on behalf of clients. You probably don't want to 71 | // enable this unless you know what you're doing. 72 | OptActive = RelayOpt(0) 73 | // OptHop configures the relay transport to accept requests to relay 74 | // traffic on behalf of third-parties. Unless OptActive is specified, 75 | // this will only relay traffic between peers already connected to this 76 | // node. 77 | OptHop = RelayOpt(1) 78 | // OptDiscovery is a no-op. It was introduced as a way to probe new 79 | // peers to see if they were willing to act as a relays. However, in 80 | // practice, it's useless. While it does test to see if these peers are 81 | // relays, it doesn't (and can't), check to see if these peers are 82 | // _active_ relays (i.e., will actively dial the target peer). 83 | // 84 | // This option may be re-enabled in the future but for now you shouldn't 85 | // use it. 86 | OptDiscovery = RelayOpt(2) 87 | ) 88 | 89 | type RelayError struct { 90 | Code pb.CircuitRelay_Status 91 | } 92 | 93 | func (e RelayError) Error() string { 94 | return fmt.Sprintf("error opening relay circuit: %s (%d)", pb.CircuitRelay_Status_name[int32(e.Code)], e.Code) 95 | } 96 | 97 | // NewRelay constructs a new relay. 98 | func NewRelay(h host.Host, upgrader transport.Upgrader, opts ...RelayOpt) (*Relay, error) { 99 | r := &Relay{ 100 | upgrader: upgrader, 101 | host: h, 102 | self: h.ID(), 103 | incoming: make(chan *Conn), 104 | hopCount: make(map[peer.ID]int), 105 | } 106 | r.ctx, r.ctxCancel = context.WithCancel(context.Background()) 107 | 108 | for _, opt := range opts { 109 | switch opt { 110 | case OptActive: 111 | r.active = true 112 | case OptHop: 113 | r.hop = true 114 | case OptDiscovery: 115 | log.Errorf( 116 | "circuit.OptDiscovery is now a no-op: %s", 117 | "dialing peers with a random relay is no longer supported", 118 | ) 119 | default: 120 | return nil, fmt.Errorf("unrecognized option: %d", opt) 121 | } 122 | } 123 | 124 | h.SetStreamHandler(ProtoID, r.handleNewStream) 125 | 126 | return r, nil 127 | } 128 | 129 | // Increment the live hop count and increment the connection manager tags by 1 for the two 130 | // sides of the hop stream. This ensures that connections with many hop streams will be protected 131 | // from pruning, thus minimizing disruption from connection trimming in a relay node. 132 | func (r *Relay) addLiveHop(from, to peer.ID) { 133 | atomic.AddInt32(&r.liveHopCount, 1) 134 | r.host.ConnManager().UpsertTag(from, "relay-hop-stream", incrementTag) 135 | r.host.ConnManager().UpsertTag(to, "relay-hop-stream", incrementTag) 136 | } 137 | 138 | // Decrement the live hpo count and decrement the connection manager tags for the two sides 139 | // of the hop stream. 140 | func (r *Relay) rmLiveHop(from, to peer.ID) { 141 | atomic.AddInt32(&r.liveHopCount, -1) 142 | r.host.ConnManager().UpsertTag(from, "relay-hop-stream", decrementTag) 143 | r.host.ConnManager().UpsertTag(to, "relay-hop-stream", decrementTag) 144 | 145 | } 146 | 147 | func (r *Relay) GetActiveHops() int32 { 148 | return atomic.LoadInt32(&r.liveHopCount) 149 | } 150 | 151 | func (r *Relay) DialPeer(ctx context.Context, relay peer.AddrInfo, dest peer.AddrInfo) (*Conn, error) { 152 | 153 | log.Debugf("dialing peer %s through relay %s", dest.ID, relay.ID) 154 | 155 | if len(relay.Addrs) > 0 { 156 | r.host.Peerstore().AddAddrs(relay.ID, relay.Addrs, peerstore.TempAddrTTL) 157 | } 158 | 159 | s, err := r.host.NewStream(ctx, relay.ID, ProtoID) 160 | if err != nil { 161 | return nil, err 162 | } 163 | 164 | rd := newDelimitedReader(s, maxMessageSize) 165 | wr := newDelimitedWriter(s) 166 | defer rd.Close() 167 | 168 | var msg pb.CircuitRelay 169 | 170 | msg.Type = pb.CircuitRelay_HOP.Enum() 171 | msg.SrcPeer = peerInfoToPeer(r.host.Peerstore().PeerInfo(r.self)) 172 | msg.DstPeer = peerInfoToPeer(dest) 173 | 174 | err = wr.WriteMsg(&msg) 175 | if err != nil { 176 | s.Reset() 177 | return nil, err 178 | } 179 | 180 | msg.Reset() 181 | 182 | err = rd.ReadMsg(&msg) 183 | if err != nil { 184 | s.Reset() 185 | return nil, err 186 | } 187 | 188 | if msg.GetType() != pb.CircuitRelay_STATUS { 189 | s.Reset() 190 | return nil, fmt.Errorf("unexpected relay response; not a status message (%d)", msg.GetType()) 191 | } 192 | 193 | if msg.GetCode() != pb.CircuitRelay_SUCCESS { 194 | s.Reset() 195 | return nil, RelayError{msg.GetCode()} 196 | } 197 | 198 | return &Conn{stream: s, remote: dest, host: r.host, relay: r}, nil 199 | } 200 | 201 | func (r *Relay) Matches(addr ma.Multiaddr) bool { 202 | // TODO: Look at the prefix transport as well. 203 | _, err := addr.ValueForProtocol(ma.P_CIRCUIT) 204 | return err == nil 205 | } 206 | 207 | // Queries a peer for support of hop relay 208 | func CanHop(ctx context.Context, host host.Host, id peer.ID) (bool, error) { 209 | s, err := host.NewStream(ctx, id, ProtoID) 210 | if err != nil { 211 | return false, err 212 | } 213 | defer s.Close() 214 | 215 | rd := newDelimitedReader(s, maxMessageSize) 216 | wr := newDelimitedWriter(s) 217 | defer rd.Close() 218 | 219 | var msg pb.CircuitRelay 220 | 221 | msg.Type = pb.CircuitRelay_CAN_HOP.Enum() 222 | 223 | if err := wr.WriteMsg(&msg); err != nil { 224 | s.Reset() 225 | return false, err 226 | } 227 | 228 | msg.Reset() 229 | 230 | if err := rd.ReadMsg(&msg); err != nil { 231 | s.Reset() 232 | return false, err 233 | } 234 | 235 | if msg.GetType() != pb.CircuitRelay_STATUS { 236 | return false, fmt.Errorf("unexpected relay response; not a status message (%d)", msg.GetType()) 237 | } 238 | 239 | return msg.GetCode() == pb.CircuitRelay_SUCCESS, nil 240 | } 241 | 242 | func (r *Relay) CanHop(ctx context.Context, id peer.ID) (bool, error) { 243 | return CanHop(ctx, r.host, id) 244 | } 245 | 246 | func (r *Relay) handleNewStream(s network.Stream) { 247 | s.SetReadDeadline(time.Now().Add(streamTimeout)) 248 | 249 | log.Infof("new relay stream from: %s", s.Conn().RemotePeer()) 250 | 251 | rd := newDelimitedReader(s, maxMessageSize) 252 | defer rd.Close() 253 | 254 | var msg pb.CircuitRelay 255 | 256 | err := rd.ReadMsg(&msg) 257 | if err != nil { 258 | r.handleError(s, pb.CircuitRelay_MALFORMED_MESSAGE) 259 | return 260 | } 261 | // reset stream deadline as message has been read 262 | s.SetReadDeadline(time.Time{}) 263 | 264 | switch msg.GetType() { 265 | case pb.CircuitRelay_HOP: 266 | r.handleHopStream(s, &msg) 267 | case pb.CircuitRelay_STOP: 268 | r.handleStopStream(s, &msg) 269 | case pb.CircuitRelay_CAN_HOP: 270 | r.handleCanHop(s, &msg) 271 | default: 272 | log.Warnf("unexpected relay handshake: %d", msg.GetType()) 273 | r.handleError(s, pb.CircuitRelay_MALFORMED_MESSAGE) 274 | } 275 | } 276 | 277 | func (r *Relay) handleHopStream(s network.Stream, msg *pb.CircuitRelay) { 278 | if !r.hop { 279 | r.handleError(s, pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) 280 | return 281 | } 282 | 283 | streamCount := atomic.AddInt32(&r.streamCount, 1) 284 | liveHopCount := atomic.LoadInt32(&r.liveHopCount) 285 | defer atomic.AddInt32(&r.streamCount, -1) 286 | 287 | if (streamCount + liveHopCount) > int32(HopStreamLimit) { 288 | log.Warn("hop stream limit exceeded; resetting stream") 289 | s.Reset() 290 | return 291 | } 292 | 293 | src, err := peerToPeerInfo(msg.GetSrcPeer()) 294 | if err != nil { 295 | r.handleError(s, pb.CircuitRelay_HOP_SRC_MULTIADDR_INVALID) 296 | return 297 | } 298 | 299 | if src.ID != s.Conn().RemotePeer() { 300 | r.handleError(s, pb.CircuitRelay_HOP_SRC_MULTIADDR_INVALID) 301 | return 302 | } 303 | 304 | dst, err := peerToPeerInfo(msg.GetDstPeer()) 305 | if err != nil { 306 | r.handleError(s, pb.CircuitRelay_HOP_DST_MULTIADDR_INVALID) 307 | return 308 | } 309 | 310 | if dst.ID == r.self { 311 | r.handleError(s, pb.CircuitRelay_HOP_CANT_RELAY_TO_SELF) 312 | return 313 | } 314 | 315 | // open stream 316 | ctx, cancel := context.WithTimeout(r.ctx, HopConnectTimeout) 317 | defer cancel() 318 | 319 | if !r.active { 320 | ctx = network.WithNoDial(ctx, "relay hop") 321 | } else if len(dst.Addrs) > 0 { 322 | r.host.Peerstore().AddAddrs(dst.ID, dst.Addrs, peerstore.TempAddrTTL) 323 | } 324 | 325 | bs, err := r.host.NewStream(ctx, dst.ID, ProtoID) 326 | if err != nil { 327 | log.Debugf("error opening relay stream to %s: %s", dst.ID.Pretty(), err.Error()) 328 | if err == network.ErrNoConn { 329 | r.handleError(s, pb.CircuitRelay_HOP_NO_CONN_TO_DST) 330 | } else { 331 | r.handleError(s, pb.CircuitRelay_HOP_CANT_DIAL_DST) 332 | } 333 | return 334 | } 335 | 336 | // stop handshake 337 | rd := newDelimitedReader(bs, maxMessageSize) 338 | wr := newDelimitedWriter(bs) 339 | defer rd.Close() 340 | 341 | // set handshake deadline 342 | bs.SetDeadline(time.Now().Add(StopHandshakeTimeout)) 343 | 344 | msg.Type = pb.CircuitRelay_STOP.Enum() 345 | 346 | err = wr.WriteMsg(msg) 347 | if err != nil { 348 | log.Debugf("error writing stop handshake: %s", err.Error()) 349 | bs.Reset() 350 | r.handleError(s, pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) 351 | return 352 | } 353 | 354 | msg.Reset() 355 | 356 | err = rd.ReadMsg(msg) 357 | if err != nil { 358 | log.Debugf("error reading stop response: %s", err.Error()) 359 | bs.Reset() 360 | r.handleError(s, pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) 361 | return 362 | } 363 | 364 | if msg.GetType() != pb.CircuitRelay_STATUS { 365 | log.Debugf("unexpected relay stop response: not a status message (%d)", msg.GetType()) 366 | bs.Reset() 367 | r.handleError(s, pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) 368 | return 369 | } 370 | 371 | if msg.GetCode() != pb.CircuitRelay_SUCCESS { 372 | log.Debugf("relay stop failure: %d", msg.GetCode()) 373 | bs.Reset() 374 | r.handleError(s, msg.GetCode()) 375 | return 376 | } 377 | 378 | err = r.writeResponse(s, pb.CircuitRelay_SUCCESS) 379 | if err != nil { 380 | log.Debugf("error writing relay response: %s", err.Error()) 381 | bs.Reset() 382 | s.Reset() 383 | return 384 | } 385 | 386 | // relay connection 387 | log.Infof("relaying connection between %s and %s", src.ID.Pretty(), dst.ID.Pretty()) 388 | 389 | // reset deadline 390 | bs.SetDeadline(time.Time{}) 391 | 392 | r.addLiveHop(src.ID, dst.ID) 393 | 394 | goroutines := new(int32) 395 | *goroutines = 2 396 | done := func() { 397 | if atomic.AddInt32(goroutines, -1) == 0 { 398 | s.Close() 399 | bs.Close() 400 | r.rmLiveHop(src.ID, dst.ID) 401 | } 402 | } 403 | 404 | // Don't reset streams after finishing or the other side will get an 405 | // error, not an EOF. 406 | go func() { 407 | defer done() 408 | 409 | buf := pool.Get(HopStreamBufferSize) 410 | defer pool.Put(buf) 411 | 412 | count, err := io.CopyBuffer(s, bs, buf) 413 | if err != nil { 414 | log.Debugf("relay copy error: %s", err) 415 | // Reset both. 416 | s.Reset() 417 | bs.Reset() 418 | } else { 419 | // propagate the close 420 | s.CloseWrite() 421 | } 422 | log.Debugf("relayed %d bytes from %s to %s", count, dst.ID.Pretty(), src.ID.Pretty()) 423 | }() 424 | 425 | go func() { 426 | defer done() 427 | 428 | buf := pool.Get(HopStreamBufferSize) 429 | defer pool.Put(buf) 430 | 431 | count, err := io.CopyBuffer(bs, s, buf) 432 | if err != nil { 433 | log.Debugf("relay copy error: %s", err) 434 | // Reset both. 435 | bs.Reset() 436 | s.Reset() 437 | } else { 438 | // propagate the close 439 | bs.CloseWrite() 440 | } 441 | log.Debugf("relayed %d bytes from %s to %s", count, src.ID.Pretty(), dst.ID.Pretty()) 442 | }() 443 | } 444 | 445 | func (r *Relay) handleStopStream(s network.Stream, msg *pb.CircuitRelay) { 446 | src, err := peerToPeerInfo(msg.GetSrcPeer()) 447 | if err != nil { 448 | r.handleError(s, pb.CircuitRelay_STOP_SRC_MULTIADDR_INVALID) 449 | return 450 | } 451 | 452 | dst, err := peerToPeerInfo(msg.GetDstPeer()) 453 | if err != nil || dst.ID != r.self { 454 | r.handleError(s, pb.CircuitRelay_STOP_DST_MULTIADDR_INVALID) 455 | return 456 | } 457 | 458 | log.Infof("relay connection from: %s", src.ID) 459 | 460 | if len(src.Addrs) > 0 { 461 | r.host.Peerstore().AddAddrs(src.ID, src.Addrs, peerstore.TempAddrTTL) 462 | } 463 | 464 | select { 465 | case r.incoming <- &Conn{stream: s, remote: src, host: r.host, relay: r}: 466 | case <-time.After(RelayAcceptTimeout): 467 | r.handleError(s, pb.CircuitRelay_STOP_RELAY_REFUSED) 468 | } 469 | } 470 | 471 | func (r *Relay) handleCanHop(s network.Stream, msg *pb.CircuitRelay) { 472 | var err error 473 | 474 | if r.hop { 475 | err = r.writeResponse(s, pb.CircuitRelay_SUCCESS) 476 | } else { 477 | err = r.writeResponse(s, pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) 478 | } 479 | 480 | if err != nil { 481 | s.Reset() 482 | log.Debugf("error writing relay response: %s", err.Error()) 483 | } else { 484 | s.Close() 485 | } 486 | } 487 | 488 | func (r *Relay) handleError(s network.Stream, code pb.CircuitRelay_Status) { 489 | log.Warnf("relay error: %s (%d)", pb.CircuitRelay_Status_name[int32(code)], code) 490 | err := r.writeResponse(s, code) 491 | if err != nil { 492 | s.Reset() 493 | log.Debugf("error writing relay response: %s", err.Error()) 494 | } else { 495 | s.Close() 496 | } 497 | } 498 | 499 | func (r *Relay) writeResponse(s network.Stream, code pb.CircuitRelay_Status) error { 500 | wr := newDelimitedWriter(s) 501 | 502 | var msg pb.CircuitRelay 503 | msg.Type = pb.CircuitRelay_STATUS.Enum() 504 | msg.Code = code.Enum() 505 | 506 | return wr.WriteMsg(&msg) 507 | } 508 | -------------------------------------------------------------------------------- /relay_test.go: -------------------------------------------------------------------------------- 1 | package relay_test 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "fmt" 7 | "io" 8 | "io/ioutil" 9 | "net" 10 | "testing" 11 | "time" 12 | 13 | . "github.com/libp2p/go-libp2p-circuit" 14 | pb "github.com/libp2p/go-libp2p-circuit/pb" 15 | 16 | bhost "github.com/libp2p/go-libp2p-blankhost" 17 | "github.com/libp2p/go-libp2p-core/host" 18 | 19 | swarm "github.com/libp2p/go-libp2p-swarm" 20 | swarmt "github.com/libp2p/go-libp2p-swarm/testing" 21 | ma "github.com/multiformats/go-multiaddr" 22 | manet "github.com/multiformats/go-multiaddr/net" 23 | ) 24 | 25 | /* TODO: add tests 26 | - simple A -[R]-> B 27 | - A tries to relay through R, R doesnt support relay 28 | - A tries to relay through R to B, B doesnt support relay 29 | - A sends too long multiaddr 30 | - R drops stream mid-message 31 | - A relays through R, R has no connection to B 32 | */ 33 | 34 | func getNetHosts(t *testing.T, n int) []host.Host { 35 | var out []host.Host 36 | 37 | for i := 0; i < n; i++ { 38 | netw := swarmt.GenSwarm(t) 39 | h := bhost.NewBlankHost(netw) 40 | out = append(out, h) 41 | } 42 | 43 | return out 44 | } 45 | 46 | func newTestRelay(t *testing.T, host host.Host, opts ...RelayOpt) *Relay { 47 | r, err := NewRelay(host, swarmt.GenUpgrader(t, host.Network().(*swarm.Swarm)), opts...) 48 | if err != nil { 49 | t.Fatal(err) 50 | } 51 | return r 52 | } 53 | 54 | func connect(t *testing.T, a, b host.Host) { 55 | pinfo := a.Peerstore().PeerInfo(a.ID()) 56 | err := b.Connect(context.Background(), pinfo) 57 | if err != nil { 58 | t.Fatal(err) 59 | } 60 | } 61 | 62 | func TestBasicRelay(t *testing.T) { 63 | ctx, cancel := context.WithCancel(context.Background()) 64 | defer cancel() 65 | 66 | hosts := getNetHosts(t, 3) 67 | 68 | connect(t, hosts[0], hosts[1]) 69 | connect(t, hosts[1], hosts[2]) 70 | 71 | time.Sleep(10 * time.Millisecond) 72 | 73 | r1 := newTestRelay(t, hosts[0]) 74 | 75 | newTestRelay(t, hosts[1], OptHop) 76 | 77 | r3 := newTestRelay(t, hosts[2]) 78 | 79 | var ( 80 | conn1, conn2 net.Conn 81 | done = make(chan struct{}) 82 | ) 83 | 84 | defer func() { 85 | <-done 86 | if conn1 != nil { 87 | conn1.Close() 88 | } 89 | if conn2 != nil { 90 | conn2.Close() 91 | } 92 | }() 93 | 94 | msg := []byte("relay works!") 95 | go func() { 96 | defer close(done) 97 | list := r3.Listener() 98 | 99 | var err error 100 | conn1, err = list.Accept() 101 | if err != nil { 102 | t.Error(err) 103 | return 104 | } 105 | 106 | _, err = conn1.Write(msg) 107 | if err != nil { 108 | t.Error(err) 109 | return 110 | } 111 | }() 112 | 113 | rinfo := hosts[1].Peerstore().PeerInfo(hosts[1].ID()) 114 | dinfo := hosts[2].Peerstore().PeerInfo(hosts[2].ID()) 115 | 116 | rctx, rcancel := context.WithTimeout(ctx, time.Second) 117 | defer rcancel() 118 | 119 | var err error 120 | conn2, err = r1.DialPeer(rctx, rinfo, dinfo) 121 | if err != nil { 122 | t.Fatal(err) 123 | } 124 | 125 | result := make([]byte, len(msg)) 126 | _, err = io.ReadFull(conn2, result) 127 | if err != nil { 128 | t.Fatal(err) 129 | } 130 | 131 | if !bytes.Equal(result, msg) { 132 | t.Fatal("message was incorrect:", string(result)) 133 | } 134 | } 135 | 136 | func TestRelayReset(t *testing.T) { 137 | ctx, cancel := context.WithCancel(context.Background()) 138 | defer cancel() 139 | 140 | hosts := getNetHosts(t, 3) 141 | 142 | connect(t, hosts[0], hosts[1]) 143 | connect(t, hosts[1], hosts[2]) 144 | 145 | time.Sleep(10 * time.Millisecond) 146 | 147 | r1 := newTestRelay(t, hosts[0]) 148 | 149 | newTestRelay(t, hosts[1], OptHop) 150 | 151 | r3 := newTestRelay(t, hosts[2]) 152 | 153 | ready := make(chan struct{}) 154 | 155 | msg := []byte("relay works!") 156 | go func() { 157 | list := r3.Listener() 158 | 159 | con, err := list.Accept() 160 | if err != nil { 161 | t.Error(err) 162 | return 163 | } 164 | 165 | <-ready 166 | 167 | _, err = con.Write(msg) 168 | if err != nil { 169 | t.Error(err) 170 | return 171 | } 172 | 173 | hosts[2].Network().ClosePeer(hosts[1].ID()) 174 | }() 175 | 176 | rinfo := hosts[1].Peerstore().PeerInfo(hosts[1].ID()) 177 | dinfo := hosts[2].Peerstore().PeerInfo(hosts[2].ID()) 178 | 179 | rctx, rcancel := context.WithTimeout(ctx, time.Second) 180 | defer rcancel() 181 | 182 | con, err := r1.DialPeer(rctx, rinfo, dinfo) 183 | if err != nil { 184 | t.Fatal(err) 185 | } 186 | 187 | close(ready) 188 | 189 | _, err = ioutil.ReadAll(con) 190 | if err == nil { 191 | t.Fatal("expected error for reset relayed connection") 192 | } 193 | } 194 | 195 | func TestBasicRelayDial(t *testing.T) { 196 | ctx, cancel := context.WithCancel(context.Background()) 197 | 198 | hosts := getNetHosts(t, 3) 199 | 200 | connect(t, hosts[0], hosts[1]) 201 | connect(t, hosts[1], hosts[2]) 202 | 203 | time.Sleep(10 * time.Millisecond) 204 | 205 | r1 := newTestRelay(t, hosts[0]) 206 | 207 | _ = newTestRelay(t, hosts[1], OptHop) 208 | r3 := newTestRelay(t, hosts[2]) 209 | 210 | var ( 211 | conn1, conn2 net.Conn 212 | done = make(chan struct{}) 213 | ) 214 | 215 | defer func() { 216 | cancel() 217 | <-done 218 | if conn1 != nil { 219 | conn1.Close() 220 | } 221 | if conn2 != nil { 222 | conn2.Close() 223 | } 224 | }() 225 | 226 | msg := []byte("relay works!") 227 | go func() { 228 | defer close(done) 229 | list := r3.Listener() 230 | 231 | var err error 232 | conn1, err = list.Accept() 233 | if err != nil { 234 | t.Error(err) 235 | return 236 | } 237 | 238 | _, err = conn1.Write(msg) 239 | if err != nil { 240 | t.Error(err) 241 | return 242 | } 243 | }() 244 | 245 | addr := ma.StringCast(fmt.Sprintf("/ipfs/%s/p2p-circuit", hosts[1].ID().Pretty())) 246 | 247 | rctx, rcancel := context.WithTimeout(ctx, time.Second) 248 | defer rcancel() 249 | 250 | var err error 251 | conn2, err = r1.Dial(rctx, addr, hosts[2].ID()) 252 | if err != nil { 253 | t.Fatal(err) 254 | } 255 | 256 | data := make([]byte, len(msg)) 257 | _, err = io.ReadFull(conn2, data) 258 | if err != nil { 259 | t.Fatal(err) 260 | } 261 | 262 | if !bytes.Equal(data, msg) { 263 | t.Fatal("message was incorrect:", string(data)) 264 | } 265 | } 266 | 267 | func TestUnspecificRelayDialFails(t *testing.T) { 268 | hosts := getNetHosts(t, 3) 269 | 270 | r1 := newTestRelay(t, hosts[0]) 271 | newTestRelay(t, hosts[1], OptHop) 272 | r3 := newTestRelay(t, hosts[2]) 273 | 274 | connect(t, hosts[0], hosts[1]) 275 | connect(t, hosts[1], hosts[2]) 276 | 277 | time.Sleep(100 * time.Millisecond) 278 | 279 | go func() { 280 | if _, err := r3.Listener().Accept(); err == nil { 281 | t.Error("should not have received relay connection") 282 | } 283 | }() 284 | 285 | addr := ma.StringCast("/p2p-circuit") 286 | 287 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 288 | defer cancel() 289 | if _, err := r1.Dial(ctx, addr, hosts[2].ID()); err == nil { 290 | t.Fatal("expected dial with unspecified relay address to fail, even if we're connected to a relay") 291 | } 292 | } 293 | 294 | func TestRelayThroughNonHop(t *testing.T) { 295 | ctx, cancel := context.WithCancel(context.Background()) 296 | defer cancel() 297 | 298 | hosts := getNetHosts(t, 3) 299 | 300 | connect(t, hosts[0], hosts[1]) 301 | connect(t, hosts[1], hosts[2]) 302 | 303 | time.Sleep(10 * time.Millisecond) 304 | 305 | r1 := newTestRelay(t, hosts[0]) 306 | 307 | newTestRelay(t, hosts[1]) 308 | 309 | newTestRelay(t, hosts[2]) 310 | 311 | rinfo := hosts[1].Peerstore().PeerInfo(hosts[1].ID()) 312 | dinfo := hosts[2].Peerstore().PeerInfo(hosts[2].ID()) 313 | 314 | rctx, rcancel := context.WithTimeout(ctx, time.Second) 315 | defer rcancel() 316 | 317 | _, err := r1.DialPeer(rctx, rinfo, dinfo) 318 | if err == nil { 319 | t.Fatal("expected error") 320 | } 321 | 322 | rerr, ok := err.(RelayError) 323 | if !ok { 324 | t.Fatalf("expected RelayError: %#v", err) 325 | } 326 | 327 | if rerr.Code != pb.CircuitRelay_HOP_CANT_SPEAK_RELAY { 328 | t.Fatal("expected 'HOP_CANT_SPEAK_RELAY' error") 329 | } 330 | } 331 | 332 | func TestRelayNoDestConnection(t *testing.T) { 333 | ctx, cancel := context.WithCancel(context.Background()) 334 | defer cancel() 335 | 336 | hosts := getNetHosts(t, 3) 337 | 338 | connect(t, hosts[0], hosts[1]) 339 | 340 | time.Sleep(10 * time.Millisecond) 341 | 342 | r1 := newTestRelay(t, hosts[0]) 343 | 344 | newTestRelay(t, hosts[1], OptHop) 345 | 346 | rinfo := hosts[1].Peerstore().PeerInfo(hosts[1].ID()) 347 | dinfo := hosts[2].Peerstore().PeerInfo(hosts[2].ID()) 348 | 349 | rctx, rcancel := context.WithTimeout(ctx, time.Second) 350 | defer rcancel() 351 | 352 | _, err := r1.DialPeer(rctx, rinfo, dinfo) 353 | if err == nil { 354 | t.Fatal("expected error") 355 | } 356 | 357 | rerr, ok := err.(RelayError) 358 | if !ok { 359 | t.Fatalf("expected RelayError: %#v", err) 360 | } 361 | 362 | if rerr.Code != pb.CircuitRelay_HOP_NO_CONN_TO_DST { 363 | t.Fatal("expected 'HOP_NO_CONN_TO_DST' error") 364 | } 365 | } 366 | 367 | func TestActiveRelay(t *testing.T) { 368 | ctx, cancel := context.WithCancel(context.Background()) 369 | defer cancel() 370 | 371 | hosts := getNetHosts(t, 3) 372 | 373 | connect(t, hosts[0], hosts[1]) 374 | 375 | time.Sleep(10 * time.Millisecond) 376 | 377 | r1 := newTestRelay(t, hosts[0]) 378 | newTestRelay(t, hosts[1], OptHop, OptActive) 379 | r3 := newTestRelay(t, hosts[2]) 380 | 381 | connChan := make(chan manet.Conn) 382 | 383 | msg := []byte("relay works!") 384 | go func() { 385 | defer close(connChan) 386 | list := r3.Listener() 387 | 388 | conn1, err := list.Accept() 389 | if err != nil { 390 | t.Error(err) 391 | return 392 | } 393 | 394 | if _, err := conn1.Write(msg); err != nil { 395 | t.Error(err) 396 | return 397 | } 398 | connChan <- conn1 399 | }() 400 | 401 | rinfo := hosts[1].Peerstore().PeerInfo(hosts[1].ID()) 402 | dinfo := hosts[2].Peerstore().PeerInfo(hosts[2].ID()) 403 | 404 | rctx, rcancel := context.WithTimeout(ctx, time.Second) 405 | defer rcancel() 406 | 407 | conn2, err := r1.DialPeer(rctx, rinfo, dinfo) 408 | if err != nil { 409 | t.Fatal(err) 410 | } 411 | defer conn2.Close() 412 | 413 | data := make([]byte, len(msg)) 414 | _, err = io.ReadFull(conn2, data) 415 | if err != nil { 416 | t.Fatal(err) 417 | } 418 | 419 | if !bytes.Equal(data, msg) { 420 | t.Fatal("message was incorrect:", string(data)) 421 | } 422 | conn1, ok := <-connChan 423 | if !ok { 424 | t.Fatal("listener didn't accept a connection") 425 | } 426 | conn1.Close() 427 | } 428 | 429 | func TestRelayCanHop(t *testing.T) { 430 | ctx, cancel := context.WithCancel(context.Background()) 431 | defer cancel() 432 | 433 | hosts := getNetHosts(t, 2) 434 | 435 | connect(t, hosts[0], hosts[1]) 436 | 437 | time.Sleep(10 * time.Millisecond) 438 | 439 | r1 := newTestRelay(t, hosts[0]) 440 | 441 | newTestRelay(t, hosts[1], OptHop) 442 | 443 | canhop, err := r1.CanHop(ctx, hosts[1].ID()) 444 | if err != nil { 445 | t.Fatal(err) 446 | } 447 | 448 | if !canhop { 449 | t.Fatal("Relay can't hop") 450 | } 451 | } 452 | -------------------------------------------------------------------------------- /transport.go: -------------------------------------------------------------------------------- 1 | package relay 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | 7 | "github.com/libp2p/go-libp2p-core/host" 8 | "github.com/libp2p/go-libp2p-core/transport" 9 | ma "github.com/multiformats/go-multiaddr" 10 | ) 11 | 12 | var circuitAddr = ma.Cast(ma.ProtocolWithCode(ma.P_CIRCUIT).VCode) 13 | 14 | var _ transport.Transport = (*RelayTransport)(nil) 15 | var _ io.Closer = (*RelayTransport)(nil) 16 | 17 | type RelayTransport Relay 18 | 19 | func (t *RelayTransport) Relay() *Relay { 20 | return (*Relay)(t) 21 | } 22 | 23 | func (r *Relay) Transport() *RelayTransport { 24 | return (*RelayTransport)(r) 25 | } 26 | 27 | func (t *RelayTransport) Listen(laddr ma.Multiaddr) (transport.Listener, error) { 28 | // TODO: Ensure we have a connection to the relay, if specified. Also, 29 | // make sure the multiaddr makes sense. 30 | if !t.Relay().Matches(laddr) { 31 | return nil, fmt.Errorf("%s is not a relay address", laddr) 32 | } 33 | return t.upgrader.UpgradeListener(t, t.Relay().Listener()), nil 34 | } 35 | 36 | func (t *RelayTransport) CanDial(raddr ma.Multiaddr) bool { 37 | return t.Relay().Matches(raddr) 38 | } 39 | 40 | func (t *RelayTransport) Proxy() bool { 41 | return true 42 | } 43 | 44 | func (t *RelayTransport) Protocols() []int { 45 | return []int{ma.P_CIRCUIT} 46 | } 47 | 48 | func (r *RelayTransport) Close() error { 49 | r.ctxCancel() 50 | return nil 51 | } 52 | 53 | // AddRelayTransport constructs a relay and adds it as a transport to the host network. 54 | func AddRelayTransport(h host.Host, upgrader transport.Upgrader, opts ...RelayOpt) error { 55 | n, ok := h.Network().(transport.TransportNetwork) 56 | if !ok { 57 | return fmt.Errorf("%v is not a transport network", h.Network()) 58 | } 59 | 60 | r, err := NewRelay(h, upgrader, opts...) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | // There's no nice way to handle these errors as we have no way to tear 66 | // down the relay. 67 | // TODO 68 | if err := n.AddTransport(r.Transport()); err != nil { 69 | log.Error("failed to add relay transport:", err) 70 | } else if err := n.Listen(r.Listener().Multiaddr()); err != nil { 71 | log.Error("failed to listen on relay transport:", err) 72 | } 73 | return nil 74 | } 75 | -------------------------------------------------------------------------------- /transport_test.go: -------------------------------------------------------------------------------- 1 | package relay_test 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "fmt" 7 | "io/ioutil" 8 | "testing" 9 | "time" 10 | 11 | . "github.com/libp2p/go-libp2p-circuit" 12 | 13 | "github.com/libp2p/go-libp2p-core/host" 14 | "github.com/libp2p/go-libp2p-core/network" 15 | "github.com/libp2p/go-libp2p-core/peerstore" 16 | 17 | swarm "github.com/libp2p/go-libp2p-swarm" 18 | swarmt "github.com/libp2p/go-libp2p-swarm/testing" 19 | ma "github.com/multiformats/go-multiaddr" 20 | ) 21 | 22 | const TestProto = "test/relay-transport" 23 | 24 | var msg = []byte("relay works!") 25 | 26 | func testSetupRelay(t *testing.T) []host.Host { 27 | hosts := getNetHosts(t, 3) 28 | 29 | err := AddRelayTransport(hosts[0], swarmt.GenUpgrader(t, hosts[0].Network().(*swarm.Swarm))) 30 | if err != nil { 31 | t.Fatal(err) 32 | } 33 | 34 | err = AddRelayTransport(hosts[1], swarmt.GenUpgrader(t, hosts[1].Network().(*swarm.Swarm)), OptHop) 35 | if err != nil { 36 | t.Fatal(err) 37 | } 38 | 39 | err = AddRelayTransport(hosts[2], swarmt.GenUpgrader(t, hosts[2].Network().(*swarm.Swarm))) 40 | if err != nil { 41 | t.Fatal(err) 42 | } 43 | 44 | connect(t, hosts[0], hosts[1]) 45 | connect(t, hosts[1], hosts[2]) 46 | 47 | time.Sleep(100 * time.Millisecond) 48 | 49 | handler := func(s network.Stream) { 50 | _, err := s.Write(msg) 51 | if err != nil { 52 | t.Error(err) 53 | } 54 | s.Close() 55 | } 56 | 57 | hosts[2].SetStreamHandler(TestProto, handler) 58 | 59 | return hosts 60 | } 61 | 62 | func TestFullAddressTransportDial(t *testing.T) { 63 | hosts := testSetupRelay(t) 64 | 65 | var relayAddr ma.Multiaddr 66 | for _, addr := range hosts[1].Addrs() { 67 | // skip relay addrs. 68 | if _, err := addr.ValueForProtocol(ma.P_CIRCUIT); err != nil { 69 | relayAddr = addr 70 | } 71 | } 72 | 73 | addr, err := ma.NewMultiaddr(fmt.Sprintf("%s/p2p/%s/p2p-circuit/p2p/%s", relayAddr.String(), hosts[1].ID().Pretty(), hosts[2].ID().Pretty())) 74 | if err != nil { 75 | t.Fatal(err) 76 | } 77 | 78 | hosts[0].Peerstore().AddAddrs(hosts[2].ID(), []ma.Multiaddr{addr}, peerstore.TempAddrTTL) 79 | 80 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 81 | defer cancel() 82 | s, err := hosts[0].NewStream(ctx, hosts[2].ID(), TestProto) 83 | if err != nil { 84 | t.Fatal(err) 85 | } 86 | 87 | data, err := ioutil.ReadAll(s) 88 | if err != nil { 89 | t.Fatal(err) 90 | } 91 | 92 | if !bytes.Equal(data, msg) { 93 | t.Fatal("message was incorrect:", string(data)) 94 | } 95 | } 96 | 97 | func TestSpecificRelayTransportDial(t *testing.T) { 98 | ctx, cancel := context.WithCancel(context.Background()) 99 | defer cancel() 100 | 101 | hosts := testSetupRelay(t) 102 | 103 | addr, err := ma.NewMultiaddr(fmt.Sprintf("/ipfs/%s/p2p-circuit/ipfs/%s", hosts[1].ID().Pretty(), hosts[2].ID().Pretty())) 104 | if err != nil { 105 | t.Fatal(err) 106 | } 107 | 108 | rctx, rcancel := context.WithTimeout(ctx, time.Second) 109 | defer rcancel() 110 | 111 | hosts[0].Peerstore().AddAddrs(hosts[2].ID(), []ma.Multiaddr{addr}, peerstore.TempAddrTTL) 112 | 113 | s, err := hosts[0].NewStream(rctx, hosts[2].ID(), TestProto) 114 | if err != nil { 115 | t.Fatal(err) 116 | } 117 | 118 | data, err := ioutil.ReadAll(s) 119 | if err != nil { 120 | t.Fatal(err) 121 | } 122 | 123 | if !bytes.Equal(data, msg) { 124 | t.Fatal("message was incorrect:", string(data)) 125 | } 126 | } 127 | 128 | func TestUnspecificRelayTransportDialFails(t *testing.T) { 129 | ctx, cancel := context.WithCancel(context.Background()) 130 | defer cancel() 131 | 132 | hosts := testSetupRelay(t) 133 | 134 | addr, err := ma.NewMultiaddr(fmt.Sprintf("/p2p-circuit/ipfs/%s", hosts[2].ID().Pretty())) 135 | if err != nil { 136 | t.Fatal(err) 137 | } 138 | 139 | rctx, rcancel := context.WithTimeout(ctx, time.Second) 140 | defer rcancel() 141 | 142 | hosts[0].Peerstore().AddAddrs(hosts[2].ID(), []ma.Multiaddr{addr}, peerstore.TempAddrTTL) 143 | 144 | _, err = hosts[0].NewStream(rctx, hosts[2].ID(), TestProto) 145 | if err == nil { 146 | t.Fatal("dial to unspecified address should have failed") 147 | } 148 | 149 | } 150 | -------------------------------------------------------------------------------- /util.go: -------------------------------------------------------------------------------- 1 | package relay 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | 7 | pb "github.com/libp2p/go-libp2p-circuit/pb" 8 | 9 | "github.com/libp2p/go-libp2p-core/peer" 10 | 11 | pool "github.com/libp2p/go-buffer-pool" 12 | "github.com/libp2p/go-msgio/protoio" 13 | 14 | "github.com/gogo/protobuf/proto" 15 | ma "github.com/multiformats/go-multiaddr" 16 | "github.com/multiformats/go-varint" 17 | ) 18 | 19 | func peerToPeerInfo(p *pb.CircuitRelay_Peer) (peer.AddrInfo, error) { 20 | if p == nil { 21 | return peer.AddrInfo{}, errors.New("nil peer") 22 | } 23 | 24 | id, err := peer.IDFromBytes(p.Id) 25 | if err != nil { 26 | return peer.AddrInfo{}, err 27 | } 28 | 29 | addrs := make([]ma.Multiaddr, 0, len(p.Addrs)) 30 | for _, addrBytes := range p.Addrs { 31 | a, err := ma.NewMultiaddrBytes(addrBytes) 32 | if err == nil { 33 | addrs = append(addrs, a) 34 | } 35 | } 36 | 37 | return peer.AddrInfo{ID: id, Addrs: addrs}, nil 38 | } 39 | 40 | func peerInfoToPeer(pi peer.AddrInfo) *pb.CircuitRelay_Peer { 41 | addrs := make([][]byte, len(pi.Addrs)) 42 | for i, addr := range pi.Addrs { 43 | addrs[i] = addr.Bytes() 44 | } 45 | 46 | p := new(pb.CircuitRelay_Peer) 47 | p.Id = []byte(pi.ID) 48 | p.Addrs = addrs 49 | 50 | return p 51 | } 52 | 53 | func incrementTag(v int) int { 54 | return v + 1 55 | } 56 | 57 | func decrementTag(v int) int { 58 | if v > 0 { 59 | return v - 1 60 | } else { 61 | return v 62 | } 63 | } 64 | 65 | type delimitedReader struct { 66 | r io.Reader 67 | buf []byte 68 | } 69 | 70 | // The gogo protobuf NewDelimitedReader is buffered, which may eat up stream data. 71 | // So we need to implement a compatible delimited reader that reads unbuffered. 72 | // There is a slowdown from unbuffered reading: when reading the message 73 | // it can take multiple single byte Reads to read the length and another Read 74 | // to read the message payload. 75 | // However, this is not critical performance degradation as 76 | // - the reader is utilized to read one (dialer, stop) or two messages (hop) during 77 | // the handshake, so it's a drop in the water for the connection lifetime. 78 | // - messages are small (max 4k) and the length fits in a couple of bytes, 79 | // so overall we have at most three reads per message. 80 | func newDelimitedReader(r io.Reader, maxSize int) *delimitedReader { 81 | return &delimitedReader{r: r, buf: pool.Get(maxSize)} 82 | } 83 | 84 | func (d *delimitedReader) Close() { 85 | if d.buf != nil { 86 | pool.Put(d.buf) 87 | d.buf = nil 88 | } 89 | } 90 | 91 | func (d *delimitedReader) ReadByte() (byte, error) { 92 | buf := d.buf[:1] 93 | _, err := d.r.Read(buf) 94 | return buf[0], err 95 | } 96 | 97 | func (d *delimitedReader) ReadMsg(msg proto.Message) error { 98 | mlen, err := varint.ReadUvarint(d) 99 | if err != nil { 100 | return err 101 | } 102 | 103 | if uint64(len(d.buf)) < mlen { 104 | return errors.New("message too large") 105 | } 106 | 107 | buf := d.buf[:mlen] 108 | _, err = io.ReadFull(d.r, buf) 109 | if err != nil { 110 | return err 111 | } 112 | 113 | return proto.Unmarshal(buf, msg) 114 | } 115 | 116 | func newDelimitedWriter(w io.Writer) protoio.WriteCloser { 117 | return protoio.NewDelimitedWriter(w) 118 | } 119 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v0.6.0" 3 | } 4 | --------------------------------------------------------------------------------