From bc2049ccbcf3da2e112c699ca83477d3becff5b1 Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Fri, 26 May 2023 19:18:51 +0200 Subject: [PATCH 01/11] wip: yamux transport + pool rewrite --- go.mod | 1 + go.sum | 69 +++++++ .../conn.go => connutil/timeout.go} | 12 +- net/connutil/usage.go | 30 ++++ net/dialer/dialer.go | 4 +- net/pool/pool.go | 72 ++++---- net/pool/poolservice.go | 37 ++-- net/secureservice/secureservice.go | 18 +- net/secureservice/secureservice_test.go | 7 +- net/transport/transport.go | 34 ++++ net/transport/yamux/config.go | 12 ++ net/transport/yamux/conn.go | 27 +++ net/transport/yamux/util.go | 18 ++ net/transport/yamux/util_windows.go | 41 +++++ net/transport/yamux/yamux.go | 168 ++++++++++++++++++ net/transport/yamux/yamux_test.go | 134 ++++++++++++++ 16 files changed, 610 insertions(+), 74 deletions(-) rename net/{timeoutconn/conn.go => connutil/timeout.go} (82%) create mode 100644 net/connutil/usage.go create mode 100644 net/transport/transport.go create mode 100644 net/transport/yamux/config.go create mode 100644 net/transport/yamux/conn.go create mode 100644 net/transport/yamux/util.go create mode 100644 net/transport/yamux/util_windows.go create mode 100644 net/transport/yamux/yamux.go create mode 100644 net/transport/yamux/yamux_test.go diff --git a/go.mod b/go.mod index dff08a5c..0f6bec3b 100644 --- a/go.mod +++ b/go.mod @@ -57,6 +57,7 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/google/pprof v0.0.0-20230510103437-eeec1cb781c3 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/yamux v0.1.1 // indirect github.com/huin/goupnp v1.2.0 // indirect github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/go-bitfield v1.1.0 // indirect diff --git a/go.sum b/go.sum index 873e3903..83407153 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,11 @@ filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/anyproto/go-chash v0.1.0 h1:I9meTPjXFRfXZHRJzjOHC/XF7Q5vzysKkiT/grsogXY= @@ -22,6 +25,9 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheggaaa/mb/v3 v3.0.1 h1:BuEOipGTqybXYi5KXVCpqhR1LWN2lrurq6UrH+VBhXc= github.com/cheggaaa/mb/v3 v3.0.1/go.mod h1:zCt2QeYukhd/g0bIdNqF+b/kKz1hnLFNDkP49qN5kqI= +github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= +github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/corona10/goimagehash v1.0.2 h1:pUfB0LnsJASMPGEZLj7tGY251vF+qLGqOgEP4rUs6kA= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= @@ -34,12 +40,20 @@ github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6Uh github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= +github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= @@ -51,6 +65,7 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/goccy/go-graphviz v0.1.1 h1:MGrsnzBxTyt7KG8FhHsFPDTGvF7UaQMmSa6A610DqPg= github.com/goccy/go-graphviz v0.1.1/go.mod h1:lpnwvVDjskayq84ZxG8tGCPeZX/WxP88W+OJajh+gFk= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -62,6 +77,7 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -70,22 +86,29 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/pprof v0.0.0-20230510103437-eeec1cb781c3 h1:2XF1Vzq06X+inNqgJ9tRnGuw+ZVCB3FazXODD6JE1R8= github.com/google/pprof v0.0.0-20230510103437-eeec1cb781c3/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= +github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= +github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY= github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/ianlancetaylor/demangle v0.0.0-20220517205856-0058ec4f073c h1:rwmN+hgiyp8QyBqzdEX43lTjKAxaqCrYHaU5op5P9J8= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= @@ -110,6 +133,8 @@ github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0M github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8= 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.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro= +github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo= github.com/ipfs/go-ipfs-blockstore v1.3.0 h1:m2EXaWgwTzAfsmt5UdJ7Is6l4gJcaM/A12XwJyvYvMM= github.com/ipfs/go-ipfs-blockstore v1.3.0/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE= github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= @@ -160,16 +185,23 @@ github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvB github.com/ipld/go-ipld-prime v0.20.0 h1:Ud3VwE9ClxpO2LkCYP7vWPc0Fo+dYdYzgxUJZ3uRG4g= github.com/ipld/go-ipld-prime v0.20.0/go.mod h1:PzqZ/ZR981eKbgdr3y2DJYeD/8bgMawdGVlJDE8kK+M= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= @@ -182,6 +214,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -189,29 +222,42 @@ github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoR github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= +github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= github.com/libp2p/go-libp2p v0.27.3 h1:tkV/zm3KCZ4R5er9Xcs2pt0YNB4JH0iBfGAtHJdLHRs= github.com/libp2p/go-libp2p v0.27.3/go.mod h1:FAvvfQa/YOShUYdiSS03IR9OXzkcJXwcNA2FUCh9ImE= github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= +github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= +github.com/libp2p/go-openssl v0.1.0 h1:LBkKEcUv6vtZIQLVTegAil8jbNpJErQ9AnT+bWV+Ooo= +github.com/libp2p/go-reuseport v0.2.0 h1:18PRvIMlpY6ZK85nIAicSBuXXvrYoSw3dsBAR7zc560= github.com/libp2p/go-yamux/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rBfZQ= +github.com/libp2p/zeroconf/v2 v2.2.0 h1:Cup06Jv6u81HLhIj1KasuNM/RHHrJ8T7wOTS4+Tv53Q= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= +github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI= github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= @@ -246,12 +292,17 @@ github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXS github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 h1:BvoENQQU+fZ9uukda/RzCAL/191HHwJA5b13R6diVlY= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= +github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= +github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -270,12 +321,14 @@ github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO github.com/prometheus/procfs v0.10.0 h1:UkG7GPYkO4UZyLnyXjaWYcgOSONqwdBqFUT95ugmt6I= github.com/prometheus/procfs v0.10.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= +github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U= github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U= github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E= github.com/quic-go/quic-go v0.34.0 h1:OvOJ9LFjTySgwOTYUZmNoq0FzVicP8YujpV0kB7m2lU= github.com/quic-go/quic-go v0.34.0/go.mod h1:+4CVgVppm0FNjpG3UcX8Joi/frKOH7/ciD5yGcwOO1g= github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU= github.com/quic-go/webtransport-go v0.5.3/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU= +github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= @@ -283,16 +336,19 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/warpfork/go-testmark v0.11.0 h1:J6LnV8KpceDvo7spaNU4+DauH2n1x+6RaO2rJrmpQ9U= @@ -303,10 +359,13 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158 h1:WXhVOwj2 github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= +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/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= @@ -324,12 +383,15 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/dig v1.16.1 h1:+alNIBsl0qfY0j6epRubp/9obgtrObRAc5aD+6jbWY8= +go.uber.org/fx v1.19.2 h1:SyFgYQFr1Wl0AYstE8vyYIzP4bFz2URrScjwC4cwUvY= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +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.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= @@ -350,6 +412,7 @@ golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERs golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/image v0.6.0 h1:bR8b5okrPI3g/gyZakLZHeWxAR8Dn5CyxXv1hLH5g/4= golang.org/x/image v0.6.0/go.mod h1:MXLdDR43H7cDJq5GEGXEVeeNhPgi+YYEQ2pC1byI1x0= +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/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -370,6 +433,7 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -403,6 +467,7 @@ golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXR golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -430,6 +495,7 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= @@ -438,6 +504,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -446,8 +513,10 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +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= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= storj.io/drpc v0.0.33 h1:yCGZ26r66ZdMP0IcTYsj7WDAUIIjzXk6DJhbhvt9FHI= storj.io/drpc v0.0.33/go.mod h1:vR804UNzhBa49NOJ6HeLjd2H3MakC1j5Gv8bsOQT6N4= diff --git a/net/timeoutconn/conn.go b/net/connutil/timeout.go similarity index 82% rename from net/timeoutconn/conn.go rename to net/connutil/timeout.go index 11e80709..381998f9 100644 --- a/net/timeoutconn/conn.go +++ b/net/connutil/timeout.go @@ -1,4 +1,4 @@ -package timeoutconn +package connutil import ( "errors" @@ -10,18 +10,18 @@ import ( "go.uber.org/zap" ) -var log = logger.NewNamed("common.net.timeoutconn") +var log = logger.NewNamed("common.net.connutil") -type Conn struct { +type TimeoutConn struct { net.Conn timeout time.Duration } -func NewConn(conn net.Conn, timeout time.Duration) *Conn { - return &Conn{conn, timeout} +func NewConn(conn net.Conn, timeout time.Duration) *TimeoutConn { + return &TimeoutConn{conn, timeout} } -func (c *Conn) Write(p []byte) (n int, err error) { +func (c *TimeoutConn) Write(p []byte) (n int, err error) { for { if c.timeout != 0 { if e := c.Conn.SetWriteDeadline(time.Now().Add(c.timeout)); e != nil { diff --git a/net/connutil/usage.go b/net/connutil/usage.go new file mode 100644 index 00000000..826d9c74 --- /dev/null +++ b/net/connutil/usage.go @@ -0,0 +1,30 @@ +package connutil + +import ( + "go.uber.org/atomic" + "net" + "time" +) + +func NewLastUsageConn(conn net.Conn) *LastUsageConn { + return &LastUsageConn{Conn: conn} +} + +type LastUsageConn struct { + net.Conn + lastUsage atomic.Time +} + +func (c *LastUsageConn) Write(p []byte) (n int, err error) { + c.lastUsage.Store(time.Now()) + return c.Conn.Write(p) +} + +func (c *LastUsageConn) Read(p []byte) (n int, err error) { + c.lastUsage.Store(time.Now()) + return c.Conn.Read(p) +} + +func (c *LastUsageConn) LastUsage() time.Time { + return c.lastUsage.Load() +} diff --git a/net/dialer/dialer.go b/net/dialer/dialer.go index 8d49c4a9..f585c1b4 100644 --- a/net/dialer/dialer.go +++ b/net/dialer/dialer.go @@ -7,10 +7,10 @@ import ( "github.com/anyproto/any-sync/app" "github.com/anyproto/any-sync/app/logger" net2 "github.com/anyproto/any-sync/net" + "github.com/anyproto/any-sync/net/connutil" "github.com/anyproto/any-sync/net/peer" "github.com/anyproto/any-sync/net/secureservice" "github.com/anyproto/any-sync/net/secureservice/handshake" - "github.com/anyproto/any-sync/net/timeoutconn" "github.com/anyproto/any-sync/nodeconf" "github.com/libp2p/go-libp2p/core/sec" "go.uber.org/zap" @@ -118,7 +118,7 @@ func (d *dialer) handshake(ctx context.Context, addr, peerId string) (conn drpc. return nil, nil, fmt.Errorf("dialTimeout error: %v; since start: %v", err, time.Since(st)) } - timeoutConn := timeoutconn.NewConn(tcpConn, time.Millisecond*time.Duration(d.config.Stream.TimeoutMilliseconds)) + timeoutConn := connutil.NewConn(tcpConn, time.Millisecond*time.Duration(d.config.Stream.TimeoutMilliseconds)) sc, err = d.transport.SecureOutbound(ctx, timeoutConn) if err != nil { if he, ok := err.(handshake.HandshakeError); ok { diff --git a/net/pool/pool.go b/net/pool/pool.go index b6c0d7df..bd0b58eb 100644 --- a/net/pool/pool.go +++ b/net/pool/pool.go @@ -13,31 +13,35 @@ import ( // Pool creates and caches outgoing connection type Pool interface { - // Get lookups to peer in existing connections or creates and cache new one + // Get lookups to peer in existing connections or creates and outgoing new one Get(ctx context.Context, id string) (peer.Peer, error) - // Dial creates new connection to peer and not use cache - Dial(ctx context.Context, id string) (peer.Peer, error) - // GetOneOf searches at least one existing connection in cache or creates a new one from a randomly selected id from given list + // GetOneOf searches at least one existing connection in outgoing or creates a new one from a randomly selected id from given list GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) - - DialOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) + // AddPeer adds incoming peer to the pool + AddPeer(ctx context.Context, p peer.Peer) (err error) } type pool struct { - cache ocache.OCache - dialer dialer.Dialer + outgoing ocache.OCache + incoming ocache.OCache + dialer dialer.Dialer } func (p *pool) Name() (name string) { return CName } -func (p *pool) Run(ctx context.Context) (err error) { - return nil +func (p *pool) Get(ctx context.Context, id string) (pr peer.Peer, err error) { + // if we have incoming connection - try to reuse it + if pr, err = p.get(ctx, p.incoming, id); err != nil { + // or try to get or create outgoing + return p.get(ctx, p.outgoing, id) + } + return } -func (p *pool) Get(ctx context.Context, id string) (peer.Peer, error) { - v, err := p.cache.Get(ctx, id) +func (p *pool) get(ctx context.Context, source ocache.OCache, id string) (peer.Peer, error) { + v, err := source.Get(ctx, id) if err != nil { return nil, err } @@ -47,7 +51,7 @@ func (p *pool) Get(ctx context.Context, id string) (peer.Peer, error) { default: return pr, nil } - _, _ = p.cache.Remove(ctx, id) + _, _ = source.Remove(ctx, id) return p.Get(ctx, id) } @@ -58,14 +62,23 @@ func (p *pool) Dial(ctx context.Context, id string) (peer.Peer, error) { func (p *pool) GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) { // finding existing connection for _, peerId := range peerIds { - if v, err := p.cache.Pick(ctx, peerId); err == nil { + if v, err := p.incoming.Pick(ctx, peerId); err == nil { pr := v.(peer.Peer) select { case <-pr.Closed(): default: return pr, nil } - _, _ = p.cache.Remove(ctx, peerId) + _, _ = p.incoming.Remove(ctx, peerId) + } + if v, err := p.outgoing.Pick(ctx, peerId); err == nil { + pr := v.(peer.Peer) + select { + case <-pr.Closed(): + default: + return pr, nil + } + _, _ = p.outgoing.Remove(ctx, peerId) } } // shuffle ids for better consistency @@ -75,8 +88,8 @@ func (p *pool) GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error // connecting var lastErr error for _, peerId := range peerIds { - if v, err := p.cache.Get(ctx, peerId); err == nil { - return v.(peer.Peer), nil + if v, err := p.Get(ctx, peerId); err == nil { + return v, nil } else { log.Debug("unable to connect", zap.String("peerId", peerId), zap.Error(err)) lastErr = err @@ -88,27 +101,6 @@ func (p *pool) GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error return nil, lastErr } -func (p *pool) DialOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) { - // shuffle ids for better consistency - rand.Shuffle(len(peerIds), func(i, j int) { - peerIds[i], peerIds[j] = peerIds[j], peerIds[i] - }) - // connecting - var lastErr error - for _, peerId := range peerIds { - if v, err := p.dialer.Dial(ctx, peerId); err == nil { - return v.(peer.Peer), nil - } else { - log.Debug("unable to connect", zap.String("peerId", peerId), zap.Error(err)) - lastErr = err - } - } - if _, ok := lastErr.(handshake.HandshakeError); !ok { - lastErr = net.ErrUnableToConnect - } - return nil, lastErr -} - -func (p *pool) Close(ctx context.Context) (err error) { - return p.cache.Close() +func (p *pool) AddPeer(ctx context.Context, pr peer.Peer) (err error) { + return p.incoming.Add(pr.Id(), pr) } diff --git a/net/pool/poolservice.go b/net/pool/poolservice.go index 9b69ae24..68daafc5 100644 --- a/net/pool/poolservice.go +++ b/net/pool/poolservice.go @@ -8,6 +8,7 @@ import ( "github.com/anyproto/any-sync/metric" "github.com/anyproto/any-sync/net/dialer" "github.com/prometheus/client_golang/prometheus" + "go.uber.org/zap" "time" ) @@ -23,7 +24,6 @@ func New() Service { type Service interface { Pool - NewPool(name string) Pool app.ComponentRunnable } @@ -40,29 +40,34 @@ func (p *poolService) Init(a *app.App) (err error) { if m := a.Component(metric.CName); m != nil { p.metricReg = m.(metric.Metric).Registry() } - p.pool.cache = ocache.New( + p.pool.outgoing = ocache.New( func(ctx context.Context, id string) (value ocache.Object, err error) { return p.dialer.Dial(ctx, id) }, ocache.WithLogger(log.Sugar()), ocache.WithGCPeriod(time.Minute), ocache.WithTTL(time.Minute*5), - ocache.WithPrometheus(p.metricReg, "netpool", "default"), + ocache.WithPrometheus(p.metricReg, "netpool", "outgoing"), + ) + p.pool.incoming = ocache.New( + func(ctx context.Context, id string) (value ocache.Object, err error) { + return nil, ocache.ErrNotExists + }, + ocache.WithLogger(log.Sugar()), + ocache.WithGCPeriod(time.Minute), + ocache.WithTTL(time.Minute*5), + ocache.WithPrometheus(p.metricReg, "netpool", "incoming"), ) return nil } -func (p *poolService) NewPool(name string) Pool { - return &pool{ - dialer: p.dialer, - cache: ocache.New( - func(ctx context.Context, id string) (value ocache.Object, err error) { - return p.dialer.Dial(ctx, id) - }, - ocache.WithLogger(log.Sugar()), - ocache.WithGCPeriod(time.Minute), - ocache.WithTTL(time.Minute*5), - ocache.WithPrometheus(p.metricReg, "netpool", name), - ), - } +func (p *pool) Run(ctx context.Context) (err error) { + return nil +} + +func (p *pool) Close(ctx context.Context) (err error) { + if e := p.incoming.Close(); e != nil { + log.Warn("close incoming cache error", zap.Error(e)) + } + return p.outgoing.Close() } diff --git a/net/secureservice/secureservice.go b/net/secureservice/secureservice.go index d7d86040..4faca6c0 100644 --- a/net/secureservice/secureservice.go +++ b/net/secureservice/secureservice.go @@ -25,7 +25,7 @@ func New() SecureService { } type SecureService interface { - SecureOutbound(ctx context.Context, conn net.Conn) (sec.SecureConn, error) + SecureOutbound(ctx context.Context, conn net.Conn) (cctx context.Context, sc sec.SecureConn, err error) SecureInbound(ctx context.Context, conn net.Conn) (cctx context.Context, sc sec.SecureConn, err error) app.Component } @@ -93,10 +93,10 @@ func (s *secureService) SecureInbound(ctx context.Context, conn net.Conn) (cctx return } -func (s *secureService) SecureOutbound(ctx context.Context, conn net.Conn) (sec.SecureConn, error) { - sc, err := s.p2pTr.SecureOutbound(ctx, conn, "") +func (s *secureService) SecureOutbound(ctx context.Context, conn net.Conn) (cctx context.Context, sc sec.SecureConn, err error) { + sc, err = s.p2pTr.SecureOutbound(ctx, conn, "") if err != nil { - return nil, handshake.HandshakeError{Err: err} + return nil, nil, handshake.HandshakeError{Err: err} } peerId := sc.RemotePeer().String() confTypes := s.nodeconf.NodeTypes(peerId) @@ -106,10 +106,12 @@ func (s *secureService) SecureOutbound(ctx context.Context, conn net.Conn) (sec. } else { checker = s.noVerifyChecker } - // ignore identity for outgoing connection because we don't need it at this moment - _, err = handshake.OutgoingHandshake(ctx, sc, checker) + identity, err := handshake.OutgoingHandshake(ctx, sc, checker) if err != nil { - return nil, err + return nil, nil, err } - return sc, nil + cctx = context.Background() + cctx = peer.CtxWithPeerId(cctx, sc.RemotePeer().String()) + cctx = peer.CtxWithIdentity(cctx, identity) + return cctx, sc, nil } diff --git a/net/secureservice/secureservice_test.go b/net/secureservice/secureservice_test.go index 2f435a65..e03b92a4 100644 --- a/net/secureservice/secureservice_test.go +++ b/net/secureservice/secureservice_test.go @@ -39,9 +39,12 @@ func TestHandshake(t *testing.T) { fxC := newFixture(t, nc, nc.GetAccountService(1), 0) defer fxC.Finish(t) - secConn, err := fxC.SecureOutbound(ctx, cc) + cctx, secConn, err := fxC.SecureOutbound(ctx, cc) + require.NoError(t, err) + ctxPeerId, err := peer.CtxPeerId(cctx) require.NoError(t, err) assert.Equal(t, nc.GetAccountService(0).Account().PeerId, secConn.RemotePeer().String()) + assert.Equal(t, nc.GetAccountService(0).Account().PeerId, ctxPeerId) res := <-resCh require.NoError(t, res.err) peerId, err := peer.CtxPeerId(res.ctx) @@ -72,7 +75,7 @@ func TestHandshakeIncompatibleVersion(t *testing.T) { }() fxC := newFixture(t, nc, nc.GetAccountService(1), 1) defer fxC.Finish(t) - _, err := fxC.SecureOutbound(ctx, cc) + _, _, err := fxC.SecureOutbound(ctx, cc) require.Equal(t, handshake.ErrIncompatibleVersion, err) res := <-resCh require.Equal(t, handshake.ErrIncompatibleVersion, res.err) diff --git a/net/transport/transport.go b/net/transport/transport.go new file mode 100644 index 00000000..3eba1414 --- /dev/null +++ b/net/transport/transport.go @@ -0,0 +1,34 @@ +package transport + +import ( + "context" + "net" + "time" +) + +// Transport is a common interface for a network transport +type Transport interface { + // SetAccepter sets accepter that will be called for new connections + // this method should be called before app start + SetAccepter(accepter Accepter) + // Dial creates a new connection by given address + Dial(ctx context.Context, addr string) (mc MultiConn, err error) +} + +// MultiConn is an object of multiplexing connection containing handshake info +type MultiConn interface { + // Context returns the connection context that contains handshake details + Context() context.Context + // Accept accepts new sub connections + Accept() (conn net.Conn, err error) + // Open opens new sub connection + Open(ctx context.Context) (conn net.Conn, err error) + // LastUsage returns the time of the last connection activity + LastUsage() time.Time + // Close closes the connection and all sub connections + Close() error +} + +type Accepter interface { + Accept(mc MultiConn) (err error) +} diff --git a/net/transport/yamux/config.go b/net/transport/yamux/config.go new file mode 100644 index 00000000..38f74d4b --- /dev/null +++ b/net/transport/yamux/config.go @@ -0,0 +1,12 @@ +package yamux + +type configGetter interface { + GetYamux() Config +} + +type Config struct { + ListenAddrs []string `yaml:"listenAddrs"` + WriteTimeoutSec int `yaml:"writeTimeoutSec"` + DialTimeoutSec int `yaml:"dialTimeoutSec"` + MaxStreams int `yaml:"maxStreams"` +} diff --git a/net/transport/yamux/conn.go b/net/transport/yamux/conn.go new file mode 100644 index 00000000..e9ad7f59 --- /dev/null +++ b/net/transport/yamux/conn.go @@ -0,0 +1,27 @@ +package yamux + +import ( + "context" + "github.com/anyproto/any-sync/net/connutil" + "github.com/hashicorp/yamux" + "net" + "time" +) + +type yamuxConn struct { + ctx context.Context + luConn *connutil.LastUsageConn + *yamux.Session +} + +func (y *yamuxConn) Open(ctx context.Context) (conn net.Conn, err error) { + return y.Session.Open() +} + +func (y *yamuxConn) LastUsage() time.Time { + return y.luConn.LastUsage() +} + +func (y *yamuxConn) Context() context.Context { + return y.ctx +} diff --git a/net/transport/yamux/util.go b/net/transport/yamux/util.go new file mode 100644 index 00000000..c1299d15 --- /dev/null +++ b/net/transport/yamux/util.go @@ -0,0 +1,18 @@ +//go:build !windows + +package yamux + +import ( + "errors" + "net" +) + +// isTemporary checks if an error is temporary. +func isTemporary(err error) bool { + var nErr net.Error + if errors.As(err, &nErr) { + return nErr.Temporary() + } + + return false +} diff --git a/net/transport/yamux/util_windows.go b/net/transport/yamux/util_windows.go new file mode 100644 index 00000000..390524d5 --- /dev/null +++ b/net/transport/yamux/util_windows.go @@ -0,0 +1,41 @@ +//go:build windows + +package yamux + +import ( + "errors" + "net" + "os" + "syscall" +) + +const ( + _WSAEMFILE syscall.Errno = 10024 + _WSAENETRESET syscall.Errno = 10052 + _WSAENOBUFS syscall.Errno = 10055 +) + +// isTemporary checks if an error is temporary. +// see related go issue for more detail: https://go-review.googlesource.com/c/go/+/208537/ +func isTemporary(err error) bool { + var nErr net.Error + if !errors.As(err, &nErr) { + return false + } + + if nErr.Temporary() { + return true + } + + var sErr *os.SyscallError + if errors.As(err, &sErr) { + switch sErr.Err { + case _WSAENETRESET, + _WSAEMFILE, + _WSAENOBUFS: + return true + } + } + + return false +} diff --git a/net/transport/yamux/yamux.go b/net/transport/yamux/yamux.go new file mode 100644 index 00000000..9d73c1f1 --- /dev/null +++ b/net/transport/yamux/yamux.go @@ -0,0 +1,168 @@ +package yamux + +import ( + "context" + "fmt" + "github.com/anyproto/any-sync/app" + "github.com/anyproto/any-sync/app/logger" + "github.com/anyproto/any-sync/net/connutil" + "github.com/anyproto/any-sync/net/secureservice" + "github.com/anyproto/any-sync/net/transport" + "github.com/hashicorp/yamux" + "go.uber.org/zap" + "net" + "time" +) + +const CName = "net.transport.yamux" + +var log = logger.NewNamed(CName) + +func New() Yamux { + return new(yamuxTransport) +} + +// Yamux implements transport.Transport with tcp+yamux +type Yamux interface { + transport.Transport + app.ComponentRunnable +} + +type yamuxTransport struct { + secure secureservice.SecureService + accepter transport.Accepter + conf Config + + listeners []net.Listener + listCtx context.Context + listCtxCancel context.CancelFunc + yamuxConf *yamux.Config +} + +func (y *yamuxTransport) Init(a *app.App) (err error) { + y.secure = a.MustComponent(secureservice.CName).(secureservice.SecureService) + y.conf = a.MustComponent("config").(configGetter).GetYamux() + y.yamuxConf = yamux.DefaultConfig() + if y.conf.MaxStreams > 0 { + y.yamuxConf.AcceptBacklog = y.conf.MaxStreams + } + y.yamuxConf.EnableKeepAlive = false + y.yamuxConf.StreamOpenTimeout = time.Duration(y.conf.DialTimeoutSec) * time.Second + y.yamuxConf.ConnectionWriteTimeout = time.Duration(y.conf.WriteTimeoutSec) * time.Second + return +} + +func (y *yamuxTransport) Name() string { + return CName +} + +func (y *yamuxTransport) Run(ctx context.Context) (err error) { + if y.accepter == nil { + return fmt.Errorf("can't run service without accepter") + } + for _, listAddr := range y.conf.ListenAddrs { + list, err := net.Listen("tcp", listAddr) + if err != nil { + return err + } + y.listeners = append(y.listeners, list) + } + y.listCtx, y.listCtxCancel = context.WithCancel(context.Background()) + for _, list := range y.listeners { + go y.acceptLoop(y.listCtx, list) + } + return +} + +func (y *yamuxTransport) SetAccepter(accepter transport.Accepter) { + y.accepter = accepter +} + +func (y *yamuxTransport) Dial(ctx context.Context, addr string) (mc transport.MultiConn, err error) { + dialTimeout := time.Duration(y.conf.DialTimeoutSec) * time.Second + conn, err := net.DialTimeout("tcp", addr, dialTimeout) + if err != nil { + return nil, err + } + ctx, cancel := context.WithTimeout(ctx, dialTimeout) + defer cancel() + cctx, sc, err := y.secure.SecureOutbound(ctx, conn) + if err != nil { + _ = conn.Close() + return nil, err + } + luc := connutil.NewLastUsageConn(sc) + sess, err := yamux.Client(luc, y.yamuxConf) + if err != nil { + return + } + mc = &yamuxConn{ + ctx: cctx, + luConn: luc, + Session: sess, + } + return +} + +func (y *yamuxTransport) acceptLoop(ctx context.Context, list net.Listener) { + l := log.With(zap.String("localAddr", list.Addr().String())) + l.Info("yamux listener started") + defer func() { + l.Debug("yamux listener stopped") + }() + for { + conn, err := list.Accept() + if err != nil { + if isTemporary(err) { + l.Debug("listener temporary accept error", zap.Error(err)) + select { + case <-time.After(time.Second): + case <-ctx.Done(): + return + } + continue + } + if err != net.ErrClosed { + l.Error("listener closed with error", zap.Error(err)) + } else { + l.Info("listener closed") + } + return + } + go y.accept(conn) + } +} + +func (y *yamuxTransport) accept(conn net.Conn) { + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(y.conf.DialTimeoutSec)*time.Second) + defer cancel() + cctx, sc, err := y.secure.SecureInbound(ctx, conn) + if err != nil { + log.Warn("incoming connection handshake error", zap.Error(err)) + return + } + luc := connutil.NewLastUsageConn(sc) + sess, err := yamux.Server(luc, y.yamuxConf) + if err != nil { + log.Warn("incoming connection yamux session error", zap.Error(err)) + return + } + mc := &yamuxConn{ + ctx: cctx, + luConn: luc, + Session: sess, + } + if err = y.accepter.Accept(mc); err != nil { + log.Warn("connection accept error", zap.Error(err)) + } +} + +func (y *yamuxTransport) Close(ctx context.Context) (err error) { + if y.listCtxCancel != nil { + y.listCtxCancel() + } + for _, l := range y.listeners { + _ = l.Close() + } + return +} diff --git a/net/transport/yamux/yamux_test.go b/net/transport/yamux/yamux_test.go new file mode 100644 index 00000000..20efdfce --- /dev/null +++ b/net/transport/yamux/yamux_test.go @@ -0,0 +1,134 @@ +package yamux + +import ( + "bytes" + "context" + "github.com/anyproto/any-sync/app" + "github.com/anyproto/any-sync/net/secureservice" + "github.com/anyproto/any-sync/net/transport" + "github.com/anyproto/any-sync/nodeconf" + "github.com/anyproto/any-sync/nodeconf/mock_nodeconf" + "github.com/anyproto/any-sync/testutil/accounttest" + "github.com/anyproto/any-sync/testutil/testnodeconf" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "io" + "testing" +) + +var ctx = context.Background() + +func TestYamuxTransport_Dial(t *testing.T) { + fxS := newFixture(t) + defer fxS.finish(t) + fxC := newFixture(t) + defer fxC.finish(t) + + mcC, err := fxC.Dial(ctx, fxS.addr) + require.NoError(t, err) + require.Len(t, fxS.accepter.mcs, 1) + mcS := fxS.accepter.mcs[0] + + var ( + sData string + acceptErr error + copyErr error + done = make(chan struct{}) + ) + + go func() { + defer close(done) + conn, serr := mcS.Accept() + if serr != nil { + acceptErr = serr + return + } + buf := bytes.NewBuffer(nil) + _, copyErr = io.Copy(buf, conn) + sData = buf.String() + return + }() + + conn, err := mcC.Open(ctx) + require.NoError(t, err) + data := "some data" + _, err = conn.Write([]byte(data)) + require.NoError(t, err) + require.NoError(t, conn.Close()) + <-done + + assert.NoError(t, acceptErr) + assert.Equal(t, data, sData) + assert.NoError(t, copyErr) +} + +type fixture struct { + *yamuxTransport + a *app.App + ctrl *gomock.Controller + mockNodeConf *mock_nodeconf.MockService + acc *accounttest.AccountTestService + accepter *testAccepter + addr string +} + +func newFixture(t *testing.T) *fixture { + fx := &fixture{ + yamuxTransport: New().(*yamuxTransport), + ctrl: gomock.NewController(t), + acc: &accounttest.AccountTestService{}, + accepter: &testAccepter{}, + a: new(app.App), + } + + fx.mockNodeConf = mock_nodeconf.NewMockService(fx.ctrl) + fx.mockNodeConf.EXPECT().Init(gomock.Any()) + fx.mockNodeConf.EXPECT().Name().Return(nodeconf.CName).AnyTimes() + fx.mockNodeConf.EXPECT().Run(ctx) + fx.mockNodeConf.EXPECT().Close(ctx) + fx.mockNodeConf.EXPECT().NodeTypes(gomock.Any()).Return([]nodeconf.NodeType{nodeconf.NodeTypeTree}).AnyTimes() + fx.a.Register(fx.acc).Register(newTestConf()).Register(fx.mockNodeConf).Register(secureservice.New()).Register(fx.yamuxTransport).Register(fx.accepter) + require.NoError(t, fx.a.Start(ctx)) + fx.addr = fx.listeners[0].Addr().String() + return fx +} + +func (fx *fixture) finish(t *testing.T) { + require.NoError(t, fx.a.Close(ctx)) + fx.ctrl.Finish() +} + +func newTestConf() *testConf { + return &testConf{testnodeconf.GenNodeConfig(1)} +} + +type testConf struct { + *testnodeconf.Config +} + +func (c *testConf) GetYamux() Config { + return Config{ + ListenAddrs: []string{"127.0.0.1:0"}, + WriteTimeoutSec: 10, + DialTimeoutSec: 10, + MaxStreams: 1024, + } +} + +type testAccepter struct { + err error + mcs []transport.MultiConn +} + +func (t *testAccepter) Accept(mc transport.MultiConn) (err error) { + t.mcs = append(t.mcs, mc) + return t.err +} + +func (t *testAccepter) Init(a *app.App) (err error) { + a.MustComponent(CName).(transport.Transport).SetAccepter(t) + return nil +} + +func (t *testAccepter) Name() (name string) { return "testAccepter" } From 7958b43da6636f742f848b30e98d19f28b8da4a9 Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Fri, 26 May 2023 20:06:22 +0200 Subject: [PATCH 02/11] peer service --- net/dialer/dialer.go | 137 --------------------------------- net/peer/peer.go | 75 +++--------------- net/peerservice/peerservice.go | 107 +++++++++++++++++++++++++ net/pool/pool.go | 22 ++---- net/pool/pool_test.go | 39 ++++++---- net/pool/poolservice.go | 12 ++- net/transport/transport.go | 4 + net/transport/yamux/conn.go | 5 ++ net/transport/yamux/yamux.go | 2 + 9 files changed, 167 insertions(+), 236 deletions(-) delete mode 100644 net/dialer/dialer.go create mode 100644 net/peerservice/peerservice.go diff --git a/net/dialer/dialer.go b/net/dialer/dialer.go deleted file mode 100644 index f585c1b4..00000000 --- a/net/dialer/dialer.go +++ /dev/null @@ -1,137 +0,0 @@ -package dialer - -import ( - "context" - "errors" - "fmt" - "github.com/anyproto/any-sync/app" - "github.com/anyproto/any-sync/app/logger" - net2 "github.com/anyproto/any-sync/net" - "github.com/anyproto/any-sync/net/connutil" - "github.com/anyproto/any-sync/net/peer" - "github.com/anyproto/any-sync/net/secureservice" - "github.com/anyproto/any-sync/net/secureservice/handshake" - "github.com/anyproto/any-sync/nodeconf" - "github.com/libp2p/go-libp2p/core/sec" - "go.uber.org/zap" - "net" - "storj.io/drpc" - "storj.io/drpc/drpcconn" - "storj.io/drpc/drpcmanager" - "storj.io/drpc/drpcwire" - "sync" - "time" -) - -const CName = "common.net.dialer" - -var ( - ErrAddrsNotFound = errors.New("addrs for peer not found") - ErrPeerIdIsUnexpected = errors.New("expected to connect with other peer id") -) - -var log = logger.NewNamed(CName) - -func New() Dialer { - return &dialer{peerAddrs: map[string][]string{}} -} - -type Dialer interface { - Dial(ctx context.Context, peerId string) (peer peer.Peer, err error) - SetPeerAddrs(peerId string, addrs []string) - app.Component -} - -type dialer struct { - transport secureservice.SecureService - config net2.Config - nodeConf nodeconf.NodeConf - peerAddrs map[string][]string - - mu sync.RWMutex -} - -func (d *dialer) Init(a *app.App) (err error) { - d.transport = a.MustComponent(secureservice.CName).(secureservice.SecureService) - d.nodeConf = a.MustComponent(nodeconf.CName).(nodeconf.NodeConf) - d.config = a.MustComponent("config").(net2.ConfigGetter).GetNet() - return -} - -func (d *dialer) Name() (name string) { - return CName -} - -func (d *dialer) SetPeerAddrs(peerId string, addrs []string) { - d.mu.Lock() - defer d.mu.Unlock() - d.peerAddrs[peerId] = addrs -} - -func (d *dialer) getPeerAddrs(peerId string) ([]string, error) { - if addrs, ok := d.nodeConf.PeerAddresses(peerId); ok { - return addrs, nil - } - addrs, ok := d.peerAddrs[peerId] - if !ok || len(addrs) == 0 { - return nil, ErrAddrsNotFound - } - return addrs, nil -} - -func (d *dialer) Dial(ctx context.Context, peerId string) (p peer.Peer, err error) { - var ctxCancel context.CancelFunc - ctx, ctxCancel = context.WithTimeout(ctx, time.Second*10) - defer ctxCancel() - d.mu.RLock() - defer d.mu.RUnlock() - - addrs, err := d.getPeerAddrs(peerId) - if err != nil { - return - } - - var ( - conn drpc.Conn - sc sec.SecureConn - ) - log.InfoCtx(ctx, "dial", zap.String("peerId", peerId), zap.Strings("addrs", addrs)) - for _, addr := range addrs { - conn, sc, err = d.handshake(ctx, addr, peerId) - if err != nil { - log.InfoCtx(ctx, "can't connect to host", zap.String("addr", addr), zap.Error(err)) - } else { - break - } - } - if err != nil { - return - } - return peer.NewPeer(sc, conn), nil -} - -func (d *dialer) handshake(ctx context.Context, addr, peerId string) (conn drpc.Conn, sc sec.SecureConn, err error) { - st := time.Now() - // TODO: move dial timeout to config - tcpConn, err := net.DialTimeout("tcp", addr, time.Second*3) - if err != nil { - return nil, nil, fmt.Errorf("dialTimeout error: %v; since start: %v", err, time.Since(st)) - } - - timeoutConn := connutil.NewConn(tcpConn, time.Millisecond*time.Duration(d.config.Stream.TimeoutMilliseconds)) - sc, err = d.transport.SecureOutbound(ctx, timeoutConn) - if err != nil { - if he, ok := err.(handshake.HandshakeError); ok { - return nil, nil, he - } - return nil, nil, fmt.Errorf("tls handshaeke error: %v; since start: %v", err, time.Since(st)) - } - if peerId != sc.RemotePeer().String() { - return nil, nil, ErrPeerIdIsUnexpected - } - log.Info("connected with remote host", zap.String("serverPeer", sc.RemotePeer().String()), zap.String("addr", addr)) - conn = drpcconn.NewWithOptions(sc, drpcconn.Options{Manager: drpcmanager.Options{ - Reader: drpcwire.ReaderOptions{MaximumBufferSize: d.config.Stream.MaxMsgSizeMb * (1 << 20)}, - }}) - return conn, sc, err -} diff --git a/net/peer/peer.go b/net/peer/peer.go index 99304ebe..cfe0b636 100644 --- a/net/peer/peer.go +++ b/net/peer/peer.go @@ -1,85 +1,39 @@ package peer import ( - "context" - "sync/atomic" + "github.com/anyproto/any-sync/net/transport" "time" "github.com/anyproto/any-sync/app/logger" - "github.com/libp2p/go-libp2p/core/sec" "go.uber.org/zap" - "storj.io/drpc" ) var log = logger.NewNamed("common.net.peer") -func NewPeer(sc sec.SecureConn, conn drpc.Conn) Peer { - return &peer{ - id: sc.RemotePeer().String(), - lastUsage: time.Now().Unix(), - sc: sc, - Conn: conn, +func NewPeer(mc transport.MultiConn) (p Peer, err error) { + ctx := mc.Context() + pr := &peer{} + if pr.id, err = CtxPeerId(ctx); err != nil { + return } + return pr, nil } type Peer interface { Id() string - LastUsage() time.Time - UpdateLastUsage() - Addr() string TryClose(objectTTL time.Duration) (res bool, err error) - drpc.Conn + transport.MultiConn } type peer struct { - id string - ttl time.Duration - lastUsage int64 - sc sec.SecureConn - drpc.Conn + id string + transport.MultiConn } func (p *peer) Id() string { return p.id } -func (p *peer) LastUsage() time.Time { - select { - case <-p.Closed(): - return time.Unix(0, 0) - default: - } - return time.Unix(atomic.LoadInt64(&p.lastUsage), 0) -} - -func (p *peer) Invoke(ctx context.Context, rpc string, enc drpc.Encoding, in, out drpc.Message) error { - defer p.UpdateLastUsage() - return p.Conn.Invoke(ctx, rpc, enc, in, out) -} - -func (p *peer) NewStream(ctx context.Context, rpc string, enc drpc.Encoding) (drpc.Stream, error) { - defer p.UpdateLastUsage() - return p.Conn.NewStream(ctx, rpc, enc) -} - -func (p *peer) Read(b []byte) (n int, err error) { - if n, err = p.sc.Read(b); err != nil { - p.UpdateLastUsage() - } - return -} - -func (p *peer) Write(b []byte) (n int, err error) { - if n, err = p.sc.Write(b); err != nil { - p.UpdateLastUsage() - } - return -} - -func (p *peer) UpdateLastUsage() { - atomic.StoreInt64(&p.lastUsage, time.Now().Unix()) -} - func (p *peer) TryClose(objectTTL time.Duration) (res bool, err error) { if time.Now().Sub(p.LastUsage()) < objectTTL { return false, nil @@ -87,14 +41,7 @@ func (p *peer) TryClose(objectTTL time.Duration) (res bool, err error) { return true, p.Close() } -func (p *peer) Addr() string { - if p.sc != nil { - return p.sc.RemoteAddr().String() - } - return "" -} - func (p *peer) Close() (err error) { log.Debug("peer close", zap.String("peerId", p.id)) - return p.Conn.Close() + return p.MultiConn.Close() } diff --git a/net/peerservice/peerservice.go b/net/peerservice/peerservice.go new file mode 100644 index 00000000..3394c5e8 --- /dev/null +++ b/net/peerservice/peerservice.go @@ -0,0 +1,107 @@ +package peerservice + +import ( + "context" + "errors" + "github.com/anyproto/any-sync/app" + "github.com/anyproto/any-sync/app/logger" + "github.com/anyproto/any-sync/net/peer" + "github.com/anyproto/any-sync/net/pool" + "github.com/anyproto/any-sync/net/transport" + "github.com/anyproto/any-sync/net/transport/yamux" + "github.com/anyproto/any-sync/nodeconf" + "go.uber.org/zap" + "sync" +) + +const CName = "net.peerservice" + +var log = logger.NewNamed(CName) + +var ( + ErrAddrsNotFound = errors.New("addrs for peer not found") +) + +func New() PeerService { + return new(peerService) +} + +type PeerService interface { + Dial(ctx context.Context, peerId string) (pr peer.Peer, err error) + SetPeerAddrs(peerId string, addrs []string) + transport.Accepter + app.Component +} + +type peerService struct { + yamux transport.Transport + nodeConf nodeconf.NodeConf + peerAddrs map[string][]string + pool pool.Pool + mu sync.RWMutex +} + +func (p *peerService) Init(a *app.App) (err error) { + p.yamux = a.MustComponent(yamux.CName).(transport.Transport) + p.nodeConf = a.MustComponent(nodeconf.CName).(nodeconf.NodeConf) + p.pool = a.MustComponent(pool.CName).(pool.Pool) + p.peerAddrs = map[string][]string{} + return nil +} + +func (p *peerService) Name() (name string) { + return CName +} + +func (p *peerService) Dial(ctx context.Context, peerId string) (pr peer.Peer, err error) { + p.mu.RLock() + defer p.mu.RUnlock() + + addrs, err := p.getPeerAddrs(peerId) + if err != nil { + return + } + + var mc transport.MultiConn + log.InfoCtx(ctx, "dial", zap.String("peerId", peerId), zap.Strings("addrs", addrs)) + for _, addr := range addrs { + mc, err = p.yamux.Dial(ctx, addr) + if err != nil { + log.InfoCtx(ctx, "can't connect to host", zap.String("addr", addr), zap.Error(err)) + } else { + break + } + } + if err != nil { + return + } + return peer.NewPeer(mc) +} + +func (p *peerService) Accept(mc transport.MultiConn) (err error) { + pr, err := peer.NewPeer(mc) + if err != nil { + return err + } + if err = p.pool.AddPeer(pr); err != nil { + _ = pr.Close() + } + return +} + +func (p *peerService) SetPeerAddrs(peerId string, addrs []string) { + p.mu.Lock() + defer p.mu.Unlock() + p.peerAddrs[peerId] = addrs +} + +func (p *peerService) getPeerAddrs(peerId string) ([]string, error) { + if addrs, ok := p.nodeConf.PeerAddresses(peerId); ok { + return addrs, nil + } + addrs, ok := p.peerAddrs[peerId] + if !ok || len(addrs) == 0 { + return nil, ErrAddrsNotFound + } + return addrs, nil +} diff --git a/net/pool/pool.go b/net/pool/pool.go index bd0b58eb..f36318df 100644 --- a/net/pool/pool.go +++ b/net/pool/pool.go @@ -4,7 +4,6 @@ import ( "context" "github.com/anyproto/any-sync/app/ocache" "github.com/anyproto/any-sync/net" - "github.com/anyproto/any-sync/net/dialer" "github.com/anyproto/any-sync/net/peer" "github.com/anyproto/any-sync/net/secureservice/handshake" "go.uber.org/zap" @@ -18,13 +17,12 @@ type Pool interface { // GetOneOf searches at least one existing connection in outgoing or creates a new one from a randomly selected id from given list GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) // AddPeer adds incoming peer to the pool - AddPeer(ctx context.Context, p peer.Peer) (err error) + AddPeer(p peer.Peer) (err error) } type pool struct { outgoing ocache.OCache incoming ocache.OCache - dialer dialer.Dialer } func (p *pool) Name() (name string) { @@ -46,36 +44,26 @@ func (p *pool) get(ctx context.Context, source ocache.OCache, id string) (peer.P return nil, err } pr := v.(peer.Peer) - select { - case <-pr.Closed(): - default: + if !pr.IsClosed() { return pr, nil } _, _ = source.Remove(ctx, id) return p.Get(ctx, id) } -func (p *pool) Dial(ctx context.Context, id string) (peer.Peer, error) { - return p.dialer.Dial(ctx, id) -} - func (p *pool) GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) { // finding existing connection for _, peerId := range peerIds { if v, err := p.incoming.Pick(ctx, peerId); err == nil { pr := v.(peer.Peer) - select { - case <-pr.Closed(): - default: + if !pr.IsClosed() { return pr, nil } _, _ = p.incoming.Remove(ctx, peerId) } if v, err := p.outgoing.Pick(ctx, peerId); err == nil { pr := v.(peer.Peer) - select { - case <-pr.Closed(): - default: + if !pr.IsClosed() { return pr, nil } _, _ = p.outgoing.Remove(ctx, peerId) @@ -101,6 +89,6 @@ func (p *pool) GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error return nil, lastErr } -func (p *pool) AddPeer(ctx context.Context, pr peer.Peer) (err error) { +func (p *pool) AddPeer(pr peer.Peer) (err error) { return p.incoming.Add(pr.Id(), pr) } diff --git a/net/pool/pool_test.go b/net/pool/pool_test.go index c82533e8..71bfa1c6 100644 --- a/net/pool/pool_test.go +++ b/net/pool/pool_test.go @@ -6,12 +6,11 @@ import ( "fmt" "github.com/anyproto/any-sync/app" "github.com/anyproto/any-sync/net" - "github.com/anyproto/any-sync/net/dialer" "github.com/anyproto/any-sync/net/peer" "github.com/anyproto/any-sync/net/secureservice/handshake" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "storj.io/drpc" + net2 "net" "testing" "time" ) @@ -158,7 +157,7 @@ type fixture struct { t *testing.T } -var _ dialer.Dialer = (*dialerMock)(nil) +var _ dialer = (*dialerMock)(nil) type dialerMock struct { dial func(ctx context.Context, peerId string) (peer peer.Peer, err error) @@ -181,7 +180,7 @@ func (d *dialerMock) Init(a *app.App) (err error) { } func (d *dialerMock) Name() (name string) { - return dialer.CName + return "net.peerservice" } func newTestPeer(id string) *testPeer { @@ -196,6 +195,21 @@ type testPeer struct { closed chan struct{} } +func (t *testPeer) Context() context.Context { + //TODO implement me + panic("implement me") +} + +func (t *testPeer) Accept() (conn net2.Conn, err error) { + //TODO implement me + panic("implement me") +} + +func (t *testPeer) Open(ctx context.Context) (conn net2.Conn, err error) { + //TODO implement me + panic("implement me") +} + func (t *testPeer) Addr() string { return "" } @@ -224,14 +238,11 @@ func (t *testPeer) Close() error { return nil } -func (t *testPeer) Closed() <-chan struct{} { - return t.closed -} - -func (t *testPeer) Invoke(ctx context.Context, rpc string, enc drpc.Encoding, in, out drpc.Message) error { - return fmt.Errorf("call Invoke on test peer") -} - -func (t *testPeer) NewStream(ctx context.Context, rpc string, enc drpc.Encoding) (drpc.Stream, error) { - return nil, fmt.Errorf("call NewStream on test peer") +func (t *testPeer) IsClosed() bool { + select { + case <-t.closed: + return true + default: + return false + } } diff --git a/net/pool/poolservice.go b/net/pool/poolservice.go index 68daafc5..2f84e5d0 100644 --- a/net/pool/poolservice.go +++ b/net/pool/poolservice.go @@ -6,7 +6,7 @@ import ( "github.com/anyproto/any-sync/app/logger" "github.com/anyproto/any-sync/app/ocache" "github.com/anyproto/any-sync/metric" - "github.com/anyproto/any-sync/net/dialer" + "github.com/anyproto/any-sync/net/peer" "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" "time" @@ -27,16 +27,20 @@ type Service interface { app.ComponentRunnable } +type dialer interface { + Dial(ctx context.Context, peerId string) (pr peer.Peer, err error) +} + type poolService struct { // default pool *pool - dialer dialer.Dialer + dialer dialer metricReg *prometheus.Registry } func (p *poolService) Init(a *app.App) (err error) { - p.dialer = a.MustComponent(dialer.CName).(dialer.Dialer) - p.pool = &pool{dialer: p.dialer} + p.dialer = a.MustComponent("net.peerservice").(dialer) + p.pool = &pool{} if m := a.Component(metric.CName); m != nil { p.metricReg = m.(metric.Metric).Registry() } diff --git a/net/transport/transport.go b/net/transport/transport.go index 3eba1414..127c9c06 100644 --- a/net/transport/transport.go +++ b/net/transport/transport.go @@ -25,6 +25,10 @@ type MultiConn interface { Open(ctx context.Context) (conn net.Conn, err error) // LastUsage returns the time of the last connection activity LastUsage() time.Time + // Addr returns remote peer address + Addr() string + // IsClosed returns true when connection is closed + IsClosed() bool // Close closes the connection and all sub connections Close() error } diff --git a/net/transport/yamux/conn.go b/net/transport/yamux/conn.go index e9ad7f59..541b8257 100644 --- a/net/transport/yamux/conn.go +++ b/net/transport/yamux/conn.go @@ -11,6 +11,7 @@ import ( type yamuxConn struct { ctx context.Context luConn *connutil.LastUsageConn + addr string *yamux.Session } @@ -25,3 +26,7 @@ func (y *yamuxConn) LastUsage() time.Time { func (y *yamuxConn) Context() context.Context { return y.ctx } + +func (y *yamuxConn) Addr() string { + return y.addr +} diff --git a/net/transport/yamux/yamux.go b/net/transport/yamux/yamux.go index 9d73c1f1..44729392 100644 --- a/net/transport/yamux/yamux.go +++ b/net/transport/yamux/yamux.go @@ -100,6 +100,7 @@ func (y *yamuxTransport) Dial(ctx context.Context, addr string) (mc transport.Mu ctx: cctx, luConn: luc, Session: sess, + addr: addr, } return } @@ -151,6 +152,7 @@ func (y *yamuxTransport) accept(conn net.Conn) { ctx: cctx, luConn: luc, Session: sess, + addr: conn.RemoteAddr().String(), } if err = y.accepter.Accept(mc); err != nil { log.Warn("connection accept error", zap.Error(err)) From fa02cfd830292057b0c5a7758f21980e65586cb8 Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Fri, 26 May 2023 20:40:50 +0200 Subject: [PATCH 03/11] mod tidy --- go.mod | 4 ++-- go.sum | 67 ---------------------------------------------------------- 2 files changed, 2 insertions(+), 69 deletions(-) diff --git a/go.mod b/go.mod index 0f6bec3b..9ff93189 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/gogo/protobuf v1.3.2 github.com/golang/mock v1.6.0 github.com/google/uuid v1.3.0 + github.com/hashicorp/yamux v0.1.1 github.com/huandu/skiplist v1.2.0 github.com/ipfs/go-block-format v0.1.2 github.com/ipfs/go-blockservice v0.5.1 @@ -33,6 +34,7 @@ require ( github.com/tyler-smith/go-bip39 v1.1.0 github.com/zeebo/blake3 v0.2.3 github.com/zeebo/errs v1.3.0 + go.uber.org/atomic v1.11.0 go.uber.org/zap v1.24.0 golang.org/x/crypto v0.9.0 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 @@ -57,7 +59,6 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/google/pprof v0.0.0-20230510103437-eeec1cb781c3 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/hashicorp/yamux v0.1.1 // indirect github.com/huin/goupnp v1.2.0 // indirect github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/go-bitfield v1.1.0 // indirect @@ -104,7 +105,6 @@ require ( github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect go.opentelemetry.io/otel v1.7.0 // indirect go.opentelemetry.io/otel/trace v1.7.0 // indirect - go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/image v0.6.0 // indirect golang.org/x/sync v0.2.0 // indirect diff --git a/go.sum b/go.sum index 83407153..be92b35f 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,8 @@ filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= -github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/anyproto/go-chash v0.1.0 h1:I9meTPjXFRfXZHRJzjOHC/XF7Q5vzysKkiT/grsogXY= @@ -25,9 +22,6 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheggaaa/mb/v3 v3.0.1 h1:BuEOipGTqybXYi5KXVCpqhR1LWN2lrurq6UrH+VBhXc= github.com/cheggaaa/mb/v3 v3.0.1/go.mod h1:zCt2QeYukhd/g0bIdNqF+b/kKz1hnLFNDkP49qN5kqI= -github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= -github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/corona10/goimagehash v1.0.2 h1:pUfB0LnsJASMPGEZLj7tGY251vF+qLGqOgEP4rUs6kA= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= @@ -40,20 +34,12 @@ github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6Uh github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= -github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= @@ -65,7 +51,6 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/goccy/go-graphviz v0.1.1 h1:MGrsnzBxTyt7KG8FhHsFPDTGvF7UaQMmSa6A610DqPg= github.com/goccy/go-graphviz v0.1.1/go.mod h1:lpnwvVDjskayq84ZxG8tGCPeZX/WxP88W+OJajh+gFk= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -77,7 +62,6 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -86,20 +70,16 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/pprof v0.0.0-20230510103437-eeec1cb781c3 h1:2XF1Vzq06X+inNqgJ9tRnGuw+ZVCB3FazXODD6JE1R8= github.com/google/pprof v0.0.0-20230510103437-eeec1cb781c3/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= -github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= -github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= @@ -108,7 +88,6 @@ github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY= github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/ianlancetaylor/demangle v0.0.0-20220517205856-0058ec4f073c h1:rwmN+hgiyp8QyBqzdEX43lTjKAxaqCrYHaU5op5P9J8= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= @@ -133,8 +112,6 @@ github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0M github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8= 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.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro= -github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo= github.com/ipfs/go-ipfs-blockstore v1.3.0 h1:m2EXaWgwTzAfsmt5UdJ7Is6l4gJcaM/A12XwJyvYvMM= github.com/ipfs/go-ipfs-blockstore v1.3.0/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE= github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= @@ -185,23 +162,16 @@ github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvB github.com/ipld/go-ipld-prime v0.20.0 h1:Ud3VwE9ClxpO2LkCYP7vWPc0Fo+dYdYzgxUJZ3uRG4g= github.com/ipld/go-ipld-prime v0.20.0/go.mod h1:PzqZ/ZR981eKbgdr3y2DJYeD/8bgMawdGVlJDE8kK+M= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= -github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= -github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= @@ -214,7 +184,6 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -222,42 +191,29 @@ github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoR github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= -github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= github.com/libp2p/go-libp2p v0.27.3 h1:tkV/zm3KCZ4R5er9Xcs2pt0YNB4JH0iBfGAtHJdLHRs= github.com/libp2p/go-libp2p v0.27.3/go.mod h1:FAvvfQa/YOShUYdiSS03IR9OXzkcJXwcNA2FUCh9ImE= github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= -github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= -github.com/libp2p/go-openssl v0.1.0 h1:LBkKEcUv6vtZIQLVTegAil8jbNpJErQ9AnT+bWV+Ooo= -github.com/libp2p/go-reuseport v0.2.0 h1:18PRvIMlpY6ZK85nIAicSBuXXvrYoSw3dsBAR7zc560= github.com/libp2p/go-yamux/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rBfZQ= -github.com/libp2p/zeroconf/v2 v2.2.0 h1:Cup06Jv6u81HLhIj1KasuNM/RHHrJ8T7wOTS4+Tv53Q= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= -github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI= github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= @@ -292,17 +248,12 @@ github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXS github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 h1:BvoENQQU+fZ9uukda/RzCAL/191HHwJA5b13R6diVlY= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= -github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= -github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -321,14 +272,12 @@ github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO github.com/prometheus/procfs v0.10.0 h1:UkG7GPYkO4UZyLnyXjaWYcgOSONqwdBqFUT95ugmt6I= github.com/prometheus/procfs v0.10.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= -github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U= github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U= github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E= github.com/quic-go/quic-go v0.34.0 h1:OvOJ9LFjTySgwOTYUZmNoq0FzVicP8YujpV0kB7m2lU= github.com/quic-go/quic-go v0.34.0/go.mod h1:+4CVgVppm0FNjpG3UcX8Joi/frKOH7/ciD5yGcwOO1g= github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU= github.com/quic-go/webtransport-go v0.5.3/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU= -github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= @@ -336,19 +285,16 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/warpfork/go-testmark v0.11.0 h1:J6LnV8KpceDvo7spaNU4+DauH2n1x+6RaO2rJrmpQ9U= @@ -359,13 +305,10 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158 h1:WXhVOwj2 github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= -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/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= @@ -383,15 +326,12 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/dig v1.16.1 h1:+alNIBsl0qfY0j6epRubp/9obgtrObRAc5aD+6jbWY8= -go.uber.org/fx v1.19.2 h1:SyFgYQFr1Wl0AYstE8vyYIzP4bFz2URrScjwC4cwUvY= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -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.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= @@ -412,7 +352,6 @@ golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERs golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/image v0.6.0 h1:bR8b5okrPI3g/gyZakLZHeWxAR8Dn5CyxXv1hLH5g/4= golang.org/x/image v0.6.0/go.mod h1:MXLdDR43H7cDJq5GEGXEVeeNhPgi+YYEQ2pC1byI1x0= -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/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -433,7 +372,6 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -467,7 +405,6 @@ golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXR golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -495,7 +432,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= @@ -504,7 +440,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -513,10 +448,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -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= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= -nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= storj.io/drpc v0.0.33 h1:yCGZ26r66ZdMP0IcTYsj7WDAUIIjzXk6DJhbhvt9FHI= storj.io/drpc v0.0.33/go.mod h1:vR804UNzhBa49NOJ6HeLjd2H3MakC1j5Gv8bsOQT6N4= From a898c6fc9ca38ab87d960eafbed32e444caecde2 Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Mon, 29 May 2023 16:33:33 +0200 Subject: [PATCH 04/11] pool.AddPeer close previous peer --- net/pool/pool.go | 18 +++++++++++++++--- net/pool/pool_test.go | 21 +++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/net/pool/pool.go b/net/pool/pool.go index f36318df..37f8328e 100644 --- a/net/pool/pool.go +++ b/net/pool/pool.go @@ -17,7 +17,7 @@ type Pool interface { // GetOneOf searches at least one existing connection in outgoing or creates a new one from a randomly selected id from given list GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) // AddPeer adds incoming peer to the pool - AddPeer(p peer.Peer) (err error) + AddPeer(ctx context.Context, p peer.Peer) (err error) } type pool struct { @@ -89,6 +89,18 @@ func (p *pool) GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error return nil, lastErr } -func (p *pool) AddPeer(pr peer.Peer) (err error) { - return p.incoming.Add(pr.Id(), pr) +func (p *pool) AddPeer(ctx context.Context, pr peer.Peer) (err error) { + if err = p.incoming.Add(pr.Id(), pr); err != nil { + if err == ocache.ErrExists { + // in case when an incoming connection with a peer already exists, we close and remove an existing connection + if v, e := p.incoming.Pick(ctx, pr.Id()); e == nil { + _ = v.Close() + _, _ = p.incoming.Remove(ctx, pr.Id()) + return p.incoming.Add(pr.Id(), pr) + } + } else { + return err + } + } + return } diff --git a/net/pool/pool_test.go b/net/pool/pool_test.go index 71bfa1c6..b1cc0087 100644 --- a/net/pool/pool_test.go +++ b/net/pool/pool_test.go @@ -132,6 +132,27 @@ func TestPool_GetOneOf(t *testing.T) { }) } +func TestPool_AddPeer(t *testing.T) { + t.Run("success", func(t *testing.T) { + fx := newFixture(t) + defer fx.Finish() + require.NoError(t, fx.AddPeer(ctx, newTestPeer("p1"))) + }) + t.Run("two peers", func(t *testing.T) { + fx := newFixture(t) + defer fx.Finish() + p1, p2 := newTestPeer("p1"), newTestPeer("p1") + require.NoError(t, fx.AddPeer(ctx, p1)) + require.NoError(t, fx.AddPeer(ctx, p2)) + select { + case <-p1.closed: + default: + assert.Truef(t, false, "peer not closed") + } + }) + +} + func newFixture(t *testing.T) *fixture { fx := &fixture{ Service: New(), From 553ed3a64b350fa53f81864c65a5b54d810a168d Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Mon, 29 May 2023 17:56:44 +0200 Subject: [PATCH 05/11] peer drpc conn pool --- net/peer/peer.go | 59 +++++- net/peer/peer_test.go | 62 ++++++ net/peerservice/peerservice.go | 2 +- net/pool/pool_test.go | 13 +- .../mock_transport/mock_transport.go | 188 ++++++++++++++++++ net/transport/transport.go | 1 + 6 files changed, 316 insertions(+), 9 deletions(-) create mode 100644 net/peer/peer_test.go create mode 100644 net/transport/mock_transport/mock_transport.go diff --git a/net/peer/peer.go b/net/peer/peer.go index cfe0b636..df8a2799 100644 --- a/net/peer/peer.go +++ b/net/peer/peer.go @@ -1,7 +1,12 @@ package peer import ( + "context" + "github.com/anyproto/any-sync/app/ocache" "github.com/anyproto/any-sync/net/transport" + "storj.io/drpc" + "storj.io/drpc/drpcconn" + "sync" "time" "github.com/anyproto/any-sync/app/logger" @@ -12,7 +17,10 @@ var log = logger.NewNamed("common.net.peer") func NewPeer(mc transport.MultiConn) (p Peer, err error) { ctx := mc.Context() - pr := &peer{} + pr := &peer{ + active: map[drpc.Conn]struct{}{}, + MultiConn: mc, + } if pr.id, err = CtxPeerId(ctx); err != nil { return } @@ -21,12 +29,25 @@ func NewPeer(mc transport.MultiConn) (p Peer, err error) { type Peer interface { Id() string + + AcquireDrpcConn(ctx context.Context) (drpc.Conn, error) + ReleaseDrpcConn(conn drpc.Conn) + + IsClosed() bool + TryClose(objectTTL time.Duration) (res bool, err error) - transport.MultiConn + + ocache.Object } type peer struct { id string + + // drpc conn pool + inactive []drpc.Conn + active map[drpc.Conn]struct{} + mu sync.Mutex + transport.MultiConn } @@ -34,10 +55,44 @@ func (p *peer) Id() string { return p.id } +func (p *peer) AcquireDrpcConn(ctx context.Context) (drpc.Conn, error) { + p.mu.Lock() + defer p.mu.Unlock() + if len(p.inactive) == 0 { + conn, err := p.Open(ctx) + if err != nil { + return nil, err + } + dconn := drpcconn.New(conn) + p.inactive = append(p.inactive, dconn) + } + idx := len(p.inactive) - 1 + res := p.inactive[idx] + p.inactive = p.inactive[:idx] + p.active[res] = struct{}{} + return res, nil +} + +func (p *peer) ReleaseDrpcConn(conn drpc.Conn) { + p.mu.Lock() + defer p.mu.Unlock() + if _, ok := p.active[conn]; ok { + delete(p.active, conn) + } + p.inactive = append(p.inactive, conn) + return +} + func (p *peer) TryClose(objectTTL time.Duration) (res bool, err error) { if time.Now().Sub(p.LastUsage()) < objectTTL { return false, nil } + p.mu.Lock() + if len(p.active) > 0 { + p.mu.Unlock() + return false, nil + } + p.mu.Unlock() return true, p.Close() } diff --git a/net/peer/peer_test.go b/net/peer/peer_test.go new file mode 100644 index 00000000..41efc45d --- /dev/null +++ b/net/peer/peer_test.go @@ -0,0 +1,62 @@ +package peer + +import ( + "context" + "github.com/anyproto/any-sync/net/transport/mock_transport" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "net" + "testing" +) + +var ctx = context.Background() + +func TestPeer_AcquireDrpcConn(t *testing.T) { + fx := newFixture(t, "p1") + defer fx.finish() + in, out := net.Pipe() + defer out.Close() + fx.mc.EXPECT().Open(gomock.Any()).Return(in, nil) + dc, err := fx.AcquireDrpcConn(ctx) + require.NoError(t, err) + assert.NotEmpty(t, dc) + defer dc.Close() + + assert.Len(t, fx.active, 1) + assert.Len(t, fx.inactive, 0) + + fx.ReleaseDrpcConn(dc) + + assert.Len(t, fx.active, 0) + assert.Len(t, fx.inactive, 1) + + dc, err = fx.AcquireDrpcConn(ctx) + require.NoError(t, err) + assert.NotEmpty(t, dc) + assert.Len(t, fx.active, 1) + assert.Len(t, fx.inactive, 0) +} + +func newFixture(t *testing.T, peerId string) *fixture { + fx := &fixture{ + ctrl: gomock.NewController(t), + } + fx.mc = mock_transport.NewMockMultiConn(fx.ctrl) + ctx := CtxWithPeerId(context.Background(), peerId) + fx.mc.EXPECT().Context().Return(ctx).AnyTimes() + p, err := NewPeer(fx.mc) + require.NoError(t, err) + fx.peer = p.(*peer) + return fx +} + +type fixture struct { + *peer + ctrl *gomock.Controller + mc *mock_transport.MockMultiConn +} + +func (fx *fixture) finish() { + fx.ctrl.Finish() +} diff --git a/net/peerservice/peerservice.go b/net/peerservice/peerservice.go index 3394c5e8..a83e6785 100644 --- a/net/peerservice/peerservice.go +++ b/net/peerservice/peerservice.go @@ -83,7 +83,7 @@ func (p *peerService) Accept(mc transport.MultiConn) (err error) { if err != nil { return err } - if err = p.pool.AddPeer(pr); err != nil { + if err = p.pool.AddPeer(context.Background(), pr); err != nil { _ = pr.Close() } return diff --git a/net/pool/pool_test.go b/net/pool/pool_test.go index b1cc0087..c31fcf69 100644 --- a/net/pool/pool_test.go +++ b/net/pool/pool_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" net2 "net" + "storj.io/drpc" "testing" "time" ) @@ -216,6 +217,12 @@ type testPeer struct { closed chan struct{} } +func (t *testPeer) AcquireDrpcConn(ctx context.Context) (drpc.Conn, error) { + return nil, fmt.Errorf("not implemented") +} + +func (t *testPeer) ReleaseDrpcConn(conn drpc.Conn) {} + func (t *testPeer) Context() context.Context { //TODO implement me panic("implement me") @@ -239,12 +246,6 @@ func (t *testPeer) Id() string { return t.id } -func (t *testPeer) LastUsage() time.Time { - return time.Now() -} - -func (t *testPeer) UpdateLastUsage() {} - func (t *testPeer) TryClose(objectTTL time.Duration) (res bool, err error) { return true, t.Close() } diff --git a/net/transport/mock_transport/mock_transport.go b/net/transport/mock_transport/mock_transport.go new file mode 100644 index 00000000..43f5572c --- /dev/null +++ b/net/transport/mock_transport/mock_transport.go @@ -0,0 +1,188 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/anyproto/any-sync/net/transport (interfaces: Transport,MultiConn) + +// Package mock_transport is a generated GoMock package. +package mock_transport + +import ( + context "context" + net "net" + reflect "reflect" + time "time" + + transport "github.com/anyproto/any-sync/net/transport" + gomock "github.com/golang/mock/gomock" +) + +// MockTransport is a mock of Transport interface. +type MockTransport struct { + ctrl *gomock.Controller + recorder *MockTransportMockRecorder +} + +// MockTransportMockRecorder is the mock recorder for MockTransport. +type MockTransportMockRecorder struct { + mock *MockTransport +} + +// NewMockTransport creates a new mock instance. +func NewMockTransport(ctrl *gomock.Controller) *MockTransport { + mock := &MockTransport{ctrl: ctrl} + mock.recorder = &MockTransportMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockTransport) EXPECT() *MockTransportMockRecorder { + return m.recorder +} + +// Dial mocks base method. +func (m *MockTransport) Dial(arg0 context.Context, arg1 string) (transport.MultiConn, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Dial", arg0, arg1) + ret0, _ := ret[0].(transport.MultiConn) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Dial indicates an expected call of Dial. +func (mr *MockTransportMockRecorder) Dial(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Dial", reflect.TypeOf((*MockTransport)(nil).Dial), arg0, arg1) +} + +// SetAccepter mocks base method. +func (m *MockTransport) SetAccepter(arg0 transport.Accepter) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetAccepter", arg0) +} + +// SetAccepter indicates an expected call of SetAccepter. +func (mr *MockTransportMockRecorder) SetAccepter(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetAccepter", reflect.TypeOf((*MockTransport)(nil).SetAccepter), arg0) +} + +// MockMultiConn is a mock of MultiConn interface. +type MockMultiConn struct { + ctrl *gomock.Controller + recorder *MockMultiConnMockRecorder +} + +// MockMultiConnMockRecorder is the mock recorder for MockMultiConn. +type MockMultiConnMockRecorder struct { + mock *MockMultiConn +} + +// NewMockMultiConn creates a new mock instance. +func NewMockMultiConn(ctrl *gomock.Controller) *MockMultiConn { + mock := &MockMultiConn{ctrl: ctrl} + mock.recorder = &MockMultiConnMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockMultiConn) EXPECT() *MockMultiConnMockRecorder { + return m.recorder +} + +// Accept mocks base method. +func (m *MockMultiConn) Accept() (net.Conn, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Accept") + ret0, _ := ret[0].(net.Conn) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Accept indicates an expected call of Accept. +func (mr *MockMultiConnMockRecorder) Accept() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Accept", reflect.TypeOf((*MockMultiConn)(nil).Accept)) +} + +// Addr mocks base method. +func (m *MockMultiConn) Addr() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Addr") + ret0, _ := ret[0].(string) + return ret0 +} + +// Addr indicates an expected call of Addr. +func (mr *MockMultiConnMockRecorder) Addr() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Addr", reflect.TypeOf((*MockMultiConn)(nil).Addr)) +} + +// Close mocks base method. +func (m *MockMultiConn) Close() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Close") + ret0, _ := ret[0].(error) + return ret0 +} + +// Close indicates an expected call of Close. +func (mr *MockMultiConnMockRecorder) Close() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockMultiConn)(nil).Close)) +} + +// Context mocks base method. +func (m *MockMultiConn) Context() context.Context { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Context") + ret0, _ := ret[0].(context.Context) + return ret0 +} + +// Context indicates an expected call of Context. +func (mr *MockMultiConnMockRecorder) Context() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MockMultiConn)(nil).Context)) +} + +// IsClosed mocks base method. +func (m *MockMultiConn) IsClosed() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsClosed") + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsClosed indicates an expected call of IsClosed. +func (mr *MockMultiConnMockRecorder) IsClosed() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsClosed", reflect.TypeOf((*MockMultiConn)(nil).IsClosed)) +} + +// LastUsage mocks base method. +func (m *MockMultiConn) LastUsage() time.Time { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LastUsage") + ret0, _ := ret[0].(time.Time) + return ret0 +} + +// LastUsage indicates an expected call of LastUsage. +func (mr *MockMultiConnMockRecorder) LastUsage() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LastUsage", reflect.TypeOf((*MockMultiConn)(nil).LastUsage)) +} + +// Open mocks base method. +func (m *MockMultiConn) Open(arg0 context.Context) (net.Conn, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Open", arg0) + ret0, _ := ret[0].(net.Conn) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Open indicates an expected call of Open. +func (mr *MockMultiConnMockRecorder) Open(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Open", reflect.TypeOf((*MockMultiConn)(nil).Open), arg0) +} diff --git a/net/transport/transport.go b/net/transport/transport.go index 127c9c06..7b247793 100644 --- a/net/transport/transport.go +++ b/net/transport/transport.go @@ -1,3 +1,4 @@ +//go:generate mockgen -destination mock_transport/mock_transport.go github.com/anyproto/any-sync/net/transport Transport,MultiConn package transport import ( From c43ac9eb84187419dd3fb2844ff71c605d2a2f27 Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Wed, 31 May 2023 16:22:49 +0200 Subject: [PATCH 06/11] handshake proto + common handshake fixes --- commonfile/fileproto/file_drpc.pb.go | 2 +- .../spacesyncproto/spacesync_drpc.pb.go | 6 +- .../coordinatorproto/coordinator_drpc.pb.go | 2 +- net/secureservice/handshake/credential.go | 125 ++++++++++ .../{handshake_test.go => credential_test.go} | 62 +++-- net/secureservice/handshake/handshake.go | 203 ++++----------- .../handshake/handshakeproto/handshake.pb.go | 235 ++++++++++++++++-- .../handshakeproto/protos/handshake.proto | 18 ++ net/secureservice/handshake/proto.go | 97 ++++++++ net/secureservice/handshake/proto_test.go | 121 +++++++++ .../testservice/testservice_drpc.pb.go | 6 +- 11 files changed, 664 insertions(+), 213 deletions(-) create mode 100644 net/secureservice/handshake/credential.go rename net/secureservice/handshake/{handshake_test.go => credential_test.go} (94%) create mode 100644 net/secureservice/handshake/proto.go create mode 100644 net/secureservice/handshake/proto_test.go diff --git a/commonfile/fileproto/file_drpc.pb.go b/commonfile/fileproto/file_drpc.pb.go index 2f9ee69d..a03c22cd 100644 --- a/commonfile/fileproto/file_drpc.pb.go +++ b/commonfile/fileproto/file_drpc.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-drpc. DO NOT EDIT. -// protoc-gen-go-drpc version: v0.0.32 +// protoc-gen-go-drpc version: v0.0.33 // source: commonfile/fileproto/protos/file.proto package fileproto diff --git a/commonspace/spacesyncproto/spacesync_drpc.pb.go b/commonspace/spacesyncproto/spacesync_drpc.pb.go index 2c82a645..55b3fed4 100644 --- a/commonspace/spacesyncproto/spacesync_drpc.pb.go +++ b/commonspace/spacesyncproto/spacesync_drpc.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-drpc. DO NOT EDIT. -// protoc-gen-go-drpc version: v0.0.32 +// protoc-gen-go-drpc version: v0.0.33 // source: commonspace/spacesyncproto/protos/spacesync.proto package spacesyncproto @@ -102,6 +102,10 @@ type drpcSpaceSync_ObjectSyncStreamClient struct { drpc.Stream } +func (x *drpcSpaceSync_ObjectSyncStreamClient) GetStream() drpc.Stream { + return x.Stream +} + func (x *drpcSpaceSync_ObjectSyncStreamClient) Send(m *ObjectSyncMessage) error { return x.MsgSend(m, drpcEncoding_File_commonspace_spacesyncproto_protos_spacesync_proto{}) } diff --git a/coordinator/coordinatorproto/coordinator_drpc.pb.go b/coordinator/coordinatorproto/coordinator_drpc.pb.go index 75e73a7b..0ed69ea2 100644 --- a/coordinator/coordinatorproto/coordinator_drpc.pb.go +++ b/coordinator/coordinatorproto/coordinator_drpc.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-drpc. DO NOT EDIT. -// protoc-gen-go-drpc version: v0.0.32 +// protoc-gen-go-drpc version: v0.0.33 // source: coordinator/coordinatorproto/protos/coordinator.proto package coordinatorproto diff --git a/net/secureservice/handshake/credential.go b/net/secureservice/handshake/credential.go new file mode 100644 index 00000000..06108928 --- /dev/null +++ b/net/secureservice/handshake/credential.go @@ -0,0 +1,125 @@ +package handshake + +import ( + "context" + "github.com/anyproto/any-sync/net/secureservice/handshake/handshakeproto" + "github.com/libp2p/go-libp2p/core/sec" +) + +func OutgoingHandshake(ctx context.Context, sc sec.SecureConn, cc CredentialChecker) (identity []byte, err error) { + if ctx == nil { + ctx = context.Background() + } + h := newHandshake() + done := make(chan struct{}) + go func() { + defer close(done) + identity, err = outgoingHandshake(h, sc, cc) + }() + select { + case <-done: + return + case <-ctx.Done(): + _ = sc.Close() + return nil, ctx.Err() + } +} + +func outgoingHandshake(h *handshake, sc sec.SecureConn, cc CredentialChecker) (identity []byte, err error) { + defer h.release() + h.conn = sc + localCred := cc.MakeCredentials(sc) + if err = h.writeCredentials(localCred); err != nil { + h.tryWriteErrAndClose(err) + return + } + msg, err := h.readMsg(msgTypeAck, msgTypeCred) + if err != nil { + h.tryWriteErrAndClose(err) + return + } + if msg.ack != nil { + if msg.ack.Error == handshakeproto.Error_InvalidCredentials { + return nil, ErrPeerDeclinedCredentials + } + return nil, HandshakeError{e: msg.ack.Error} + } + + if identity, err = cc.CheckCredential(sc, msg.cred); err != nil { + h.tryWriteErrAndClose(err) + return + } + + if err = h.writeAck(handshakeproto.Error_Null); err != nil { + h.tryWriteErrAndClose(err) + return nil, err + } + + msg, err = h.readMsg(msgTypeAck) + if err != nil { + h.tryWriteErrAndClose(err) + return nil, err + } + if msg.ack.Error == handshakeproto.Error_Null { + return identity, nil + } else { + _ = h.conn.Close() + return nil, HandshakeError{e: msg.ack.Error} + } +} + +func IncomingHandshake(ctx context.Context, sc sec.SecureConn, cc CredentialChecker) (identity []byte, err error) { + if ctx == nil { + ctx = context.Background() + } + h := newHandshake() + done := make(chan struct{}) + go func() { + defer close(done) + identity, err = incomingHandshake(h, sc, cc) + }() + select { + case <-done: + return + case <-ctx.Done(): + _ = sc.Close() + return nil, ctx.Err() + } +} + +func incomingHandshake(h *handshake, sc sec.SecureConn, cc CredentialChecker) (identity []byte, err error) { + defer h.release() + h.conn = sc + + msg, err := h.readMsg(msgTypeCred) + if err != nil { + h.tryWriteErrAndClose(err) + return + } + if identity, err = cc.CheckCredential(sc, msg.cred); err != nil { + h.tryWriteErrAndClose(err) + return + } + + if err = h.writeCredentials(cc.MakeCredentials(sc)); err != nil { + h.tryWriteErrAndClose(err) + return nil, err + } + + msg, err = h.readMsg(msgTypeAck) + if err != nil { + h.tryWriteErrAndClose(err) + return nil, err + } + if msg.ack.Error != handshakeproto.Error_Null { + if msg.ack.Error == handshakeproto.Error_InvalidCredentials { + return nil, ErrPeerDeclinedCredentials + } + return nil, HandshakeError{e: msg.ack.Error} + } + if err = h.writeAck(handshakeproto.Error_Null); err != nil { + h.tryWriteErrAndClose(err) + return nil, err + } + return +} diff --git a/net/secureservice/handshake/handshake_test.go b/net/secureservice/handshake/credential_test.go similarity index 94% rename from net/secureservice/handshake/handshake_test.go rename to net/secureservice/handshake/credential_test.go index 0d8b16d7..6a34f9cb 100644 --- a/net/secureservice/handshake/handshake_test.go +++ b/net/secureservice/handshake/credential_test.go @@ -38,15 +38,14 @@ func TestOutgoingHandshake(t *testing.T) { h := newHandshake() h.conn = c2 // receive credential message - msg, err := h.readMsg() + msg, err := h.readMsg(msgTypeCred, msgTypeAck, msgTypeProto) require.NoError(t, err) - require.Nil(t, msg.ack) _, err = noVerifyChecker.CheckCredential(c2, msg.cred) require.NoError(t, err) // send credential message require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) // receive ack - msg, err = h.readMsg() + msg, err = h.readMsg(msgTypeAck) require.NoError(t, err) require.Equal(t, handshakeproto.Error_Null, msg.ack.Error) // send ack @@ -76,7 +75,7 @@ func TestOutgoingHandshake(t *testing.T) { h := newHandshake() h.conn = c2 // receive credential message - _, err := h.readMsg() + _, err := h.readMsg(msgTypeCred) require.NoError(t, err) _ = c2.Close() res := <-handshakeResCh @@ -92,7 +91,7 @@ func TestOutgoingHandshake(t *testing.T) { h := newHandshake() h.conn = c2 // receive credential message - _, err := h.readMsg() + _, err := h.readMsg(msgTypeCred) require.NoError(t, err) require.NoError(t, h.writeAck(ErrInvalidCredentials.e)) res := <-handshakeResCh @@ -108,10 +107,10 @@ func TestOutgoingHandshake(t *testing.T) { h := newHandshake() h.conn = c2 // receive credential message - _, err := h.readMsg() + _, err := h.readMsg(msgTypeCred) require.NoError(t, err) require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) - msg, err := h.readMsg() + msg, err := h.readMsg(msgTypeAck) require.NoError(t, err) assert.Equal(t, ErrInvalidCredentials.e, msg.ack.Error) res := <-handshakeResCh @@ -127,7 +126,7 @@ func TestOutgoingHandshake(t *testing.T) { h := newHandshake() h.conn = c2 // receive credential message - _, err := h.readMsg() + _, err := h.readMsg(msgTypeCred) require.NoError(t, err) // write credentials and close conn require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) @@ -145,12 +144,12 @@ func TestOutgoingHandshake(t *testing.T) { h := newHandshake() h.conn = c2 // receive credential message - _, err := h.readMsg() + _, err := h.readMsg(msgTypeCred) require.NoError(t, err) // write credentials require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) // read ack and close conn - _, err = h.readMsg() + _, err = h.readMsg(msgTypeAck) require.NoError(t, err) _ = c2.Close() res := <-handshakeResCh @@ -166,18 +165,17 @@ func TestOutgoingHandshake(t *testing.T) { h := newHandshake() h.conn = c2 // receive credential message - _, err := h.readMsg() + _, err := h.readMsg(msgTypeCred) require.NoError(t, err) // write credentials require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) // read ack - _, err = h.readMsg() + _, err = h.readMsg(msgTypeAck) require.NoError(t, err) // write cred instead ack require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) - msg, err := h.readMsg() - require.NoError(t, err) - assert.Equal(t, handshakeproto.Error_UnexpectedPayload, msg.ack.Error) + _, err = h.readMsg(msgTypeAck) + require.Error(t, err) res := <-handshakeResCh require.Error(t, res.err) }) @@ -191,7 +189,7 @@ func TestOutgoingHandshake(t *testing.T) { h := newHandshake() h.conn = c2 // receive credential message - msg, err := h.readMsg() + msg, err := h.readMsg(msgTypeCred) require.NoError(t, err) require.Nil(t, msg.ack) _, err = noVerifyChecker.CheckCredential(c2, msg.cred) @@ -199,7 +197,7 @@ func TestOutgoingHandshake(t *testing.T) { // send credential message require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) // receive ack - msg, err = h.readMsg() + msg, err = h.readMsg(msgTypeAck) require.NoError(t, err) require.Equal(t, handshakeproto.Error_Null, msg.ack.Error) // send ack @@ -219,7 +217,7 @@ func TestOutgoingHandshake(t *testing.T) { h := newHandshake() h.conn = c2 // receive credential message - _, err := h.readMsg() + _, err := h.readMsg(msgTypeCred) require.NoError(t, err) ctxCancel() res := <-handshakeResCh @@ -244,14 +242,14 @@ func TestIncomingHandshake(t *testing.T) { // write credentials require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) // wait credentials - msg, err := h.readMsg() + msg, err := h.readMsg(msgTypeCred) require.NoError(t, err) require.Nil(t, msg.ack) require.Equal(t, handshakeproto.CredentialsType_SkipVerify, msg.cred.Type) // write ack require.NoError(t, h.writeAck(handshakeproto.Error_Null)) // wait ack - msg, err = h.readMsg() + msg, err = h.readMsg(msgTypeAck) require.NoError(t, err) assert.Equal(t, handshakeproto.Error_Null, msg.ack.Error) res := <-handshakeResCh @@ -310,7 +308,7 @@ func TestIncomingHandshake(t *testing.T) { // write credentials require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) // except ack with error - msg, err := h.readMsg() + msg, err := h.readMsg(msgTypeAck) require.NoError(t, err) require.Nil(t, msg.cred) require.Equal(t, handshakeproto.Error_InvalidCredentials, msg.ack.Error) @@ -330,7 +328,7 @@ func TestIncomingHandshake(t *testing.T) { // write credentials require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) // except ack with error - msg, err := h.readMsg() + msg, err := h.readMsg(msgTypeAck) require.NoError(t, err) require.Nil(t, msg.cred) require.Equal(t, handshakeproto.Error_IncompatibleVersion, msg.ack.Error) @@ -350,13 +348,13 @@ func TestIncomingHandshake(t *testing.T) { // write credentials require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) // read cred - _, err := h.readMsg() + _, err := h.readMsg(msgTypeCred) require.NoError(t, err) // write cred instead ack require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) - // expect ack with error - msg, err := h.readMsg() - require.Equal(t, handshakeproto.Error_UnexpectedPayload, msg.ack.Error) + // expect EOF + _, err = h.readMsg(msgTypeAck) + require.Error(t, err) res := <-handshakeResCh require.Error(t, res.err) }) @@ -372,7 +370,7 @@ func TestIncomingHandshake(t *testing.T) { // write credentials require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) // read cred and close conn - _, err := h.readMsg() + _, err := h.readMsg(msgTypeCred) require.NoError(t, err) _ = c2.Close() @@ -391,7 +389,7 @@ func TestIncomingHandshake(t *testing.T) { // write credentials require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) // wait credentials - msg, err := h.readMsg() + msg, err := h.readMsg(msgTypeCred) require.NoError(t, err) require.Nil(t, msg.ack) require.Equal(t, handshakeproto.CredentialsType_SkipVerify, msg.cred.Type) @@ -413,7 +411,7 @@ func TestIncomingHandshake(t *testing.T) { // write credentials require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) // wait credentials - msg, err := h.readMsg() + msg, err := h.readMsg(msgTypeCred) require.NoError(t, err) require.Nil(t, msg.ack) require.Equal(t, handshakeproto.CredentialsType_SkipVerify, msg.cred.Type) @@ -435,7 +433,7 @@ func TestIncomingHandshake(t *testing.T) { // write credentials require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) // wait credentials - msg, err := h.readMsg() + msg, err := h.readMsg(msgTypeCred) require.NoError(t, err) require.Nil(t, msg.ack) require.Equal(t, handshakeproto.CredentialsType_SkipVerify, msg.cred.Type) @@ -458,7 +456,7 @@ func TestIncomingHandshake(t *testing.T) { // write credentials require.NoError(t, h.writeCredentials(noVerifyChecker.MakeCredentials(c2))) // wait credentials - _, err := h.readMsg() + _, err := h.readMsg(msgTypeCred) require.NoError(t, err) ctxCancel() res := <-handshakeResCh @@ -482,7 +480,7 @@ func TestNotAHandshakeMessage(t *testing.T) { _, err := c2.Write([]byte("some unexpected bytes")) require.Error(t, err) res := <-handshakeResCh - assert.EqualError(t, res.err, ErrGotNotAHandshakeMessage.Error()) + assert.Error(t, res.err) } func TestEndToEnd(t *testing.T) { diff --git a/net/secureservice/handshake/handshake.go b/net/secureservice/handshake/handshake.go index 04a9de72..39e6656f 100644 --- a/net/secureservice/handshake/handshake.go +++ b/net/secureservice/handshake/handshake.go @@ -1,7 +1,6 @@ package handshake import ( - "context" "encoding/binary" "errors" "github.com/anyproto/any-sync/net/secureservice/handshake/handshakeproto" @@ -14,8 +13,17 @@ import ( const headerSize = 5 // 1 byte for type + 4 byte for uint32 size const ( - msgTypeCred = byte(1) - msgTypeAck = byte(2) + msgTypeCred = byte(1) + msgTypeAck = byte(2) + msgTypeProto = byte(3) + + sizeLimit = 200 * 1024 // 200 Kb +) + +var ( + credMsgTypes = []byte{msgTypeCred, msgTypeAck} + protoMsgTypes = []byte{msgTypeProto, msgTypeAck} + protoMsgTypesAck = []byte{msgTypeAck} ) type HandshakeError struct { @@ -38,17 +46,20 @@ var ( ErrSkipVerifyNotAllowed = HandshakeError{e: handshakeproto.Error_SkipVerifyNotAllowed} ErrUnexpected = HandshakeError{e: handshakeproto.Error_Unexpected} - ErrIncompatibleVersion = HandshakeError{e: handshakeproto.Error_IncompatibleVersion} + ErrIncompatibleVersion = HandshakeError{e: handshakeproto.Error_IncompatibleVersion} + ErrIncompatibleProto = HandshakeError{e: handshakeproto.Error_IncompatibleProto} + ErrRemoteIncompatibleProto = HandshakeError{Err: errors.New("remote peer declined the proto")} - ErrGotNotAHandshakeMessage = errors.New("go not a handshake message") + ErrGotUnexpectedMessage = errors.New("go not a handshake message") ) var handshakePool = &sync.Pool{New: func() any { return &handshake{ - remoteCred: &handshakeproto.Credentials{}, - remoteAck: &handshakeproto.Ack{}, - localAck: &handshakeproto.Ack{}, - buf: make([]byte, 0, 1024), + remoteCred: &handshakeproto.Credentials{}, + remoteAck: &handshakeproto.Ack{}, + localAck: &handshakeproto.Ack{}, + remoteProto: &handshakeproto.Proto{}, + buf: make([]byte, 0, 1024), } }} @@ -57,147 +68,17 @@ type CredentialChecker interface { CheckCredential(sc sec.SecureConn, cred *handshakeproto.Credentials) (identity []byte, err error) } -func OutgoingHandshake(ctx context.Context, sc sec.SecureConn, cc CredentialChecker) (identity []byte, err error) { - if ctx == nil { - ctx = context.Background() - } - h := newHandshake() - done := make(chan struct{}) - go func() { - defer close(done) - identity, err = outgoingHandshake(h, sc, cc) - }() - select { - case <-done: - return - case <-ctx.Done(): - _ = sc.Close() - return nil, ctx.Err() - } -} - -func outgoingHandshake(h *handshake, sc sec.SecureConn, cc CredentialChecker) (identity []byte, err error) { - defer h.release() - h.conn = sc - localCred := cc.MakeCredentials(sc) - if err = h.writeCredentials(localCred); err != nil { - h.tryWriteErrAndClose(err) - return - } - msg, err := h.readMsg() - if err != nil { - h.tryWriteErrAndClose(err) - return - } - if msg.ack != nil { - if msg.ack.Error == handshakeproto.Error_InvalidCredentials { - return nil, ErrPeerDeclinedCredentials - } - return nil, HandshakeError{e: msg.ack.Error} - } - - if identity, err = cc.CheckCredential(sc, msg.cred); err != nil { - h.tryWriteErrAndClose(err) - return - } - - if err = h.writeAck(handshakeproto.Error_Null); err != nil { - h.tryWriteErrAndClose(err) - return nil, err - } - - msg, err = h.readMsg() - if err != nil { - h.tryWriteErrAndClose(err) - return nil, err - } - if msg.ack == nil { - err = ErrUnexpectedPayload - h.tryWriteErrAndClose(err) - return nil, err - } - if msg.ack.Error == handshakeproto.Error_Null { - return identity, nil - } else { - _ = h.conn.Close() - return nil, HandshakeError{e: msg.ack.Error} - } -} - -func IncomingHandshake(ctx context.Context, sc sec.SecureConn, cc CredentialChecker) (identity []byte, err error) { - if ctx == nil { - ctx = context.Background() - } - h := newHandshake() - done := make(chan struct{}) - go func() { - defer close(done) - identity, err = incomingHandshake(h, sc, cc) - }() - select { - case <-done: - return - case <-ctx.Done(): - _ = sc.Close() - return nil, ctx.Err() - } -} - -func incomingHandshake(h *handshake, sc sec.SecureConn, cc CredentialChecker) (identity []byte, err error) { - defer h.release() - h.conn = sc - - msg, err := h.readMsg() - if err != nil { - h.tryWriteErrAndClose(err) - return - } - if msg.ack != nil { - return nil, ErrUnexpectedPayload - } - if identity, err = cc.CheckCredential(sc, msg.cred); err != nil { - h.tryWriteErrAndClose(err) - return - } - - if err = h.writeCredentials(cc.MakeCredentials(sc)); err != nil { - h.tryWriteErrAndClose(err) - return nil, err - } - - msg, err = h.readMsg() - if err != nil { - h.tryWriteErrAndClose(err) - return nil, err - } - if msg.ack == nil { - err = ErrUnexpectedPayload - h.tryWriteErrAndClose(err) - return nil, err - } - if msg.ack.Error != handshakeproto.Error_Null { - if msg.ack.Error == handshakeproto.Error_InvalidCredentials { - return nil, ErrPeerDeclinedCredentials - } - return nil, HandshakeError{e: msg.ack.Error} - } - if err = h.writeAck(handshakeproto.Error_Null); err != nil { - h.tryWriteErrAndClose(err) - return nil, err - } - return -} - func newHandshake() *handshake { return handshakePool.Get().(*handshake) } type handshake struct { - conn sec.SecureConn - remoteCred *handshakeproto.Credentials - remoteAck *handshakeproto.Ack - localAck *handshakeproto.Ack - buf []byte + conn sec.SecureConn + remoteCred *handshakeproto.Credentials + remoteProto *handshakeproto.Proto + remoteAck *handshakeproto.Ack + localAck *handshakeproto.Ack + buf []byte } func (h *handshake) writeCredentials(cred *handshakeproto.Credentials) (err error) { @@ -209,8 +90,17 @@ func (h *handshake) writeCredentials(cred *handshakeproto.Credentials) (err erro return h.writeData(msgTypeCred, n) } +func (h *handshake) writeProto(proto *handshakeproto.Proto) (err error) { + h.buf = slices.Grow(h.buf, proto.Size()+headerSize)[:proto.Size()+headerSize] + n, err := proto.MarshalToSizedBuffer(h.buf[headerSize:]) + if err != nil { + return err + } + return h.writeData(msgTypeProto, n) +} + func (h *handshake) tryWriteErrAndClose(err error) { - if err == ErrGotNotAHandshakeMessage { + if err == ErrUnexpectedPayload { // if we got unexpected message - just close the connection _ = h.conn.Close() return @@ -243,21 +133,26 @@ func (h *handshake) writeData(tp byte, size int) (err error) { } type message struct { - cred *handshakeproto.Credentials - ack *handshakeproto.Ack + cred *handshakeproto.Credentials + proto *handshakeproto.Proto + ack *handshakeproto.Ack } -func (h *handshake) readMsg() (msg message, err error) { +func (h *handshake) readMsg(allowedTypes ...byte) (msg message, err error) { h.buf = slices.Grow(h.buf, headerSize)[:headerSize] if _, err = io.ReadFull(h.conn, h.buf[:headerSize]); err != nil { return } tp := h.buf[0] - if tp != msgTypeCred && tp != msgTypeAck { - err = ErrGotNotAHandshakeMessage + if !slices.Contains(allowedTypes, tp) { + err = ErrUnexpectedPayload return } size := binary.LittleEndian.Uint32(h.buf[1:headerSize]) + if size > sizeLimit { + err = ErrGotUnexpectedMessage + return + } h.buf = slices.Grow(h.buf, int(size))[:size] if _, err = io.ReadFull(h.conn, h.buf[:size]); err != nil { return @@ -273,6 +168,11 @@ func (h *handshake) readMsg() (msg message, err error) { return } msg.ack = h.remoteAck + case msgTypeProto: + if err = h.remoteProto.Unmarshal(h.buf[:size]); err != nil { + return + } + msg.proto = h.remoteProto } return } @@ -284,5 +184,6 @@ func (h *handshake) release() { h.remoteAck.Error = 0 h.remoteCred.Type = 0 h.remoteCred.Payload = h.remoteCred.Payload[:0] + h.remoteProto.Proto = 0 handshakePool.Put(h) } diff --git a/net/secureservice/handshake/handshakeproto/handshake.pb.go b/net/secureservice/handshake/handshakeproto/handshake.pb.go index 3d868ef0..e9d6dfcb 100644 --- a/net/secureservice/handshake/handshakeproto/handshake.pb.go +++ b/net/secureservice/handshake/handshakeproto/handshake.pb.go @@ -59,6 +59,7 @@ const ( Error_SkipVerifyNotAllowed Error = 4 Error_DeadlineExceeded Error = 5 Error_IncompatibleVersion Error = 6 + Error_IncompatibleProto Error = 7 ) var Error_name = map[int32]string{ @@ -69,6 +70,7 @@ var Error_name = map[int32]string{ 4: "SkipVerifyNotAllowed", 5: "DeadlineExceeded", 6: "IncompatibleVersion", + 7: "IncompatibleProto", } var Error_value = map[string]int32{ @@ -79,6 +81,7 @@ var Error_value = map[string]int32{ "SkipVerifyNotAllowed": 4, "DeadlineExceeded": 5, "IncompatibleVersion": 6, + "IncompatibleProto": 7, } func (x Error) String() string { @@ -89,6 +92,28 @@ func (Error) EnumDescriptor() ([]byte, []int) { return fileDescriptor_60283fc75f020893, []int{1} } +type ProtoType int32 + +const ( + ProtoType_DRPC ProtoType = 0 +) + +var ProtoType_name = map[int32]string{ + 0: "DRPC", +} + +var ProtoType_value = map[string]int32{ + "DRPC": 0, +} + +func (x ProtoType) String() string { + return proto.EnumName(ProtoType_name, int32(x)) +} + +func (ProtoType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_60283fc75f020893, []int{2} +} + type Credentials struct { Type CredentialsType `protobuf:"varint,1,opt,name=type,proto3,enum=anyHandshake.CredentialsType" json:"type,omitempty"` Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"` @@ -247,12 +272,58 @@ func (m *Ack) GetError() Error { return Error_Null } +type Proto struct { + Proto ProtoType `protobuf:"varint,1,opt,name=proto,proto3,enum=anyHandshake.ProtoType" json:"proto,omitempty"` +} + +func (m *Proto) Reset() { *m = Proto{} } +func (m *Proto) String() string { return proto.CompactTextString(m) } +func (*Proto) ProtoMessage() {} +func (*Proto) Descriptor() ([]byte, []int) { + return fileDescriptor_60283fc75f020893, []int{3} +} +func (m *Proto) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Proto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Proto.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Proto) XXX_Merge(src proto.Message) { + xxx_messageInfo_Proto.Merge(m, src) +} +func (m *Proto) XXX_Size() int { + return m.Size() +} +func (m *Proto) XXX_DiscardUnknown() { + xxx_messageInfo_Proto.DiscardUnknown(m) +} + +var xxx_messageInfo_Proto proto.InternalMessageInfo + +func (m *Proto) GetProto() ProtoType { + if m != nil { + return m.Proto + } + return ProtoType_DRPC +} + func init() { proto.RegisterEnum("anyHandshake.CredentialsType", CredentialsType_name, CredentialsType_value) proto.RegisterEnum("anyHandshake.Error", Error_name, Error_value) + proto.RegisterEnum("anyHandshake.ProtoType", ProtoType_name, ProtoType_value) proto.RegisterType((*Credentials)(nil), "anyHandshake.Credentials") proto.RegisterType((*PayloadSignedPeerIds)(nil), "anyHandshake.PayloadSignedPeerIds") proto.RegisterType((*Ack)(nil), "anyHandshake.Ack") + proto.RegisterType((*Proto)(nil), "anyHandshake.Proto") } func init() { @@ -260,32 +331,35 @@ func init() { } var fileDescriptor_60283fc75f020893 = []byte{ - // 395 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xcd, 0x6e, 0x13, 0x31, - 0x10, 0xc7, 0xd7, 0x4d, 0x52, 0xaa, 0x21, 0x2d, 0xee, 0x34, 0xc0, 0x0a, 0x89, 0x55, 0x94, 0x53, - 0xc8, 0x21, 0xe1, 0xeb, 0x05, 0x02, 0x2d, 0x22, 0x97, 0xaa, 0xda, 0x42, 0x0f, 0xdc, 0xdc, 0xf5, - 0xd0, 0x5a, 0x31, 0xf6, 0xca, 0x76, 0x43, 0xf7, 0x2d, 0xb8, 0xf2, 0x46, 0x1c, 0x7b, 0xe4, 0x88, - 0x92, 0x17, 0x41, 0x71, 0x12, 0x92, 0x70, 0xea, 0xc5, 0x9e, 0x8f, 0x9f, 0xfd, 0xff, 0x8f, 0x65, - 0x18, 0x1a, 0x0a, 0x03, 0x4f, 0xc5, 0x8d, 0x23, 0x4f, 0x6e, 0xa2, 0x0a, 0x1a, 0x5c, 0x0b, 0x23, - 0xfd, 0xb5, 0x18, 0x6f, 0x44, 0xa5, 0xb3, 0xc1, 0x0e, 0xe2, 0xea, 0xd7, 0xd5, 0x7e, 0x2c, 0x60, - 0x53, 0x98, 0xea, 0xe3, 0xaa, 0xd6, 0x09, 0xf0, 0xf0, 0xbd, 0x23, 0x49, 0x26, 0x28, 0xa1, 0x3d, - 0xbe, 0x82, 0x7a, 0xa8, 0x4a, 0x4a, 0x59, 0x9b, 0x75, 0x0f, 0x5e, 0x3f, 0xef, 0x6f, 0xb2, 0xfd, - 0x0d, 0xf0, 0x53, 0x55, 0x52, 0x1e, 0x51, 0x4c, 0xe1, 0x41, 0x29, 0x2a, 0x6d, 0x85, 0x4c, 0x77, - 0xda, 0xac, 0xdb, 0xcc, 0x57, 0xe9, 0xbc, 0x33, 0x21, 0xe7, 0x95, 0x35, 0x69, 0xad, 0xcd, 0xba, - 0xfb, 0xf9, 0x2a, 0xed, 0x7c, 0x80, 0xd6, 0xd9, 0x02, 0x3a, 0x57, 0x57, 0x86, 0xe4, 0x19, 0x91, - 0x1b, 0x49, 0x8f, 0xcf, 0x60, 0x4f, 0x45, 0x89, 0x50, 0x45, 0x0b, 0xcd, 0xfc, 0x5f, 0x8e, 0x08, - 0x75, 0xaf, 0xae, 0xcc, 0x52, 0x24, 0xc6, 0x9d, 0x97, 0x50, 0x1b, 0x16, 0x63, 0x7c, 0x01, 0x0d, - 0x72, 0xce, 0xba, 0xa5, 0xed, 0xa3, 0x6d, 0xdb, 0x27, 0xf3, 0x56, 0xbe, 0x20, 0x7a, 0x6f, 0xe1, - 0xd1, 0x7f, 0x63, 0xe0, 0x01, 0xc0, 0xf9, 0x58, 0x95, 0x17, 0xe4, 0xd4, 0xd7, 0x8a, 0x27, 0x78, - 0x08, 0xfb, 0x5b, 0xae, 0x38, 0xeb, 0xfd, 0x64, 0xd0, 0x88, 0xd7, 0xe0, 0x1e, 0xd4, 0x4f, 0x6f, - 0xb4, 0xe6, 0xc9, 0xfc, 0xd8, 0x67, 0x43, 0xb7, 0x25, 0x15, 0x81, 0x24, 0x67, 0xf8, 0x04, 0x70, - 0x64, 0x26, 0x42, 0x2b, 0xb9, 0x21, 0xc0, 0x77, 0xf0, 0x31, 0x1c, 0xae, 0xb9, 0xe5, 0xd4, 0xbc, - 0x86, 0x29, 0xb4, 0xd6, 0xaa, 0xa7, 0x36, 0x0c, 0xb5, 0xb6, 0xdf, 0x49, 0xf2, 0x3a, 0xb6, 0x80, - 0x1f, 0x93, 0x90, 0x5a, 0x19, 0x3a, 0xb9, 0x2d, 0x88, 0x24, 0x49, 0xde, 0xc0, 0xa7, 0x70, 0x34, - 0x32, 0x85, 0xfd, 0x56, 0x8a, 0xa0, 0x2e, 0x35, 0x5d, 0x2c, 0x5e, 0x92, 0xef, 0xbe, 0x3b, 0xfe, - 0x35, 0xcd, 0xd8, 0xdd, 0x34, 0x63, 0x7f, 0xa6, 0x19, 0xfb, 0x31, 0xcb, 0x92, 0xbb, 0x59, 0x96, - 0xfc, 0x9e, 0x65, 0xc9, 0x97, 0xde, 0xfd, 0x3f, 0xcb, 0xe5, 0x6e, 0xdc, 0xde, 0xfc, 0x0d, 0x00, - 0x00, 0xff, 0xff, 0xbf, 0x78, 0x2f, 0x36, 0x61, 0x02, 0x00, 0x00, + // 439 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xcf, 0x6e, 0xd3, 0x40, + 0x10, 0xc6, 0xbd, 0x4d, 0xdc, 0x96, 0x21, 0x2d, 0xdb, 0x6d, 0x4a, 0x2d, 0x24, 0xac, 0x28, 0xa7, + 0x10, 0x89, 0x84, 0x7f, 0xe2, 0x1e, 0x9a, 0x22, 0x72, 0xa9, 0x22, 0x17, 0x7a, 0xe0, 0xb6, 0xf5, + 0x0e, 0xed, 0x2a, 0xcb, 0xda, 0xda, 0xdd, 0x86, 0xfa, 0x2d, 0x78, 0x14, 0x1e, 0x83, 0x63, 0x8f, + 0x1c, 0x51, 0xf2, 0x22, 0xc8, 0x9b, 0xa4, 0x71, 0x38, 0xf5, 0x62, 0xef, 0xcc, 0xfc, 0xc6, 0xdf, + 0x7c, 0xe3, 0x85, 0x81, 0x46, 0xd7, 0xb7, 0x98, 0xde, 0x18, 0xb4, 0x68, 0xa6, 0x32, 0xc5, 0xfe, + 0x35, 0xd7, 0xc2, 0x5e, 0xf3, 0x49, 0xe5, 0x94, 0x9b, 0xcc, 0x65, 0x7d, 0xff, 0xb4, 0xeb, 0x6c, + 0xcf, 0x27, 0x58, 0x83, 0xeb, 0xe2, 0xd3, 0x2a, 0xd7, 0x76, 0xf0, 0xf8, 0xc4, 0xa0, 0x40, 0xed, + 0x24, 0x57, 0x96, 0xbd, 0x86, 0xba, 0x2b, 0x72, 0x8c, 0x48, 0x8b, 0x74, 0xf6, 0xdf, 0x3c, 0xef, + 0x55, 0xd9, 0x5e, 0x05, 0xfc, 0x5c, 0xe4, 0x98, 0x78, 0x94, 0x45, 0xb0, 0x93, 0xf3, 0x42, 0x65, + 0x5c, 0x44, 0x5b, 0x2d, 0xd2, 0x69, 0x24, 0xab, 0xb0, 0xac, 0x4c, 0xd1, 0x58, 0x99, 0xe9, 0xa8, + 0xd6, 0x22, 0x9d, 0xbd, 0x64, 0x15, 0xb6, 0x3f, 0x42, 0x73, 0xbc, 0x80, 0xce, 0xe5, 0x95, 0x46, + 0x31, 0x46, 0x34, 0x23, 0x61, 0xd9, 0x33, 0xd8, 0x95, 0x5e, 0xc2, 0x15, 0x7e, 0x84, 0x46, 0x72, + 0x1f, 0x33, 0x06, 0x75, 0x2b, 0xaf, 0xf4, 0x52, 0xc4, 0x9f, 0xdb, 0xaf, 0xa0, 0x36, 0x48, 0x27, + 0xec, 0x05, 0x84, 0x68, 0x4c, 0x66, 0x96, 0x63, 0x1f, 0x6e, 0x8e, 0x7d, 0x5a, 0x96, 0x92, 0x05, + 0xd1, 0x7e, 0x0f, 0xe1, 0xd8, 0xaf, 0xe1, 0x25, 0x84, 0x7e, 0x1f, 0xcb, 0x9e, 0xe3, 0xcd, 0x1e, + 0xcf, 0x78, 0x93, 0x0b, 0xaa, 0xfb, 0x0e, 0x9e, 0xfc, 0x67, 0x9f, 0xed, 0x03, 0x9c, 0x4f, 0x64, + 0x7e, 0x81, 0x46, 0x7e, 0x2b, 0x68, 0xc0, 0x0e, 0x60, 0x6f, 0xc3, 0x0d, 0x25, 0xdd, 0x5f, 0x04, + 0x42, 0x2f, 0xcf, 0x76, 0xa1, 0x7e, 0x76, 0xa3, 0x14, 0x0d, 0xca, 0xb6, 0x2f, 0x1a, 0x6f, 0x73, + 0x4c, 0x1d, 0x0a, 0x4a, 0xd8, 0x53, 0x60, 0x23, 0x3d, 0xe5, 0x4a, 0x8a, 0x8a, 0x00, 0xdd, 0x62, + 0x47, 0x70, 0xb0, 0xe6, 0x96, 0xdb, 0xa2, 0x35, 0x16, 0x41, 0x73, 0xad, 0x7a, 0x96, 0xb9, 0x81, + 0x52, 0xd9, 0x0f, 0x14, 0xb4, 0xce, 0x9a, 0x40, 0x87, 0xc8, 0x85, 0x92, 0x1a, 0x4f, 0x6f, 0x53, + 0x44, 0x81, 0x82, 0x86, 0xec, 0x18, 0x0e, 0x47, 0x3a, 0xcd, 0xbe, 0xe7, 0xdc, 0xc9, 0x4b, 0x85, + 0x17, 0x8b, 0x3f, 0x40, 0xb7, 0xcb, 0xef, 0x57, 0x0b, 0xde, 0x31, 0xdd, 0xe9, 0x1e, 0xc1, 0xa3, + 0x7b, 0xf3, 0xe5, 0xd4, 0xc3, 0x64, 0x7c, 0x42, 0x83, 0x0f, 0xc3, 0xdf, 0xb3, 0x98, 0xdc, 0xcd, + 0x62, 0xf2, 0x77, 0x16, 0x93, 0x9f, 0xf3, 0x38, 0xb8, 0x9b, 0xc7, 0xc1, 0x9f, 0x79, 0x1c, 0x7c, + 0xed, 0x3e, 0xfc, 0x4a, 0x5e, 0x6e, 0xfb, 0xd7, 0xdb, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x53, + 0x32, 0xf7, 0x79, 0xc7, 0x02, 0x00, 0x00, } func (m *Credentials) Marshal() (dAtA []byte, err error) { @@ -393,6 +467,34 @@ func (m *Ack) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *Proto) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Proto) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Proto) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Proto != 0 { + i = encodeVarintHandshake(dAtA, i, uint64(m.Proto)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintHandshake(dAtA []byte, offset int, v uint64) int { offset -= sovHandshake(v) base := offset @@ -452,6 +554,18 @@ func (m *Ack) Size() (n int) { return n } +func (m *Proto) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Proto != 0 { + n += 1 + sovHandshake(uint64(m.Proto)) + } + return n +} + func sovHandshake(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -767,6 +881,75 @@ func (m *Ack) Unmarshal(dAtA []byte) error { } return nil } +func (m *Proto) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowHandshake + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Proto: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Proto: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Proto", wireType) + } + m.Proto = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowHandshake + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Proto |= ProtoType(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipHandshake(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthHandshake + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipHandshake(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/net/secureservice/handshake/handshakeproto/protos/handshake.proto b/net/secureservice/handshake/handshakeproto/protos/handshake.proto index cca5822e..1ea66b28 100644 --- a/net/secureservice/handshake/handshakeproto/protos/handshake.proto +++ b/net/secureservice/handshake/handshakeproto/protos/handshake.proto @@ -5,6 +5,8 @@ option go_package = "net/secureservice/handshake/handshakeproto"; /* +CREDENTIALS HANDSHAKE + Alice opens a new connection with Bob 1. TLS handshake done successfully; both sides know local and remote peer identifiers. @@ -68,4 +70,20 @@ enum Error { SkipVerifyNotAllowed = 4; DeadlineExceeded = 5; IncompatibleVersion = 6; + IncompatibleProto = 7; +} + + +/* + +PROTO HANDSHAKE + + */ + +message Proto { + ProtoType proto = 1; +} + +enum ProtoType { + DRPC = 0; } \ No newline at end of file diff --git a/net/secureservice/handshake/proto.go b/net/secureservice/handshake/proto.go new file mode 100644 index 00000000..1e133069 --- /dev/null +++ b/net/secureservice/handshake/proto.go @@ -0,0 +1,97 @@ +package handshake + +import ( + "context" + "github.com/anyproto/any-sync/net/secureservice/handshake/handshakeproto" + "github.com/libp2p/go-libp2p/core/sec" + "golang.org/x/exp/slices" +) + +type ProtoChecker struct { + AllowedProtoTypes []handshakeproto.ProtoType +} + +func OutgoingProtoHandshake(ctx context.Context, sc sec.SecureConn, pt handshakeproto.ProtoType) (err error) { + if ctx == nil { + ctx = context.Background() + } + h := newHandshake() + done := make(chan struct{}) + go func() { + defer close(done) + err = outgoingProtoHandshake(h, sc, pt) + }() + select { + case <-done: + return + case <-ctx.Done(): + _ = sc.Close() + return ctx.Err() + } +} + +func outgoingProtoHandshake(h *handshake, sc sec.SecureConn, pt handshakeproto.ProtoType) (err error) { + defer h.release() + h.conn = sc + localProto := &handshakeproto.Proto{ + Proto: pt, + } + if err = h.writeProto(localProto); err != nil { + h.tryWriteErrAndClose(err) + return + } + msg, err := h.readMsg(msgTypeAck) + if err != nil { + h.tryWriteErrAndClose(err) + return + } + if msg.ack.Error == handshakeproto.Error_IncompatibleProto { + return ErrRemoteIncompatibleProto + } + if msg.ack.Error == handshakeproto.Error_Null { + return nil + } + return HandshakeError{e: msg.ack.Error} +} + +func IncomingProtoHandshake(ctx context.Context, sc sec.SecureConn, pt ProtoChecker) (protoType handshakeproto.ProtoType, err error) { + if ctx == nil { + ctx = context.Background() + } + h := newHandshake() + done := make(chan struct{}) + go func() { + defer close(done) + protoType, err = incomingProtoHandshake(h, sc, pt) + }() + select { + case <-done: + return + case <-ctx.Done(): + _ = sc.Close() + return 0, ctx.Err() + } +} + +func incomingProtoHandshake(h *handshake, sc sec.SecureConn, pt ProtoChecker) (protoType handshakeproto.ProtoType, err error) { + defer h.release() + h.conn = sc + + msg, err := h.readMsg(msgTypeProto) + if err != nil { + h.tryWriteErrAndClose(err) + return + } + if !slices.Contains(pt.AllowedProtoTypes, msg.proto.Proto) { + err = ErrIncompatibleProto + h.tryWriteErrAndClose(err) + return + } + + if err = h.writeAck(handshakeproto.Error_Null); err != nil { + h.tryWriteErrAndClose(err) + return 0, err + } else { + return msg.proto.Proto, nil + } +} diff --git a/net/secureservice/handshake/proto_test.go b/net/secureservice/handshake/proto_test.go new file mode 100644 index 00000000..f689e372 --- /dev/null +++ b/net/secureservice/handshake/proto_test.go @@ -0,0 +1,121 @@ +package handshake + +import ( + "github.com/anyproto/any-sync/net/secureservice/handshake/handshakeproto" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +type protoRes struct { + protoType handshakeproto.ProtoType + err error +} + +func newProtoChecker(types ...handshakeproto.ProtoType) ProtoChecker { + return ProtoChecker{AllowedProtoTypes: types} +} +func TestIncomingProtoHandshake(t *testing.T) { + t.Run("success", func(t *testing.T) { + c1, c2 := newConnPair(t) + var protoResCh = make(chan protoRes, 1) + go func() { + protoType, err := IncomingProtoHandshake(nil, c1, newProtoChecker(1)) + protoResCh <- protoRes{protoType: protoType, err: err} + }() + h := newHandshake() + h.conn = c2 + + // write desired proto + require.NoError(t, h.writeProto(&handshakeproto.Proto{Proto: handshakeproto.ProtoType(1)})) + msg, err := h.readMsg(msgTypeAck) + require.NoError(t, err) + assert.Equal(t, handshakeproto.Error_Null, msg.ack.Error) + res := <-protoResCh + require.NoError(t, res.err) + assert.Equal(t, handshakeproto.ProtoType(1), res.protoType) + }) + t.Run("incompatible", func(t *testing.T) { + c1, c2 := newConnPair(t) + var protoResCh = make(chan protoRes, 1) + go func() { + protoType, err := IncomingProtoHandshake(nil, c1, newProtoChecker(1)) + protoResCh <- protoRes{protoType: protoType, err: err} + }() + h := newHandshake() + h.conn = c2 + + // write desired proto + require.NoError(t, h.writeProto(&handshakeproto.Proto{Proto: 0})) + msg, err := h.readMsg(msgTypeAck) + require.NoError(t, err) + assert.Equal(t, handshakeproto.Error_IncompatibleProto, msg.ack.Error) + res := <-protoResCh + require.Error(t, res.err, ErrIncompatibleProto.Error()) + }) +} + +func TestOutgoingProtoHandshake(t *testing.T) { + t.Run("success", func(t *testing.T) { + c1, c2 := newConnPair(t) + var protoResCh = make(chan protoRes, 1) + go func() { + err := OutgoingProtoHandshake(nil, c1, 1) + protoResCh <- protoRes{err: err} + }() + h := newHandshake() + h.conn = c2 + + msg, err := h.readMsg(msgTypeProto) + require.NoError(t, err) + assert.Equal(t, handshakeproto.ProtoType(1), msg.proto.Proto) + require.NoError(t, h.writeAck(handshakeproto.Error_Null)) + + res := <-protoResCh + assert.NoError(t, res.err) + }) + t.Run("incompatible", func(t *testing.T) { + c1, c2 := newConnPair(t) + var protoResCh = make(chan protoRes, 1) + go func() { + err := OutgoingProtoHandshake(nil, c1, 1) + protoResCh <- protoRes{err: err} + }() + h := newHandshake() + h.conn = c2 + + msg, err := h.readMsg(msgTypeProto) + require.NoError(t, err) + assert.Equal(t, handshakeproto.ProtoType(1), msg.proto.Proto) + require.NoError(t, h.writeAck(handshakeproto.Error_IncompatibleProto)) + + res := <-protoResCh + assert.EqualError(t, res.err, ErrRemoteIncompatibleProto.Error()) + }) +} + +func TestEndToEndProto(t *testing.T) { + c1, c2 := newConnPair(t) + var ( + inResCh = make(chan protoRes, 1) + outResCh = make(chan protoRes, 1) + ) + st := time.Now() + go func() { + err := OutgoingProtoHandshake(nil, c1, 0) + outResCh <- protoRes{err: err} + }() + go func() { + protoType, err := IncomingProtoHandshake(nil, c2, newProtoChecker(0, 1)) + inResCh <- protoRes{protoType: protoType, err: err} + }() + + outRes := <-outResCh + assert.NoError(t, outRes.err) + + inRes := <-inResCh + assert.NoError(t, inRes.err) + assert.Equal(t, handshakeproto.ProtoType(0), inRes.protoType) + t.Log("dur", time.Since(st)) +} diff --git a/net/streampool/testservice/testservice_drpc.pb.go b/net/streampool/testservice/testservice_drpc.pb.go index f50fdbe7..cfe5bce9 100644 --- a/net/streampool/testservice/testservice_drpc.pb.go +++ b/net/streampool/testservice/testservice_drpc.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-drpc. DO NOT EDIT. -// protoc-gen-go-drpc version: v0.0.32 +// protoc-gen-go-drpc version: v0.0.33 // source: net/streampool/testservice/protos/testservice.proto package testservice @@ -72,6 +72,10 @@ type drpcTest_TestStreamClient struct { drpc.Stream } +func (x *drpcTest_TestStreamClient) GetStream() drpc.Stream { + return x.Stream +} + func (x *drpcTest_TestStreamClient) Send(m *StreamMessage) error { return x.MsgSend(m, drpcEncoding_File_net_streampool_testservice_protos_testservice_proto{}) } From 00c582e157c875204015f37ceddc8a8ed1c710f1 Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Wed, 31 May 2023 19:24:23 +0200 Subject: [PATCH 07/11] use net.Conn for a proto handshake --- net/secureservice/handshake/handshake.go | 3 ++- net/secureservice/handshake/proto.go | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/net/secureservice/handshake/handshake.go b/net/secureservice/handshake/handshake.go index 39e6656f..abbafeb5 100644 --- a/net/secureservice/handshake/handshake.go +++ b/net/secureservice/handshake/handshake.go @@ -7,6 +7,7 @@ import ( "github.com/libp2p/go-libp2p/core/sec" "golang.org/x/exp/slices" "io" + "net" "sync" ) @@ -73,7 +74,7 @@ func newHandshake() *handshake { } type handshake struct { - conn sec.SecureConn + conn net.Conn remoteCred *handshakeproto.Credentials remoteProto *handshakeproto.Proto remoteAck *handshakeproto.Ack diff --git a/net/secureservice/handshake/proto.go b/net/secureservice/handshake/proto.go index 1e133069..45e95ab5 100644 --- a/net/secureservice/handshake/proto.go +++ b/net/secureservice/handshake/proto.go @@ -3,15 +3,15 @@ package handshake import ( "context" "github.com/anyproto/any-sync/net/secureservice/handshake/handshakeproto" - "github.com/libp2p/go-libp2p/core/sec" "golang.org/x/exp/slices" + "net" ) type ProtoChecker struct { AllowedProtoTypes []handshakeproto.ProtoType } -func OutgoingProtoHandshake(ctx context.Context, sc sec.SecureConn, pt handshakeproto.ProtoType) (err error) { +func OutgoingProtoHandshake(ctx context.Context, conn net.Conn, pt handshakeproto.ProtoType) (err error) { if ctx == nil { ctx = context.Background() } @@ -19,20 +19,20 @@ func OutgoingProtoHandshake(ctx context.Context, sc sec.SecureConn, pt handshake done := make(chan struct{}) go func() { defer close(done) - err = outgoingProtoHandshake(h, sc, pt) + err = outgoingProtoHandshake(h, conn, pt) }() select { case <-done: return case <-ctx.Done(): - _ = sc.Close() + _ = conn.Close() return ctx.Err() } } -func outgoingProtoHandshake(h *handshake, sc sec.SecureConn, pt handshakeproto.ProtoType) (err error) { +func outgoingProtoHandshake(h *handshake, conn net.Conn, pt handshakeproto.ProtoType) (err error) { defer h.release() - h.conn = sc + h.conn = conn localProto := &handshakeproto.Proto{ Proto: pt, } @@ -54,7 +54,7 @@ func outgoingProtoHandshake(h *handshake, sc sec.SecureConn, pt handshakeproto.P return HandshakeError{e: msg.ack.Error} } -func IncomingProtoHandshake(ctx context.Context, sc sec.SecureConn, pt ProtoChecker) (protoType handshakeproto.ProtoType, err error) { +func IncomingProtoHandshake(ctx context.Context, conn net.Conn, pt ProtoChecker) (protoType handshakeproto.ProtoType, err error) { if ctx == nil { ctx = context.Background() } @@ -62,20 +62,20 @@ func IncomingProtoHandshake(ctx context.Context, sc sec.SecureConn, pt ProtoChec done := make(chan struct{}) go func() { defer close(done) - protoType, err = incomingProtoHandshake(h, sc, pt) + protoType, err = incomingProtoHandshake(h, conn, pt) }() select { case <-done: return case <-ctx.Done(): - _ = sc.Close() + _ = conn.Close() return 0, ctx.Err() } } -func incomingProtoHandshake(h *handshake, sc sec.SecureConn, pt ProtoChecker) (protoType handshakeproto.ProtoType, err error) { +func incomingProtoHandshake(h *handshake, conn net.Conn, pt ProtoChecker) (protoType handshakeproto.ProtoType, err error) { defer h.release() - h.conn = sc + h.conn = conn msg, err := h.readMsg(msgTypeProto) if err != nil { From fb007211f0e64ff63bab051ae4510dc501db4818 Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Wed, 31 May 2023 20:24:07 +0200 Subject: [PATCH 08/11] simplify drpc server + peer accept loop --- net/peer/peer.go | 67 ++++++++++++++--- net/peer/peer_test.go | 83 +++++++++++++++++++- net/peerservice/peerservice.go | 7 +- net/rpc/server/baseserver.go | 134 --------------------------------- net/rpc/server/drpcserver.go | 61 ++++++++------- net/rpc/server/util.go | 18 ----- net/rpc/server/util_windows.go | 41 ---------- net/transport/transport.go | 5 ++ net/transport/yamux/conn.go | 10 +++ 9 files changed, 185 insertions(+), 241 deletions(-) delete mode 100644 net/rpc/server/baseserver.go delete mode 100644 net/rpc/server/util.go delete mode 100644 net/rpc/server/util_windows.go diff --git a/net/peer/peer.go b/net/peer/peer.go index df8a2799..9c8e0ddc 100644 --- a/net/peer/peer.go +++ b/net/peer/peer.go @@ -2,28 +2,37 @@ package peer import ( "context" + "github.com/anyproto/any-sync/app/logger" "github.com/anyproto/any-sync/app/ocache" + "github.com/anyproto/any-sync/net/secureservice/handshake" + "github.com/anyproto/any-sync/net/secureservice/handshake/handshakeproto" "github.com/anyproto/any-sync/net/transport" + "go.uber.org/zap" + "io" + "net" "storj.io/drpc" "storj.io/drpc/drpcconn" "sync" "time" - - "github.com/anyproto/any-sync/app/logger" - "go.uber.org/zap" ) var log = logger.NewNamed("common.net.peer") -func NewPeer(mc transport.MultiConn) (p Peer, err error) { +type connCtrl interface { + ServeConn(ctx context.Context, conn net.Conn) (err error) +} + +func NewPeer(mc transport.MultiConn, ctrl connCtrl) (p Peer, err error) { ctx := mc.Context() pr := &peer{ active: map[drpc.Conn]struct{}{}, MultiConn: mc, + ctrl: ctrl, } if pr.id, err = CtxPeerId(ctx); err != nil { return } + go pr.acceptLoop() return pr, nil } @@ -43,10 +52,13 @@ type Peer interface { type peer struct { id string + ctrl connCtrl + // drpc conn pool inactive []drpc.Conn active map[drpc.Conn]struct{} - mu sync.Mutex + + mu sync.Mutex transport.MultiConn } @@ -83,16 +95,49 @@ func (p *peer) ReleaseDrpcConn(conn drpc.Conn) { return } +func (p *peer) acceptLoop() { + var exitErr error + defer func() { + if exitErr != transport.ErrConnClosed { + log.Warn("accept error: close connection", zap.Error(exitErr)) + _ = p.MultiConn.Close() + } + }() + for { + conn, err := p.Accept() + if err != nil { + exitErr = err + return + } + go func() { + serveErr := p.serve(conn) + if serveErr != io.EOF && serveErr != transport.ErrConnClosed { + log.InfoCtx(p.Context(), "serve connection error", zap.Error(serveErr)) + } + }() + } +} + +var defaultProtoChecker = handshake.ProtoChecker{ + AllowedProtoTypes: []handshakeproto.ProtoType{ + handshakeproto.ProtoType_DRPC, + }, +} + +func (p *peer) serve(conn net.Conn) (err error) { + hsCtx, cancel := context.WithTimeout(p.Context(), time.Second*20) + if _, err = handshake.IncomingProtoHandshake(hsCtx, conn, defaultProtoChecker); err != nil { + cancel() + return + } + cancel() + return p.ctrl.ServeConn(p.Context(), conn) +} + func (p *peer) TryClose(objectTTL time.Duration) (res bool, err error) { if time.Now().Sub(p.LastUsage()) < objectTTL { return false, nil } - p.mu.Lock() - if len(p.active) > 0 { - p.mu.Unlock() - return false, nil - } - p.mu.Unlock() return true, p.Close() } diff --git a/net/peer/peer_test.go b/net/peer/peer_test.go index 41efc45d..00a14252 100644 --- a/net/peer/peer_test.go +++ b/net/peer/peer_test.go @@ -2,12 +2,16 @@ package peer import ( "context" + "github.com/anyproto/any-sync/net/secureservice/handshake" + "github.com/anyproto/any-sync/net/secureservice/handshake/handshakeproto" "github.com/anyproto/any-sync/net/transport/mock_transport" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "io" "net" "testing" + "time" ) var ctx = context.Background() @@ -38,14 +42,63 @@ func TestPeer_AcquireDrpcConn(t *testing.T) { assert.Len(t, fx.inactive, 0) } +func TestPeerAccept(t *testing.T) { + fx := newFixture(t, "p1") + defer fx.finish() + in, out := net.Pipe() + defer out.Close() + + var outHandshakeCh = make(chan error) + go func() { + outHandshakeCh <- handshake.OutgoingProtoHandshake(ctx, out, handshakeproto.ProtoType_DRPC) + }() + fx.acceptCh <- acceptedConn{conn: in} + cn := <-fx.testCtrl.serveConn + assert.Equal(t, in, cn) + assert.NoError(t, <-outHandshakeCh) +} + +func TestPeer_TryClose(t *testing.T) { + t.Run("ttl", func(t *testing.T) { + fx := newFixture(t, "p1") + defer fx.finish() + lu := time.Now() + fx.mc.EXPECT().LastUsage().Return(lu) + res, err := fx.TryClose(time.Second) + require.NoError(t, err) + assert.False(t, res) + }) + t.Run("close", func(t *testing.T) { + fx := newFixture(t, "p1") + defer fx.finish() + lu := time.Now().Add(-time.Second * 2) + fx.mc.EXPECT().LastUsage().Return(lu) + res, err := fx.TryClose(time.Second) + require.NoError(t, err) + assert.True(t, res) + }) +} + +type acceptedConn struct { + conn net.Conn + err error +} + func newFixture(t *testing.T, peerId string) *fixture { fx := &fixture{ - ctrl: gomock.NewController(t), + ctrl: gomock.NewController(t), + acceptCh: make(chan acceptedConn), + testCtrl: newTesCtrl(), } fx.mc = mock_transport.NewMockMultiConn(fx.ctrl) ctx := CtxWithPeerId(context.Background(), peerId) fx.mc.EXPECT().Context().Return(ctx).AnyTimes() - p, err := NewPeer(fx.mc) + fx.mc.EXPECT().Accept().DoAndReturn(func() (net.Conn, error) { + ac := <-fx.acceptCh + return ac.conn, ac.err + }).AnyTimes() + fx.mc.EXPECT().Close().AnyTimes() + p, err := NewPeer(fx.mc, fx.testCtrl) require.NoError(t, err) fx.peer = p.(*peer) return fx @@ -53,10 +106,32 @@ func newFixture(t *testing.T, peerId string) *fixture { type fixture struct { *peer - ctrl *gomock.Controller - mc *mock_transport.MockMultiConn + ctrl *gomock.Controller + mc *mock_transport.MockMultiConn + acceptCh chan acceptedConn + testCtrl *testCtrl } func (fx *fixture) finish() { + fx.testCtrl.close() fx.ctrl.Finish() } + +func newTesCtrl() *testCtrl { + return &testCtrl{closeCh: make(chan struct{}), serveConn: make(chan net.Conn, 10)} +} + +type testCtrl struct { + serveConn chan net.Conn + closeCh chan struct{} +} + +func (t *testCtrl) ServeConn(ctx context.Context, conn net.Conn) (err error) { + t.serveConn <- conn + <-t.closeCh + return io.EOF +} + +func (t *testCtrl) close() { + close(t.closeCh) +} diff --git a/net/peerservice/peerservice.go b/net/peerservice/peerservice.go index a83e6785..e0691733 100644 --- a/net/peerservice/peerservice.go +++ b/net/peerservice/peerservice.go @@ -7,6 +7,7 @@ import ( "github.com/anyproto/any-sync/app/logger" "github.com/anyproto/any-sync/net/peer" "github.com/anyproto/any-sync/net/pool" + "github.com/anyproto/any-sync/net/rpc/server" "github.com/anyproto/any-sync/net/transport" "github.com/anyproto/any-sync/net/transport/yamux" "github.com/anyproto/any-sync/nodeconf" @@ -38,6 +39,7 @@ type peerService struct { nodeConf nodeconf.NodeConf peerAddrs map[string][]string pool pool.Pool + server server.DRPCServer mu sync.RWMutex } @@ -45,6 +47,7 @@ func (p *peerService) Init(a *app.App) (err error) { p.yamux = a.MustComponent(yamux.CName).(transport.Transport) p.nodeConf = a.MustComponent(nodeconf.CName).(nodeconf.NodeConf) p.pool = a.MustComponent(pool.CName).(pool.Pool) + p.server = a.MustComponent(server.CName).(server.DRPCServer) p.peerAddrs = map[string][]string{} return nil } @@ -75,11 +78,11 @@ func (p *peerService) Dial(ctx context.Context, peerId string) (pr peer.Peer, er if err != nil { return } - return peer.NewPeer(mc) + return peer.NewPeer(mc, p.server) } func (p *peerService) Accept(mc transport.MultiConn) (err error) { - pr, err := peer.NewPeer(mc) + pr, err := peer.NewPeer(mc, p.server) if err != nil { return err } diff --git a/net/rpc/server/baseserver.go b/net/rpc/server/baseserver.go deleted file mode 100644 index cb3047ed..00000000 --- a/net/rpc/server/baseserver.go +++ /dev/null @@ -1,134 +0,0 @@ -package server - -import ( - "context" - "github.com/anyproto/any-sync/net/peer" - "github.com/anyproto/any-sync/net/secureservice" - "github.com/libp2p/go-libp2p/core/sec" - "github.com/zeebo/errs" - "go.uber.org/zap" - "io" - "net" - "storj.io/drpc" - "storj.io/drpc/drpcmanager" - "storj.io/drpc/drpcmux" - "storj.io/drpc/drpcserver" - "storj.io/drpc/drpcwire" - "time" -) - -type BaseDrpcServer struct { - drpcServer *drpcserver.Server - transport secureservice.SecureService - listeners []net.Listener - handshake func(conn net.Conn) (cCtx context.Context, sc sec.SecureConn, err error) - cancel func() - *drpcmux.Mux -} - -type DRPCHandlerWrapper func(handler drpc.Handler) drpc.Handler - -type Params struct { - BufferSizeMb int - ListenAddrs []string - Wrapper DRPCHandlerWrapper - TimeoutMillis int - Handshake func(conn net.Conn) (cCtx context.Context, sc sec.SecureConn, err error) -} - -func NewBaseDrpcServer() *BaseDrpcServer { - return &BaseDrpcServer{Mux: drpcmux.New()} -} - -func (s *BaseDrpcServer) Run(ctx context.Context, params Params) (err error) { - s.drpcServer = drpcserver.NewWithOptions(params.Wrapper(s.Mux), drpcserver.Options{Manager: drpcmanager.Options{ - Reader: drpcwire.ReaderOptions{MaximumBufferSize: params.BufferSizeMb * (1 << 20)}, - }}) - s.handshake = params.Handshake - ctx, s.cancel = context.WithCancel(ctx) - for _, addr := range params.ListenAddrs { - list, err := net.Listen("tcp", addr) - if err != nil { - return err - } - s.listeners = append(s.listeners, list) - go s.serve(ctx, list) - } - return -} - -func (s *BaseDrpcServer) serve(ctx context.Context, lis net.Listener) { - l := log.With(zap.String("localAddr", lis.Addr().String())) - l.Info("drpc listener started") - defer func() { - l.Debug("drpc listener stopped") - }() - for { - select { - case <-ctx.Done(): - return - default: - } - conn, err := lis.Accept() - if err != nil { - if isTemporary(err) { - l.Debug("listener temporary accept error", zap.Error(err)) - select { - case <-time.After(time.Second): - case <-ctx.Done(): - return - } - continue - } - l.Error("listener accept error", zap.Error(err)) - return - } - go s.serveConn(conn) - } -} - -func (s *BaseDrpcServer) serveConn(conn net.Conn) { - l := log.With(zap.String("remoteAddr", conn.RemoteAddr().String())).With(zap.String("localAddr", conn.LocalAddr().String())) - var ( - ctx = context.Background() - err error - ) - if s.handshake != nil { - ctx, conn, err = s.handshake(conn) - if err != nil { - l.Info("handshake error", zap.Error(err)) - return - } - if sc, ok := conn.(sec.SecureConn); ok { - ctx = peer.CtxWithPeerId(ctx, sc.RemotePeer().String()) - } - } - ctx = peer.CtxWithPeerAddr(ctx, conn.RemoteAddr().String()) - l.Debug("connection opened") - if err := s.drpcServer.ServeOne(ctx, conn); err != nil { - if errs.Is(err, context.Canceled) || errs.Is(err, io.EOF) { - l.Debug("connection closed") - } else { - l.Warn("serve connection error", zap.Error(err)) - } - } -} - -func (s *BaseDrpcServer) ListenAddrs() (addrs []net.Addr) { - for _, list := range s.listeners { - addrs = append(addrs, list.Addr()) - } - return -} - -func (s *BaseDrpcServer) Close(ctx context.Context) (err error) { - if s.cancel != nil { - s.cancel() - } - for _, l := range s.listeners { - if e := l.Close(); e != nil { - log.Warn("close listener error", zap.Error(e)) - } - } - return -} diff --git a/net/rpc/server/drpcserver.go b/net/rpc/server/drpcserver.go index 1874d16a..2b061515 100644 --- a/net/rpc/server/drpcserver.go +++ b/net/rpc/server/drpcserver.go @@ -6,11 +6,13 @@ import ( "github.com/anyproto/any-sync/app/logger" "github.com/anyproto/any-sync/metric" anyNet "github.com/anyproto/any-sync/net" - "github.com/anyproto/any-sync/net/secureservice" - "github.com/libp2p/go-libp2p/core/sec" + "go.uber.org/zap" "net" "storj.io/drpc" - "time" + "storj.io/drpc/drpcmanager" + "storj.io/drpc/drpcmux" + "storj.io/drpc/drpcserver" + "storj.io/drpc/drpcwire" ) const CName = "common.net.drpcserver" @@ -18,49 +20,46 @@ const CName = "common.net.drpcserver" var log = logger.NewNamed(CName) func New() DRPCServer { - return &drpcServer{BaseDrpcServer: NewBaseDrpcServer()} + return &drpcServer{} } type DRPCServer interface { - app.ComponentRunnable + ServeConn(ctx context.Context, conn net.Conn) (err error) + app.Component drpc.Mux } type drpcServer struct { - config anyNet.Config - metric metric.Metric - transport secureservice.SecureService - *BaseDrpcServer + drpcServer *drpcserver.Server + *drpcmux.Mux + config anyNet.Config + metric metric.Metric } -func (s *drpcServer) Init(a *app.App) (err error) { - s.config = a.MustComponent("config").(anyNet.ConfigGetter).GetNet() - s.metric = a.MustComponent(metric.CName).(metric.Metric) - s.transport = a.MustComponent(secureservice.CName).(secureservice.SecureService) - return nil -} +type DRPCHandlerWrapper func(handler drpc.Handler) drpc.Handler func (s *drpcServer) Name() (name string) { return CName } -func (s *drpcServer) Run(ctx context.Context) (err error) { - params := Params{ - BufferSizeMb: s.config.Stream.MaxMsgSizeMb, - TimeoutMillis: s.config.Stream.TimeoutMilliseconds, - ListenAddrs: s.config.Server.ListenAddrs, - Wrapper: func(handler drpc.Handler) drpc.Handler { - return s.metric.WrapDRPCHandler(handler) - }, - Handshake: func(conn net.Conn) (cCtx context.Context, sc sec.SecureConn, err error) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) - defer cancel() - return s.transport.SecureInbound(ctx, conn) - }, +func (s *drpcServer) Init(a *app.App) (err error) { + s.config = a.MustComponent("config").(anyNet.ConfigGetter).GetNet() + s.metric, _ = a.Component(metric.CName).(metric.Metric) + s.Mux = drpcmux.New() + + var handler drpc.Handler + handler = s + if s.metric != nil { + handler = s.metric.WrapDRPCHandler(s) } - return s.BaseDrpcServer.Run(ctx, params) + s.drpcServer = drpcserver.NewWithOptions(handler, drpcserver.Options{Manager: drpcmanager.Options{ + Reader: drpcwire.ReaderOptions{MaximumBufferSize: s.config.Stream.MaxMsgSizeMb * (1 << 20)}, + }}) + return } -func (s *drpcServer) Close(ctx context.Context) (err error) { - return s.BaseDrpcServer.Close(ctx) +func (s *drpcServer) ServeConn(ctx context.Context, conn net.Conn) (err error) { + l := log.With(zap.String("remoteAddr", conn.RemoteAddr().String())).With(zap.String("localAddr", conn.LocalAddr().String())) + l.Debug("drpc serve peer") + return s.drpcServer.ServeOne(ctx, conn) } diff --git a/net/rpc/server/util.go b/net/rpc/server/util.go deleted file mode 100644 index 5852288a..00000000 --- a/net/rpc/server/util.go +++ /dev/null @@ -1,18 +0,0 @@ -//go:build !windows - -package server - -import ( - "errors" - "net" -) - -// isTemporary checks if an error is temporary. -func isTemporary(err error) bool { - var nErr net.Error - if errors.As(err, &nErr) { - return nErr.Temporary() - } - - return false -} diff --git a/net/rpc/server/util_windows.go b/net/rpc/server/util_windows.go deleted file mode 100644 index efef2915..00000000 --- a/net/rpc/server/util_windows.go +++ /dev/null @@ -1,41 +0,0 @@ -//go:build windows - -package server - -import ( - "errors" - "net" - "os" - "syscall" -) - -const ( - _WSAEMFILE syscall.Errno = 10024 - _WSAENETRESET syscall.Errno = 10052 - _WSAENOBUFS syscall.Errno = 10055 -) - -// isTemporary checks if an error is temporary. -// see related go issue for more detail: https://go-review.googlesource.com/c/go/+/208537/ -func isTemporary(err error) bool { - var nErr net.Error - if !errors.As(err, &nErr) { - return false - } - - if nErr.Temporary() { - return true - } - - var sErr *os.SyscallError - if errors.As(err, &sErr) { - switch sErr.Err { - case _WSAENETRESET, - _WSAEMFILE, - _WSAENOBUFS: - return true - } - } - - return false -} diff --git a/net/transport/transport.go b/net/transport/transport.go index 7b247793..2dab5348 100644 --- a/net/transport/transport.go +++ b/net/transport/transport.go @@ -3,10 +3,15 @@ package transport import ( "context" + "errors" "net" "time" ) +var ( + ErrConnClosed = errors.New("connection closed") +) + // Transport is a common interface for a network transport type Transport interface { // SetAccepter sets accepter that will be called for new connections diff --git a/net/transport/yamux/conn.go b/net/transport/yamux/conn.go index 541b8257..d563df34 100644 --- a/net/transport/yamux/conn.go +++ b/net/transport/yamux/conn.go @@ -3,6 +3,7 @@ package yamux import ( "context" "github.com/anyproto/any-sync/net/connutil" + "github.com/anyproto/any-sync/net/transport" "github.com/hashicorp/yamux" "net" "time" @@ -30,3 +31,12 @@ func (y *yamuxConn) Context() context.Context { func (y *yamuxConn) Addr() string { return y.addr } + +func (y *yamuxConn) Accept() (conn net.Conn, err error) { + if conn, err = y.Session.Accept(); err != nil { + if err == yamux.ErrSessionShutdown { + err = transport.ErrConnClosed + } + } + return +} From 1206071dd655b7334c90f93071605fd11c40576d Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Fri, 2 Jun 2023 10:34:49 +0200 Subject: [PATCH 09/11] fix pool test --- net/pool/pool_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/pool/pool_test.go b/net/pool/pool_test.go index c31fcf69..c93c9aec 100644 --- a/net/pool/pool_test.go +++ b/net/pool/pool_test.go @@ -217,6 +217,10 @@ type testPeer struct { closed chan struct{} } +func (t *testPeer) DoDrpc(ctx context.Context, do func(conn drpc.Conn) error) error { + return fmt.Errorf("not implemented") +} + func (t *testPeer) AcquireDrpcConn(ctx context.Context) (drpc.Conn, error) { return nil, fmt.Errorf("not implemented") } From e9f23e2dd91e9c094a9282775e8aed86b8d2366e Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Fri, 2 Jun 2023 10:39:24 +0200 Subject: [PATCH 10/11] peer.DoDrpc method --- net/peer/peer.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/net/peer/peer.go b/net/peer/peer.go index 9c8e0ddc..879f6f9b 100644 --- a/net/peer/peer.go +++ b/net/peer/peer.go @@ -41,6 +41,7 @@ type Peer interface { AcquireDrpcConn(ctx context.Context) (drpc.Conn, error) ReleaseDrpcConn(conn drpc.Conn) + DoDrpc(ctx context.Context, do func(conn drpc.Conn) error) error IsClosed() bool @@ -95,6 +96,15 @@ func (p *peer) ReleaseDrpcConn(conn drpc.Conn) { return } +func (p *peer) DoDrpc(ctx context.Context, do func(conn drpc.Conn) error) error { + conn, err := p.AcquireDrpcConn(ctx) + if err != nil { + return err + } + defer p.ReleaseDrpcConn(conn) + return do(conn) +} + func (p *peer) acceptLoop() { var exitErr error defer func() { From 96768adaae2f64d07f03a5dc0ed633b5bf0590e7 Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Fri, 2 Jun 2023 10:39:48 +0200 Subject: [PATCH 11/11] switch coordinator to new peer api --- .../coordinatorclient/coordinatorclient.go | 156 +++++++++--------- 1 file changed, 77 insertions(+), 79 deletions(-) diff --git a/coordinator/coordinatorclient/coordinatorclient.go b/coordinator/coordinatorclient/coordinatorclient.go index 4847ade7..b804d9a5 100644 --- a/coordinator/coordinatorclient/coordinatorclient.go +++ b/coordinator/coordinatorclient/coordinatorclient.go @@ -10,6 +10,7 @@ import ( "github.com/anyproto/any-sync/net/rpc/rpcerr" "github.com/anyproto/any-sync/nodeconf" "github.com/anyproto/any-sync/util/crypto" + "storj.io/drpc" ) const CName = "common.coordinator.coordinatorclient" @@ -39,42 +40,8 @@ type coordinatorClient struct { nodeConf nodeconf.Service } -func (c *coordinatorClient) ChangeStatus(ctx context.Context, spaceId string, deleteRaw *treechangeproto.RawTreeChangeWithId) (status *coordinatorproto.SpaceStatusPayload, err error) { - cl, err := c.client(ctx) - if err != nil { - return - } - resp, err := cl.SpaceStatusChange(ctx, &coordinatorproto.SpaceStatusChangeRequest{ - SpaceId: spaceId, - DeletionChangeId: deleteRaw.GetId(), - DeletionChangePayload: deleteRaw.GetRawChange(), - }) - if err != nil { - err = rpcerr.Unwrap(err) - return - } - status = resp.Payload - return -} - -func (c *coordinatorClient) StatusCheck(ctx context.Context, spaceId string) (status *coordinatorproto.SpaceStatusPayload, err error) { - cl, err := c.client(ctx) - if err != nil { - return - } - resp, err := cl.SpaceStatusCheck(ctx, &coordinatorproto.SpaceStatusCheckRequest{ - SpaceId: spaceId, - }) - if err != nil { - err = rpcerr.Unwrap(err) - return - } - status = resp.Payload - return -} - func (c *coordinatorClient) Init(a *app.App) (err error) { - c.pool = a.MustComponent(pool.CName).(pool.Service).NewPool(CName) + c.pool = a.MustComponent(pool.CName).(pool.Service) c.nodeConf = a.MustComponent(nodeconf.CName).(nodeconf.Service) return } @@ -83,8 +50,37 @@ func (c *coordinatorClient) Name() (name string) { return CName } +func (c *coordinatorClient) ChangeStatus(ctx context.Context, spaceId string, deleteRaw *treechangeproto.RawTreeChangeWithId) (status *coordinatorproto.SpaceStatusPayload, err error) { + err = c.doClient(ctx, func(cl coordinatorproto.DRPCCoordinatorClient) error { + resp, err := cl.SpaceStatusChange(ctx, &coordinatorproto.SpaceStatusChangeRequest{ + SpaceId: spaceId, + DeletionChangeId: deleteRaw.GetId(), + DeletionChangePayload: deleteRaw.GetRawChange(), + }) + if err != nil { + return rpcerr.Unwrap(err) + } + status = resp.Payload + return nil + }) + return +} + +func (c *coordinatorClient) StatusCheck(ctx context.Context, spaceId string) (status *coordinatorproto.SpaceStatusPayload, err error) { + err = c.doClient(ctx, func(cl coordinatorproto.DRPCCoordinatorClient) error { + resp, err := cl.SpaceStatusCheck(ctx, &coordinatorproto.SpaceStatusCheckRequest{ + SpaceId: spaceId, + }) + if err != nil { + return rpcerr.Unwrap(err) + } + status = resp.Payload + return nil + }) + return +} + func (c *coordinatorClient) SpaceSign(ctx context.Context, payload SpaceSignPayload) (receipt *coordinatorproto.SpaceReceiptWithSignature, err error) { - cl, err := c.client(ctx) if err != nil { return } @@ -100,54 +96,56 @@ func (c *coordinatorClient) SpaceSign(ctx context.Context, payload SpaceSignPayl if err != nil { return } - resp, err := cl.SpaceSign(ctx, &coordinatorproto.SpaceSignRequest{ - SpaceId: payload.SpaceId, - Header: payload.SpaceHeader, - OldIdentity: oldIdentity, - NewIdentitySignature: newSignature, + err = c.doClient(ctx, func(cl coordinatorproto.DRPCCoordinatorClient) error { + resp, err := cl.SpaceSign(ctx, &coordinatorproto.SpaceSignRequest{ + SpaceId: payload.SpaceId, + Header: payload.SpaceHeader, + OldIdentity: oldIdentity, + NewIdentitySignature: newSignature, + }) + if err != nil { + return rpcerr.Unwrap(err) + } + receipt = resp.Receipt + return nil }) - if err != nil { - err = rpcerr.Unwrap(err) - return - } - return resp.Receipt, nil -} - -func (c *coordinatorClient) FileLimitCheck(ctx context.Context, spaceId string, identity []byte) (limit uint64, err error) { - cl, err := c.client(ctx) - if err != nil { - return - } - resp, err := cl.FileLimitCheck(ctx, &coordinatorproto.FileLimitCheckRequest{ - AccountIdentity: identity, - SpaceId: spaceId, - }) - if err != nil { - err = rpcerr.Unwrap(err) - return - } - return resp.Limit, nil -} - -func (c *coordinatorClient) NetworkConfiguration(ctx context.Context, currentId string) (resp *coordinatorproto.NetworkConfigurationResponse, err error) { - cl, err := c.client(ctx) - if err != nil { - return - } - resp, err = cl.NetworkConfiguration(ctx, &coordinatorproto.NetworkConfigurationRequest{ - CurrentId: currentId, - }) - if err != nil { - err = rpcerr.Unwrap(err) - return - } return } -func (c *coordinatorClient) client(ctx context.Context) (coordinatorproto.DRPCCoordinatorClient, error) { +func (c *coordinatorClient) FileLimitCheck(ctx context.Context, spaceId string, identity []byte) (limit uint64, err error) { + err = c.doClient(ctx, func(cl coordinatorproto.DRPCCoordinatorClient) error { + resp, err := cl.FileLimitCheck(ctx, &coordinatorproto.FileLimitCheckRequest{ + AccountIdentity: identity, + SpaceId: spaceId, + }) + if err != nil { + return rpcerr.Unwrap(err) + } + limit = resp.Limit + return nil + }) + return +} + +func (c *coordinatorClient) NetworkConfiguration(ctx context.Context, currentId string) (resp *coordinatorproto.NetworkConfigurationResponse, err error) { + err = c.doClient(ctx, func(cl coordinatorproto.DRPCCoordinatorClient) error { + resp, err = cl.NetworkConfiguration(ctx, &coordinatorproto.NetworkConfigurationRequest{ + CurrentId: currentId, + }) + if err != nil { + return rpcerr.Unwrap(err) + } + return nil + }) + return +} + +func (c *coordinatorClient) doClient(ctx context.Context, f func(cl coordinatorproto.DRPCCoordinatorClient) error) error { p, err := c.pool.GetOneOf(ctx, c.nodeConf.CoordinatorPeers()) if err != nil { - return nil, err + return err } - return coordinatorproto.NewDRPCCoordinatorClient(p), nil + return p.DoDrpc(ctx, func(conn drpc.Conn) error { + return f(coordinatorproto.NewDRPCCoordinatorClient(conn)) + }) }