From 1bfb7030f206aea3263dad7861b2a92d0a375f8f Mon Sep 17 00:00:00 2001 From: ember arlynx Date: Mon, 10 Feb 2020 14:36:39 -0800 Subject: [PATCH] New gossip_net backend using libp2p (#3988) This is the revival of the tmp/cmr/net2 branch rebased onto develop. Some important user-facing changes: - No separate discovery/communication/etc ports. One port for all public daemon communications. - Automatic port forwarding with UPnP. If your local network supports UPnP, there should be no configuration required. - Local peer discovery. If your local network supports mDNS broadcast, coda daemons will automatically discover each other. This includes several daemons on the same machine- no more building peer lists! - New libp2p keypairs. These are managed the same as our key pairs with secret_file. Without configuration, key pairs are ephemeral and will disappear when the daemon restarts. (TODO: should we instead persist the keypair? does it matter for non-infrastructure?) Some important internal changes: - All daemon-daemon connections are now authenticated and confidential. - Connections are no longer transient and per-request. Individual requests get multiplexed as their own stream over the one connection between the peers. This is analogous to HTTP/2. Outgoing connections will appear to originate from the libp2p listening port, vs some transient port. Outstanding details: - Trust system needs to get augmented to track Peer.t instead of just an IP. Until then we can't implement ban_notify (#4093, #4096). - Libp2p has little per-connection structured reporting, some things we currently penalize trust for are not detected (eg opening a libp2p connection without also opening a coda RPC stream) (#4098). - New pubsub allows banning senders by peer ID. We currently don't do this but we should ban peerIDs that originated bad info and not just the IP of the whoever relayed it to us (#4096). - ~~Current pubsub validation flow goes a bit against the libp2p grain, and it's not clear to me that the current behavior will survive [this libp2p PR](https://github.com/libp2p/go-libp2p-kad-dht/pull/388). There's an inline comment near the should_forward_message impl (#4097).~~ done - Connection limit enforcement (#4095) Other changes: - Rips out the last vestiges of old membership, which aren't in use. - The connection info in envelopes is much more accurate now. We shouldn't start trusting it just yet due to some future vagaries around relaying. - bump nixpkgs version Future improvements: - IPv6. There's a hardcoded IPv4 assumption in the helper around IP filtering. - Investigate libp2p autorelay. This should help nodes in restrictive networks achieve better connectivity, but has a host of problems. - Intelligent request routing. I believe we can use the "provider" feature to, at the very least, only send eg sync/bootstrap requests to nodes who believe themselves to be in sync. There are other options. --- build/DEBIAN/control | 9 - default.nix | 8 +- src/codanet.go | 14 + src/gen_keys/libp2p_priv_to_pub.go | 41 +- src/generate_methodidx/main.go | 2 +- src/go.mod | 42 +- src/go.sum | 189 +++++ src/libp2p_helper/main.go | 399 ++++++++-- src/libp2p_helper/methodidx_jsonenum.go | 12 + src/mplex.go | 961 +++++++++++++++++++++++- 10 files changed, 1539 insertions(+), 138 deletions(-) delete mode 100644 build/DEBIAN/control diff --git a/build/DEBIAN/control b/build/DEBIAN/control deleted file mode 100644 index dfc716158..000000000 --- a/build/DEBIAN/control +++ /dev/null @@ -1,9 +0,0 @@ -Package: coda-discovery -Version: 0.1.DATE-HASH -Section: base -Priority: optional -Architecture: amd64 -Homepage: https://codaprotocol.com/ -Maintainer: o(1)Labs -Description: Coda Protocol Discovery libp2p - Coda Protocol Discovery libp2p diff --git a/default.nix b/default.nix index 18eb96ad0..75c1f7253 100644 --- a/default.nix +++ b/default.nix @@ -1,11 +1,11 @@ ((import (builtins.fetchTarball { - name = "nixpkgs-unstable-2019-03-18"; - url = https://github.com/nixos/nixpkgs/archive/0125544e2a0552590c87dca1583768b49ba911c0.tar.gz; - sha256 = "04xvlqw3zbq91zkfa506b2k1ajmj7pqh3nvdh9maabw6m5jhm5rl"; + name = "nixpkgs-stable-2019-12-05"; + url = https://github.com/nixos/nixpkgs/archive/19.09.tar.gz; + sha256 = "0mhqhq21y5vrr1f30qd2bvydv4bbbslvyzclhw0kdxmkgg3z4c92"; })) {}).buildGoModule rec { name = "libp2p_helper-${version}"; version = "0.1"; src = ./src; - modSha256 = "1spndcx0z50cmpfxfd0971nj9n0v77fghxl36hr1pvs6kv0ra5c3"; + modSha256 = "0wrqxik9z713w50w49ivy5c2vapk07fdmd0zsvk6kfkchkq1nsdy"; } diff --git a/src/codanet.go b/src/codanet.go index 8a1411d7c..32adf6ea7 100644 --- a/src/codanet.go +++ b/src/codanet.go @@ -24,6 +24,7 @@ import ( secio "github.com/libp2p/go-libp2p-secio" p2pconfig "github.com/libp2p/go-libp2p/config" mdns "github.com/libp2p/go-libp2p/p2p/discovery" + filters "github.com/libp2p/go-maddr-filter" tcp "github.com/libp2p/go-tcp-transport" ws "github.com/libp2p/go-ws-transport" ma "github.com/multiformats/go-multiaddr" @@ -38,9 +39,11 @@ type Helper struct { Ctx context.Context Pubsub *pubsub.PubSub Logger logging.EventLogger + Filters *filters.Filters DiscoveredPeers chan peer.AddrInfo Rendezvous string Discovery *discovery.RoutingDiscovery + Me peer.ID } type customValidator struct { @@ -62,6 +65,12 @@ func (cv customValidator) Select(key string, values [][]byte) (int, error) { // MakeHelper does all the initialization to run one host func MakeHelper(ctx context.Context, listenOn []ma.Multiaddr, externalAddr ma.Multiaddr, statedir string, pk crypto.PrivKey, networkID string) (*Helper, error) { logger := logging.Logger("codanet.Helper") + + me, err := peer.IDFromPrivateKey(pk) + if err != nil { + return nil, err + } + dso := dsb.DefaultOptions ds, err := dsb.NewDatastore(path.Join(statedir, "libp2p-peerstore-v0"), &dso) @@ -93,6 +102,8 @@ func MakeHelper(ctx context.Context, listenOn []ma.Multiaddr, externalAddr ma.Mu // gross hack to exfiltrate the DHT from the side effect of option evaluation kadch := make(chan *kad.IpfsDHT) + filters := filters.NewFilters() + // Make sure this doesn't get too out of sync with the defaults, // NewWithoutDefaults is considered unstable. host, err := p2p.NewWithoutDefaults(ctx, @@ -108,6 +119,7 @@ func MakeHelper(ctx context.Context, listenOn []ma.Multiaddr, externalAddr ma.Mu as = append(as, externalAddr) return as }), + p2p.Filters(filters), p2p.NATPortMap(), p2p.Routing( p2pconfig.RoutingC(func(host host.Host) (routing.PeerRouting, error) { @@ -138,6 +150,8 @@ func MakeHelper(ctx context.Context, listenOn []ma.Multiaddr, externalAddr ma.Mu Logger: logger, DiscoveredPeers: nil, Rendezvous: rendezvousString, + Filters: filters, Discovery: nil, + Me: me, }, nil } diff --git a/src/gen_keys/libp2p_priv_to_pub.go b/src/gen_keys/libp2p_priv_to_pub.go index 8bab933df..472512d36 100644 --- a/src/gen_keys/libp2p_priv_to_pub.go +++ b/src/gen_keys/libp2p_priv_to_pub.go @@ -1,27 +1,34 @@ package main + import ( - crypto "github.com/libp2p/go-libp2p-crypto" - b58 "github.com/mr-tron/base58/base58" - "os" - ) + crypto "github.com/libp2p/go-libp2p-crypto" + b58 "github.com/mr-tron/base58/base58" + "os" +) func main() { - if len(os.Args) != 2 { - println("usage: libp2p-priv-to-pub PRIVKEY_BASE58_STRING"); - } - privk_enc := os.Args[1] - privk_raw, err := b58.Decode(privk_enc) - if err != nil { panic(err); } + if len(os.Args) != 2 { + println("usage: libp2p-priv-to-pub PRIVKEY_BASE58_STRING") + } + privk_enc := os.Args[1] + privk_raw, err := b58.Decode(privk_enc) + if err != nil { + panic(err) + } - priv, err := crypto.UnmarshalPrivateKey(privk_raw) - if err != nil { panic(err); } + priv, err := crypto.UnmarshalPrivateKey(privk_raw) + if err != nil { + panic(err) + } - pub := priv.GetPublic() + pub := priv.GetPublic() - pubk_raw, err := crypto.MarshalPublicKey(pub) - if err != nil { panic(err); } + pubk_raw, err := crypto.MarshalPublicKey(pub) + if err != nil { + panic(err) + } - pubk_enc := b58.Encode(pubk_raw) + pubk_enc := b58.Encode(pubk_raw) - println(pubk_enc) + println(pubk_enc) } diff --git a/src/generate_methodidx/main.go b/src/generate_methodidx/main.go index 0049115c1..480fa2285 100644 --- a/src/generate_methodidx/main.go +++ b/src/generate_methodidx/main.go @@ -99,7 +99,7 @@ func main() { Command: "generate_methodidx", PackageName: "main", TypesAndValues: map[string][]string{ - "methodIdx": []string{"configure", "listen", "publish", "subscribe", "unsubscribe", "validationComplete", "generateKeypair", "openStream", "closeStream", "resetStream", "sendStreamMsg", "removeStreamHandler", "addStreamHandler", "listeningAddrs", "addPeer", "beginAdvertising"}, + "methodIdx": []string{"configure", "listen", "publish", "subscribe", "unsubscribe", "validationComplete", "generateKeypair", "openStream", "closeStream", "resetStream", "sendStreamMsg", "removeStreamHandler", "addStreamHandler", "listeningAddrs", "addPeer", "beginAdvertising", "findPeer", "listPeers", "banIP", "unbanIP"}, }, } diff --git a/src/go.mod b/src/go.mod index 383bb83eb..754345040 100644 --- a/src/go.mod +++ b/src/go.mod @@ -4,72 +4,59 @@ go 1.12 require ( cloud.google.com/go v0.43.0 // indirect - github.com/Kubuxu/go-os-helper v0.0.1 // indirect - github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8 // indirect github.com/btcsuite/goleveldb v1.0.0 // indirect github.com/campoy/jsonenums v0.0.0-20180221195324-eec6d38da64e github.com/coreos/bbolt v1.3.3 // indirect github.com/coreos/etcd v3.3.13+incompatible // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect github.com/davidlazar/go-crypto v0.0.0-20190522120613-62389b5e4ae0 // indirect - github.com/dgraph-io/badger v1.6.0 // indirect github.com/go-errors/errors v1.0.1 github.com/go-kit/kit v0.9.0 // indirect - github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect github.com/golang/snappy v0.0.1 // indirect github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70 // indirect github.com/grpc-ecosystem/grpc-gateway v1.9.5 // indirect github.com/hashicorp/go-multierror v1.0.0 // indirect - github.com/hashicorp/golang-lru v0.5.3 // indirect - github.com/ipfs/go-cid v0.0.3 // indirect - github.com/ipfs/go-ds-badger v0.0.5 - github.com/ipfs/go-ds-leveldb v0.0.2 // indirect + github.com/ipfs/go-ds-badger v0.0.7 github.com/ipfs/go-ipfs-delay v0.0.1 // indirect github.com/ipfs/go-log v0.0.1 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/kisielk/errcheck v1.2.0 // indirect github.com/kkdai/bstream v1.0.0 // indirect github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/kr/pty v1.1.8 // indirect + github.com/libp2p/go-buffer-pool v0.0.2 github.com/libp2p/go-conn-security v0.1.0 // indirect - github.com/libp2p/go-eventbus v0.0.3 // indirect - github.com/libp2p/go-libp2p v0.2.1 - github.com/libp2p/go-libp2p-circuit v0.1.1 // indirect - github.com/libp2p/go-libp2p-core v0.2.0 + github.com/libp2p/go-libp2p v0.4.2 + github.com/libp2p/go-libp2p-core v0.2.4 github.com/libp2p/go-libp2p-crypto v0.1.0 - github.com/libp2p/go-libp2p-discovery v0.1.0 + github.com/libp2p/go-libp2p-discovery v0.2.0 github.com/libp2p/go-libp2p-host v0.1.0 github.com/libp2p/go-libp2p-interface-connmgr v0.1.0 // indirect github.com/libp2p/go-libp2p-interface-pnet v0.1.0 // indirect - github.com/libp2p/go-libp2p-kad-dht v0.1.1 + github.com/libp2p/go-libp2p-kad-dht v0.3.0 github.com/libp2p/go-libp2p-metrics v0.1.0 // indirect github.com/libp2p/go-libp2p-net v0.1.0 github.com/libp2p/go-libp2p-peer v0.2.0 - github.com/libp2p/go-libp2p-peerstore v0.1.3 + github.com/libp2p/go-libp2p-peerstore v0.1.4 github.com/libp2p/go-libp2p-pnet v0.1.0 github.com/libp2p/go-libp2p-protocol v0.1.0 - github.com/libp2p/go-libp2p-pubsub v0.1.0 + github.com/libp2p/go-libp2p-pubsub v0.2.3 github.com/libp2p/go-libp2p-record v0.1.1 github.com/libp2p/go-libp2p-routing v0.1.0 - github.com/libp2p/go-libp2p-secio v0.1.1 - github.com/libp2p/go-libp2p-testing v0.1.0 // indirect + github.com/libp2p/go-libp2p-secio v0.2.1 github.com/libp2p/go-libp2p-transport v0.1.0 // indirect + github.com/libp2p/go-maddr-filter v0.0.5 github.com/libp2p/go-mplex v0.1.0 github.com/libp2p/go-stream-muxer v0.1.0 - github.com/libp2p/go-tcp-transport v0.1.0 + github.com/libp2p/go-tcp-transport v0.1.1 github.com/libp2p/go-testutil v0.1.0 // indirect - github.com/libp2p/go-ws-transport v0.1.0 + github.com/libp2p/go-ws-transport v0.1.2 github.com/magiconair/properties v1.8.1 // indirect github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e // indirect github.com/mattn/go-colorable v0.1.2 // indirect github.com/miekg/dns v1.1.15 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect github.com/mr-tron/base58 v1.1.2 - github.com/multiformats/go-multiaddr v0.0.4 - github.com/multiformats/go-multiaddr-dns v0.0.3 // indirect + github.com/multiformats/go-multiaddr v0.1.1 github.com/multiformats/go-multicodec v0.1.6 // indirect - github.com/multiformats/go-multihash v0.0.6 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/opentracing/opentracing-go v1.1.0 // indirect github.com/pelletier/go-toml v1.4.0 // indirect @@ -89,13 +76,12 @@ require ( github.com/whyrusleeping/go-smux-yamux v2.0.9+incompatible // indirect github.com/whyrusleeping/yamux v1.2.0 // indirect go.etcd.io/bbolt v1.3.3 // indirect - golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 + golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect golang.org/x/image v0.0.0-20190802002840-cff245a6509b // indirect golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 // indirect golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 // indirect golang.org/x/tools v0.0.0-20190802220118-1d1727260058 // indirect - golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 // indirect google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64 // indirect google.golang.org/grpc v1.22.1 // indirect gopkg.in/src-d/go-cli.v0 v0.0.0-20190422143124-3a646154da79 // indirect diff --git a/src/go.sum b/src/go.sum index 7401d9290..28a3acac8 100644 --- a/src/go.sum +++ b/src/go.sum @@ -7,6 +7,9 @@ github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 h1:PqzgE6kAMi github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9 h1:HD8gA2tkByhMAwYaFAX9w2l7vxvBQ5NMoxDrkhqhtn4= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= +github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Kubuxu/go-os-helper v0.0.1 h1:EJiD2VUQyh5A9hWJLmc6iWg6yIcJ7jpBcwC8GMGXfDk= @@ -30,6 +33,10 @@ github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50 h1:4i3KsuVA0o0KoBxAC github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8 h1:mOg8/RgDSHTQ1R0IR+LMDuW4TDShPv+JzYHuR4GLoNA= github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3 h1:A/EVblehb75cUgXA5njHPn0kLAsykn6mJGz7rnmW5W0= +github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -66,6 +73,8 @@ github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= github.com/davidlazar/go-crypto v0.0.0-20190522120613-62389b5e4ae0 h1:t2BzsfK9SPTlddm0l5PgRQp5fBzByku985NYG1otL/U= github.com/davidlazar/go-crypto v0.0.0-20190522120613-62389b5e4ae0/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= +github.com/davidlazar/go-crypto v0.0.0-20190912175916-7055855a373f h1:BOaYiTvg8p9vBUXpklC22XSK/mifLF7lG9jtmYYi3Tc= +github.com/davidlazar/go-crypto v0.0.0-20190912175916-7055855a373f/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f h1:6itBiEUtu+gOzXZWn46bM5/qm8LlV6/byR7Yflx/y6M= github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= github.com/dgraph-io/badger v1.6.0-rc1 h1:JphPpoBZJ3WHha133BGYlQqltSGIhV+VsEID0++nN9A= @@ -79,6 +88,8 @@ github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f h1:dDxpBYafY/GYpcl github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20191112170834-c2139c5d712b h1:SeiGBzKrEtuDddnBABHkp4kq9sBGE9nuYmk6FPTg0zg= +github.com/dgryski/go-farm v0.0.0-20191112170834-c2139c5d712b/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dgryski/go-sip13 v0.0.0-20190329191031-25c5027a8c7b/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= @@ -98,6 +109,10 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -130,6 +145,8 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= @@ -165,6 +182,13 @@ github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAK github.com/ipfs/go-datastore v0.0.3/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= github.com/ipfs/go-datastore v0.0.5 h1:q3OfiOZV5rlsK1H5V8benjeUApRfMGs4Mrhmr6NriQo= github.com/ipfs/go-datastore v0.0.5/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= +github.com/ipfs/go-datastore v0.1.0 h1:TOxI04l8CmO4zGtesENhzm4PwkFwJXY3rKiYaaMf9fI= +github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= +github.com/ipfs/go-datastore v0.1.1 h1:F4k0TkTAZGLFzBOrVKDAvch6JZtuN4NHkfdcEZL50aI= +github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= +github.com/ipfs/go-datastore v0.3.0/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= +github.com/ipfs/go-datastore v0.3.1 h1:SS1t869a6cctoSYmZXUk8eL6AzVXgASmKIWFNQkQ1jU= +github.com/ipfs/go-datastore v0.3.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= github.com/ipfs/go-ds-badger v0.0.2 h1:7ToQt7QByBhOTuZF2USMv+PGlMcBC7FW7FdgQ4FCsoo= @@ -173,21 +197,32 @@ github.com/ipfs/go-ds-badger v0.0.3 h1:sVYE2YlCzltznTZeAP1S+bp3qipz7VzogfZDtf6tG github.com/ipfs/go-ds-badger v0.0.3/go.mod h1:7AzMKCsGav0u46HpdLiAEAOqizR1H6AZsjpHpQSPYCQ= github.com/ipfs/go-ds-badger v0.0.5 h1:dxKuqw5T1Jm8OuV+lchA76H9QZFyPKZeLuT6bN42hJQ= github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= +github.com/ipfs/go-ds-badger v0.0.7 h1:NMyh88Q50HG6/S2YD58DLkq0c0/ZQPMbSojONH+PRf4= +github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= +github.com/ipfs/go-ds-badger v0.2.0 h1:3h0U3L4o0v7LT2qyK5GScXH23DoYxat+VU2a4Ldt8yo= +github.com/ipfs/go-ds-badger v0.2.0/go.mod h1:471n2X/Qtk8rRO1iuxcgdwmHJdWjDj9VRGhaP/tvoZw= github.com/ipfs/go-ds-leveldb v0.0.1 h1:Z0lsTFciec9qYsyngAw1f/czhRU35qBLR2vhavPFgqA= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ds-leveldb v0.0.2/go.mod h1:CWFeBh5IAAscWyG/QRH+lJaAlnLWjsfPSNs4teyPUp0= +github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50= github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= +github.com/ipfs/go-log v1.0.0 h1:BW3LQIiZzpNyolt84yvKNCd3FU+AK4VDw1hnHR+1aiI= +github.com/ipfs/go-log v1.0.0/go.mod h1:JO7RzlMK6rA+CIxFMLOuB6Wf5b81GDiKElL7UPSIKjA= github.com/ipfs/go-todocounter v0.0.1 h1:kITWA5ZcQZfrUnDNkRn04Xzh0YFaDFXsoO2A81Eb6Lw= github.com/ipfs/go-todocounter v0.0.1/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= +github.com/ipfs/go-todocounter v0.0.2 h1:9UBngSQhylg2UDcxSAtpkT+rEWFr26hDPXVStE8LFyc= +github.com/ipfs/go-todocounter v0.0.2/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA= github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec h1:DQqZhhDvrTrEQ3Qod5yfavcA064e53xlQ+xajiorXgM= github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= @@ -217,6 +252,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b h1:wxtKgYHEncAU00muMD06dzLiahtGM1eouRNOzVV7tdQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= +github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d h1:68u9r4wEvL3gYg2jvAOgROwZ3H+Y3hIDk4tbbmIjcYQ= +github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -233,6 +270,7 @@ github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOS github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/libp2p/go-conn-security v0.0.1 h1:4kMMrqrt9EUNCNjX1xagSJC+bq16uqjMe9lk1KBMVNs= github.com/libp2p/go-conn-security v0.0.1/go.mod h1:bGmu51N0KU9IEjX7kl2PQjgZa40JQWnayTvNMgD/vyk= +github.com/libp2p/go-conn-security v0.1.0 h1:q8ii9TUOtSBD1gIoKTSOZIzPFP/agPM28amrCCoeIIA= github.com/libp2p/go-conn-security v0.1.0/go.mod h1:NQdPF4opCZ5twtEUadzPL0tNSdkrbFc/HmLO7eWqEzY= github.com/libp2p/go-conn-security-multistream v0.0.1 h1:XefjAQRHcnUaxKb26RGupToucx3uU4ecbOZ3aACXlDU= github.com/libp2p/go-conn-security-multistream v0.0.1/go.mod h1:nc9vud7inQ+d6SO0I/6dSWrdMnHnzZNHeyUQqrAJulE= @@ -241,8 +279,14 @@ github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2h github.com/libp2p/go-eventbus v0.0.2/go.mod h1:Hr/yGlwxA/stuLnpMiu82lpNKpvRy3EaJxPu40XYOwk= github.com/libp2p/go-eventbus v0.0.3 h1:4sB0NrwnWr6qGeq2RWUp/JG1wNajf6gyILInId72hrw= github.com/libp2p/go-eventbus v0.0.3/go.mod h1:Hr/yGlwxA/stuLnpMiu82lpNKpvRy3EaJxPu40XYOwk= +github.com/libp2p/go-eventbus v0.1.0 h1:mlawomSAjjkk97QnYiEmHsLu7E136+2oCWSHRUvMfzQ= +github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= +github.com/libp2p/go-flow-metrics v0.0.2 h1:U5TvqfoyR6GVRM+bC15Ux1ltar1kbj6Zw6xOVR02CZs= +github.com/libp2p/go-flow-metrics v0.0.2/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= +github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM= +github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= github.com/libp2p/go-libp2p v0.0.12/go.mod h1:l8kmLMc4DToz2TtA0aWEaE4/jVMALRKw8Kv2WTR0LHc= github.com/libp2p/go-libp2p v0.0.13 h1:F8EJzBX3eipwW1yrvlmpkpc3jh5YpGwZiG7zVAt8mjM= github.com/libp2p/go-libp2p v0.0.13/go.mod h1:99u6nHehR0M9pxJM682dq44GDdowQBcQPxXNTPGoEgU= @@ -251,20 +295,31 @@ github.com/libp2p/go-libp2p v0.1.1 h1:52sB0TJuDk2nYMcMfHOKaPoaayDZjaYVCq6Vk1ejUT github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8= github.com/libp2p/go-libp2p v0.2.1 h1:Z6po5cdEj+SvSppsPxeZIlKVVl0REA915fEa4YlcBNM= github.com/libp2p/go-libp2p v0.2.1/go.mod h1:HZbtEOrgZN4F1fGZVvkV+930Wx3DkqlpBlO8dIoZWds= +github.com/libp2p/go-libp2p v0.3.1 h1:opd8/1Sm9zFG37LzNQsIzMTMeBabhlcX5VlvLrNZPV0= +github.com/libp2p/go-libp2p v0.3.1/go.mod h1:e6bwxbdYH1HqWTz8faTChKGR0BjPc8p+6SyP8GTTR7Y= +github.com/libp2p/go-libp2p v0.4.2 h1:p0cthB0jDNHO4gH2HzS8/nAMMXbfUlFHs0jwZ4U+F2g= +github.com/libp2p/go-libp2p v0.4.2/go.mod h1:MNmgUxUw5pMsdOzMlT0EE7oKjRasl+WyVwM0IBlpKgQ= +github.com/libp2p/go-libp2p v6.0.23+incompatible h1:J/h9LNTeQwMhJeg3M96r/UOPLGxJn1vqJBb3LeKufpM= +github.com/libp2p/go-libp2p v6.0.23+incompatible/go.mod h1:CyUlFa6Mw04PkmMg8gBIlHUl8j3TrEiA6oFiF4SgD8w= github.com/libp2p/go-libp2p-autonat v0.0.4 h1:cZzdB9KW1ZkHnSjLCB6aFNw47XS4r+SecCVMuVB1xgo= github.com/libp2p/go-libp2p-autonat v0.0.4/go.mod h1:fs71q5Xk+pdnKU014o2iq1RhMs9/PMaG5zXRFNnIIT4= github.com/libp2p/go-libp2p-autonat v0.1.0 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= +github.com/libp2p/go-libp2p-autonat v0.1.1 h1:WLBZcIRsjZlWdAZj9CiBSvU2wQXoUOiS1Zk1tM7DTJI= +github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE= github.com/libp2p/go-libp2p-blankhost v0.0.1 h1:/mZuuiwntNR8RywnCFlGHLKrKLYne+qciBpQXWqp5fk= github.com/libp2p/go-libp2p-blankhost v0.0.1/go.mod h1:Ibpbw/7cPPYwFb7PACIWdvxxv0t0XCCI10t7czjAjTc= github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= github.com/libp2p/go-libp2p-blankhost v0.1.3/go.mod h1:KML1//wiKR8vuuJO0y3LUd1uLv+tlkGTAr3jC0S5cLg= +github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU= github.com/libp2p/go-libp2p-circuit v0.0.4 h1:yOgEadnSVFj3e9KLBuLG+edqCImeav0VXxXvcimpOUQ= github.com/libp2p/go-libp2p-circuit v0.0.4/go.mod h1:p1cHJnB9xnX5/1vZLkXgKwmNEOQQuF/Hp+SkATXnXYk= github.com/libp2p/go-libp2p-circuit v0.1.0 h1:eniLL3Y9aq/sryfyV1IAHj5rlvuyj3b7iz8tSiZpdhY= github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= github.com/libp2p/go-libp2p-circuit v0.1.1 h1:eopfG9fAg6rEHWQO1TSrLosXDgYbbbu/RTva/tBANus= github.com/libp2p/go-libp2p-circuit v0.1.1/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= +github.com/libp2p/go-libp2p-circuit v0.1.4 h1:Phzbmrg3BkVzbqd4ZZ149JxCuUWu2wZcXf/Kr6hZJj8= +github.com/libp2p/go-libp2p-circuit v0.1.4/go.mod h1:CY67BrEjKNDhdTk8UgBX1Y/H5c3xkAcs3gnksxY7osU= github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= github.com/libp2p/go-libp2p-core v0.0.3 h1:+IonUYY0nJZLb5Fdv6a6DOjtGP1L8Bb3faamiI2q5FY= github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE= @@ -272,6 +327,12 @@ github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7O github.com/libp2p/go-libp2p-core v0.0.6/go.mod h1:0d9xmaYAVY5qmbp/fcgxHT3ZJsLjYeYPMJAUKpaCHrE= github.com/libp2p/go-libp2p-core v0.2.0 h1:ycFtuNwtZBAJSxzaHbyv6NjG3Yj5Nmra1csHaQ3zwaw= github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.2.2 h1:Sv1ggdoMx9c7v7FOFkR7agraHCnAgqYsXrU1ARSRUMs= +github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= +github.com/libp2p/go-libp2p-core v0.2.4 h1:Et6ykkTwI6PU44tr8qUF9k43vP0aduMNniShAbUJJw8= +github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g= +github.com/libp2p/go-libp2p-core v0.2.5 h1:iP1PIiIrlRrGbE1fYq2918yBc5NlCH3pFuIPSWU9hds= +github.com/libp2p/go-libp2p-core v0.2.5/go.mod h1:6+5zJmKhsf7yHn1RbmYDu08qDUpIUxGdqHuEZckmZOA= github.com/libp2p/go-libp2p-crypto v0.0.1 h1:JNQd8CmoGTohO/akqrH16ewsqZpci2CbgYH/LmYl8gw= github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE= github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= @@ -280,14 +341,19 @@ github.com/libp2p/go-libp2p-discovery v0.0.1 h1:VkjCKmJQMwpDUwtA8Qc1z3TQAHJgQ5nG github.com/libp2p/go-libp2p-discovery v0.0.1/go.mod h1:ZkkF9xIFRLA1xCc7bstYFkd80gBGK8Fc1JqGoU2i+zI= github.com/libp2p/go-libp2p-discovery v0.1.0 h1:j+R6cokKcGbnZLf4kcNwpx6mDEUPF3N6SrqMymQhmvs= github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g= +github.com/libp2p/go-libp2p-discovery v0.2.0 h1:1p3YSOq7VsgaL+xVHPi8XAmtGyas6D2J6rWBEfz/aiY= +github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg= github.com/libp2p/go-libp2p-host v0.0.1 h1:dnqusU+DheGcdxrE718kG4XgHNuL2n9eEv8Rg5zy8hQ= github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= +github.com/libp2p/go-libp2p-host v0.1.0 h1:OZwENiFm6JOK3YR5PZJxkXlJE8a5u8g4YvAUrEV2MjM= github.com/libp2p/go-libp2p-host v0.1.0/go.mod h1:5+fWuLbDn8OxoxPN3CV0vsLe1hAKScSMbT84qRfxum8= github.com/libp2p/go-libp2p-interface-connmgr v0.0.1 h1:Q9EkNSLAOF+u90L88qmE9z/fTdjLh8OsJwGw74mkwk4= github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= +github.com/libp2p/go-libp2p-interface-connmgr v0.1.0 h1:dFYeUNi5NjKIAVE+yQJULS99CovMUx9p/IgxI+2e+uc= github.com/libp2p/go-libp2p-interface-connmgr v0.1.0/go.mod h1:bmmppYG/Bc6FTdLYEdpuSfifDa5Nr+5Ia1Mm6lE2+Eg= github.com/libp2p/go-libp2p-interface-pnet v0.0.1 h1:7GnzRrBTJHEsofi1ahFdPN9Si6skwXQE9UqR2S+Pkh8= github.com/libp2p/go-libp2p-interface-pnet v0.0.1/go.mod h1:el9jHpQAXK5dnTpKA4yfCNBZXvrzdOU75zz+C6ryp3k= +github.com/libp2p/go-libp2p-interface-pnet v0.1.0 h1:PaofJtuDcrGBukgTymiGyuI313nxARRQFmE/oxZXlog= github.com/libp2p/go-libp2p-interface-pnet v0.1.0/go.mod h1:8+FQ08+xMxR6BjG0tUZoQzKxPAV2W7ck6IxjCWqZ6ek= github.com/libp2p/go-libp2p-kad-dht v0.0.8 h1:oUnAqkCAWYvAoF5TmnDIf4k1fIcipMAFec6sQlTXGKE= github.com/libp2p/go-libp2p-kad-dht v0.0.8/go.mod h1:fGQfSQWWOxQFB97kETE09lYRLPRKaZZdguIq98fE5PI= @@ -295,25 +361,35 @@ github.com/libp2p/go-libp2p-kad-dht v0.1.0 h1:cupGornmncdQCnjArAv9Txkqy43wgQCxoe github.com/libp2p/go-libp2p-kad-dht v0.1.0/go.mod h1:EiH74cOsCxcu2Yh1XxQMpf1uHcLNm/hYEJBOIRlzHNE= github.com/libp2p/go-libp2p-kad-dht v0.1.1 h1:IH6NQuoUv5w5e1O8Jc3KyVDtr0rNd0G9aaADpLI1xVo= github.com/libp2p/go-libp2p-kad-dht v0.1.1/go.mod h1:1kj2Rk5pX3/0RwqMm9AMNCT7DzcMHYhgDN5VTi+cY0M= +github.com/libp2p/go-libp2p-kad-dht v0.3.0 h1:KUJaqW3kkHP6zcL0s1CDg+yO0NYNNPkXmG4FrnZbwzM= +github.com/libp2p/go-libp2p-kad-dht v0.3.0/go.mod h1:7nBsfkMq2zN1qPs6n/fNopJfvmK9NZRNicRrCnwQR8o= +github.com/libp2p/go-libp2p-kad-dht v0.3.1 h1:Ogu9ZFXX/VJfcaZklBIsS2HV+lfMrYy9mHvYfoADpj4= +github.com/libp2p/go-libp2p-kad-dht v0.3.1/go.mod h1:xPb9+X4cU5TchWtgfuJ73hyMZZ/MRt3E+PrA1Dap/ow= github.com/libp2p/go-libp2p-kbucket v0.0.1 h1:7H5hM851hkEpLOFjrVNSrrxo6J4bWrUQxxv+z1JW9xk= github.com/libp2p/go-libp2p-kbucket v0.0.1/go.mod h1:Y0iQDHRTk/ZgM8PC4jExoF+E4j+yXWwRkdldkMa5Xm4= github.com/libp2p/go-libp2p-kbucket v0.2.0 h1:FB2a0VkOTNGTP5gu/I444u4WabNM9V1zCkQcWb7zajI= github.com/libp2p/go-libp2p-kbucket v0.2.0/go.mod h1:JNymBToym3QXKBMKGy3m29+xprg0EVr/GJFHxFEdgh8= +github.com/libp2p/go-libp2p-kbucket v0.2.1 h1:q9Jfwww9XnXc1K9dyYuARJxJvIvhgYVaQCuziO/dF3c= +github.com/libp2p/go-libp2p-kbucket v0.2.1/go.mod h1:/Rtu8tqbJ4WQ2KTCOMJhggMukOLNLNPY1EtEWWLxUvc= github.com/libp2p/go-libp2p-loggables v0.0.1 h1:HVww9oAnINIxbt69LJNkxD8lnbfgteXR97Xm4p3l9ps= github.com/libp2p/go-libp2p-loggables v0.0.1/go.mod h1:lDipDlBNYbpyqyPX/KcoO+eq0sJYEVR2JgOexcivchg= github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8= github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= github.com/libp2p/go-libp2p-metrics v0.0.1 h1:yumdPC/P2VzINdmcKZd0pciSUCpou+s0lwYCjBbzQZU= github.com/libp2p/go-libp2p-metrics v0.0.1/go.mod h1:jQJ95SXXA/K1VZi13h52WZMa9ja78zjyy5rspMsC/08= +github.com/libp2p/go-libp2p-metrics v0.1.0 h1:v7YMUTHNobFaQeqaMfJJMbnK3EPlZeb6/KFm4gE9dks= github.com/libp2p/go-libp2p-metrics v0.1.0/go.mod h1:rpoJmXWFxnj7qs5sJ02sxSzrhaZvpqBn8GCG6Sx6E1k= github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo= github.com/libp2p/go-libp2p-mplex v0.2.1 h1:E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8iGvirYI= github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= github.com/libp2p/go-libp2p-nat v0.0.4 h1:+KXK324yaY701On8a0aGjTnw8467kW3ExKcqW2wwmyw= github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= +github.com/libp2p/go-libp2p-nat v0.0.5 h1:/mH8pXFVKleflDL1YwqMg27W9GD8kjEx7NY0P6eGc98= +github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE= github.com/libp2p/go-libp2p-net v0.0.1/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= github.com/libp2p/go-libp2p-net v0.0.2 h1:qP06u4TYXfl7uW/hzqPhlVVTSA2nw1B/bHBJaUnbh6M= github.com/libp2p/go-libp2p-net v0.0.2/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= +github.com/libp2p/go-libp2p-net v0.1.0 h1:3t23V5cR4GXcNoFriNoZKFdUZEUDZgUkvfwkD2INvQE= github.com/libp2p/go-libp2p-net v0.1.0/go.mod h1:R5VZbutk75tkC5YJJS61OCO1NWoajxYjCEV2RoHh3FY= github.com/libp2p/go-libp2p-netutil v0.0.1 h1:LgD6+skofkOx8z6odD9+MZHKjupv3ng1u6KRhaADTnA= github.com/libp2p/go-libp2p-netutil v0.0.1/go.mod h1:GdusFvujWZI9Vt0X5BKqwWWmZFxecf9Gt03cKxm2f/Q= @@ -330,23 +406,32 @@ github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HB github.com/libp2p/go-libp2p-peerstore v0.1.2/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= github.com/libp2p/go-libp2p-peerstore v0.1.3 h1:wMgajt1uM2tMiqf4M+4qWKVyyFc8SfA+84VV9glZq1M= github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= +github.com/libp2p/go-libp2p-peerstore v0.1.4 h1:d23fvq5oYMJ/lkkbO4oTwBp/JP+I/1m5gZJobNXCE/k= +github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs= github.com/libp2p/go-libp2p-pnet v0.0.1 h1:2e5d15M8XplUKsU4Fqrll5eDfqGg/7mHUufLkhbfKHM= github.com/libp2p/go-libp2p-pnet v0.0.1/go.mod h1:bWN8HqdpgCdKnXSCsJhbWjiU3UZFa/tIe4no5jCmHVw= github.com/libp2p/go-libp2p-pnet v0.1.0 h1:kRUES28dktfnHNIRW4Ro78F7rKBHBiw5MJpl0ikrLIA= github.com/libp2p/go-libp2p-pnet v0.1.0/go.mod h1:ZkyZw3d0ZFOex71halXRihWf9WH/j3OevcJdTmD0lyE= github.com/libp2p/go-libp2p-protocol v0.0.1 h1:+zkEmZ2yFDi5adpVE3t9dqh/N9TbpFWywowzeEzBbLM= github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= +github.com/libp2p/go-libp2p-protocol v0.1.0 h1:HdqhEyhg0ToCaxgMhnOmUO8snQtt/kQlcjVk3UoJU3c= github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= github.com/libp2p/go-libp2p-pubsub v0.0.1 h1:iJWpvBDZiZOoRBGqEifu9yUHti9ptnSODHt6tgrBC6c= github.com/libp2p/go-libp2p-pubsub v0.0.1/go.mod h1:fYKlZBOF2yrJzYlgeEVFSbYWfbS+E8Zix6gMZ0A6WgE= github.com/libp2p/go-libp2p-pubsub v0.1.0 h1:SmQeMa7IUv5vadh0fYgYsafWCBA1sCy5d/68kIYqGcU= github.com/libp2p/go-libp2p-pubsub v0.1.0/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q= +github.com/libp2p/go-libp2p-pubsub v0.2.3 h1:qJRnRnM7Z4xnHb4i6EBb3DKQXRPgtFWlKP4AmfJudLQ= +github.com/libp2p/go-libp2p-pubsub v0.2.3/go.mod h1:Jscj3fk23R5mCrOwb625xjVs5ZEyTZcx/OlTwMDqU+g= +github.com/libp2p/go-libp2p-pubsub v0.2.4 h1:O4BcaKpPQ9p82yTBtzIzgDFoOXkqhrQpfcVac3FAywU= +github.com/libp2p/go-libp2p-pubsub v0.2.4/go.mod h1:1tJwAfySvZQ49R9uTVlkwtSTMVLeQQdrnLTJrr91gVc= github.com/libp2p/go-libp2p-record v0.0.1 h1:zN7AS3X46qmwsw5JLxdDuI43cH5UYwovKxHPjKBYQxw= github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q= github.com/libp2p/go-libp2p-record v0.1.0 h1:wHwBGbFzymoIl69BpgwIu0O6ta3TXGcMPvHUAcodzRc= github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q= github.com/libp2p/go-libp2p-record v0.1.1 h1:ZJK2bHXYUBqObHX+rHLSNrM3M8fmJUlUHrodDPPATmY= github.com/libp2p/go-libp2p-record v0.1.1/go.mod h1:VRgKajOyMVgP/F0L5g3kH7SVskp17vFi2xheb5uMJtg= +github.com/libp2p/go-libp2p-record v0.1.2 h1:M50VKzWnmUrk/M5/Dz99qO9Xh4vs8ijsK+7HkJvRP+0= +github.com/libp2p/go-libp2p-record v0.1.2/go.mod h1:pal0eNcT5nqZaTV7UGhqeGqxFgGdsU/9W//C8dqjQDk= github.com/libp2p/go-libp2p-routing v0.0.1 h1:hPMAWktf9rYi3ME4MG48qE7dq1ofJxiQbfdvpNntjhc= github.com/libp2p/go-libp2p-routing v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys= github.com/libp2p/go-libp2p-routing v0.1.0 h1:hFnj3WR3E2tOcKaGpyzfP4gvFZ3t8JkQmbapN0Ct+oU= @@ -357,6 +442,10 @@ github.com/libp2p/go-libp2p-secio v0.1.0 h1:NNP5KLxuP97sE5Bu3iuwOWyT/dKEGMN5zSLM github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= github.com/libp2p/go-libp2p-secio v0.1.1 h1:NQ9nTGmyf7/pgiVdThRrZylPsOQObVMyhT1XG9sEyOQ= github.com/libp2p/go-libp2p-secio v0.1.1/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= +github.com/libp2p/go-libp2p-secio v0.2.0 h1:ywzZBsWEEz2KNTn5RtzauEDq5RFEefPsttXYwAWqHng= +github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= +github.com/libp2p/go-libp2p-secio v0.2.1 h1:eNWbJTdyPA7NxhP7J3c5lT97DC5d+u+IldkgCYFTPVA= +github.com/libp2p/go-libp2p-secio v0.2.1/go.mod h1:cWtZpILJqkqrSkiYcDBh5lA3wbT2Q+hz3rJQq3iftD8= github.com/libp2p/go-libp2p-swarm v0.0.1/go.mod h1:mh+KZxkbd3lQnveQ3j2q60BM1Cw2mX36XXQqwfPOShs= github.com/libp2p/go-libp2p-swarm v0.0.2 h1:cpHHXTeU2IgUu8LPemF7vaLPGtVC6VxMoll2EwqlC+E= github.com/libp2p/go-libp2p-swarm v0.0.2/go.mod h1:n0cAAcKyndIrJWctQwjqXlAdIPBZzfdpBjx1SSvz30g= @@ -364,14 +453,20 @@ github.com/libp2p/go-libp2p-swarm v0.1.0 h1:HrFk2p0awrGEgch9JXK/qp/hfjqQfgNxpLWn github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= github.com/libp2p/go-libp2p-swarm v0.1.1 h1:QW7pjyTRIxt9yyBid52YmMRGtkFXUE/rbEVWsQ0ae+w= github.com/libp2p/go-libp2p-swarm v0.1.1/go.mod h1:4NVJaLwq/dr5kEq79Jo6pMin7ZFwLx73ln1FTefR91Q= +github.com/libp2p/go-libp2p-swarm v0.2.1 h1:9A8oQqPIZvbaRyrjViHeDYS7fE7fNtP7BRWdJrBHbe8= +github.com/libp2p/go-libp2p-swarm v0.2.1/go.mod h1:x07b4zkMFo2EvgPV2bMTlNmdQc8i+74Jjio7xGvsTgU= +github.com/libp2p/go-libp2p-swarm v0.2.2 h1:T4hUpgEs2r371PweU3DuH7EOmBIdTBCwWs+FLcgx3bQ= +github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU= github.com/libp2p/go-libp2p-testing v0.0.1/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= +github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= github.com/libp2p/go-libp2p-transport v0.0.1/go.mod h1:UzbUs9X+PHOSw7S3ZmeOxfnwaQY5vGDzZmKPod3N3tk= github.com/libp2p/go-libp2p-transport v0.0.4 h1:/CPHQMN75/IQwkhBxxIo6p6PtL3rwFZtlzBROT3e8mw= github.com/libp2p/go-libp2p-transport v0.0.4/go.mod h1:StoY3sx6IqsP6XKoabsPnHCwqKXWUMWU7Rfcsubee/A= +github.com/libp2p/go-libp2p-transport v0.1.0 h1:q68SOTvX+71mk+n5eE3+FnUEPY5UL1CSFImH0bq0Vg8= github.com/libp2p/go-libp2p-transport v0.1.0/go.mod h1:iL3c2tV3OVldqSwJrds8pmIWf4t/TwiF+eI/mhw/jjQ= github.com/libp2p/go-libp2p-transport-upgrader v0.0.1 h1:rNtXkY6dty46mxYOHHAZQchI7gQdJStF683FhVnei/k= github.com/libp2p/go-libp2p-transport-upgrader v0.0.1/go.mod h1:NJpUAgQab/8K6K0m+JmZCe5RUXG10UMEx4kWe9Ipj5c= @@ -400,6 +495,12 @@ github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-nat v0.0.3 h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI= github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI= +github.com/libp2p/go-nat v0.0.4 h1:KbizNnq8YIf7+Hn7+VFL/xE0eDrkPru2zIO9NMwL8UQ= +github.com/libp2p/go-nat v0.0.4/go.mod h1:Nmw50VAvKuk38jUBcmNh6p9lUJLoODbJRvYAa/+KSDo= +github.com/libp2p/go-openssl v0.0.2 h1:9pP2d3Ubaxkv7ZisLjx9BFwgOGnQdQYnfcH29HNY3ls= +github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= +github.com/libp2p/go-openssl v0.0.3 h1:wjlG7HvQkt4Fq4cfH33Ivpwp0omaElYEi9z26qaIkIk= +github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw= github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= github.com/libp2p/go-reuseport-transport v0.0.1/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= @@ -416,6 +517,8 @@ github.com/libp2p/go-tcp-transport v0.0.2 h1:EzOSRaHpyrGpJ5qe+9SaxJM1mrWlkSLFfNT github.com/libp2p/go-tcp-transport v0.0.2/go.mod h1:VjZFHasNJ0QiJQNNwiFDy25qyGWTXQWs8GM5DR4/L1k= github.com/libp2p/go-tcp-transport v0.1.0 h1:IGhowvEqyMFknOar4FWCKSWE0zL36UFKQtiRQD60/8o= github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= +github.com/libp2p/go-tcp-transport v0.1.1 h1:yGlqURmqgNA2fvzjSgZNlHcsd/IulAnKM8Ncu+vlqnw= +github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= github.com/libp2p/go-testutil v0.0.1 h1:Xg+O0G2HIMfHqBOBDcMS1iSZJ3GEcId4qOxCQvsGZHk= github.com/libp2p/go-testutil v0.0.1/go.mod h1:iAcJc/DKJQanJ5ws2V+u5ywdL2n12X1WbbEG+Jjy69I= github.com/libp2p/go-testutil v0.1.0/go.mod h1:81b2n5HypcVyrCg/MJx4Wgfp/VHojytjVe/gLzZ2Ehc= @@ -423,9 +526,12 @@ github.com/libp2p/go-ws-transport v0.0.2 h1:PtK1AoM16nm96FwPBQoq+4T4t9LdDwOhkB+m github.com/libp2p/go-ws-transport v0.0.2/go.mod h1:p3bKjDWHEgtuKKj+2OdPYs5dAPIjtpQGHF2tJfGz7Ww= github.com/libp2p/go-ws-transport v0.1.0 h1:F+0OvvdmPTDsVc4AjPHjV7L7Pk1B7D5QwtDcKE2oag4= github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo= +github.com/libp2p/go-ws-transport v0.1.2 h1:VnxQcLfSGtqupqPpBNu8fUiCv+IN1RJ2BcVqQEM+z8E= +github.com/libp2p/go-ws-transport v0.1.2/go.mod h1:dsh2Ld8F+XNmzpkaAijmg5Is+e9l6/1tK/6VFOdN69Y= github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.2.3 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI= github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/libp2p/go-yamux v1.2.4/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -435,11 +541,13 @@ github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0X github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/miekg/dns v1.1.4 h1:rCMZsU2ScVSYcAsOXgmC6+AKOK+6pmQTOcw03nfwYV0= @@ -449,6 +557,8 @@ github.com/miekg/dns v1.1.14 h1:wkQWn9wIp4mZbwW8XV6Km6owkvRPbOiV004ZM2CkGvA= github.com/miekg/dns v1.1.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.15 h1:CSSIDtllwGLMoA6zjdKnaE6Tx6eVUxQ29LUgGetiDCI= github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.22 h1:Jm64b3bO9kP43ddLjL2EY3Io6bmy1qGb9Xxz6TqS6rc= +github.com/miekg/dns v1.1.22/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ= @@ -456,6 +566,9 @@ github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+ github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.1.0 h1:U41/2erhAKcmSI14xh/ZTUdBPOzDOIfS93ibzUSl8KM= github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -467,6 +580,8 @@ github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVq github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc= +github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= github.com/multiformats/go-multiaddr v0.0.1 h1:/QUV3VBMDI6pi6xfiw7lr6xhDWWvQKn9udPn68kLSdY= @@ -475,15 +590,28 @@ github.com/multiformats/go-multiaddr v0.0.2 h1:RBysRCv5rv3FWlhKWKoXv8tnsCUpEpIZp github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4= github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1 h1:rVAztJYMhCQ7vEFr8FvxW3mS+HF2eY/oPbOMeS0ZDnE= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.1.2 h1:HWYHNSyyllbQopmVIF5K7JKJugiah+L9/kuZKHbmNdQ= +github.com/multiformats/go-multiaddr v0.1.2/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.3 h1:P19q/k9jwmtgh+qXFkKfgFM7rCg/9l5AVqh7VNxSXhs= github.com/multiformats/go-multiaddr-dns v0.0.3/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= +github.com/multiformats/go-multiaddr-dns v0.2.0 h1:YWJoIDwLePniH7OU5hBnDZV6SWuvJqJ0YtN6pLeH9zA= +github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= github.com/multiformats/go-multiaddr-fmt v0.0.1 h1:5YjeOIzbX8OTKVaN72aOzGIYW7PnrZrnkDyOfAWRSMA= github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= +github.com/multiformats/go-multiaddr-net v0.1.0 h1:ZepO8Ezwovd+7b5XPPDhQhayk1yt0AJpzQBpq9fejx4= +github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= +github.com/multiformats/go-multiaddr-net v0.1.1 h1:jFFKUuXTXv+3ARyHZi3XUqQO+YWMKgBdhEvuGRfnL6s= +github.com/multiformats/go-multiaddr-net v0.1.1/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multicodec v0.1.6 h1:4u6lcjbE4VVVoigU4QJSSVYsGVP4j2jtDkR8lPwOrLE= @@ -494,10 +622,17 @@ github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= github.com/multiformats/go-multihash v0.0.6 h1:cAVKO4epVd+SSpYJQD6d3vbdqQJvsrtGbTGzsp+V094= github.com/multiformats/go-multihash v0.0.6/go.mod h1:XuKXPp8VHcTygube3OWZC+aZrA+H1IhmjoCDtJc7PXM= +github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.9/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.10 h1:lMoNbh2Ssd9PUF74Nz008KGzGPlfeV6wH3rit5IIGCM= +github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multistream v0.0.1 h1:JV4VfSdY9n7ECTtY59/TlSyFCzRILvYx4T4Ws8ZgihU= github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= +github.com/multiformats/go-varint v0.0.1 h1:TR/0rdQtnNxuN2IhiB639xC3tWM4IUi7DkTBVTdGW/M= +github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -546,6 +681,7 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= @@ -566,6 +702,7 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -581,6 +718,7 @@ github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdz github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= +github.com/whyrusleeping/go-logging v0.0.1/go.mod h1:lDPYj54zutzG1XYfHAhcc7oNXEburHQBn+Iqd4yS4vE= github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f h1:M/lL30eFZTKnomXY6huvM6G0+gVquFNf6mxghaWlFUg= github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8= github.com/whyrusleeping/go-smux-multiplex v3.0.16+incompatible h1:iqksILj8STw03EJQe7Laj4ubnw+ojOyik18cd5vPL1o= @@ -594,12 +732,15 @@ github.com/whyrusleeping/mafmt v1.2.8 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg5 github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30 h1:nMCC9Pwz1pxfC1Y6mYncdk+kq8d5aLx0Q+/gyZGE44M= github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9 h1:Y1/FEOpaCpD21WxrmfeIYCFPuVPRCY2XZTWzTNHGw30= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg= github.com/whyrusleeping/yamux v1.1.5 h1:4CK3aUUJQu0qpKZv5gEWJjNOQtdbdDhVVS6PJ+HimdE= github.com/whyrusleeping/yamux v1.1.5/go.mod h1:E8LnQQ8HKx5KD29HZFUwM1PxCOdPRzGwur1mcYhXcD8= +github.com/whyrusleeping/yamux v1.2.0 h1:PzUrk7/Z0g/N5V4/+DesmKXYcCToALgj+SbATgs0B34= github.com/whyrusleeping/yamux v1.2.0/go.mod h1:Cgw3gpb4DrDZ1FrP/5pxg/cpiY54Gr5uCXwUylwi2GE= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -609,9 +750,26 @@ go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.1 h1:8dP3SGL7MPB94crU3bEPplMPe83FI4EouesJUeFHv50= +go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= +go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.5.1 h1:rsqfU5vBkVknbhUGbAUwQKR2H4ItV8tjJ+6kJX4cxHM= +go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E= +go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -631,6 +789,11 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd h1:GGJVjV8waZKRHrgwvtH66z9ZGVurTD1MT0n1Bb+q4aM= +golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -643,6 +806,10 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190607214518-6fa95d984e88/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -672,6 +839,9 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191204025024-5ee1b9f4859a h1:+HHJiFUXVOIS9mr1ThqkQD1N8vpFCfCShqADBM12KTc= +golang.org/x/net v0.0.0-20191204025024-5ee1b9f4859a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -705,6 +875,12 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e h1:9vRrk9YW2BTzLP0VCB9ZDjU4cPqkg+IDWL7XgxA1yxQ= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -730,13 +906,24 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190610181509-5ae6a9745e44/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190802220118-1d1727260058 h1:OsDcfiJHbqcv+S4eovUaiPY2ILzR76hXrjILS4sV4Wg= golang.org/x/tools v0.0.0-20190802220118-1d1727260058/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191205225056-3393d29bb9fe h1:BEVcKURC7E0EF+vD1l52Jb3LOM5Iwu7OI5FpdPuU50o= +golang.org/x/tools v0.0.0-20191205225056-3393d29bb9fe/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3 h1:P6iTFmrTQqWrqLZPX1VMzCUbCRCAUXSUsSpkEOvWzJ0= golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522 h1:bhOzK9QyoD0ogCnFro1m2mz41+Ib0oOhfJnBp5MR4K4= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -783,4 +970,6 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190607181801-497c8f037f5a/go.mod h1:JlmFZigtG9vBVR3QGIQ9g/Usz4BzH+Xm6Z8iHQWRYUw= honnef.co/go/tools v0.0.1-2019.2.2/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/src/libp2p_helper/main.go b/src/libp2p_helper/main.go index 50848bd83..ff915d226 100644 --- a/src/libp2p_helper/main.go +++ b/src/libp2p_helper/main.go @@ -9,12 +9,17 @@ import ( "fmt" "io" "log" + gonet "net" "os" + "runtime/debug" + "strconv" "sync" "time" mdns "github.com/libp2p/go-libp2p/p2p/discovery" + "encoding/base64" + "github.com/go-errors/errors" logging "github.com/ipfs/go-log" logwriter "github.com/ipfs/go-log/writer" @@ -25,7 +30,7 @@ import ( protocol "github.com/libp2p/go-libp2p-core/protocol" discovery "github.com/libp2p/go-libp2p-discovery" pubsub "github.com/libp2p/go-libp2p-pubsub" - b58 "github.com/mr-tron/base58/base58" + filter "github.com/libp2p/go-maddr-filter" "github.com/multiformats/go-multiaddr" logging2 "github.com/whyrusleeping/go-logging" ) @@ -38,14 +43,16 @@ type subscription struct { } type app struct { - P2p *codanet.Helper - Ctx context.Context - Subs map[int]subscription - Validators map[int]chan bool - Streams map[int]net.Stream - OutLock sync.Mutex - Out *bufio.Writer - RpcLock sync.Mutex + P2p *codanet.Helper + Ctx context.Context + Subs map[int]subscription + Validators map[int]chan bool + ValidatorMutex *sync.Mutex + Streams map[int]net.Stream + OutLock sync.Mutex + Out *bufio.Writer + UnsafeNoTrustIP bool + Extra *os.File } var seqs = make(chan int) @@ -70,8 +77,18 @@ const ( listeningAddrs addPeer beginAdvertising + findPeer + listPeers + banIP + unbanIP ) +type codaPeerInfo struct { + Libp2pPort int `json:"libp2p_port"` + Host string `json:"host"` + PeerID string `json:"peer_id"` +} + type envelope struct { Method methodIdx `json:"method"` Seqno int `json:"seqno"` @@ -82,6 +99,7 @@ func (app *app) writeMsg(msg interface{}) { app.OutLock.Lock() defer app.OutLock.Unlock() bytes, err := json.Marshal(msg) + app.Extra.Write(bytes) if err == nil { n, err := app.Out.Write(bytes) if err != nil { @@ -141,12 +159,56 @@ func needsDHT() error { return badRPC(errors.New("helper not yet joined to pubsub")) } +func parseMultiaddrWithID(ma multiaddr.Multiaddr, id peer.ID) (*codaPeerInfo, error) { + ipComponent, tcpMaddr := multiaddr.SplitFirst(ma) + if !(ipComponent.Protocol().Code == multiaddr.P_IP4 || ipComponent.Protocol().Code == multiaddr.P_IP6) { + return nil, badRPC(errors.New(fmt.Sprintf("only IP connections are supported right now, how did this peer connect?: %s", ma.String()))) + } + + tcpComponent, _ := multiaddr.SplitFirst(tcpMaddr) + if tcpComponent.Protocol().Code != multiaddr.P_TCP { + return nil, badRPC(errors.New("only TCP connections are supported right now, how did this peer connect?")) + } + + port, err := strconv.Atoi(tcpComponent.Value()) + if err != nil { + return nil, err + } + + return &codaPeerInfo{Libp2pPort: port, Host: ipComponent.Value(), PeerID: peer.IDB58Encode(id)}, nil +} + +func findPeerInfo(app *app, id peer.ID) (*codaPeerInfo, error) { + if app.P2p == nil { + return nil, needsConfigure() + } + + conns := app.P2p.Host.Network().ConnsToPeer(id) + + if len(conns) == 0 { + if app.UnsafeNoTrustIP { + app.P2p.Logger.Info("UnsafeNoTrustIP: pretending it's localhost") + return &codaPeerInfo{Libp2pPort: 0, Host: "127.0.0.1", PeerID: peer.IDB58Encode(id)}, nil + } + return nil, badp2p(errors.New("tried to find peer info but no open connections to that peer ID")) + } + + conn := conns[0] + + maybePeer, err := parseMultiaddrWithID(conn.RemoteMultiaddr(), conn.RemotePeer()) + if err != nil { + return nil, err + } + return maybePeer, nil +} + type configureMsg struct { - Statedir string `json:"statedir"` - Privk string `json:"privk"` - NetworkID string `json:"network_id"` - ListenOn []string `json:"ifaces"` - External string `json:"external_maddr"` + Statedir string `json:"statedir"` + Privk string `json:"privk"` + NetworkID string `json:"network_id"` + ListenOn []string `json:"ifaces"` + External string `json:"external_maddr"` + UnsafeNoTrustIP bool `json:"unsafe_no_trust_ip"` } type discoveredPeerUpcall struct { @@ -156,7 +218,8 @@ type discoveredPeerUpcall struct { } func (m *configureMsg) run(app *app) (interface{}, error) { - privkBytes, err := b58.Decode(m.Privk) + app.UnsafeNoTrustIP = m.UnsafeNoTrustIP + privkBytes, err := codaDecode(m.Privk) if err != nil { return nil, badRPC(err) } @@ -227,7 +290,7 @@ func (t *publishMsg) run(app *app) (interface{}, error) { return nil, needsDHT() } - data, err := b58.Decode(t.Data) + data, err := codaDecode(t.Data) if err != nil { return nil, badRPC(err) } @@ -243,9 +306,21 @@ type subscribeMsg struct { } type publishUpcall struct { - Upcall string `json:"upcall"` - Subscription int `json:"subscription_idx"` - Data string `json:"data"` + Upcall string `json:"upcall"` + Subscription int `json:"subscription_idx"` + Data string `json:"data"` + Sender *codaPeerInfo `json:"sender"` +} + +// we use base64 for encoding blobs in our JSON protocol. there are more +// efficient options but this one is easy to reach to. + +func codaEncode(data []byte) string { + return base64.StdEncoding.EncodeToString(data) +} + +func codaDecode(data string) ([]byte, error) { + return base64.StdEncoding.DecodeString(data) } func (s *subscribeMsg) run(app *app) (interface{}, error) { @@ -256,12 +331,33 @@ func (s *subscribeMsg) run(app *app) (interface{}, error) { return nil, needsDHT() } err := app.P2p.Pubsub.RegisterTopicValidator(s.Topic, func(ctx context.Context, id peer.ID, msg *pubsub.Message) bool { + if id == app.P2p.Me { + // messages from ourself are valid. + app.P2p.Logger.Info("would have validated but it's from us!") + return true + } + seqno := <-seqs - ch := make(chan bool) + ch := make(chan bool, 1) + app.ValidatorMutex.Lock() app.Validators[seqno] = ch + app.ValidatorMutex.Unlock() + + app.P2p.Logger.Info("validating a new pubsub message ...") + + sender, err := findPeerInfo(app, id) + + if err != nil && !app.UnsafeNoTrustIP { + app.P2p.Logger.Errorf("failed to connect to peer %s that just sent us a pubsub message, dropping it", peer.IDB58Encode(id)) + app.ValidatorMutex.Lock() + defer app.ValidatorMutex.Unlock() + delete(app.Validators, seqno) + return false + } + app.writeMsg(validateUpcall{ - PeerID: id.Pretty(), - Data: b58.Encode(msg.Data), + Sender: sender, + Data: codaEncode(msg.Data), Seqno: seqno, Upcall: "validate", Idx: s.Subscription, @@ -270,15 +366,26 @@ func (s *subscribeMsg) run(app *app) (interface{}, error) { // Wait for the validation response, but be sure to honor any timeout/deadline in ctx select { case <-ctx.Done(): - // do NOT delete app.Validators[seqno] here! the ocaml side doesn't + // XXX: do πŸ…½πŸ…ΎπŸ†ƒ delete app.Validators[seqno] here! the ocaml side doesn't // care about the timeout and will validate it anyway. // validationComplete will remove app.Validators[seqno] once the // coda process gets around to it. + app.P2p.Logger.Error("validation timed out :(") + if app.UnsafeNoTrustIP { + app.P2p.Logger.Info("validated!") + return true + } + app.P2p.Logger.Info("unvalidated :(") return false case res := <-ch: + if !res { + app.P2p.Logger.Error("why u fail to validate :(") + } else { + app.P2p.Logger.Info("validated!") + } return res } - }, pubsub.WithValidatorConcurrency(1), pubsub.WithValidatorTimeout(5*time.Second)) + }, pubsub.WithValidatorTimeout(5*time.Minute)) if err != nil { return nil, badp2p(err) @@ -299,15 +406,21 @@ func (s *subscribeMsg) run(app *app) (interface{}, error) { for { msg, err := sub.Next(ctx) if err == nil { - data := b58.Encode(msg.Data) - app.writeMsg(publishUpcall{ - Upcall: "publish", - Subscription: s.Subscription, - Data: data, - }) + sender, err := findPeerInfo(app, msg.ReceivedFrom) + if err != nil && !app.UnsafeNoTrustIP { + app.P2p.Logger.Errorf("failed to connect to peer %s that just sent us an already-validated pubsub message, dropping it", peer.IDB58Encode(msg.ReceivedFrom)) + } else { + data := codaEncode(msg.Data) + app.writeMsg(publishUpcall{ + Upcall: "publish", + Subscription: s.Subscription, + Data: data, + Sender: sender, + }) + } } else { if ctx.Err() != context.Canceled { - log.Print("sub.Next failed: ", err) + app.P2p.Logger.Error("sub.Next failed: ", err) } else { break } @@ -328,17 +441,18 @@ func (u *unsubscribeMsg) run(app *app) (interface{}, error) { if sub, ok := app.Subs[u.Subscription]; ok { sub.Sub.Cancel() sub.Cancel() + delete(app.Subs, u.Subscription) return "unsubscribe success", nil } return nil, badRPC(errors.New("subscription not found")) } type validateUpcall struct { - PeerID string `json:"peer_id"` - Data string `json:"data"` - Seqno int `json:"seqno"` - Upcall string `json:"upcall"` - Idx int `json:"subscription_idx"` + Sender *codaPeerInfo `json:"sender"` + Data string `json:"data"` + Seqno int `json:"seqno"` + Upcall string `json:"upcall"` + Idx int `json:"subscription_idx"` } type validationCompleteMsg struct { @@ -350,6 +464,8 @@ func (r *validationCompleteMsg) run(app *app) (interface{}, error) { if app.P2p == nil { return nil, needsConfigure() } + app.ValidatorMutex.Lock() + defer app.ValidatorMutex.Unlock() if ch, ok := app.Validators[r.Seqno]; ok { ch <- r.Valid delete(app.Validators, r.Seqno) @@ -387,7 +503,7 @@ func (*generateKeypairMsg) run(app *app) (interface{}, error) { return nil, badp2p(err) } - return generatedKeypair{Private: b58.Encode(privkBytes), Public: b58.Encode(pubkBytes), PeerID: peer.IDB58Encode(peerID)}, nil + return generatedKeypair{Private: codaEncode(privkBytes), Public: codaEncode(pubkBytes), PeerID: peer.IDB58Encode(peerID)}, nil } type streamLostUpcall struct { @@ -421,7 +537,7 @@ func handleStreamReads(app *app, stream net.Stream, idx int) { if len != 0 { app.writeMsg(incomingMsgUpcall{ Upcall: "incomingStreamMsg", - Data: b58.Encode(buf[:len]), + Data: codaEncode(buf[:len]), StreamIdx: idx, }) } @@ -447,9 +563,8 @@ func handleStreamReads(app *app, stream net.Stream, idx int) { } type openStreamResult struct { - StreamIdx int `json:"stream_idx"` - RemoteAddr string `json:"remote_addr"` - RemotePeerID string `json:"remote_peerid"` + StreamIdx int `json:"stream_idx"` + Peer codaPeerInfo `json:"peer"` } func (o *openStreamMsg) run(app *app) (interface{}, error) { @@ -470,13 +585,20 @@ func (o *openStreamMsg) run(app *app) (interface{}, error) { return nil, badp2p(err) } + maybePeer, err := parseMultiaddrWithID(stream.Conn().RemoteMultiaddr(), stream.Conn().RemotePeer()) + + if err != nil { + stream.Reset() + return nil, badp2p(err) + } + app.Streams[streamIdx] = stream go func() { // FIXME HACK: allow time for the openStreamResult to get printed before we start inserting stream events time.Sleep(250 * time.Millisecond) handleStreamReads(app, stream, streamIdx) }() - return openStreamResult{StreamIdx: streamIdx, RemoteAddr: stream.Conn().RemoteMultiaddr().String(), RemotePeerID: stream.Conn().RemotePeer().String()}, nil + return openStreamResult{StreamIdx: streamIdx, Peer: *maybePeer}, nil } type closeStreamMsg struct { @@ -507,6 +629,7 @@ func (cs *resetStreamMsg) run(app *app) (interface{}, error) { } if stream, ok := app.Streams[cs.StreamIdx]; ok { err := stream.Reset() + delete(app.Streams, cs.StreamIdx) if err != nil { return nil, badp2p(err) } @@ -524,15 +647,15 @@ func (cs *sendStreamMsgMsg) run(app *app) (interface{}, error) { if app.P2p == nil { return nil, needsConfigure() } - data, err := b58.Decode(cs.Data) + data, err := codaDecode(cs.Data) if err != nil { return nil, badRPC(err) } if stream, ok := app.Streams[cs.StreamIdx]; ok { - _, err := stream.Write(data) + n, err := stream.Write(data) if err != nil { - return nil, badp2p(err) + return nil, wrapError(badp2p(err), fmt.Sprintf("only wrote %d out of %d bytes", n, len(data))) } return "sendStreamMsg success", nil } @@ -544,11 +667,10 @@ type addStreamHandlerMsg struct { } type incomingStreamUpcall struct { - Upcall string `json:"upcall"` - RemoteAddr string `json:"remote_addr"` - RemotePeerID string `json:"remote_peerid"` - StreamIdx int `json:"stream_idx"` - Protocol string `json:"protocol"` + Upcall string `json:"upcall"` + Peer codaPeerInfo `json:"peer"` + StreamIdx int `json:"stream_idx"` + Protocol string `json:"protocol"` } func (as *addStreamHandlerMsg) run(app *app) (interface{}, error) { @@ -556,14 +678,18 @@ func (as *addStreamHandlerMsg) run(app *app) (interface{}, error) { return nil, needsConfigure() } app.P2p.Host.SetStreamHandler(protocol.ID(as.Protocol), func(stream net.Stream) { + peerinfo, err := parseMultiaddrWithID(stream.Conn().RemoteMultiaddr(), stream.Conn().RemotePeer()) + if err != nil { + app.P2p.Logger.Errorf("failed to parse remote connection information, silently dropping stream: %s", err.Error()) + return + } streamIdx := <-seqs app.Streams[streamIdx] = stream app.writeMsg(incomingStreamUpcall{ - Upcall: "incomingStream", - RemoteAddr: stream.Conn().RemoteMultiaddr().String(), - RemotePeerID: stream.Conn().RemotePeer().String(), - StreamIdx: streamIdx, - Protocol: as.Protocol, + Upcall: "incomingStream", + Peer: *peerinfo, + StreamIdx: streamIdx, + Protocol: as.Protocol, }) handleStreamReads(app, stream, streamIdx) }) @@ -657,9 +783,9 @@ func (ap *beginAdvertisingMsg) run(app *app) (interface{}, error) { ctx, cancel := context.WithTimeout(app.Ctx, 15*time.Second) defer cancel() if err := app.P2p.Host.Connect(ctx, info); err != nil { - app.P2p.Logger.Warning("couldn't connect to %s peer %v (maybe the network ID mismatched?): %v", source, info.Loggable(), err) + app.P2p.Logger.Warningf("couldn't connect to %s peer %v (maybe the network ID mismatched?): %v", source, info.Loggable(), err) } else { - app.P2p.Logger.Info("Found a %s peer: %s", source, info.Loggable()) + app.P2p.Logger.Infof("Found a %s peer: %s", source, info.Loggable()) app.P2p.Host.Peerstore().AddAddrs(info.ID, info.Addrs, peerstore.ConnectedAddrTTL) addrStrings := make([]string, len(info.Addrs)) for i, a := range info.Addrs { @@ -681,8 +807,17 @@ func (ap *beginAdvertisingMsg) run(app *app) (interface{}, error) { } }() + if err := app.P2p.Dht.Bootstrap(app.Ctx); err != nil { + return nil, badp2p(err) + } + + discovery.Advertise(app.Ctx, routingDiscovery, app.P2p.Rendezvous) + // report dht peers go func() { + // wait a bit for our advertisement to go out and get some responses + time.Sleep(5 * time.Second) + for { // default is to yield only 100 peers at a time. for now, always be // looking... TODO: Is there a better way to use discovery? Should we only @@ -698,13 +833,107 @@ func (ap *beginAdvertisingMsg) run(app *app) (interface{}, error) { } }() - if err := app.P2p.Dht.Bootstrap(app.Ctx); err != nil { - return nil, badp2p(err) + return "beginAdvertising success", nil +} + +type findPeerMsg struct { + PeerID string `json:"peer_id"` +} + +func (ap *findPeerMsg) run(app *app) (interface{}, error) { + id, err := peer.IDB58Decode(ap.PeerID) + if err != nil { + return nil, err } - discovery.Advertise(app.Ctx, routingDiscovery, app.P2p.Rendezvous) + maybePeer, err := findPeerInfo(app, id) - return "beginAdvertising success", nil + if err != nil { + return nil, err + } + + return *maybePeer, nil +} + +type listPeersMsg struct { +} + +func (lp *listPeersMsg) run(app *app) (interface{}, error) { + if app.P2p == nil { + return nil, needsConfigure() + } + + connsHere := app.P2p.Host.Network().Conns() + + peerInfos := make([]codaPeerInfo, len(connsHere)) + + for _, conn := range connsHere { + maybePeer, err := parseMultiaddrWithID(conn.RemoteMultiaddr(), conn.RemotePeer()) + if err != nil { + app.P2p.Logger.Warning("skipping maddr ", conn.RemoteMultiaddr().String(), " because it failed to parse: ", err.Error()) + continue + } + peerInfos = append(peerInfos, *maybePeer) + } + + return peerInfos, nil +} + +type banIPMsg struct { + IP string `json:"ip"` +} + +func (ban *banIPMsg) run(app *app) (interface{}, error) { + if app.P2p == nil { + return nil, needsConfigure() + } + + ip := gonet.ParseIP(ban.IP).To4() + + if ip == nil { + // TODO: how to compute mask for IPv6? + return nil, badRPC(errors.New("unparsable IP or IPv6")) + } + + ipnet := gonet.IPNet{Mask: gonet.IPv4Mask(255, 255, 255, 255), IP: ip} + + currentAction, isFromRule := app.P2p.Filters.ActionForFilter(ipnet) + + app.P2p.Filters.AddFilter(ipnet, filter.ActionDeny) + + if currentAction == filter.ActionDeny && isFromRule { + return "banIP already banned", nil + } + return "banIP success", nil +} + +type unbanIPMsg struct { + IP string `json:"ip"` +} + +func (unban *unbanIPMsg) run(app *app) (interface{}, error) { + if app.P2p == nil { + return nil, needsConfigure() + } + + ip := gonet.ParseIP(unban.IP).To4() + + if ip == nil { + // TODO: how to compute mask for IPv6? + return nil, badRPC(errors.New("unparsable IP or IPv6")) + } + + ipnet := gonet.IPNet{Mask: gonet.IPv4Mask(255, 255, 255, 255), IP: ip} + + currentAction, isFromRule := app.P2p.Filters.ActionForFilter(ipnet) + + if !isFromRule || currentAction == filter.ActionAccept { + return "unbanIP not banned", nil + } + + app.P2p.Filters.RemoveLiteral(ipnet) + + return "unbanIP success", nil } var msgHandlers = map[methodIdx]func() action{ @@ -724,6 +953,10 @@ var msgHandlers = map[methodIdx]func() action{ listeningAddrs: func() action { return &listeningAddrsMsg{} }, addPeer: func() action { return &addPeerMsg{} }, beginAdvertising: func() action { return &beginAdvertisingMsg{} }, + findPeer: func() action { return &findPeerMsg{} }, + listPeers: func() action { return &listPeersMsg{} }, + banIP: func() action { return &banIPMsg{} }, + unbanIP: func() action { return &unbanIPMsg{} }, } type errorResult struct { @@ -732,13 +965,19 @@ type errorResult struct { } type successResult struct { - Seqno int `json:"seqno"` - Success json.RawMessage `json:"success"` + Seqno int `json:"seqno"` + Success json.RawMessage `json:"success"` + Duration string `json:"duration"` } func main() { - logwriter.Configure(logwriter.Output(os.Stderr), logwriter.LdJSONFormatter) - log.SetOutput(os.Stderr) + logwriter.Configure(logwriter.Output(os.Stderr), logwriter.LdJSONFormatter) + os.Mkdir("/tmp/artifacts", os.ModePerm) + logfile, err := os.Create("/tmp/artifacts/helper.log") + if err != nil { + panic(err) + } + log.SetOutput(logfile) logging.SetAllLoggers(logging2.INFO) helperLog := logging.Logger("helper top-level JSON handling") @@ -751,17 +990,21 @@ func main() { }() lines := bufio.NewScanner(os.Stdin) + // 11MiB buffer size, larger than the 10.66MB minimum for 8MiB to be b64'd + bufsize := (1024 * 1024) * 11 + lines.Buffer(make([]byte, bufsize), bufsize) out := bufio.NewWriter(os.Stdout) app := &app{ - P2p: nil, - Ctx: context.Background(), - Subs: make(map[int]subscription), - Validators: make(map[int]chan bool), - Streams: make(map[int]net.Stream), + P2p: nil, + Ctx: context.Background(), + Subs: make(map[int]subscription), + ValidatorMutex: &sync.Mutex{}, + Validators: make(map[int]chan bool), + Streams: make(map[int]net.Stream), + Extra: logfile, // OutLock doesn't need to be initialized Out: out, - // RpcLock doesn't need to be initialized } for lines.Scan() { @@ -772,23 +1015,24 @@ func main() { } if err := json.Unmarshal([]byte(line), &env); err != nil { log.Print("when unmarshaling the envelope...") - log.Fatal(err) + log.Panic(err) } msg := msgHandlers[env.Method]() if err := json.Unmarshal(raw, msg); err != nil { log.Print("when unmarshaling the method invocation...") - log.Fatal(err) + log.Panic(err) } defer func() { if r := recover(); r != nil { - helperLog.Error("While handling RPC:", line, "\nThe following panic occurred: ", r) + helperLog.Error("While handling RPC:", line, "\nThe following panic occurred: ", r, "\nstack:\n", debug.Stack()) } }() + start := time.Now() res, err := msg.run(app) if err == nil { res, err := json.Marshal(res) if err == nil { - app.writeMsg(successResult{Seqno: env.Seqno, Success: res}) + app.writeMsg(successResult{Seqno: env.Seqno, Success: res, Duration: time.Now().Sub(start).String()}) } else { app.writeMsg(errorResult{Seqno: env.Seqno, Errorr: err.Error()}) } @@ -796,7 +1040,10 @@ func main() { app.writeMsg(errorResult{Seqno: env.Seqno, Errorr: err.Error()}) } } - os.Exit(0) + app.writeMsg(errorResult{Seqno: 0, Errorr: fmt.Sprintf("helper stdin scanning stopped because %v", lines.Err())}) + // we never want the helper to get here, it should be killed or gracefully + // shut down instead of stdin closed. + os.Exit(1) } var _ json.Marshaler = (*methodIdx)(nil) diff --git a/src/libp2p_helper/methodidx_jsonenum.go b/src/libp2p_helper/methodidx_jsonenum.go index d87e80c0b..72e560220 100644 --- a/src/libp2p_helper/methodidx_jsonenum.go +++ b/src/libp2p_helper/methodidx_jsonenum.go @@ -25,6 +25,10 @@ var ( "listeningAddrs": listeningAddrs, "addPeer": addPeer, "beginAdvertising": beginAdvertising, + "findPeer": findPeer, + "listPeers": listPeers, + "banIP": banIP, + "unbanIP": unbanIP, } _methodIdxValueToName = map[methodIdx]string{ @@ -44,6 +48,10 @@ var ( listeningAddrs: "listeningAddrs", addPeer: "addPeer", beginAdvertising: "beginAdvertising", + findPeer: "findPeer", + listPeers: "listPeers", + banIP: "banIP", + unbanIP: "unbanIP", } ) @@ -67,6 +75,10 @@ func init() { interface{}(listeningAddrs).(fmt.Stringer).String(): listeningAddrs, interface{}(addPeer).(fmt.Stringer).String(): addPeer, interface{}(beginAdvertising).(fmt.Stringer).String(): beginAdvertising, + interface{}(findPeer).(fmt.Stringer).String(): findPeer, + interface{}(listPeers).(fmt.Stringer).String(): listPeers, + interface{}(banIP).(fmt.Stringer).String(): banIP, + interface{}(unbanIP).(fmt.Stringer).String(): unbanIP, } } } diff --git a/src/mplex.go b/src/mplex.go index 552820dd8..84c880764 100644 --- a/src/mplex.go +++ b/src/mplex.go @@ -1,14 +1,27 @@ package codanet import ( + "bufio" + "encoding/binary" + "fmt" "net" - mp "github.com/libp2p/go-mplex" // Conn is a connection to a remote peer. + logging "github.com/ipfs/go-log" smux "github.com/libp2p/go-stream-muxer" // Conn is a connection to a remote peer. + + "context" + "errors" + "io" + "sync" + "time" + + "github.com/libp2p/go-libp2p-core/mux" + + pool "github.com/libp2p/go-buffer-pool" ) type conn struct { - *mp.Multiplex + *Multiplex } func (c *conn) Close() error { @@ -38,5 +51,947 @@ var DefaultMplexTransport = &MplexTransport{} // NewConn opens a new conn func (t *MplexTransport) NewConn(nc net.Conn, isServer bool) (smux.Conn, error) { - return &conn{mp.NewMultiplex(nc, isServer)}, nil + return &conn{NewMultiplex(nc, isServer)}, nil +} + +// below is libp2p/go-mplex inlined in a bad way to change the MaxMessageSize. +// The MIT License (MIT) +// +// Copyright (c) 2016 Jeromy Johnson +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +var mplexlog = logging.Logger("mplex") + +// Max message size in bytes before dropping (8MiB) +var MaxMessageSize = 1 << 23 + +// Max time to block waiting for a slow reader to read from a stream before +// resetting it. Preferably, we'd have some form of back-pressure mechanism but +// we don't have that in this protocol. +var ReceiveTimeout = 5 * time.Second + +// ErrShutdown is returned when operating on a shutdown session +var ErrShutdown = errors.New("session shut down") + +// ErrTwoInitiators is returned when both sides think they're the initiator +var ErrTwoInitiators = errors.New("two initiators") + +// ErrInvalidState is returned when the other side does something it shouldn't. +// In this case, we close the connection to be safe. +var ErrInvalidState = errors.New("received an unexpected message from the peer") + +var errTimeout = timeout{} +var errStreamClosed = errors.New("stream closed") + +var ( + NewStreamTimeout = time.Minute + ResetStreamTimeout = 2 * time.Minute + + WriteCoalesceDelay = 100 * time.Microsecond +) + +type timeout struct{} + +func (_ timeout) Error() string { + return "i/o deadline exceeded" +} + +func (_ timeout) Temporary() bool { + return true +} + +func (_ timeout) Timeout() bool { + return true +} + +// +1 for initiator +const ( + newStreamTag = 0 + messageTag = 2 + closeTag = 4 + resetTag = 6 +) + +// Multiplex is a mplex session. +type Multiplex struct { + con net.Conn + buf *bufio.Reader + nextID uint64 + initiator bool + + closed chan struct{} + shutdown chan struct{} + shutdownErr error + shutdownLock sync.Mutex + + writeCh chan []byte + writeTimer *time.Timer + writeTimerFired bool + + nstreams chan *Stream + + channels map[streamID]*Stream + chLock sync.Mutex +} + +// NewMultiplex creates a new multiplexer session. +func NewMultiplex(con net.Conn, initiator bool) *Multiplex { + mp := &Multiplex{ + con: con, + initiator: initiator, + buf: bufio.NewReader(con), + channels: make(map[streamID]*Stream), + closed: make(chan struct{}), + shutdown: make(chan struct{}), + writeCh: make(chan []byte, 16), + writeTimer: time.NewTimer(0), + nstreams: make(chan *Stream, 16), + } + + go mp.handleIncoming() + go mp.handleOutgoing() + + return mp +} + +func (mp *Multiplex) newStream(id streamID, name string) (s *Stream) { + s = &Stream{ + id: id, + name: name, + dataIn: make(chan []byte, 8), + reset: make(chan struct{}), + rDeadline: makePipeDeadline(), + wDeadline: makePipeDeadline(), + mp: mp, + } + + s.closedLocal, s.doCloseLocal = context.WithCancel(context.Background()) + return +} + +// Accept accepts the next stream from the connection. +func (m *Multiplex) Accept() (*Stream, error) { + select { + case s, ok := <-m.nstreams: + if !ok { + return nil, errors.New("multiplex closed") + } + return s, nil + case <-m.closed: + return nil, m.shutdownErr + } +} + +// Close closes the session. +func (mp *Multiplex) Close() error { + mp.closeNoWait() + + // Wait for the receive loop to finish. + <-mp.closed + + return nil +} + +func (mp *Multiplex) closeNoWait() { + mp.shutdownLock.Lock() + select { + case <-mp.shutdown: + default: + mp.con.Close() + close(mp.shutdown) + } + mp.shutdownLock.Unlock() +} + +// IsClosed returns true if the session is closed. +func (mp *Multiplex) IsClosed() bool { + select { + case <-mp.closed: + return true + default: + return false + } +} + +func (mp *Multiplex) sendMsg(done <-chan struct{}, header uint64, data []byte) error { + buf := pool.Get(len(data) + 20) + + n := 0 + n += binary.PutUvarint(buf[n:], header) + n += binary.PutUvarint(buf[n:], uint64(len(data))) + n += copy(buf[n:], data) + + select { + case mp.writeCh <- buf[:n]: + return nil + case <-mp.shutdown: + return ErrShutdown + case <-done: + return errTimeout + } +} + +func (mp *Multiplex) handleOutgoing() { + for { + select { + case <-mp.shutdown: + return + + case data := <-mp.writeCh: + err := mp.writeMsg(data) + if err != nil { + // the connection is closed by this time + mplexlog.Warningf("error writing data: %s", err.Error()) + return + } + } + } +} + +func (mp *Multiplex) writeMsg(data []byte) error { + if len(data) >= 512 { + err := mp.doWriteMsg(data) + pool.Put(data) + return err + } + + buf := pool.Get(4096) + defer pool.Put(buf) + + n := copy(buf, data) + pool.Put(data) + + if !mp.writeTimerFired { + if !mp.writeTimer.Stop() { + <-mp.writeTimer.C + } + } + mp.writeTimer.Reset(WriteCoalesceDelay) + mp.writeTimerFired = false + + for { + select { + case data = <-mp.writeCh: + wr := copy(buf[n:], data) + if wr < len(data) { + // we filled the buffer, send it + err := mp.doWriteMsg(buf) + if err != nil { + pool.Put(data) + return err + } + + if len(data)-wr >= 512 { + // the remaining data is not a small write, send it + err := mp.doWriteMsg(data[wr:]) + pool.Put(data) + return err + } + + n = copy(buf, data[wr:]) + + // we've written some, reset the timer to coalesce the rest + if !mp.writeTimer.Stop() { + <-mp.writeTimer.C + } + mp.writeTimer.Reset(WriteCoalesceDelay) + } else { + n += wr + } + + pool.Put(data) + + case <-mp.writeTimer.C: + mp.writeTimerFired = true + return mp.doWriteMsg(buf[:n]) + + case <-mp.shutdown: + return ErrShutdown + } + } +} + +func (mp *Multiplex) doWriteMsg(data []byte) error { + if mp.isShutdown() { + return ErrShutdown + } + + _, err := mp.con.Write(data) + if err != nil { + mp.closeNoWait() + } + + return err +} + +func (mp *Multiplex) nextChanID() uint64 { + out := mp.nextID + mp.nextID++ + return out +} + +// NewStream creates a new stream. +func (mp *Multiplex) NewStream() (*Stream, error) { + return mp.NewNamedStream("") +} + +// NewNamedStream creates a new named stream. +func (mp *Multiplex) NewNamedStream(name string) (*Stream, error) { + mp.chLock.Lock() + + // We could call IsClosed but this is faster (given that we already have + // the lock). + if mp.channels == nil { + mp.chLock.Unlock() + return nil, ErrShutdown + } + + sid := mp.nextChanID() + header := (sid << 3) | newStreamTag + + if name == "" { + name = fmt.Sprint(sid) + } + s := mp.newStream(streamID{ + id: sid, + initiator: true, + }, name) + mp.channels[s.id] = s + mp.chLock.Unlock() + + ctx, cancel := context.WithTimeout(context.Background(), NewStreamTimeout) + defer cancel() + + err := mp.sendMsg(ctx.Done(), header, []byte(name)) + if err != nil { + return nil, err + } + + return s, nil +} + +func (mp *Multiplex) cleanup() { + mp.closeNoWait() + mp.chLock.Lock() + defer mp.chLock.Unlock() + for _, msch := range mp.channels { + msch.clLock.Lock() + if !msch.closedRemote { + msch.closedRemote = true + // Cancel readers + close(msch.reset) + } + + msch.doCloseLocal() + msch.clLock.Unlock() + } + // Don't remove this nil assignment. We check if this is nil to check if + // the connection is closed when we already have the lock (faster than + // checking if the stream is closed). + mp.channels = nil + if mp.shutdownErr == nil { + mp.shutdownErr = ErrShutdown + } + close(mp.closed) +} + +func (mp *Multiplex) handleIncoming() { + defer mp.cleanup() + + recvTimeout := time.NewTimer(0) + defer recvTimeout.Stop() + + if !recvTimeout.Stop() { + <-recvTimeout.C + } + + for { + chID, tag, err := mp.readNextHeader() + if err != nil { + mp.shutdownErr = err + return + } + + remoteIsInitiator := tag&1 == 0 + ch := streamID{ + // true if *I'm* the initiator. + initiator: !remoteIsInitiator, + id: chID, + } + // Rounds up the tag: + // 0 -> 0 + // 1 -> 2 + // 2 -> 2 + // 3 -> 4 + // etc... + tag += (tag & 1) + + b, err := mp.readNext() + if err != nil { + mp.shutdownErr = err + return + } + + mp.chLock.Lock() + msch, ok := mp.channels[ch] + mp.chLock.Unlock() + + switch tag { + case newStreamTag: + if ok { + mplexlog.Debugf("received NewStream message for existing stream: %d", ch) + mp.shutdownErr = ErrInvalidState + return + } + + name := string(b) + pool.Put(b) + + msch = mp.newStream(ch, name) + mp.chLock.Lock() + mp.channels[ch] = msch + mp.chLock.Unlock() + select { + case mp.nstreams <- msch: + case <-mp.shutdown: + return + } + + case resetTag: + if !ok { + // This is *ok*. We forget the stream on reset. + continue + } + msch.clLock.Lock() + + isClosed := msch.isClosed() + + if !msch.closedRemote { + close(msch.reset) + msch.closedRemote = true + } + + if !isClosed { + msch.doCloseLocal() + } + + msch.clLock.Unlock() + + msch.cancelDeadlines() + + mp.chLock.Lock() + delete(mp.channels, ch) + mp.chLock.Unlock() + case closeTag: + if !ok { + continue + } + + msch.clLock.Lock() + + if msch.closedRemote { + msch.clLock.Unlock() + // Technically a bug on the other side. We + // should consider killing the connection. + continue + } + + close(msch.dataIn) + msch.closedRemote = true + + cleanup := msch.isClosed() + + msch.clLock.Unlock() + + if cleanup { + msch.cancelDeadlines() + mp.chLock.Lock() + delete(mp.channels, ch) + mp.chLock.Unlock() + } + case messageTag: + if !ok { + // reset stream, return b + pool.Put(b) + + // This is a perfectly valid case when we reset + // and forget about the stream. + mplexlog.Debugf("message for non-existant stream, dropping data: %d", ch) + // go mp.sendResetMsg(ch.header(resetTag), false) + continue + } + + msch.clLock.Lock() + remoteClosed := msch.closedRemote + msch.clLock.Unlock() + if remoteClosed { + // closed stream, return b + pool.Put(b) + + mplexlog.Warningf("Received data from remote after stream was closed by them. (len = %d)", len(b)) + // go mp.sendResetMsg(msch.id.header(resetTag), false) + continue + } + + recvTimeout.Reset(ReceiveTimeout) + select { + case msch.dataIn <- b: + case <-msch.reset: + pool.Put(b) + case <-recvTimeout.C: + pool.Put(b) + mplexlog.Warningf("timed out receiving message into stream queue.") + // Do not do this asynchronously. Otherwise, we + // could drop a message, then receive a message, + // then reset. + msch.Reset() + continue + case <-mp.shutdown: + pool.Put(b) + return + } + if !recvTimeout.Stop() { + <-recvTimeout.C + } + default: + mplexlog.Debugf("message with unknown header on stream %s", ch) + if ok { + msch.Reset() + } + } + } +} + +func (mp *Multiplex) isShutdown() bool { + select { + case <-mp.shutdown: + return true + default: + return false + } +} + +func (mp *Multiplex) sendResetMsg(header uint64, hard bool) { + ctx, cancel := context.WithTimeout(context.Background(), ResetStreamTimeout) + defer cancel() + + err := mp.sendMsg(ctx.Done(), header, nil) + if err != nil && !mp.isShutdown() { + if hard { + mplexlog.Warningf("error sending reset message: %s; killing connection", err.Error()) + mp.Close() + } else { + mplexlog.Debugf("error sending reset message: %s", err.Error()) + } + } +} + +func (mp *Multiplex) readNextHeader() (uint64, uint64, error) { + h, err := binary.ReadUvarint(mp.buf) + if err != nil { + return 0, 0, err + } + + // get channel ID + ch := h >> 3 + + rem := h & 7 + + return ch, rem, nil +} + +func (mp *Multiplex) readNext() ([]byte, error) { + // get length + l, err := binary.ReadUvarint(mp.buf) + if err != nil { + return nil, err + } + + if l > uint64(MaxMessageSize) { + return nil, fmt.Errorf("message size too large!") + } + + if l == 0 { + return nil, nil + } + + buf := pool.Get(int(l)) + n, err := io.ReadFull(mp.buf, buf) + if err != nil { + return nil, err + } + + return buf[:n], nil +} + +func isFatalNetworkError(err error) bool { + nerr, ok := err.(net.Error) + if ok { + return !(nerr.Timeout() || nerr.Temporary()) + } + return false +} + +// streamID is a convenience type for operating on stream IDs +type streamID struct { + id uint64 + initiator bool +} + +// header computes the header for the given tag +func (id *streamID) header(tag uint64) uint64 { + header := id.id<<3 | tag + if !id.initiator { + header-- + } + return header +} + +type Stream struct { + id streamID + name string + dataIn chan []byte + mp *Multiplex + + extra []byte + + // exbuf is for holding the reference to the beginning of the extra slice + // for later memory pool freeing + exbuf []byte + + rDeadline, wDeadline pipeDeadline + + clLock sync.Mutex + closedRemote bool + + // Closed when the connection is reset. + reset chan struct{} + + // Closed when the writer is closed (reset will also be closed) + closedLocal context.Context + doCloseLocal context.CancelFunc +} + +func (s *Stream) Name() string { + return s.name +} + +// tries to preload pending data +func (s *Stream) preloadData() { + select { + case read, ok := <-s.dataIn: + if !ok { + return + } + s.extra = read + s.exbuf = read + default: + } +} + +func (s *Stream) waitForData() error { + select { + case <-s.reset: + // This is the only place where it's safe to return these. + s.returnBuffers() + return mux.ErrReset + case read, ok := <-s.dataIn: + if !ok { + return io.EOF + } + s.extra = read + s.exbuf = read + return nil + case <-s.rDeadline.wait(): + return errTimeout + } +} + +func (s *Stream) returnBuffers() { + if s.exbuf != nil { + pool.Put(s.exbuf) + s.exbuf = nil + s.extra = nil + } + for { + select { + case read, ok := <-s.dataIn: + if !ok { + return + } + if read == nil { + continue + } + pool.Put(read) + default: + return + } + } +} + +func (s *Stream) Read(b []byte) (int, error) { + select { + case <-s.reset: + return 0, mux.ErrReset + default: + } + if s.extra == nil { + err := s.waitForData() + if err != nil { + return 0, err + } + } + n := 0 + for s.extra != nil && n < len(b) { + read := copy(b[n:], s.extra) + n += read + if read < len(s.extra) { + s.extra = s.extra[read:] + } else { + if s.exbuf != nil { + pool.Put(s.exbuf) + } + s.extra = nil + s.exbuf = nil + s.preloadData() + } + } + return n, nil +} + +func (s *Stream) Write(b []byte) (int, error) { + var written int + for written < len(b) { + wl := len(b) - written + if wl > MaxMessageSize { + wl = MaxMessageSize + } + + n, err := s.write(b[written : written+wl]) + if err != nil { + return written, err + } + + written += n + } + + return written, nil +} + +func (s *Stream) write(b []byte) (int, error) { + if s.isClosed() { + return 0, errors.New("cannot write to closed stream") + } + + err := s.mp.sendMsg(s.wDeadline.wait(), s.id.header(messageTag), b) + + if err != nil { + if err == context.Canceled { + err = errors.New("cannot write to closed stream") + } + return 0, err + } + + return len(b), nil +} + +func (s *Stream) isClosed() bool { + return s.closedLocal.Err() != nil +} + +func (s *Stream) Close() error { + ctx, cancel := context.WithTimeout(context.Background(), ResetStreamTimeout) + defer cancel() + + err := s.mp.sendMsg(ctx.Done(), s.id.header(closeTag), nil) + + if s.isClosed() { + return nil + } + + s.clLock.Lock() + remote := s.closedRemote + s.clLock.Unlock() + + s.doCloseLocal() + + if remote { + s.cancelDeadlines() + s.mp.chLock.Lock() + delete(s.mp.channels, s.id) + s.mp.chLock.Unlock() + } + + if err != nil && !s.mp.isShutdown() { + mplexlog.Warningf("Error closing stream: %s; killing connection", err.Error()) + s.mp.Close() + } + + return err +} + +func (s *Stream) Reset() error { + s.clLock.Lock() + + // Don't reset when fully closed. + if s.closedRemote && s.isClosed() { + s.clLock.Unlock() + return nil + } + + // Don't reset twice. + select { + case <-s.reset: + s.clLock.Unlock() + return nil + default: + } + + close(s.reset) + s.doCloseLocal() + s.closedRemote = true + s.cancelDeadlines() + + go s.mp.sendResetMsg(s.id.header(resetTag), true) + + s.clLock.Unlock() + + s.mp.chLock.Lock() + delete(s.mp.channels, s.id) + s.mp.chLock.Unlock() + + return nil +} + +func (s *Stream) cancelDeadlines() { + s.rDeadline.set(time.Time{}) + s.wDeadline.set(time.Time{}) +} + +func (s *Stream) SetDeadline(t time.Time) error { + s.clLock.Lock() + defer s.clLock.Unlock() + + if s.closedRemote && s.isClosed() { + return errStreamClosed + } + + if !s.closedRemote { + s.rDeadline.set(t) + } + + if !s.isClosed() { + s.wDeadline.set(t) + } + + return nil +} + +func (s *Stream) SetReadDeadline(t time.Time) error { + s.clLock.Lock() + defer s.clLock.Unlock() + + if s.closedRemote { + return errStreamClosed + } + + s.rDeadline.set(t) + return nil +} + +func (s *Stream) SetWriteDeadline(t time.Time) error { + s.clLock.Lock() + defer s.clLock.Unlock() + + if s.isClosed() { + return errStreamClosed + } + + s.wDeadline.set(t) + return nil +} + +// pipeDeadline is an abstraction for handling timeouts. +type pipeDeadline struct { + mu sync.Mutex // Guards timer and cancel + timer *time.Timer + cancel chan struct{} // Must be non-nil +} + +func makePipeDeadline() pipeDeadline { + return pipeDeadline{cancel: make(chan struct{})} +} + +// set sets the point in time when the deadline will time out. +// A timeout event is signaled by closing the channel returned by waiter. +// Once a timeout has occurred, the deadline can be refreshed by specifying a +// t value in the future. +// +// A zero value for t prevents timeout. +func (d *pipeDeadline) set(t time.Time) { + d.mu.Lock() + defer d.mu.Unlock() + + if d.timer != nil && !d.timer.Stop() { + <-d.cancel // Wait for the timer callback to finish and close cancel + } + d.timer = nil + + // Time is zero, then there is no deadline. + closed := isClosedChan(d.cancel) + if t.IsZero() { + if closed { + d.cancel = make(chan struct{}) + } + return + } + + // Time in the future, setup a timer to cancel in the future. + if dur := time.Until(t); dur > 0 { + if closed { + d.cancel = make(chan struct{}) + } + d.timer = time.AfterFunc(dur, func() { + close(d.cancel) + }) + return + } + + // Time in the past, so close immediately. + if !closed { + close(d.cancel) + } +} + +// wait returns a channel that is closed when the deadline is exceeded. +func (d *pipeDeadline) wait() chan struct{} { + d.mu.Lock() + defer d.mu.Unlock() + return d.cancel +} + +func isClosedChan(c <-chan struct{}) bool { + select { + case <-c: + return true + default: + return false + } }