storj/private/server: listen for noiseconn requests
Change-Id: Ia74dcc576fa0c97460207d93d129aa7d88cd2fba
This commit is contained in:
parent
73ffa0827f
commit
3e01e9c07a
8
go.mod
8
go.mod
@ -9,6 +9,7 @@ require (
|
||||
github.com/calebcase/tmpfile v1.0.3
|
||||
github.com/cheggaaa/pb/v3 v3.0.5
|
||||
github.com/fatih/color v1.9.0
|
||||
github.com/flynn/noise v1.0.0
|
||||
github.com/go-oauth2/oauth2/v4 v4.4.2
|
||||
github.com/go-redis/redis/v8 v8.11.5
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
@ -22,6 +23,7 @@ require (
|
||||
github.com/jackc/pgx/v4 v4.15.0
|
||||
github.com/jtolds/monkit-hw/v2 v2.0.0-20191108235325-141a0da276b3
|
||||
github.com/jtolio/eventkit v0.0.0-20221007130042-690145affff8
|
||||
github.com/jtolio/noiseconn v0.0.0-20230111204749-d7ec1a08b0b8
|
||||
github.com/loov/hrtime v1.0.3
|
||||
github.com/mattn/go-sqlite3 v1.14.12
|
||||
github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce
|
||||
@ -37,6 +39,7 @@ require (
|
||||
github.com/stripe/stripe-go/v72 v72.51.0
|
||||
github.com/vivint/infectious v0.0.0-20200605153912-25a574ae18a3
|
||||
github.com/zeebo/assert v1.3.1
|
||||
github.com/zeebo/blake3 v0.2.3
|
||||
github.com/zeebo/clingy v0.0.0-20220926155919-717640cb8ccd
|
||||
github.com/zeebo/errs v1.3.0
|
||||
github.com/zeebo/ini v0.0.0-20210331155437-86af75b4f524
|
||||
@ -45,8 +48,8 @@ require (
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
|
||||
golang.org/x/sync v0.1.0
|
||||
golang.org/x/sys v0.1.0
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
||||
golang.org/x/text v0.3.7
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
|
||||
@ -113,7 +116,6 @@ require (
|
||||
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect
|
||||
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb // indirect
|
||||
github.com/zeebo/admission/v3 v3.0.3 // indirect
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
github.com/zeebo/errs/v2 v2.0.3 // indirect
|
||||
github.com/zeebo/float16 v0.1.0 // indirect
|
||||
github.com/zeebo/incenc v0.0.0-20180505221441-0d92902eec54 // indirect
|
||||
|
18
go.sum
18
go.sum
@ -93,6 +93,7 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dsnet/try v0.0.3 h1:ptR59SsrcFUYbT/FhAbKTV6iLkeD6O18qfIWRml2fqI=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
@ -103,6 +104,8 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL
|
||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
|
||||
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
|
||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
@ -293,6 +296,8 @@ github.com/jtolds/tracetagger/v2 v2.0.0-rc5 h1:SriMFVtftPsQmG+0xaABotz9HnoKoo1QM
|
||||
github.com/jtolds/tracetagger/v2 v2.0.0-rc5/go.mod h1:61Fh+XhbBONy+RsqkA+xTtmaFbEVL040m9FAF/hTrjQ=
|
||||
github.com/jtolio/eventkit v0.0.0-20221007130042-690145affff8 h1:Jm6SYrxKgQMKHUVLhV9qc2Y7PuSQRKUxxk/NSrtaxdQ=
|
||||
github.com/jtolio/eventkit v0.0.0-20221007130042-690145affff8/go.mod h1:q7yMR8BavTz/gBNtIT/uF487LMgcuEpNGKISLAjNQes=
|
||||
github.com/jtolio/noiseconn v0.0.0-20230111204749-d7ec1a08b0b8 h1:+A1uT26XjTsxiUUZjAAuveILWWy+Sy2TPX8OIgGvPQE=
|
||||
github.com/jtolio/noiseconn v0.0.0-20230111204749-d7ec1a08b0b8/go.mod h1:f0ijQHcvHYAuxX6JA/JUr/Z0FVn12D9REaT/HAWVgP4=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
@ -308,8 +313,9 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
@ -644,6 +650,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
@ -731,8 +738,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -778,8 +786,9 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
@ -903,8 +912,9 @@ google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
|
28
private/server/noise.go
Normal file
28
private/server/noise.go
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2022 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/flynn/noise"
|
||||
|
||||
"storj.io/common/pb"
|
||||
)
|
||||
|
||||
// NoiseHeader is the drpcmigrate.Header prefix for DRPC over Noise.
|
||||
const NoiseHeader = "DRPC!N!1"
|
||||
|
||||
// defaultNoiseProto is the protobuf enum value that specifies what noise
|
||||
// protocol is in use.
|
||||
// defaultNoiseInfo and defaultNoiseConfig should be changed together.
|
||||
var defaultNoiseProto = pb.NoiseProtocol_NOISE_IK_25519_CHACHAPOLY_BLAKE2B
|
||||
|
||||
// defaultNoiseConfig returns the structure that tells this node what Noise
|
||||
// settings to use.
|
||||
// defaultNoiseProto and defaultNoiseConfig should be changed together.
|
||||
func defaultNoiseConfig() noise.Config {
|
||||
return noise.Config{
|
||||
CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashBLAKE2b),
|
||||
Pattern: noise.HandshakeIK,
|
||||
}
|
||||
}
|
51
private/server/replay.go
Normal file
51
private/server/replay.go
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright (C) 2023 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/zeebo/errs"
|
||||
|
||||
"storj.io/common/pb"
|
||||
"storj.io/drpc"
|
||||
)
|
||||
|
||||
type replayRouter struct {
|
||||
replaySafe, all drpc.Mux
|
||||
}
|
||||
|
||||
func newReplayRouter(replaySafe, all drpc.Mux) drpc.Mux {
|
||||
return &replayRouter{
|
||||
replaySafe: replaySafe,
|
||||
all: all,
|
||||
}
|
||||
}
|
||||
|
||||
// Register implements drpc.Mux.
|
||||
func (r *replayRouter) Register(srv interface{}, desc drpc.Description) error {
|
||||
allErr := r.all.Register(srv, desc)
|
||||
switch desc.(type) {
|
||||
case pb.DRPCPiecestoreDescription:
|
||||
return errs.Combine(allErr, r.replaySafe.Register(srv, replaySafePiecestore{}))
|
||||
default:
|
||||
return allErr
|
||||
}
|
||||
}
|
||||
|
||||
type replaySafePiecestore struct{}
|
||||
|
||||
func (replaySafePiecestore) NumMethods() int { return 2 }
|
||||
|
||||
func (replaySafePiecestore) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) {
|
||||
switch n {
|
||||
case 0:
|
||||
rpc, enc, receiver, method, ok := (pb.DRPCPiecestoreDescription{}).Method(0)
|
||||
return rpc, enc, receiver, method, ok && rpc == "/piecestore.Piecestore/Upload"
|
||||
|
||||
case 1:
|
||||
rpc, enc, receiver, method, ok := (pb.DRPCPiecestoreDescription{}).Method(1)
|
||||
return rpc, enc, receiver, method, ok && rpc == "/piecestore.Piecestore/Download"
|
||||
default:
|
||||
return "", nil, nil, nil, false
|
||||
}
|
||||
}
|
@ -6,7 +6,9 @@ package server
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -14,6 +16,9 @@ import (
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/flynn/noise"
|
||||
"github.com/jtolio/noiseconn"
|
||||
"github.com/zeebo/blake3"
|
||||
"github.com/zeebo/errs"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@ -21,10 +26,12 @@ import (
|
||||
"storj.io/common/errs2"
|
||||
"storj.io/common/experiment"
|
||||
"storj.io/common/identity"
|
||||
"storj.io/common/pb"
|
||||
"storj.io/common/peertls/tlsopts"
|
||||
"storj.io/common/rpc"
|
||||
"storj.io/common/rpc/quic"
|
||||
"storj.io/common/rpc/rpctracing"
|
||||
"storj.io/drpc"
|
||||
"storj.io/drpc/drpcmigrate"
|
||||
"storj.io/drpc/drpcmux"
|
||||
"storj.io/drpc/drpcserver"
|
||||
@ -38,38 +45,30 @@ type Config struct {
|
||||
PrivateAddress string `user:"true" help:"private address to listen on" default:"127.0.0.1:7778"`
|
||||
DisableQUIC bool `help:"disable QUIC listener on a server" hidden:"true" default:"false"`
|
||||
|
||||
DisableTCPTLS bool `help:"disable TCP/TLS listener on a server" internal:"true"`
|
||||
DisableTCP bool `help:"disable TCP listener on a server" internal:"true"`
|
||||
DebugLogTraffic bool `hidden:"true" default:"false"` // Deprecated
|
||||
}
|
||||
|
||||
type public struct {
|
||||
tcpListener net.Listener
|
||||
udpConn *net.UDPConn
|
||||
quicListener net.Listener
|
||||
addr net.Addr
|
||||
disableTCPTLS bool
|
||||
disableQUIC bool
|
||||
|
||||
drpc *drpcserver.Server
|
||||
// http fallback for the public endpoint
|
||||
http http.HandlerFunc
|
||||
|
||||
mux *drpcmux.Mux
|
||||
}
|
||||
|
||||
type private struct {
|
||||
listener net.Listener
|
||||
drpc *drpcserver.Server
|
||||
mux *drpcmux.Mux
|
||||
}
|
||||
|
||||
// Server represents a bundle of services defined by a specific ID.
|
||||
// Examples of servers are the satellite, the storagenode, and the uplink.
|
||||
type Server struct {
|
||||
log *zap.Logger
|
||||
public public
|
||||
private private
|
||||
tlsOptions *tlsopts.Options
|
||||
noiseConf noise.Config
|
||||
config Config
|
||||
|
||||
publicTCPListener net.Listener
|
||||
publicUDPConn *net.UDPConn
|
||||
publicQUICListener net.Listener
|
||||
privateTCPListener net.Listener
|
||||
addr net.Addr
|
||||
|
||||
publicEndpointsReplaySafe *endpointCollection
|
||||
publicEndpointsAll *endpointCollection
|
||||
privateEndpoints *endpointCollection
|
||||
|
||||
// http fallback for the public endpoint
|
||||
publicHTTP http.HandlerFunc
|
||||
|
||||
mu sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
@ -77,34 +76,109 @@ type Server struct {
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
// New creates a Server out of an Identity, a net.Listener,
|
||||
// and interceptors.
|
||||
func New(log *zap.Logger, tlsOptions *tlsopts.Options, config Config) (_ *Server, err error) {
|
||||
server := &Server{
|
||||
log: log,
|
||||
tlsOptions: tlsOptions,
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
func identityBasedEntropy(context string, ident *identity.FullIdentity) (io.Reader, error) {
|
||||
h := blake3.NewDeriveKey(context)
|
||||
|
||||
server.public, err = newPublic(config.Address, config.DisableTCPTLS, config.DisableQUIC)
|
||||
serialized, err := x509.MarshalPKCS8PrivateKey(ident.Key)
|
||||
if err != nil {
|
||||
return nil, Error.Wrap(err)
|
||||
}
|
||||
|
||||
serverOptions := drpcserver.Options{
|
||||
Manager: rpc.NewDefaultManagerOptions(),
|
||||
}
|
||||
privateListener, err := net.Listen("tcp", config.PrivateAddress)
|
||||
_, err = h.Write(serialized)
|
||||
return h.Digest(), Error.Wrap(err)
|
||||
}
|
||||
|
||||
func generateNoiseConf(ident *identity.FullIdentity) (noise.Config, error) {
|
||||
noiseConf := defaultNoiseConfig()
|
||||
noiseConf.Initiator = false
|
||||
entropy, err := identityBasedEntropy("noise key", ident)
|
||||
if err != nil {
|
||||
return nil, errs.Combine(err, server.public.Close())
|
||||
return noise.Config{}, err
|
||||
}
|
||||
privateMux := drpcmux.New()
|
||||
privateTracingHandler := rpctracing.NewHandler(privateMux, jaeger.RemoteTraceHandler)
|
||||
server.private = private{
|
||||
listener: wrapListener(privateListener),
|
||||
drpc: drpcserver.NewWithOptions(experiment.NewHandler(privateTracingHandler), serverOptions),
|
||||
mux: privateMux,
|
||||
noiseConf.StaticKeypair, err = noiseConf.CipherSuite.GenerateKeypair(entropy)
|
||||
if err != nil {
|
||||
return noise.Config{}, Error.Wrap(err)
|
||||
}
|
||||
return noiseConf, nil
|
||||
}
|
||||
|
||||
// New creates a Server out of an Identity, a net.Listener,
|
||||
// and interceptors.
|
||||
func New(log *zap.Logger, tlsOptions *tlsopts.Options, config Config) (_ *Server, err error) {
|
||||
noiseConf, err := generateNoiseConf(tlsOptions.Ident)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
log: log,
|
||||
tlsOptions: tlsOptions,
|
||||
noiseConf: noiseConf,
|
||||
config: config,
|
||||
|
||||
publicEndpointsReplaySafe: newEndpointCollection(),
|
||||
publicEndpointsAll: newEndpointCollection(),
|
||||
privateEndpoints: newEndpointCollection(),
|
||||
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
|
||||
for retry := 0; ; retry++ {
|
||||
addr := config.Address
|
||||
if !config.DisableTCP {
|
||||
publicTCPListener, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addr = publicTCPListener.Addr().String()
|
||||
server.publicTCPListener = wrapListener(publicTCPListener)
|
||||
}
|
||||
|
||||
if !config.DisableQUIC {
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
if server.publicTCPListener != nil {
|
||||
_ = server.publicTCPListener.Close()
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
publicUDPConn, err := net.ListenUDP("udp", udpAddr)
|
||||
if err != nil {
|
||||
_, port, splitErr := net.SplitHostPort(config.Address)
|
||||
if splitErr == nil && port == "0" && retry < 10 && isErrorAddressAlreadyInUse(err) {
|
||||
// from here, we know for sure that the tcp port chosen by the
|
||||
// os is available, but we don't know if the same port number
|
||||
// for udp is also available.
|
||||
// if a udp port is already in use, we will close the tcp port and retry
|
||||
// to find one that is available for both udp and tcp.
|
||||
if server.publicTCPListener != nil {
|
||||
_ = server.publicTCPListener.Close()
|
||||
}
|
||||
continue
|
||||
}
|
||||
if server.publicTCPListener != nil {
|
||||
return nil, errs.Combine(err, server.publicTCPListener.Close())
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
server.publicUDPConn = publicUDPConn
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
if server.publicTCPListener != nil {
|
||||
server.addr = server.publicTCPListener.Addr()
|
||||
} else if server.publicUDPConn != nil {
|
||||
server.addr = server.publicUDPConn.LocalAddr()
|
||||
}
|
||||
|
||||
privateTCPListener, err := net.Listen("tcp", config.PrivateAddress)
|
||||
if err != nil {
|
||||
return nil, errs.Combine(err, server.Close())
|
||||
}
|
||||
server.privateTCPListener = wrapListener(privateTCPListener)
|
||||
|
||||
return server, nil
|
||||
}
|
||||
@ -113,19 +187,33 @@ func New(log *zap.Logger, tlsOptions *tlsopts.Options, config Config) (_ *Server
|
||||
func (p *Server) Identity() *identity.FullIdentity { return p.tlsOptions.Ident }
|
||||
|
||||
// Addr returns the server's public listener address.
|
||||
func (p *Server) Addr() net.Addr { return p.public.addr }
|
||||
func (p *Server) Addr() net.Addr { return p.addr }
|
||||
|
||||
// PrivateAddr returns the server's private listener address.
|
||||
func (p *Server) PrivateAddr() net.Addr { return p.private.listener.Addr() }
|
||||
func (p *Server) PrivateAddr() net.Addr { return p.privateTCPListener.Addr() }
|
||||
|
||||
// DRPC returns the server's dRPC mux for registration purposes.
|
||||
func (p *Server) DRPC() *drpcmux.Mux { return p.public.mux }
|
||||
// DRPC returns the server's DRPC mux for registration purposes.
|
||||
func (p *Server) DRPC() drpc.Mux {
|
||||
return newReplayRouter(
|
||||
p.publicEndpointsReplaySafe.mux,
|
||||
p.publicEndpointsAll.mux,
|
||||
)
|
||||
}
|
||||
|
||||
// PrivateDRPC returns the server's dRPC mux for registration purposes.
|
||||
func (p *Server) PrivateDRPC() *drpcmux.Mux { return p.private.mux }
|
||||
// PrivateDRPC returns the server's DRPC mux for registration purposes.
|
||||
func (p *Server) PrivateDRPC() drpc.Mux { return p.privateEndpoints.mux }
|
||||
|
||||
// IsQUICEnabled checks if QUIC is enabled by config and udp port is open.
|
||||
func (p *Server) IsQUICEnabled() bool { return !p.public.disableQUIC && p.public.udpConn != nil }
|
||||
func (p *Server) IsQUICEnabled() bool { return !p.config.DisableQUIC && p.publicUDPConn != nil }
|
||||
|
||||
// NoiseInfo returns the noise configuration for this server. This includes the
|
||||
// keypair in use.
|
||||
func (p *Server) NoiseInfo() *pb.NoiseInfo {
|
||||
return &pb.NoiseInfo{
|
||||
Proto: defaultNoiseProto,
|
||||
PublicKey: p.noiseConf.StaticKeypair.Public,
|
||||
}
|
||||
}
|
||||
|
||||
// Close shuts down the server.
|
||||
func (p *Server) Close() error {
|
||||
@ -140,14 +228,24 @@ func (p *Server) Close() error {
|
||||
// We ignore these errors because there's not really anything to do
|
||||
// even if they happen, and they'll just be errors due to duplicate
|
||||
// closes anyway.
|
||||
_ = p.public.Close()
|
||||
_ = p.private.listener.Close()
|
||||
if p.publicQUICListener != nil {
|
||||
_ = p.publicQUICListener.Close()
|
||||
}
|
||||
if p.publicUDPConn != nil {
|
||||
_ = p.publicUDPConn.Close()
|
||||
}
|
||||
if p.publicTCPListener != nil {
|
||||
_ = p.publicTCPListener.Close()
|
||||
}
|
||||
if p.privateTCPListener != nil {
|
||||
_ = p.privateTCPListener.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddHTTPFallback adds http fallback to the drpc endpoint.
|
||||
func (p *Server) AddHTTPFallback(httpHandler http.HandlerFunc) {
|
||||
p.public.http = httpHandler
|
||||
p.publicHTTP = httpHandler
|
||||
}
|
||||
|
||||
// Run will run the server and all of its services.
|
||||
@ -174,29 +272,27 @@ func (p *Server) Run(ctx context.Context) (err error) {
|
||||
// a chance to be notified that they're done running.
|
||||
|
||||
var (
|
||||
publicMux *drpcmigrate.ListenMux
|
||||
publicDRPCListener net.Listener
|
||||
publicHTTPListener net.Listener
|
||||
publicTLSDRPCListener net.Listener
|
||||
publicNoiseDRPCListener net.Listener
|
||||
publicHTTPListener net.Listener
|
||||
privateDRPCListener net.Listener
|
||||
)
|
||||
if p.public.tcpListener != nil {
|
||||
publicMux = drpcmigrate.NewListenMux(p.public.tcpListener, len(drpcmigrate.DRPCHeader))
|
||||
publicDRPCListener = tls.NewListener(publicMux.Route(drpcmigrate.DRPCHeader), p.tlsOptions.ServerTLSConfig())
|
||||
|
||||
if p.public.http != nil {
|
||||
publicHTTPListener = NewPrefixedListener([]byte("GET / HT"), publicMux.Route("GET / HT"))
|
||||
}
|
||||
}
|
||||
|
||||
if p.public.udpConn != nil {
|
||||
p.public.quicListener, err = quic.NewListener(p.public.udpConn, p.tlsOptions.ServerTLSConfig(), nil)
|
||||
if p.publicUDPConn != nil {
|
||||
// TODO: we goofed here. we need something like a drpcmigrate.ListenMux
|
||||
// for UDP packets.
|
||||
publicQUICListener, err := quic.NewListener(p.publicUDPConn, p.tlsOptions.ServerTLSConfig(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: this is also strange. why does (*Server).Close() need to close
|
||||
// the quic listener? Shouldn't closing p.publicUDPConn be enough?
|
||||
// We should be able to remove UDP-specific protocols from the Server
|
||||
// struct and keep them localized to (*Server).Run, akin to TLS vs
|
||||
// Noise drpcmigrate.ListenMuxed listeners over TCP.
|
||||
p.publicQUICListener = wrapListener(publicQUICListener)
|
||||
}
|
||||
|
||||
privateMux := drpcmigrate.NewListenMux(p.private.listener, len(drpcmigrate.DRPCHeader))
|
||||
privateDRPCListener := privateMux.Route(drpcmigrate.DRPCHeader)
|
||||
|
||||
// We need a new context chain because we require this context to be
|
||||
// canceled only after all of the upcoming drpc servers have
|
||||
// fully exited. The reason why is because Run closes listener for
|
||||
@ -206,14 +302,26 @@ func (p *Server) Run(ctx context.Context) (err error) {
|
||||
defer muxCancel()
|
||||
|
||||
var muxGroup errgroup.Group
|
||||
if publicMux != nil {
|
||||
|
||||
if p.publicTCPListener != nil {
|
||||
publicLMux := drpcmigrate.NewListenMux(p.publicTCPListener, len(drpcmigrate.DRPCHeader))
|
||||
publicTLSDRPCListener = tls.NewListener(publicLMux.Route(drpcmigrate.DRPCHeader), p.tlsOptions.ServerTLSConfig())
|
||||
publicNoiseDRPCListener = noiseconn.NewListener(publicLMux.Route(NoiseHeader), p.noiseConf)
|
||||
if p.publicHTTP != nil {
|
||||
publicHTTPListener = NewPrefixedListener([]byte("GET / HT"), publicLMux.Route("GET / HT"))
|
||||
}
|
||||
muxGroup.Go(func() error {
|
||||
return publicMux.Run(muxCtx)
|
||||
return publicLMux.Run(muxCtx)
|
||||
})
|
||||
}
|
||||
|
||||
{
|
||||
privateLMux := drpcmigrate.NewListenMux(p.privateTCPListener, len(drpcmigrate.DRPCHeader))
|
||||
privateDRPCListener = privateLMux.Route(drpcmigrate.DRPCHeader)
|
||||
muxGroup.Go(func() error {
|
||||
return privateLMux.Run(muxCtx)
|
||||
})
|
||||
}
|
||||
muxGroup.Go(func() error {
|
||||
return privateMux.Run(muxCtx)
|
||||
})
|
||||
|
||||
// Now we launch all the stuff that uses the listeners.
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
@ -230,24 +338,24 @@ func (p *Server) Run(ctx context.Context) (err error) {
|
||||
return nil
|
||||
})
|
||||
|
||||
if publicDRPCListener != nil {
|
||||
group.Go(func() error {
|
||||
defer cancel()
|
||||
return p.public.drpc.Serve(ctx, publicDRPCListener)
|
||||
})
|
||||
connectListenerToEndpoints := func(ctx context.Context, listener net.Listener, endpoints *endpointCollection) {
|
||||
if listener != nil {
|
||||
group.Go(func() error {
|
||||
defer cancel()
|
||||
return endpoints.drpc.Serve(ctx, listener)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if p.public.quicListener != nil {
|
||||
group.Go(func() error {
|
||||
defer cancel()
|
||||
return p.public.drpc.Serve(ctx, wrapListener(p.public.quicListener))
|
||||
})
|
||||
}
|
||||
connectListenerToEndpoints(ctx, publicTLSDRPCListener, p.publicEndpointsAll)
|
||||
connectListenerToEndpoints(ctx, p.publicQUICListener, p.publicEndpointsAll)
|
||||
connectListenerToEndpoints(ctx, publicNoiseDRPCListener, p.publicEndpointsReplaySafe)
|
||||
connectListenerToEndpoints(ctx, privateDRPCListener, p.privateEndpoints)
|
||||
|
||||
if publicHTTPListener != nil {
|
||||
// this http server listens on the filtered messages of the incoming DRPC port, instead of a separated port
|
||||
httpServer := http.Server{
|
||||
Handler: p.public.http,
|
||||
Handler: p.publicHTTP,
|
||||
}
|
||||
|
||||
group.Go(func() error {
|
||||
@ -264,11 +372,6 @@ func (p *Server) Run(ctx context.Context) (err error) {
|
||||
})
|
||||
}
|
||||
|
||||
group.Go(func() error {
|
||||
defer cancel()
|
||||
return p.private.drpc.Serve(ctx, privateDRPCListener)
|
||||
})
|
||||
|
||||
// Now we wait for all the stuff using the listeners to exit.
|
||||
err = group.Wait()
|
||||
|
||||
@ -277,88 +380,26 @@ func (p *Server) Run(ctx context.Context) (err error) {
|
||||
return errs.Combine(err, muxGroup.Wait())
|
||||
}
|
||||
|
||||
func newPublic(publicAddr string, disableTCPTLS, disableQUIC bool) (public, error) {
|
||||
var (
|
||||
err error
|
||||
publicTCPListener net.Listener
|
||||
publicUDPConn *net.UDPConn
|
||||
)
|
||||
|
||||
for retry := 0; ; retry++ {
|
||||
addr := publicAddr
|
||||
if !disableTCPTLS {
|
||||
publicTCPListener, err = net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return public{}, err
|
||||
}
|
||||
|
||||
addr = publicTCPListener.Addr().String()
|
||||
}
|
||||
|
||||
if !disableQUIC {
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return public{}, err
|
||||
}
|
||||
|
||||
publicUDPConn, err = net.ListenUDP("udp", udpAddr)
|
||||
if err != nil {
|
||||
_, port, _ := net.SplitHostPort(publicAddr)
|
||||
if port == "0" && retry < 10 && isErrorAddressAlreadyInUse(err) {
|
||||
// from here, we know for sure that the tcp port chosen by the
|
||||
// os is available, but we don't know if the same port number
|
||||
// for udp is also available.
|
||||
// if a udp port is already in use, we will close the tcp port and retry
|
||||
// to find one that is available for both udp and tcp.
|
||||
_ = publicTCPListener.Close()
|
||||
continue
|
||||
}
|
||||
return public{}, errs.Combine(err, publicTCPListener.Close())
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
publicMux := drpcmux.New()
|
||||
publicTracingHandler := rpctracing.NewHandler(publicMux, jaeger.RemoteTraceHandler)
|
||||
|
||||
serverOptions := drpcserver.Options{
|
||||
Manager: rpc.NewDefaultManagerOptions(),
|
||||
}
|
||||
|
||||
var netAddr net.Addr
|
||||
if publicTCPListener != nil {
|
||||
netAddr = publicTCPListener.Addr()
|
||||
}
|
||||
|
||||
if publicUDPConn != nil && netAddr == nil {
|
||||
netAddr = publicUDPConn.LocalAddr()
|
||||
}
|
||||
|
||||
return public{
|
||||
tcpListener: wrapListener(publicTCPListener),
|
||||
udpConn: publicUDPConn,
|
||||
addr: netAddr,
|
||||
drpc: drpcserver.NewWithOptions(experiment.NewHandler(publicTracingHandler), serverOptions),
|
||||
mux: publicMux,
|
||||
disableTCPTLS: disableTCPTLS,
|
||||
disableQUIC: disableQUIC,
|
||||
}, nil
|
||||
type endpointCollection struct {
|
||||
mux *drpcmux.Mux
|
||||
drpc *drpcserver.Server
|
||||
}
|
||||
|
||||
func (p public) Close() (err error) {
|
||||
if p.quicListener != nil {
|
||||
err = p.quicListener.Close()
|
||||
func newEndpointCollection() *endpointCollection {
|
||||
mux := drpcmux.New()
|
||||
return &endpointCollection{
|
||||
mux: mux,
|
||||
drpc: drpcserver.NewWithOptions(
|
||||
experiment.NewHandler(
|
||||
rpctracing.NewHandler(
|
||||
mux,
|
||||
jaeger.RemoteTraceHandler),
|
||||
),
|
||||
drpcserver.Options{
|
||||
Manager: rpc.NewDefaultManagerOptions(),
|
||||
},
|
||||
),
|
||||
}
|
||||
if p.udpConn != nil {
|
||||
err = errs.Combine(err, p.udpConn.Close())
|
||||
}
|
||||
if p.tcpListener != nil {
|
||||
err = errs.Combine(err, p.tcpListener.Close())
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// isErrorAddressAlreadyInUse checks whether the error is corresponding to
|
||||
|
@ -113,10 +113,10 @@ var MaxObjectKeyLength = func(maxObjectKeyLength int) func(log *zap.Logger, inde
|
||||
// tcp connections.
|
||||
var DisableTCP = Reconfigure{
|
||||
Satellite: func(log *zap.Logger, index int, config *satellite.Config) {
|
||||
config.Server.DisableTCPTLS = true
|
||||
config.Server.DisableTCP = true
|
||||
},
|
||||
StorageNode: func(index int, config *storagenode.Config) {
|
||||
config.Server.DisableTCPTLS = true
|
||||
config.Server.DisableTCP = true
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ require (
|
||||
github.com/stretchr/testify v1.8.0
|
||||
github.com/zeebo/errs v1.3.0
|
||||
go.uber.org/zap v1.21.0
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde
|
||||
golang.org/x/sync v0.1.0
|
||||
storj.io/common v0.0.0-20230125172029-ac90a56db6dd
|
||||
storj.io/private v0.0.0-20230123202745-d3e63b336444
|
||||
storj.io/storj v1.63.1
|
||||
@ -39,6 +39,7 @@ require (
|
||||
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
||||
github.com/ethereum/go-ethereum v1.10.16 // indirect
|
||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
|
||||
github.com/flynn/noise v1.0.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
|
||||
github.com/go-oauth2/oauth2/v4 v4.4.2 // indirect
|
||||
@ -79,6 +80,7 @@ require (
|
||||
github.com/jtolds/monkit-hw/v2 v2.0.0-20191108235325-141a0da276b3 // indirect
|
||||
github.com/jtolds/tracetagger/v2 v2.0.0-rc5 // indirect
|
||||
github.com/jtolio/eventkit v0.0.0-20221007130042-690145affff8 // indirect
|
||||
github.com/jtolio/noiseconn v0.0.0-20230111204749-d7ec1a08b0b8 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
|
||||
github.com/lucas-clemente/quic-go v0.28.1 // indirect
|
||||
github.com/magefile/mage v1.13.0 // indirect
|
||||
@ -131,7 +133,7 @@ require (
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
|
||||
golang.org/x/tools v0.1.10 // indirect
|
||||
|
@ -176,6 +176,8 @@ github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r
|
||||
github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
|
||||
github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
|
||||
github.com/dsnet/try v0.0.3 h1:ptR59SsrcFUYbT/FhAbKTV6iLkeD6O18qfIWRml2fqI=
|
||||
github.com/dsnet/try v0.0.3/go.mod h1:WBM8tRpUmnXXhY1U6/S8dt6UWdHTQ7y8A5YSkRCkq40=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
|
||||
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
|
||||
@ -193,6 +195,8 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga
|
||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
|
||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
|
||||
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
|
||||
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
@ -456,6 +460,8 @@ github.com/jtolds/tracetagger/v2 v2.0.0-rc5/go.mod h1:61Fh+XhbBONy+RsqkA+xTtmaFb
|
||||
github.com/jtolio/eventkit v0.0.0-20221004135224-074cf276595b/go.mod h1:q7yMR8BavTz/gBNtIT/uF487LMgcuEpNGKISLAjNQes=
|
||||
github.com/jtolio/eventkit v0.0.0-20221007130042-690145affff8 h1:Jm6SYrxKgQMKHUVLhV9qc2Y7PuSQRKUxxk/NSrtaxdQ=
|
||||
github.com/jtolio/eventkit v0.0.0-20221007130042-690145affff8/go.mod h1:q7yMR8BavTz/gBNtIT/uF487LMgcuEpNGKISLAjNQes=
|
||||
github.com/jtolio/noiseconn v0.0.0-20230111204749-d7ec1a08b0b8 h1:+A1uT26XjTsxiUUZjAAuveILWWy+Sy2TPX8OIgGvPQE=
|
||||
github.com/jtolio/noiseconn v0.0.0-20230111204749-d7ec1a08b0b8/go.mod h1:f0ijQHcvHYAuxX6JA/JUr/Z0FVn12D9REaT/HAWVgP4=
|
||||
github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||
@ -1003,8 +1009,9 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -1062,8 +1069,9 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
|
@ -55,6 +55,7 @@ require (
|
||||
github.com/fatih/color v1.10.0 // indirect
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||
github.com/flynn/noise v1.0.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
github.com/go-oauth2/oauth2/v4 v4.4.2 // indirect
|
||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||
@ -100,6 +101,7 @@ require (
|
||||
github.com/jtolds/monkit-hw/v2 v2.0.0-20191108235325-141a0da276b3 // indirect
|
||||
github.com/jtolds/tracetagger/v2 v2.0.0-rc5 // indirect
|
||||
github.com/jtolio/eventkit v0.0.0-20221007130042-690145affff8 // indirect
|
||||
github.com/jtolio/noiseconn v0.0.0-20230111204749-d7ec1a08b0b8 // indirect
|
||||
github.com/klauspost/compress v1.15.10 // indirect
|
||||
github.com/klauspost/cpuid v1.3.1 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
|
||||
@ -197,8 +199,8 @@ require (
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
|
||||
golang.org/x/tools v0.1.10 // indirect
|
||||
|
@ -187,6 +187,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/djherbis/atime v1.0.0 h1:ySLvBAM0EvOGaX7TI4dAM5lWj+RdJUCKtGSEHN8SGBg=
|
||||
github.com/djherbis/atime v1.0.0/go.mod h1:5W+KBIuTwVGcqjIfaTwt+KSYX1o6uep8dtevevQP/f8=
|
||||
github.com/dsnet/try v0.0.3 h1:ptR59SsrcFUYbT/FhAbKTV6iLkeD6O18qfIWRml2fqI=
|
||||
github.com/dsnet/try v0.0.3/go.mod h1:WBM8tRpUmnXXhY1U6/S8dt6UWdHTQ7y8A5YSkRCkq40=
|
||||
github.com/dswarbrick/smart v0.0.0-20190505152634-909a45200d6d h1:QK8IYltsNy+5QZcDFbVkyInrs98/wHy1tfUTGG91sps=
|
||||
github.com/dswarbrick/smart v0.0.0-20190505152634-909a45200d6d/go.mod h1:apXo4PA/BgBPrt66j0N45O2stlBTRowdip2igwcUWVc=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
@ -217,6 +219,8 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga
|
||||
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
|
||||
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
|
||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||
@ -516,6 +520,8 @@ github.com/jtolds/tracetagger/v2 v2.0.0-rc5/go.mod h1:61Fh+XhbBONy+RsqkA+xTtmaFb
|
||||
github.com/jtolio/eventkit v0.0.0-20221004135224-074cf276595b/go.mod h1:q7yMR8BavTz/gBNtIT/uF487LMgcuEpNGKISLAjNQes=
|
||||
github.com/jtolio/eventkit v0.0.0-20221007130042-690145affff8 h1:Jm6SYrxKgQMKHUVLhV9qc2Y7PuSQRKUxxk/NSrtaxdQ=
|
||||
github.com/jtolio/eventkit v0.0.0-20221007130042-690145affff8/go.mod h1:q7yMR8BavTz/gBNtIT/uF487LMgcuEpNGKISLAjNQes=
|
||||
github.com/jtolio/noiseconn v0.0.0-20230111204749-d7ec1a08b0b8 h1:+A1uT26XjTsxiUUZjAAuveILWWy+Sy2TPX8OIgGvPQE=
|
||||
github.com/jtolio/noiseconn v0.0.0-20230111204749-d7ec1a08b0b8/go.mod h1:f0ijQHcvHYAuxX6JA/JUr/Z0FVn12D9REaT/HAWVgP4=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
|
||||
@ -703,7 +709,6 @@ github.com/ncw/directio v1.0.5 h1:JSUBhdjEvVaJvOoyPAbcW0fnd0tvRXD76wEfZ1KcQz4=
|
||||
github.com/ncw/directio v1.0.5/go.mod h1:rX/pKEYkOXBGOggmcyJeJGloCkleSvphPx2eV3t6ROk=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs=
|
||||
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
|
||||
@ -1114,6 +1119,7 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
@ -1211,8 +1217,9 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -1281,8 +1288,9 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211020064051-0ec99a608a1b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@ -1426,8 +1434,9 @@ gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUy
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
|
Loading…
Reference in New Issue
Block a user