diff --git a/.travis.yml b/.travis.yml index 9efb34395..ec247cd0c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: go go: - # - "1.13.x" At minimum the code should run make check on the latest two go versions in the default linux environment provided by Travis. - - "1.13.x" + # - "1.14.x" At minimum the code should run make check on the latest two go versions in the default linux environment provided by Travis. + - "1.14.x" dist: xenial @@ -19,6 +19,7 @@ before_install: install: - go get -u github.com/FiloSottile/vendorcheck - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $GOPATH/bin v1.27.0 + - make tidy before_script: - ci_scripts/create-ip-aliases.sh diff --git a/cmd/setup-node/commands/root.go b/cmd/setup-node/commands/root.go index a29d14aa9..ce0b146d3 100644 --- a/cmd/setup-node/commands/root.go +++ b/cmd/setup-node/commands/root.go @@ -2,6 +2,7 @@ package commands import ( "bufio" + "context" "encoding/json" "io" "io/ioutil" @@ -10,6 +11,7 @@ import ( "os" "github.com/SkycoinProject/dmsg/buildinfo" + "github.com/SkycoinProject/dmsg/cmdutil" "github.com/SkycoinProject/skycoin/src/util/logging" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/spf13/cobra" @@ -87,7 +89,10 @@ var rootCmd = &cobra.Command{ } }() - logger.Fatal(sn.Serve()) + ctx, cancel := cmdutil.SignalContext(context.Background(), logger) + defer cancel() + + logger.Fatal(sn.Serve(ctx)) }, } diff --git a/go.mod b/go.mod index 1f62b04f8..1966c7f77 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/SkycoinProject/skywire-mainnet -go 1.13 +go 1.14 require ( github.com/SkycoinProject/dmsg v0.2.2 @@ -10,9 +10,9 @@ require ( github.com/go-chi/chi v4.0.2+incompatible github.com/google/uuid v1.1.1 github.com/gorilla/securecookie v1.1.1 - github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect github.com/libp2p/go-reuseport v0.0.1 github.com/mholt/archiver/v3 v3.3.0 + github.com/pkg/errors v0.9.1 // indirect github.com/pkg/profile v1.3.0 github.com/prometheus/client_golang v1.3.0 github.com/prometheus/common v0.7.0 @@ -23,9 +23,7 @@ require ( github.com/spf13/cobra v0.0.5 github.com/stretchr/testify v1.5.1 go.etcd.io/bbolt v1.3.4 - golang.org/x/crypto v0.0.0-20200427165652-729f1e841bcc // indirect golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e - golang.org/x/sys v0.0.0-20200428200454-593003d681fa // indirect golang.zx2c4.com/wireguard v0.0.20200320 nhooyr.io/websocket v1.8.2 ) diff --git a/go.sum b/go.sum index 5e5b4a67d..af763a719 100644 --- a/go.sum +++ b/go.sum @@ -118,9 +118,8 @@ github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo github.com/klauspost/pgzip v1.2.1 h1:oIPZROsWuPHpOdMVWLuJZXwgjhrW8r1yEX8UqMyeNHM= github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= @@ -166,6 +165,8 @@ github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 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= github.com/pkg/profile v1.3.0 h1:OQIvuDgm00gWVWGTf4m4mCt6W1/0YqU7Ntg0mySWgaI= github.com/pkg/profile v1.3.0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -221,7 +222,6 @@ github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= @@ -247,9 +247,8 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200427165652-729f1e841bcc h1:ZGI/fILM2+ueot/UixBSoj9188jCAxVHEZEGhqq67I4= -golang.org/x/crypto v0.0.0-20200427165652-729f1e841bcc/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -286,9 +285,8 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200428200454-593003d681fa h1:yMbJOvnfYkO1dSAviTu/ZguZWLBTXx4xE3LYrxUCCiA= -golang.org/x/sys v0.0.0-20200428200454-593003d681fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -313,7 +311,6 @@ google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= 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 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 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= diff --git a/pkg/routefinder/rfclient/client.go b/pkg/routefinder/rfclient/client.go index e1fb0f52a..5efea38ee 100644 --- a/pkg/routefinder/rfclient/client.go +++ b/pkg/routefinder/rfclient/client.go @@ -46,7 +46,7 @@ type HTTPError struct { // Client implements route finding operations. type Client interface { - FindRoutes(ctx context.Context, rts []routing.PathEdges, opts *RouteOptions) (map[routing.PathEdges][]routing.Path, error) + FindRoutes(ctx context.Context, rts []routing.PathEdges, opts *RouteOptions) (map[routing.PathEdges][][]routing.Hop, error) } // APIClient implements Client interface @@ -71,7 +71,7 @@ func NewHTTP(addr string, apiTimeout time.Duration) Client { // FindRoutes returns routes from source skywire visor to destiny, that has at least the given minHops and as much // the given maxHops as well as the reverse routes from destiny to source. -func (c *apiClient) FindRoutes(ctx context.Context, rts []routing.PathEdges, opts *RouteOptions) (map[routing.PathEdges][]routing.Path, error) { +func (c *apiClient) FindRoutes(ctx context.Context, rts []routing.PathEdges, opts *RouteOptions) (map[routing.PathEdges][][]routing.Hop, error) { requestBody := &FindRoutesRequest{ Edges: rts, Opts: opts, @@ -113,7 +113,7 @@ func (c *apiClient) FindRoutes(ctx context.Context, rts []routing.PathEdges, opt return nil, errors.New(apiErr.Error.Message) } - var paths map[routing.PathEdges][]routing.Path + var paths map[routing.PathEdges][][]routing.Hop err = json.NewDecoder(res.Body).Decode(&paths) if err != nil { return nil, err diff --git a/pkg/routefinder/rfclient/mock.go b/pkg/routefinder/rfclient/mock.go index d5cc19375..05572334d 100644 --- a/pkg/routefinder/rfclient/mock.go +++ b/pkg/routefinder/rfclient/mock.go @@ -27,7 +27,7 @@ func (r *mockClient) SetError(err error) { } // FindRoutes implements Client for MockClient -func (r *mockClient) FindRoutes(ctx context.Context, rts []routing.PathEdges, opts *RouteOptions) (map[routing.PathEdges][]routing.Path, error) { +func (r *mockClient) FindRoutes(ctx context.Context, rts []routing.PathEdges, opts *RouteOptions) (map[routing.PathEdges][][]routing.Hop, error) { if r.err != nil { return nil, r.err } @@ -36,7 +36,7 @@ func (r *mockClient) FindRoutes(ctx context.Context, rts []routing.PathEdges, op return nil, fmt.Errorf("no edges provided to returns routes from") } - return map[routing.PathEdges][]routing.Path{ + return map[routing.PathEdges][][]routing.Hop{ [2]cipher.PubKey{rts[0][0], rts[0][1]}: { { routing.Hop{ diff --git a/pkg/router/router.go b/pkg/router/router.go index ab40f07f6..81024028a 100644 --- a/pkg/router/router.go +++ b/pkg/router/router.go @@ -386,7 +386,7 @@ func (r *router) handleDataPacket(ctx context.Context, packet routing.Packet) er return err } - if rule.Type() == routing.RuleConsume { + if rule.Type() == routing.RuleReverse { r.logger.Debugf("Handling packet of type %s with route ID %d", packet.Type(), packet.RouteID()) } else { r.logger.Debugf("Handling packet of type %s with route ID %d and next ID %d", packet.Type(), @@ -394,7 +394,7 @@ func (r *router) handleDataPacket(ctx context.Context, packet routing.Packet) er } switch rule.Type() { - case routing.RuleForward, routing.RuleIntermediaryForward: + case routing.RuleForward, routing.RuleIntermediary: r.logger.Infoln("Handling intermediary data packet") return r.forwardPacket(ctx, packet, rule) } @@ -429,7 +429,7 @@ func (r *router) handleClosePacket(ctx context.Context, packet routing.Packet) e return err } - if rule.Type() == routing.RuleConsume { + if rule.Type() == routing.RuleReverse { r.logger.Debugf("Handling packet of type %s with route ID %d", packet.Type(), packet.RouteID()) } else { r.logger.Debugf("Handling packet of type %s with route ID %d and next ID %d", packet.Type(), @@ -441,7 +441,7 @@ func (r *router) handleClosePacket(ctx context.Context, packet routing.Packet) e r.rt.DelRules(routeIDs) }() - if t := rule.Type(); t == routing.RuleIntermediaryForward { + if t := rule.Type(); t == routing.RuleIntermediary { r.logger.Infoln("Handling intermediary close packet") return r.forwardPacket(ctx, packet, rule) } @@ -489,7 +489,7 @@ func (r *router) handleKeepAlivePacket(ctx context.Context, packet routing.Packe return err } - if rule.Type() == routing.RuleConsume { + if rule.Type() == routing.RuleReverse { r.logger.Debugf("Handling packet of type %s with route ID %d", packet.Type(), packet.RouteID()) } else { r.logger.Debugf("Handling packet of type %s with route ID %d and next ID %d", packet.Type(), @@ -498,7 +498,7 @@ func (r *router) handleKeepAlivePacket(ctx context.Context, packet routing.Packe // propagate packet only for intermediary rule. forward rule workflow doesn't get here, // consume rules should be omitted, activity is already updated - if t := rule.Type(); t == routing.RuleIntermediaryForward { + if t := rule.Type(); t == routing.RuleIntermediary { r.logger.Infoln("Handling intermediary keep-alive packet") return r.forwardPacket(ctx, packet, rule) } @@ -605,7 +605,7 @@ func (r *router) forwardPacket(ctx context.Context, packet routing.Packet, rule func (r *router) RemoveRouteDescriptor(desc routing.RouteDescriptor) { rules := r.rt.AllRules() for _, rule := range rules { - if rule.Type() != routing.RuleConsume { + if rule.Type() != routing.RuleReverse { continue } @@ -617,7 +617,7 @@ func (r *router) RemoveRouteDescriptor(desc routing.RouteDescriptor) { } } -func (r *router) fetchBestRoutes(src, dst cipher.PubKey, opts *DialOptions) (fwd, rev routing.Path, err error) { +func (r *router) fetchBestRoutes(src, dst cipher.PubKey, opts *DialOptions) (fwd, rev []routing.Hop, err error) { // TODO(nkryuchkov): use opts if opts == nil { opts = DefaultDialOptions() // nolint @@ -802,7 +802,7 @@ func (r *router) removeRouteGroupOfRule(rule routing.Rule) { // we need to process only consume rules, cause we don't // really care about the other ones, other rules removal // doesn't affect our work here - if rule.Type() != routing.RuleConsume { + if rule.Type() != routing.RuleReverse { log. WithField("func", "removeRouteGroupOfRule"). WithField("rule", rule.Type().String()). diff --git a/pkg/router/routerclient/client.go b/pkg/router/routerclient/client.go index d992689b5..a574f8aef 100644 --- a/pkg/router/routerclient/client.go +++ b/pkg/router/routerclient/client.go @@ -2,33 +2,44 @@ package routerclient import ( "context" + "fmt" + "io" "net/rpc" "github.com/SkycoinProject/dmsg/cipher" + "github.com/SkycoinProject/skycoin/src/util/logging" + "github.com/sirupsen/logrus" "github.com/SkycoinProject/skywire-mainnet/pkg/routing" "github.com/SkycoinProject/skywire-mainnet/pkg/snet" ) -const rpcName = "RPCGateway" +// RPCName is the RPC gateway object name. +const RPCName = "RPCGateway" -// Client is an RPC client for router. +// Client is used to interact with the router's API remotely. The setup node uses this. type Client struct { rpc *rpc.Client + rPK cipher.PubKey // public key of remote router + log logrus.FieldLogger } // NewClient creates a new Client. -func NewClient(ctx context.Context, dialer snet.Dialer, pk cipher.PubKey) (*Client, error) { - s, err := dialer.Dial(ctx, pk, snet.AwaitSetupPort) +func NewClient(ctx context.Context, dialer snet.Dialer, rPK cipher.PubKey) (*Client, error) { + s, err := dialer.Dial(ctx, rPK, snet.AwaitSetupPort) if err != nil { return nil, err } + return NewClientFromRaw(s, rPK), nil +} - client := &Client{ - rpc: rpc.NewClient(s), +// NewClientFromRaw creates a new client from a raw connection. +func NewClientFromRaw(conn io.ReadWriteCloser, rPK cipher.PubKey) *Client { + return &Client{ + rpc: rpc.NewClient(conn), + rPK: rPK, + log: logging.MustGetLogger(fmt.Sprintf("router_client:%s", rPK.String())), } - - return client, nil } // Close closes a Client. @@ -36,41 +47,32 @@ func (c *Client) Close() error { if c == nil { return nil } - - if err := c.rpc.Close(); err != nil { - return err - } - - return nil + return c.rpc.Close() } // AddEdgeRules adds forward and consume rules to router (forward and reverse). -func (c *Client) AddEdgeRules(ctx context.Context, rules routing.EdgeRules) (bool, error) { - var ok bool - err := c.call(ctx, rpcName+".AddEdgeRules", rules, &ok) - +func (c *Client) AddEdgeRules(ctx context.Context, rules routing.EdgeRules) (ok bool, err error) { + const method = "AddEdgeRules" + err = c.call(ctx, method, rules, &ok) return ok, err } // AddIntermediaryRules adds intermediary rules to router. -func (c *Client) AddIntermediaryRules(ctx context.Context, rules []routing.Rule) (bool, error) { - var ok bool - err := c.call(ctx, rpcName+".AddIntermediaryRules", rules, &ok) - +func (c *Client) AddIntermediaryRules(ctx context.Context, rules []routing.Rule) (ok bool, err error) { + const method = "AddIntermediaryRules" + err = c.call(ctx, method, rules, &ok) return ok, err } // ReserveIDs reserves n IDs and returns them. -func (c *Client) ReserveIDs(ctx context.Context, n uint8) ([]routing.RouteID, error) { - var routeIDs []routing.RouteID - err := c.call(ctx, rpcName+".ReserveIDs", n, &routeIDs) - - return routeIDs, err +func (c *Client) ReserveIDs(ctx context.Context, n uint8) (rtIDs []routing.RouteID, err error) { + const method = "ReserveIDs" + err = c.call(ctx, method, n, &rtIDs) + return rtIDs, err } -func (c *Client) call(ctx context.Context, serviceMethod string, args interface{}, reply interface{}) error { - call := c.rpc.Go(serviceMethod, args, reply, nil) - +func (c *Client) call(ctx context.Context, method string, args interface{}, reply interface{}) error { + call := c.rpc.Go(RPCName+"."+method, args, reply, nil) select { case <-ctx.Done(): return ctx.Err() diff --git a/pkg/router/routerclient/client_test.go b/pkg/router/routerclient/client_test.go index a2d823e41..4bcc02907 100644 --- a/pkg/router/routerclient/client_test.go +++ b/pkg/router/routerclient/client_test.go @@ -92,12 +92,8 @@ func prepRPCServerAndClient(t *testing.T, r router.Router) (s *rpc.Server, cl *C l, err := nettest.NewLocalListener("tcp") require.NoError(t, err) - gateway := router.NewRPCGateway(r) - s = rpc.NewServer() - err = s.Register(gateway) - require.NoError(t, err) - + require.NoError(t, s.Register(router.NewRPCGateway(r))) go s.Accept(l) conn, err := net.Dial("tcp", l.Addr().String()) diff --git a/pkg/router/routerclient/dmsg_wrapper.go b/pkg/router/routerclient/dmsg_wrapper.go new file mode 100644 index 000000000..5b0a851cf --- /dev/null +++ b/pkg/router/routerclient/dmsg_wrapper.go @@ -0,0 +1,28 @@ +package routerclient + +import ( + "context" + "net" + + "github.com/SkycoinProject/dmsg" + "github.com/SkycoinProject/dmsg/cipher" + + "github.com/SkycoinProject/skywire-mainnet/pkg/snet" +) + +// WrapDmsgClient wraps a dmsg client to implement snet.Dialer +func WrapDmsgClient(dmsgC *dmsg.Client) snet.Dialer { + return &dmsgClientDialer{Client: dmsgC} +} + +type dmsgClientDialer struct { + *dmsg.Client +} + +func (w *dmsgClientDialer) Dial(ctx context.Context, remote cipher.PubKey, port uint16) (net.Conn, error) { + return w.Client.Dial(ctx, dmsg.Addr{PK: remote, Port: port}) +} + +func (w *dmsgClientDialer) Type() string { + return dmsg.Type +} diff --git a/pkg/router/routerclient/map.go b/pkg/router/routerclient/map.go new file mode 100644 index 000000000..ef5d44535 --- /dev/null +++ b/pkg/router/routerclient/map.go @@ -0,0 +1,79 @@ +package routerclient + +import ( + "context" + + "github.com/SkycoinProject/dmsg/cipher" + + "github.com/SkycoinProject/skywire-mainnet/pkg/snet" +) + +// Map is a map of router RPC clients associated with the router's visor PK. +type Map map[cipher.PubKey]*Client + +type dialResult struct { + client *Client + err error +} + +// MakeMap makes a Map of the router clients, where the key is the router's visor public key. +// It creates these router clients by dialing to them concurrently. +func MakeMap(ctx context.Context, dialer snet.Dialer, pks []cipher.PubKey) (Map, error) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + results := make(chan dialResult) + defer close(results) + + for _, pk := range pks { + go func(pk cipher.PubKey) { + client, err := NewClient(ctx, dialer, pk) + results <- dialResult{client: client, err: err} + }(pk) + } + + rcM := make(Map, len(pks)) + var err error + for range pks { + res := <-results + if isDone(ctx) { + continue + } + if res.err != nil { + cancel() + err = res.err + continue + } + rcM[res.client.rPK] = res.client + } + + if err != nil { + rcM.CloseAll() // TODO: log this + } + return rcM, err +} + +// Client returns a router client of given public key. +func (cm Map) Client(rPK cipher.PubKey) *Client { + return cm[rPK] +} + +// CloseAll closes all contained router clients. +func (cm Map) CloseAll() (errs []error) { + for k, c := range cm { + if err := c.Close(); err != nil { + errs = append(errs, err) + } + delete(cm, k) + } + return errs +} + +func isDone(ctx context.Context) bool { + select { + case <-ctx.Done(): + return true + default: + return false + } +} diff --git a/pkg/router/routerclient/map_test.go b/pkg/router/routerclient/map_test.go new file mode 100644 index 000000000..70d071283 --- /dev/null +++ b/pkg/router/routerclient/map_test.go @@ -0,0 +1,164 @@ +package routerclient + +import ( + "context" + "errors" + "fmt" + "net" + "net/rpc" + "testing" + "time" + + "github.com/SkycoinProject/dmsg" + "github.com/SkycoinProject/dmsg/cipher" + "github.com/SkycoinProject/skycoin/src/util/logging" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "golang.org/x/net/nettest" + + "github.com/SkycoinProject/skywire-mainnet/pkg/router" + "github.com/SkycoinProject/skywire-mainnet/pkg/routing" +) + +func TestMakeMap(t *testing.T) { + logging.SetLevel(logrus.WarnLevel) + + const timeout = time.Second * 5 + + type testCase struct { + okays int // Number of routers to generate, that can be successfully dialed to. + fails []time.Duration // Number of routers to generate, that should fail when dialed to. + } + + cases := []testCase{ + {1, nil}, + {4, nil}, + {7, make([]time.Duration, 5)}, + {8, []time.Duration{0, time.Second, time.Millisecond}}, + {0, make([]time.Duration, 10)}, + {1, []time.Duration{timeout * 2}}, // this should still get canceled from hard deadline + } + + for i, tc := range cases { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + var successes = tc.okays + var fails = len(tc.fails) + var total = successes + fails + + // Arrange: dialer that dials to remote routers, used for creating router clients + dialer := newTestDialer(total) + + // Arrange: successful mock router + okayR := new(router.MockRouter) + okayR.On("ReserveKeys", mock.Anything).Return([]routing.RouteID{}, nil) + + // Arrange: serve router gateways (via single mock router) + for i := 0; i < successes; i++ { + addr := serveRouterRPC(t, okayR) + dialer.Add(addr, nil) + } + for i := 0; i < fails; i++ { + addr := serveRouterRPC(t, okayR) + duration := time.Second + dialer.Add(addr, &duration) + } + + // Arrange: Ensure MakeMap call has a hard deadline + ctx, cancel := context.WithDeadline(context.TODO(), time.Now().Add(timeout)) + defer cancel() + + // Act: MakeMap dials to all routers + rcM, err := MakeMap(ctx, dialer, dialer.PKs()) + t.Cleanup(func() { + for _, err := range rcM.CloseAll() { + assert.NoError(t, err) + } + }) + + if fails == 0 { + // Assert: (all dials successful) we can successfully interact with the remote router via all clients + require.NoError(t, err) + for _, pk := range dialer.PKs() { + routerC := rcM.Client(pk) + assert.NotNil(t, routerC) + _, err := rcM.Client(pk).ReserveIDs(context.Background(), 0) + assert.NoError(t, err) + } + } else { + // Assert: (some dials fail) should return error and internal clients are all nil + require.Error(t, err) + for _, pk := range dialer.PKs() { + routerC := rcM.Client(pk) + assert.Nil(t, routerC) + } + } + }) + } +} + +// serves a router over RPC and returns the bound TCP address +func serveRouterRPC(t *testing.T, r router.Router) (addr string) { + l, err := nettest.NewLocalListener("tcp") + require.NoError(t, err) + t.Cleanup(func() { assert.NoError(t, l.Close()) }) + + rpcS := rpc.NewServer() + require.NoError(t, rpcS.Register(router.NewRPCGateway(r))) + go rpcS.Accept(l) + + return l.Addr().String() +} + +func pkFromAddr(addr string) (pk cipher.PubKey) { + h := cipher.SumSHA256([]byte(addr)) + copy(pk[1:], h[:]) + return +} + +// testDialer mocks a snet dialer which should dial to a 'pk:port' address +// To achieve this, we use a map that associates pks with a TCP addresses and dial via TCP. +// Ports become irrelevant. +type testDialer struct { + m map[cipher.PubKey]string + failures map[cipher.PubKey]time.Duration +} + +func newTestDialer(routers int) *testDialer { + return &testDialer{ + m: make(map[cipher.PubKey]string, routers), + failures: make(map[cipher.PubKey]time.Duration), + } +} + +func (d *testDialer) Add(addr string, failure *time.Duration) cipher.PubKey { + pk := pkFromAddr(addr) + d.m[pk] = addr + if failure != nil { + d.failures[pk] = *failure + } + return pk +} + +func (d *testDialer) PKs() []cipher.PubKey { + out := make([]cipher.PubKey, 0, len(d.m)) + for pk := range d.m { + out = append(out, pk) + } + return out +} + +func (d *testDialer) Dial(_ context.Context, remote cipher.PubKey, _ uint16) (net.Conn, error) { + if wait, ok := d.failures[remote]; ok { + if wait != 0 { + time.Sleep(wait) + } + return nil, errors.New("test error: failed to dial, as expected") + } + return net.Dial("tcp", d.m[remote]) +} + +func (testDialer) Type() string { + return dmsg.Type +} diff --git a/pkg/router/routerclient/wrappers.go b/pkg/router/routerclient/wrappers.go deleted file mode 100644 index 4325f9365..000000000 --- a/pkg/router/routerclient/wrappers.go +++ /dev/null @@ -1,113 +0,0 @@ -package routerclient - -import ( - "context" - "fmt" - "net" - - "github.com/SkycoinProject/dmsg" - "github.com/SkycoinProject/dmsg/cipher" - "github.com/SkycoinProject/skycoin/src/util/logging" - - "github.com/SkycoinProject/skywire-mainnet/pkg/routing" -) - -// TODO: remove this -// dmsgClientWrapper is a temporary workaround to make dmsg client implement `snet.Dialer`. -// The only reason to use this is because client's `Dial` returns `*dmsg.Stream` instead of `net.Conn`, -// so this stuff should be removed as soon as the func's signature changes -type dmsgClientWrapper struct { - *dmsg.Client -} - -func wrapDmsgC(dmsgC *dmsg.Client) *dmsgClientWrapper { - return &dmsgClientWrapper{Client: dmsgC} -} - -func (w *dmsgClientWrapper) Dial(ctx context.Context, remote cipher.PubKey, port uint16) (net.Conn, error) { - addr := dmsg.Addr{ - PK: remote, - Port: port, - } - - return w.Client.Dial(ctx, addr) -} - -func (w *dmsgClientWrapper) Type() string { - return dmsg.Type -} - -// AddEdgeRules is a wrapper for (*Client).AddEdgeRules. -func AddEdgeRules( - ctx context.Context, - log *logging.Logger, - dmsgC *dmsg.Client, - pk cipher.PubKey, - rules routing.EdgeRules, -) (bool, error) { - client, err := NewClient(ctx, wrapDmsgC(dmsgC), pk) - if err != nil { - return false, fmt.Errorf("failed to dial remote: %w", err) - } - - defer closeClient(log, client) - - ok, err := client.AddEdgeRules(ctx, rules) - if err != nil { - return false, fmt.Errorf("failed to add rules: %w", err) - } - - return ok, nil -} - -// AddIntermediaryRules is a wrapper for (*Client).AddIntermediaryRules. -func AddIntermediaryRules( - ctx context.Context, - log *logging.Logger, - dmsgC *dmsg.Client, - pk cipher.PubKey, - rules []routing.Rule, -) (bool, error) { - client, err := NewClient(ctx, wrapDmsgC(dmsgC), pk) - if err != nil { - return false, fmt.Errorf("failed to dial remote: %w", err) - } - - defer closeClient(log, client) - - routeIDs, err := client.AddIntermediaryRules(ctx, rules) - if err != nil { - return false, fmt.Errorf("failed to add rules: %w", err) - } - - return routeIDs, nil -} - -// ReserveIDs is a wrapper for (*Client).ReserveIDs. -func ReserveIDs( - ctx context.Context, - log *logging.Logger, - dmsgC *dmsg.Client, - pk cipher.PubKey, - n uint8, -) ([]routing.RouteID, error) { - client, err := NewClient(ctx, wrapDmsgC(dmsgC), pk) - if err != nil { - return nil, fmt.Errorf("failed to dial remote: %w", err) - } - - defer closeClient(log, client) - - routeIDs, err := client.ReserveIDs(ctx, n) - if err != nil { - return nil, fmt.Errorf("failed to add rules: %w", err) - } - - return routeIDs, nil -} - -func closeClient(log *logging.Logger, client *Client) { - if err := client.Close(); err != nil { - log.Warn(err) - } -} diff --git a/pkg/routing/route.go b/pkg/routing/route.go index 61bd09a9d..e142d7abe 100644 --- a/pkg/routing/route.go +++ b/pkg/routing/route.go @@ -4,6 +4,8 @@ package routing import ( "bytes" + "encoding/json" + "errors" "fmt" "time" @@ -14,44 +16,89 @@ import ( // Route is a succession of transport entries that denotes a path from source visor to destination visor type Route struct { Desc RouteDescriptor `json:"desc"` - Path Path `json:"path"` + Hops []Hop `json:"path"` KeepAlive time.Duration `json:"keep_alive"` } func (r Route) String() string { res := fmt.Sprintf("[KeepAlive: %s] %s\n", r.KeepAlive, r.Desc.String()) - for _, hop := range r.Path { + for _, hop := range r.Hops { res += fmt.Sprintf("\t%s\n", hop) } return res } +// Errors associated with BidirectionalRoute +var ( + ErrBiRouteHasNoForwardHops = errors.New("bidirectional route does not have forward hops") + ErrBiRouteHasNoReverseHops = errors.New("bidirectional route does not have reverse hops") + ErrBiRouteHasInvalidDesc = errors.New("bidirectional route has an invalid route description") +) + // BidirectionalRoute is a Route with both forward and reverse Paths. type BidirectionalRoute struct { Desc RouteDescriptor KeepAlive time.Duration - Forward Path - Reverse Path + Forward []Hop + Reverse []Hop } // ForwardAndReverse generate forward and reverse routes for bidirectional route. func (br *BidirectionalRoute) ForwardAndReverse() (forward, reverse Route) { forwardRoute := Route{ Desc: br.Desc, - Path: br.Forward, + Hops: br.Forward, KeepAlive: br.KeepAlive, } reverseRoute := Route{ Desc: br.Desc.Invert(), - Path: br.Reverse, + Hops: br.Reverse, KeepAlive: br.KeepAlive, } return forwardRoute, reverseRoute } +// Check checks whether the bidirectional route is valid. +func (br *BidirectionalRoute) Check() error { + if len(br.Forward) == 0 { + return ErrBiRouteHasNoForwardHops + } + + if len(br.Reverse) == 0 { + return ErrBiRouteHasNoReverseHops + } + + if srcPK := br.Desc.SrcPK(); br.Forward[0].From != srcPK || br.Reverse[len(br.Reverse)-1].To != srcPK { + return ErrBiRouteHasInvalidDesc + } + + if dstPK := br.Desc.DstPK(); br.Reverse[0].From != dstPK || br.Forward[len(br.Forward)-1].To != dstPK { + return ErrBiRouteHasInvalidDesc + } + + return nil +} + +// String implements fmt.Stringer +func (br *BidirectionalRoute) String() string { + m := map[string]interface{}{ + "descriptor": br.Desc.String(), + "keep_alive": br.KeepAlive.String(), + "fwd_hops": br.Forward, + "rev_hops": br.Reverse, + } + + j, err := json.MarshalIndent(m, "", "\t") + if err != nil { + panic(err) // should never happen + } + + return string(j) +} + // EdgeRules represents edge forward and reverse rules. Edge rules are forward and consume rules. type EdgeRules struct { Desc RouteDescriptor @@ -59,12 +106,22 @@ type EdgeRules struct { Reverse Rule } -func (er *EdgeRules) String() string { - if er == nil { - return "" +// String implements fmt.Stringer +func (er EdgeRules) String() string { + m := map[string]interface{}{ + "descriptor": er.Desc.String(), + "routing_rules": []string{ + er.Forward.String(), + er.Reverse.String(), + }, + } + + j, err := json.MarshalIndent(m, "", "\t") + if err != nil { + panic(err) } - return fmt.Sprintf("desc: %v, fwd: %v, rvs: %v", er.Desc, er.Forward, er.Reverse) + return string(j) } // Hop defines a route hop between 2 nodes. @@ -74,9 +131,7 @@ type Hop struct { To cipher.PubKey } -// Path is a list of hops between nodes (transports), and indicates a route between the edges -type Path []Hop - +// String implements fmt.Stringer func (h Hop) String() string { return fmt.Sprintf("%s -> %s @ %s", h.From, h.To, h.TpID) } diff --git a/pkg/routing/route_descriptor.go b/pkg/routing/route_descriptor.go index 047b86276..5ccf7633d 100644 --- a/pkg/routing/route_descriptor.go +++ b/pkg/routing/route_descriptor.go @@ -92,5 +92,5 @@ func (rd *RouteDescriptor) Invert() RouteDescriptor { } func (rd *RouteDescriptor) String() string { - return fmt.Sprintf("rPK:%s, lPK:%s, rPort:%d, lPort:%d", rd.DstPK(), rd.SrcPK(), rd.DstPort(), rd.SrcPort()) + return fmt.Sprintf("rAddr:%s, lAddr:%s", rd.Dst().String(), rd.Src().String()) } diff --git a/pkg/routing/rule.go b/pkg/routing/rule.go index e5d1f04f1..a6f476715 100644 --- a/pkg/routing/rule.go +++ b/pkg/routing/rule.go @@ -25,11 +25,11 @@ type RuleType byte func (rt RuleType) String() string { switch rt { - case RuleConsume: + case RuleReverse: return "Consume" case RuleForward: return "Forward" - case RuleIntermediaryForward: + case RuleIntermediary: return "IntermediaryForward" } @@ -37,17 +37,17 @@ func (rt RuleType) String() string { } const ( - // RuleConsume represents a hop to the route's destination visor. + // RuleReverse represents a hop to the route's destination visor. // A packet referencing this rule is to be consumed locally. - RuleConsume = RuleType(0) + RuleReverse = RuleType(0) // RuleForward represents a hop from the route's source visor. // A packet referencing this rule is to be sent to a remote visor. RuleForward = RuleType(1) - // RuleIntermediaryForward represents a hop which is not from the route's source, + // RuleIntermediary represents a hop which is not from the route's source, // nor to the route's destination. - RuleIntermediaryForward = RuleType(2) + RuleIntermediary = RuleType(2) ) // Rule represents a routing rule. @@ -111,7 +111,7 @@ func (r Rule) Body() []byte { // RouteDescriptor returns RouteDescriptor from the rule. func (r Rule) RouteDescriptor() RouteDescriptor { switch t := r.Type(); t { - case RuleConsume, RuleForward: + case RuleReverse, RuleForward: r.assertLen(RuleHeaderSize + routeDescriptorSize) var desc RouteDescriptor @@ -132,7 +132,7 @@ func (r Rule) NextRouteID() RouteID { case RuleForward: offset += routeDescriptorSize fallthrough - case RuleIntermediaryForward: + case RuleIntermediary: r.assertLen(offset + 4) return RouteID(binary.BigEndian.Uint32(r[offset : offset+4])) default: @@ -148,7 +148,7 @@ func (r Rule) setNextRouteID(id RouteID) { case RuleForward: offset += routeDescriptorSize fallthrough - case RuleIntermediaryForward: + case RuleIntermediary: r.assertLen(offset + 4) binary.BigEndian.PutUint32(r[offset:offset+4], uint32(id)) default: @@ -164,7 +164,7 @@ func (r Rule) NextTransportID() uuid.UUID { case RuleForward: offset += routeDescriptorSize fallthrough - case RuleIntermediaryForward: + case RuleIntermediary: r.assertLen(offset + 4) return uuid.Must(uuid.FromBytes(r[offset : offset+uuidSize])) @@ -181,7 +181,7 @@ func (r Rule) setNextTransportID(id uuid.UUID) { case RuleForward: offset += routeDescriptorSize fallthrough - case RuleIntermediaryForward: + case RuleIntermediary: r.assertLen(offset + 4) copy(r[offset:offset+uuidSize], id[:]) default: @@ -192,7 +192,7 @@ func (r Rule) setNextTransportID(id uuid.UUID) { // setSrcPK sets source public key of a rule. func (r Rule) setSrcPK(pk cipher.PubKey) { switch t := r.Type(); t { - case RuleConsume, RuleForward: + case RuleReverse, RuleForward: r.assertLen(RuleHeaderSize + pkSize) copy(r[RuleHeaderSize:RuleHeaderSize+pkSize], pk[:]) default: @@ -203,7 +203,7 @@ func (r Rule) setSrcPK(pk cipher.PubKey) { // setDstPK sets destination public key of a rule. func (r Rule) setDstPK(pk cipher.PubKey) { switch t := r.Type(); t { - case RuleConsume, RuleForward: + case RuleReverse, RuleForward: r.assertLen(RuleHeaderSize + pkSize*2) copy(r[RuleHeaderSize+pkSize:RuleHeaderSize+pkSize*2], pk[:]) default: @@ -214,7 +214,7 @@ func (r Rule) setDstPK(pk cipher.PubKey) { // setSrcPort sets source port of a rule. func (r Rule) setSrcPort(port Port) { switch t := r.Type(); t { - case RuleConsume, RuleForward: + case RuleReverse, RuleForward: r.assertLen(RuleHeaderSize + pkSize*2 + 2) binary.BigEndian.PutUint16(r[RuleHeaderSize+pkSize*2:RuleHeaderSize+pkSize*2+2], uint16(port)) default: @@ -225,7 +225,7 @@ func (r Rule) setSrcPort(port Port) { // setDstPort sets destination port of a rule. func (r Rule) setDstPort(port Port) { switch t := r.Type(); t { - case RuleConsume, RuleForward: + case RuleReverse, RuleForward: r.assertLen(RuleHeaderSize + pkSize*2 + 2*2) binary.BigEndian.PutUint16(r[RuleHeaderSize+pkSize*2+2:RuleHeaderSize+pkSize*2+2*2], uint16(port)) default: @@ -236,16 +236,16 @@ func (r Rule) setDstPort(port Port) { // String returns rule's string representation. func (r Rule) String() string { switch t := r.Type(); t { - case RuleConsume: + case RuleReverse: rd := r.RouteDescriptor() - return fmt.Sprintf("APP(keyRtID:%d, %s)", + return fmt.Sprintf("REV(keyRtID:%d, %s)", r.KeyRouteID(), rd.String()) case RuleForward: rd := r.RouteDescriptor() return fmt.Sprintf("FWD(keyRtID:%d, nxtRtID:%d, nxtTpID:%s, %s)", r.KeyRouteID(), r.NextRouteID(), r.NextTransportID(), rd.String()) - case RuleIntermediaryForward: - return fmt.Sprintf("IFWD(keyRtID:%d, nxtRtID:%d, nxtTpID:%s)", + case RuleIntermediary: + return fmt.Sprintf("INTER(keyRtID:%d, nxtRtID:%d, nxtTpID:%s)", r.KeyRouteID(), r.NextRouteID(), r.NextTransportID()) default: panic(fmt.Sprintf("invalid rule: %v", t.String())) @@ -291,7 +291,7 @@ type RuleSummary struct { // ToRule converts RoutingRuleSummary to RoutingRule. func (rs *RuleSummary) ToRule() (Rule, error) { switch { - case rs.Type == RuleConsume: + case rs.Type == RuleReverse: if rs.ConsumeFields == nil || rs.ForwardFields != nil || rs.IntermediaryForwardFields != nil { return nil, errors.New("invalid routing rule summary") } @@ -309,7 +309,7 @@ func (rs *RuleSummary) ToRule() (Rule, error) { d := f.RouteDescriptor return ForwardRule(rs.KeepAlive, rs.KeyRouteID, f.NextRID, f.NextTID, d.SrcPK, d.DstPK, d.SrcPort, d.DstPort), nil - case rs.Type == RuleIntermediaryForward: + case rs.Type == RuleIntermediary: if rs.ConsumeFields != nil || rs.ForwardFields != nil || rs.IntermediaryForwardFields == nil { return nil, errors.New("invalid routing rule summary") } @@ -331,7 +331,7 @@ func (r Rule) Summary() *RuleSummary { } switch t := summary.Type; t { - case RuleConsume: + case RuleReverse: rd := r.RouteDescriptor() summary.ConsumeFields = &RuleConsumeFields{ @@ -355,7 +355,7 @@ func (r Rule) Summary() *RuleSummary { NextRID: r.NextRouteID(), NextTID: r.NextTransportID(), } - case RuleIntermediaryForward: + case RuleIntermediary: summary.IntermediaryForwardFields = &RuleIntermediaryForwardFields{ NextRID: r.NextRouteID(), NextTID: r.NextTransportID(), @@ -372,7 +372,7 @@ func ConsumeRule(keepAlive time.Duration, key RouteID, lPK, rPK cipher.PubKey, l rule := Rule(make([]byte, RuleHeaderSize+routeDescriptorSize)) rule.setKeepAlive(keepAlive) - rule.setType(RuleConsume) + rule.setType(RuleReverse) rule.SetKeyRouteID(key) rule.setSrcPK(lPK) @@ -412,7 +412,7 @@ func IntermediaryForwardRule(keepAlive time.Duration, key, nextRoute RouteID, ne rule := Rule(make([]byte, RuleHeaderSize+4+pkSize)) rule.setKeepAlive(keepAlive) - rule.setType(RuleIntermediaryForward) + rule.setType(RuleIntermediary) rule.SetKeyRouteID(key) rule.setNextRouteID(nextRoute) rule.setNextTransportID(nextTransport) diff --git a/pkg/routing/rule_test.go b/pkg/routing/rule_test.go index c60d0e5c2..11833fd7c 100644 --- a/pkg/routing/rule_test.go +++ b/pkg/routing/rule_test.go @@ -17,7 +17,7 @@ func TestConsumeRule(t *testing.T) { rule := ConsumeRule(keepAlive, 1, localPK, remotePK, 2, 3) assert.Equal(t, keepAlive, rule.KeepAlive()) - assert.Equal(t, RuleConsume, rule.Type()) + assert.Equal(t, RuleReverse, rule.Type()) assert.Equal(t, RouteID(1), rule.KeyRouteID()) rd := rule.RouteDescriptor() @@ -59,7 +59,7 @@ func TestIntermediaryForwardRule(t *testing.T) { rule := IntermediaryForwardRule(keepAlive, 1, 2, trID) assert.Equal(t, keepAlive, rule.KeepAlive()) - assert.Equal(t, RuleIntermediaryForward, rule.Type()) + assert.Equal(t, RuleIntermediary, rule.Type()) assert.Equal(t, RouteID(1), rule.KeyRouteID()) assert.Equal(t, RouteID(2), rule.NextRouteID()) assert.Equal(t, trID, rule.NextTransportID()) diff --git a/pkg/routing/table.go b/pkg/routing/table.go index 0b11d5af6..5f8b173f5 100644 --- a/pkg/routing/table.go +++ b/pkg/routing/table.go @@ -123,7 +123,7 @@ func (mt *memTable) Rule(key RouteID) (Rule, error) { // crucial, we do this when we have nowhere in the network to forward packet to. // In this case we update activity immediately not to acquire the lock for the second time ruleType := rule.Type() - if ruleType == RuleConsume { + if ruleType == RuleReverse { mt.activity[key] = time.Now() } diff --git a/pkg/setup/config.go b/pkg/setup/config.go index 36349076d..a441958b4 100644 --- a/pkg/setup/config.go +++ b/pkg/setup/config.go @@ -18,12 +18,9 @@ const ( // Config defines configuration parameters for setup Node. type Config struct { - PubKey cipher.PubKey `json:"public_key"` - SecKey cipher.SecKey `json:"secret_key"` - - Dmsg snet.DmsgConfig `json:"dmsg"` - - TransportDiscovery string `json:"transport_discovery"` - - LogLevel string `json:"log_level"` + PK cipher.PubKey `json:"public_key"` + SK cipher.SecKey `json:"secret_key"` + Dmsg snet.DmsgConfig `json:"dmsg"` + TransportDiscovery string `json:"transport_discovery"` + LogLevel string `json:"log_level"` } diff --git a/pkg/setup/id_reserver.go b/pkg/setup/id_reserver.go new file mode 100644 index 000000000..b86667422 --- /dev/null +++ b/pkg/setup/id_reserver.go @@ -0,0 +1,158 @@ +package setup + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "sync" + + "github.com/SkycoinProject/dmsg/cipher" + + "github.com/SkycoinProject/skywire-mainnet/pkg/router/routerclient" + "github.com/SkycoinProject/skywire-mainnet/pkg/routing" + "github.com/SkycoinProject/skywire-mainnet/pkg/snet" +) + +// ErrNoKey is returned when key is not found. +var ErrNoKey = errors.New("id reservoir has no key") + +//go:generate mockery -name IDReserver -case underscore -inpkg + +// IDReserver reserves route IDs from remote routers. +// It takes in a slice of paths where each path is a slice of hops and each hop has src and dst public keys and also a +// transport ID. +type IDReserver interface { + io.Closer + fmt.Stringer + + // ReserveIDs reserves route IDs from the router clients. + // It uses an internal map to know how many ids to reserve from each router. + ReserveIDs(ctx context.Context) error + + // PopID pops a reserved route ID from the ID stack of the given public key. + PopID(pk cipher.PubKey) (routing.RouteID, bool) + + // TotalIDs returns the total number of route IDs we have reserved from the routers. + TotalIDs() int + + // Client returns a router client of given public key. + Client(pk cipher.PubKey) *routerclient.Client +} + +type idReserver struct { + total int // the total number of route IDs we reserve from the routers + rcM routerclient.Map // map of router clients + rec map[cipher.PubKey]uint8 // this records the number of expected rules per visor PK + ids map[cipher.PubKey][]routing.RouteID // this records the obtained rules per visor PK + mx sync.Mutex +} + +// NewIDReserver creates a new route ID reserver from a dialer and a slice of paths. +// The exact number of route IDs to reserve from each router is determined from the slice of paths. +func NewIDReserver(ctx context.Context, dialer snet.Dialer, paths [][]routing.Hop) (IDReserver, error) { + var total int // the total number of route IDs we reserve from the routers + + // Prepare 'rec': A map representing the number of expected rules per visor PK. + rec := make(map[cipher.PubKey]uint8) + for _, hops := range paths { + if len(hops) == 0 { + continue + } + rec[hops[0].From]++ + for _, hop := range hops { + rec[hop.To]++ + } + total += len(hops) + 1 + } + + // Prepare 'clients': A map of router clients. + pks := make([]cipher.PubKey, 0, len(rec)) + for pk := range rec { + pks = append(pks, pk) + } + clients, err := routerclient.MakeMap(ctx, dialer, pks) + if err != nil { + return nil, fmt.Errorf("a dial attempt failed with: %v", err) + } + + // Return result. + return &idReserver{ + total: total, + rcM: clients, + rec: rec, + ids: make(map[cipher.PubKey][]routing.RouteID, total), + }, nil +} + +func (idr *idReserver) ReserveIDs(ctx context.Context) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + errCh := make(chan error, len(idr.rec)) + defer close(errCh) + + for pk, n := range idr.rec { + go func(pk cipher.PubKey, n uint8) { + rtIDs, err := idr.rcM.Client(pk).ReserveIDs(ctx, n) + if err != nil { + cancel() + errCh <- fmt.Errorf("reserve routeID from %s failed: %w", pk, err) + return + } + idr.mx.Lock() + idr.ids[pk] = rtIDs + idr.mx.Unlock() + errCh <- nil + }(pk, n) + } + + return firstError(len(idr.rec), errCh) +} + +func (idr *idReserver) PopID(pk cipher.PubKey) (routing.RouteID, bool) { + idr.mx.Lock() + defer idr.mx.Unlock() + + ids, ok := idr.ids[pk] + if !ok || len(ids) == 0 { + return 0, false + } + + idr.ids[pk] = ids[1:] + + return ids[0], true +} + +func (idr *idReserver) TotalIDs() int { + return idr.total +} + +func (idr *idReserver) Client(pk cipher.PubKey) *routerclient.Client { + return idr.rcM[pk] +} + +func (idr *idReserver) String() string { + idr.mx.Lock() + defer idr.mx.Unlock() + b, _ := json.MarshalIndent(idr.ids, "", "\t") //nolint:errcheck + return string(b) +} + +func (idr *idReserver) Close() error { + if errs := idr.rcM.CloseAll(); errs != nil { + return fmt.Errorf("router client map closed with errors: %v", errs) + } + return nil +} + +func firstError(n int, errCh <-chan error) error { + var firstErr error + for i := 0; i < n; i++ { + if err := <-errCh; firstErr == nil && err != nil { + firstErr = err + } + } + return firstErr +} diff --git a/pkg/setup/id_reserver_test.go b/pkg/setup/id_reserver_test.go new file mode 100644 index 000000000..2f5271096 --- /dev/null +++ b/pkg/setup/id_reserver_test.go @@ -0,0 +1,236 @@ +package setup + +import ( + "context" + "errors" + "strconv" + "testing" + "time" + + "github.com/SkycoinProject/dmsg/cipher" + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/SkycoinProject/skywire-mainnet/pkg/routing" +) + +// We check the contents of 'idReserver.rec' is as expected after calling 'NewIDReserver'. +// We assume that all dials by the dialer are successful. +func TestNewIDReserver(t *testing.T) { + pkA, _ := cipher.GenerateKeyPair() + pkB, _ := cipher.GenerateKeyPair() + pkC, _ := cipher.GenerateKeyPair() + + type testCase struct { + paths [][]routing.Hop // test input + expRec map[cipher.PubKey]uint8 // expected 'idReserver.rec' result + expTotal int // expected 'idReserver.total' result + } + + testCases := []testCase{ + { + paths: nil, + expRec: map[cipher.PubKey]uint8{}, + expTotal: 0, + }, + { + paths: [][]routing.Hop{makeHops(pkA, pkB), makeHops(pkB, pkA)}, + expRec: map[cipher.PubKey]uint8{pkA: 2, pkB: 2}, + expTotal: 4, + }, + { + paths: [][]routing.Hop{makeHops(pkA, pkB, pkC), makeHops(pkC, pkA)}, + expRec: map[cipher.PubKey]uint8{pkA: 2, pkB: 1, pkC: 2}, + expTotal: 5, + }, + { + paths: [][]routing.Hop{makeHops(pkA, pkB, pkC), makeHops(pkC, pkB, pkA)}, + expRec: map[cipher.PubKey]uint8{pkA: 2, pkB: 2, pkC: 2}, + expTotal: 6, + }, + } + + for i, tc := range testCases { + t.Run(strconv.Itoa(i), func(t *testing.T) { + // arrange + dialer := newMockDialer(t, nil) + + // act + rtIDR, err := NewIDReserver(context.TODO(), dialer, tc.paths) + require.NoError(t, err) + t.Cleanup(func() { assert.NoError(t, rtIDR.Close()) }) + + // assert + v := rtIDR.(*idReserver) + assert.Equal(t, tc.expTotal, v.total) + assert.Equal(t, tc.expRec, v.rec) + }) + } +} + +func TestIdReserver_ReserveIDs(t *testing.T) { + pkA, _ := cipher.GenerateKeyPair() + pkB, _ := cipher.GenerateKeyPair() + pkC, _ := cipher.GenerateKeyPair() + + // timeout given for all calls to .ReserveIDs + // this is passed with a context with deadline + timeout := time.Second + + type testCase struct { + testName string // test name + routers map[cipher.PubKey]interface{} // arrange: map of mock router gateways + paths [][]routing.Hop // arrange: idReserver input + expErr error // assert: expected error + } + + makeRun := func(tc testCase) func(t *testing.T) { + return func(t *testing.T) { + // arrange + dialer := newMockDialer(t, tc.routers) + + rtIDR, err := NewIDReserver(context.TODO(), dialer, tc.paths) + require.NoError(t, err) + t.Cleanup(func() { assert.NoError(t, rtIDR.Close()) }) + + ctx, cancel := context.WithDeadline(context.TODO(), time.Now().Add(timeout)) + defer cancel() + + // act + err = rtIDR.ReserveIDs(ctx) + + if tc.expErr != nil { + // assert (expected error) + assert.EqualError(t, errors.Unwrap(err), context.DeadlineExceeded.Error()) + } else { + // assert (no expected error) + checkIDReserver(t, rtIDR.(*idReserver)) + } + } + } + + // .ReserveIDs should correctly reserve IDs if all remote routers are functional. + t.Run("correctly_reserve_rtIDs", func(t *testing.T) { + testCases := []testCase{ + { + testName: "fwd1_rev1", + routers: map[cipher.PubKey]interface{}{ + pkA: &mockGatewayForDialer{}, + pkC: &mockGatewayForDialer{}, + }, + paths: [][]routing.Hop{makeHops(pkA, pkC), makeHops(pkC, pkA)}, + expErr: nil, + }, + { + testName: "fwd2_rev2", + routers: map[cipher.PubKey]interface{}{ + pkA: &mockGatewayForDialer{}, + pkB: &mockGatewayForDialer{}, + pkC: &mockGatewayForDialer{}, + }, + paths: [][]routing.Hop{makeHops(pkA, pkB, pkC), makeHops(pkC, pkB, pkA)}, + expErr: nil, + }, + { + testName: "fwd1_rev2", + routers: map[cipher.PubKey]interface{}{ + pkA: &mockGatewayForDialer{}, + pkB: &mockGatewayForDialer{}, + pkC: &mockGatewayForDialer{}, + }, + paths: [][]routing.Hop{makeHops(pkA, pkC), makeHops(pkC, pkB, pkA)}, + expErr: nil, + }, + } + + for _, tc := range testCases { + t.Run(tc.testName, makeRun(tc)) + } + }) + + // Calling .ReserveIDs should never hang indefinitely if we set context with timeout. + // We set this by providing a context.Context with a timeout. + // Hence, .ReserveIDs should return context.DeadlineExceeded when the timeout triggers. + // Any other errors, or further delays is considered a failure. + t.Run("no_hangs_with_ctx_timeout", func(t *testing.T) { + testCases := []testCase{ + { + testName: "all_routers_hang", + routers: map[cipher.PubKey]interface{}{ + pkA: &mockGatewayForDialer{hangDuration: time.Second * 5}, + pkC: &mockGatewayForDialer{hangDuration: time.Second * 5}, + }, + paths: [][]routing.Hop{makeHops(pkA, pkC), makeHops(pkC, pkA)}, + expErr: context.DeadlineExceeded, + }, + { + testName: "intermediary_router_hangs", + routers: map[cipher.PubKey]interface{}{ + pkA: &mockGatewayForDialer{}, + pkB: &mockGatewayForDialer{hangDuration: time.Second * 5}, + pkC: &mockGatewayForDialer{}, + }, + paths: [][]routing.Hop{makeHops(pkA, pkB, pkC), makeHops(pkC, pkB, pkA)}, + expErr: context.DeadlineExceeded, + }, + { + testName: "initiating_router_hangs", + routers: map[cipher.PubKey]interface{}{ + pkA: &mockGatewayForDialer{hangDuration: time.Second * 5}, + pkB: &mockGatewayForDialer{}, + pkC: &mockGatewayForDialer{}, + }, + paths: [][]routing.Hop{makeHops(pkA, pkC), makeHops(pkC, pkB, pkA)}, + expErr: context.DeadlineExceeded, + }, + { + testName: "responding_router_hangs", + routers: map[cipher.PubKey]interface{}{ + pkA: &mockGatewayForDialer{}, + pkB: &mockGatewayForDialer{}, + pkC: &mockGatewayForDialer{hangDuration: time.Second * 5}, + }, + paths: [][]routing.Hop{makeHops(pkA, pkB, pkC), makeHops(pkC, pkB, pkA)}, + expErr: context.DeadlineExceeded, + }, + } + + for _, tc := range testCases { + t.Run(tc.testName, makeRun(tc)) + } + }) +} + +// makes a slice of hops from pks +func makeHops(pks ...cipher.PubKey) []routing.Hop { + hops := make([]routing.Hop, len(pks)-1) + for i, pk := range pks[:len(pks)-1] { + hops[i] = routing.Hop{ + TpID: uuid.New(), + From: pk, + To: pks[i+1], + } + } + return hops +} + +// ensures that the internal idReserver.rec and idReserver.ids match up +func checkIDReserver(t *testing.T, rtIDR *idReserver) { + assert.Equal(t, len(rtIDR.rec), len(rtIDR.ids)) + + // ensure values of .ids are okay + for pk, rec := range rtIDR.rec { + ids, ok := rtIDR.ids[pk] + + assert.True(t, ok) + assert.Len(t, ids, int(rec)) + + // ensure there are no duplicates in 'ids' + idMap := make(map[routing.RouteID]struct{}, len(ids)) + for _, id := range ids { + idMap[id] = struct{}{} + } + assert.Len(t, idMap, len(ids)) + } +} diff --git a/pkg/setup/idreservoir.go b/pkg/setup/idreservoir.go deleted file mode 100644 index 761cfbb50..000000000 --- a/pkg/setup/idreservoir.go +++ /dev/null @@ -1,200 +0,0 @@ -package setup - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "sync" - - "github.com/SkycoinProject/dmsg" - "github.com/SkycoinProject/dmsg/cipher" - "github.com/SkycoinProject/skycoin/src/util/logging" - - "github.com/SkycoinProject/skywire-mainnet/pkg/routing" -) - -// ErrNoKey is returned when key is not found. -var ErrNoKey = errors.New("id reservoir has no key") - -type idReservoir struct { - rec map[cipher.PubKey]uint8 - ids map[cipher.PubKey][]routing.RouteID - mx sync.Mutex -} - -func newIDReservoir(paths ...routing.Path) (*idReservoir, int) { - rec := make(map[cipher.PubKey]uint8) - - var total int - - for _, path := range paths { - if len(path) == 0 { - continue - } - - rec[path[0].From]++ - - for _, hop := range path { - rec[hop.To]++ - } - - total += len(path) + 1 - } - - return &idReservoir{ - rec: rec, - ids: make(map[cipher.PubKey][]routing.RouteID), - }, total -} - -type reserveFunc func( - ctx context.Context, - log *logging.Logger, - dmsgC *dmsg.Client, - pk cipher.PubKey, - n uint8, -) ([]routing.RouteID, error) - -func (idr *idReservoir) ReserveIDs( - ctx context.Context, - log *logging.Logger, - dmsgC *dmsg.Client, - reserve reserveFunc, -) error { - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - errCh := make(chan error, len(idr.rec)) - defer close(errCh) - - for pk, n := range idr.rec { - go func(pk cipher.PubKey, n uint8) { - ids, err := reserve(ctx, log, dmsgC, pk, n) - if err != nil { - errCh <- fmt.Errorf("reserve routeID from %s failed: %w", pk, err) - return - } - idr.mx.Lock() - idr.ids[pk] = ids - idr.mx.Unlock() - errCh <- nil - }(pk, n) - } - - return finalError(len(idr.rec), errCh) -} - -func (idr *idReservoir) PopID(pk cipher.PubKey) (routing.RouteID, bool) { - idr.mx.Lock() - defer idr.mx.Unlock() - - ids, ok := idr.ids[pk] - if !ok || len(ids) == 0 { - return 0, false - } - - idr.ids[pk] = ids[1:] - - return ids[0], true -} - -func (idr *idReservoir) String() string { - idr.mx.Lock() - defer idr.mx.Unlock() - - b, _ := json.MarshalIndent(idr.ids, "", "\t") //nolint:errcheck - - return string(b) -} - -// RuleMap associates a rule to a visor's public key. -type RuleMap map[cipher.PubKey]routing.Rule - -// RulesMap associates a slice of rules to a visor's public key. -type RulesMap map[cipher.PubKey][]routing.Rule - -func (rm RulesMap) String() string { - out := make(map[cipher.PubKey][]string, len(rm)) - - for pk, rules := range rm { - str := make([]string, len(rules)) - for i, rule := range rules { - str[i] = rule.String() - } - - out[pk] = str - } - - jb, err := json.MarshalIndent(out, "", "\t") - if err != nil { - panic(err) - } - - return string(jb) -} - -// GenerateRules generates rules for given forward and reverse routes. -// The outputs are as follows: -// - maps that relate slices of forward, consume and intermediary routing rules to a given visor's public key. -// - an error (if any). -func (idr *idReservoir) GenerateRules(fwd, rev routing.Route) ( - forwardRules, consumeRules RuleMap, - intermediaryRules RulesMap, - err error, -) { - forwardRules = make(RuleMap) - consumeRules = make(RuleMap) - intermediaryRules = make(RulesMap) - - for _, route := range []routing.Route{fwd, rev} { - // 'firstRID' is the first visor's key routeID - firstRID, ok := idr.PopID(route.Path[0].From) - if !ok { - return nil, nil, nil, ErrNoKey - } - - desc := route.Desc - srcPK := desc.SrcPK() - dstPK := desc.DstPK() - srcPort := desc.SrcPort() - dstPort := desc.DstPort() - - var rID = firstRID - - for i, hop := range route.Path { - nxtRID, ok := idr.PopID(hop.To) - if !ok { - return nil, nil, nil, ErrNoKey - } - - if i == 0 { - rule := routing.ForwardRule(route.KeepAlive, rID, nxtRID, hop.TpID, srcPK, dstPK, srcPort, dstPort) - forwardRules[hop.From] = rule - } else { - rule := routing.IntermediaryForwardRule(route.KeepAlive, rID, nxtRID, hop.TpID) - intermediaryRules[hop.From] = append(intermediaryRules[hop.From], rule) - } - - rID = nxtRID - } - - fmt.Printf("GENERATING CONSUME RULE WITH SRC %s\n", srcPK) - rule := routing.ConsumeRule(route.KeepAlive, rID, srcPK, dstPK, srcPort, dstPort) - consumeRules[dstPK] = rule - } - - return forwardRules, consumeRules, intermediaryRules, nil -} - -func finalError(n int, errCh <-chan error) error { - var finalErr error - - for i := 0; i < n; i++ { - if err := <-errCh; err != nil { - finalErr = err - } - } - - return finalErr -} diff --git a/pkg/setup/mock_id_reserver.go b/pkg/setup/mock_id_reserver.go new file mode 100644 index 000000000..ba93431b1 --- /dev/null +++ b/pkg/setup/mock_id_reserver.go @@ -0,0 +1,111 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package setup + +import ( + context "context" + + cipher "github.com/SkycoinProject/dmsg/cipher" + mock "github.com/stretchr/testify/mock" + + routerclient "github.com/SkycoinProject/skywire-mainnet/pkg/router/routerclient" + routing "github.com/SkycoinProject/skywire-mainnet/pkg/routing" +) + +// MockIDReserver is an autogenerated mock type for the IDReserver type +type MockIDReserver struct { + mock.Mock +} + +// Client provides a mock function with given fields: pk +func (_m *MockIDReserver) Client(pk cipher.PubKey) *routerclient.Client { + ret := _m.Called(pk) + + var r0 *routerclient.Client + if rf, ok := ret.Get(0).(func(cipher.PubKey) *routerclient.Client); ok { + r0 = rf(pk) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*routerclient.Client) + } + } + + return r0 +} + +// Close provides a mock function with given fields: +func (_m *MockIDReserver) Close() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// PopID provides a mock function with given fields: pk +func (_m *MockIDReserver) PopID(pk cipher.PubKey) (routing.RouteID, bool) { + ret := _m.Called(pk) + + var r0 routing.RouteID + if rf, ok := ret.Get(0).(func(cipher.PubKey) routing.RouteID); ok { + r0 = rf(pk) + } else { + r0 = ret.Get(0).(routing.RouteID) + } + + var r1 bool + if rf, ok := ret.Get(1).(func(cipher.PubKey) bool); ok { + r1 = rf(pk) + } else { + r1 = ret.Get(1).(bool) + } + + return r0, r1 +} + +// ReserveIDs provides a mock function with given fields: ctx +func (_m *MockIDReserver) ReserveIDs(ctx context.Context) error { + ret := _m.Called(ctx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// String provides a mock function with given fields: +func (_m *MockIDReserver) String() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// TotalIDs provides a mock function with given fields: +func (_m *MockIDReserver) TotalIDs() int { + ret := _m.Called() + + var r0 int + if rf, ok := ret.Get(0).(func() int); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int) + } + + return r0 +} diff --git a/pkg/setup/node.go b/pkg/setup/node.go index e82ea15fa..4171820fc 100644 --- a/pkg/setup/node.go +++ b/pkg/setup/node.go @@ -4,66 +4,50 @@ import ( "context" "fmt" "net/rpc" - "sync" "time" "github.com/SkycoinProject/dmsg" + "github.com/SkycoinProject/dmsg/cipher" "github.com/SkycoinProject/dmsg/disc" "github.com/SkycoinProject/skycoin/src/util/logging" + "github.com/sirupsen/logrus" "github.com/SkycoinProject/skywire-mainnet/pkg/metrics" "github.com/SkycoinProject/skywire-mainnet/pkg/router/routerclient" "github.com/SkycoinProject/skywire-mainnet/pkg/routing" "github.com/SkycoinProject/skywire-mainnet/pkg/skyenv" + "github.com/SkycoinProject/skywire-mainnet/pkg/snet" ) +var log = logging.MustGetLogger("setup_node") + // Node performs routes setup operations over messaging channel. type Node struct { - logger *logging.Logger - dmsgC *dmsg.Client - dmsgL *dmsg.Listener - sessionsCount int - metrics metrics.Recorder + dmsgC *dmsg.Client + metrics metrics.Recorder } // NewNode constructs a new SetupNode. func NewNode(conf *Config, metrics metrics.Recorder) (*Node, error) { - logger := logging.NewMasterLogger() - if lvl, err := logging.LevelFromString(conf.LogLevel); err == nil { - logger.SetLevel(lvl) + logging.SetLevel(lvl) } - log := logger.PackageLogger("setup_node") - - // Prepare dmsg. - dmsgC := dmsg.NewClient( - conf.PubKey, - conf.SecKey, - disc.NewHTTP(conf.Dmsg.Discovery), - &dmsg.Config{MinSessions: conf.Dmsg.SessionsCount}, - ) - dmsgC.SetLogger(logger.PackageLogger(dmsg.Type)) - + // Connect to dmsg network. + dmsgDisc := disc.NewHTTP(conf.Dmsg.Discovery) + dmsgConf := &dmsg.Config{MinSessions: conf.Dmsg.SessionsCount} + dmsgC := dmsg.NewClient(conf.PK, conf.SK, dmsgDisc, dmsgConf) go dmsgC.Serve() - log.Info("connected to dmsg servers") - - dmsgL, err := dmsgC.Listen(skyenv.DmsgSetupPort) - if err != nil { - return nil, fmt.Errorf("failed to listen on dmsg port %d: %v", skyenv.DmsgSetupPort, dmsgL) - } - - log.Info("started listening for dmsg connections") + log.WithField("local_pk", conf.PK).WithField("dmsg_conf", conf.Dmsg). + Info("Connecting to the dmsg network.") + <-dmsgC.Ready() + log.Info("Connected!") node := &Node{ - logger: log, - dmsgC: dmsgC, - dmsgL: dmsgL, - sessionsCount: conf.Dmsg.SessionsCount, - metrics: metrics, + dmsgC: dmsgC, + metrics: metrics, } - return node, nil } @@ -72,125 +56,214 @@ func (sn *Node) Close() error { if sn == nil { return nil } - return sn.dmsgC.Close() } // Serve starts transport listening loop. -func (sn *Node) Serve() error { - sn.logger.Info("Serving setup node") +func (sn *Node) Serve(ctx context.Context) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + const dmsgPort = skyenv.DmsgSetupPort + const timeout = 30 * time.Second + + log.WithField("dmsg_port", dmsgPort).Info("Starting listener.") + lis, err := sn.dmsgC.Listen(skyenv.DmsgSetupPort) + if err != nil { + return fmt.Errorf("failed to listen on dmsg port %d: %v", skyenv.DmsgSetupPort, lis) + } + defer func() { + if err := lis.Close(); err != nil { + log.WithError(err).Warn("Dmsg listener closed with non-nil error.") + } + }() + + log.WithField("dmsg_port", dmsgPort).Info("Accepting dmsg streams.") for { - conn, err := sn.dmsgL.AcceptStream() + conn, err := lis.AcceptStream() if err != nil { return err } - - remote := conn.RemoteAddr().(dmsg.Addr) - sn.logger.WithField("requester", remote.PK).Infof("Received request.") - - const timeout = 30 * time.Second - + gw := &RPCGateway{ + Metrics: sn.metrics, + Ctx: ctx, + Conn: conn, + ReqPK: conn.RemoteAddr().(dmsg.Addr).PK, + Dialer: routerclient.WrapDmsgClient(sn.dmsgC), + Timeout: timeout, + } rpcS := rpc.NewServer() - if err := rpcS.Register(NewRPCGateway(remote.PK, sn, timeout)); err != nil { + if err := rpcS.Register(gw); err != nil { return err } - go rpcS.ServeConn(conn) } } -func (sn *Node) handleDialRouteGroup(ctx context.Context, route routing.BidirectionalRoute) (routing.EdgeRules, error) { - sn.logger.Infof("Setup route from %s to %s", route.Desc.SrcPK(), route.Desc.DstPK()) +// CreateRouteGroup creates a route group by communicating with routers used within the bidirectional route. +// The following steps are taken: +// * Check the validity of bi route input. +// * Route IDs are reserved from the routers. +// * Intermediary rules are broadcasted to the intermediary routers. +// * Edge rules are broadcasted to the responding router. +// * Edge rules is returned (to the initiating router). +func CreateRouteGroup(ctx context.Context, dialer snet.Dialer, biRt routing.BidirectionalRoute) (resp routing.EdgeRules, err error) { + start := time.Now() + log := logging.MustGetLogger(fmt.Sprintf("request:%s->%s", biRt.Desc.SrcPK(), biRt.Desc.DstPK())) + log.Info("Processing request.") + defer func() { + elapsed := time.Since(start) + log := log.WithField("elapsed", elapsed) + if err != nil { + log.WithError(err).Warn("Request processed with error.") + } else { + log.Info("Request processed successfully.") + } + }() - idr, err := sn.reserveRouteIDs(ctx, route) - if err != nil { + // Ensure bi routes input is valid. + if err = biRt.Check(); err != nil { return routing.EdgeRules{}, err } - forwardRoute, reverseRoute := route.ForwardAndReverse() + // Reserve route IDs from remote routers. + rtIDR, err := ReserveRouteIDs(ctx, log, dialer, biRt) + if err != nil { + return routing.EdgeRules{}, err + } + defer func() { log.WithError(rtIDR.Close()).Debug("Closing route id reserver.") }() - // Determine the rules to send to visors using route group descriptor and reserved route IDs. - forwardRules, consumeRules, intermediaryRules, err := idr.GenerateRules(forwardRoute, reverseRoute) + // Generate forward and reverse routes. + fwdRt, revRt := biRt.ForwardAndReverse() + srcPK := biRt.Desc.SrcPK() + dstPK := biRt.Desc.DstPK() + // Generate routing rules (for edge and intermediary routers) that are to be sent. + // Rules are grouped by rule type [FWD, REV, INTER]. + fwdRules, revRules, interRules, err := GenerateRules(rtIDR, []routing.Route{fwdRt, revRt}) if err != nil { - sn.logger.WithError(err).Error("ERROR GENERATING RULES") return routing.EdgeRules{}, err } + initEdge := routing.EdgeRules{Desc: revRt.Desc, Forward: fwdRules[srcPK][0], Reverse: revRules[srcPK][0]} + respEdge := routing.EdgeRules{Desc: fwdRt.Desc, Forward: fwdRules[dstPK][0], Reverse: revRules[dstPK][0]} - sn.logger.Infof("generated forward rules: %v", forwardRules) - sn.logger.Infof("generated consume rules: %v", consumeRules) - sn.logger.Infof("generated intermediary rules: %v", intermediaryRules) + log.Infof("Generated routing rules:\nInitiating edge: %v\nResponding edge: %v\nIntermediaries: %v", + initEdge.String(), respEdge.String(), interRules.String()) - if err := sn.addIntermediaryRules(ctx, intermediaryRules); err != nil { + // Broadcast intermediary rules to intermediary routers. + if err := BroadcastIntermediaryRules(ctx, log, rtIDR, interRules); err != nil { return routing.EdgeRules{}, err } - initRouteRules := routing.EdgeRules{ - Desc: reverseRoute.Desc, - Forward: forwardRules[route.Desc.SrcPK()], - Reverse: consumeRules[route.Desc.SrcPK()], + // Broadcast rules to responding router. + log.Debug("Broadcasting responding rules...") + ok, err := rtIDR.Client(biRt.Desc.DstPK()).AddEdgeRules(ctx, respEdge) + if err != nil || !ok { + return routing.EdgeRules{}, fmt.Errorf("failed to broadcast rules to destination router: %v", err) } - respRouteRules := routing.EdgeRules{ - Desc: forwardRoute.Desc, - Forward: forwardRules[route.Desc.DstPK()], - Reverse: consumeRules[route.Desc.DstPK()], - } + // Return rules to initiating router. + return initEdge, nil +} - sn.logger.Infof("initRouteRules: Desc(%s), %s", &initRouteRules.Desc, initRouteRules) - sn.logger.Infof("respRouteRules: Desc(%s), %s", &respRouteRules.Desc, respRouteRules) +// ReserveRouteIDs dials to all routers and reserves required route IDs from them. +// The number of route IDs to be reserved per router, is extrapolated from the 'route' input. +func ReserveRouteIDs(ctx context.Context, log logrus.FieldLogger, dialer snet.Dialer, route routing.BidirectionalRoute) (idR IDReserver, err error) { + log.Debug("Reserving route IDs...") + defer func() { + if err != nil { + log.WithError(err).Warn("Failed to reserve route IDs.") + } + }() - // Confirm routes with responding visor. - ok, err := routerclient.AddEdgeRules(ctx, sn.logger, sn.dmsgC, route.Desc.DstPK(), respRouteRules) - if err != nil || !ok { - return routing.EdgeRules{}, fmt.Errorf("failed to confirm route group with destination visor: %w", err) + idR, err = NewIDReserver(ctx, dialer, [][]routing.Hop{route.Forward, route.Reverse}) + if err != nil { + return nil, fmt.Errorf("failed to instantiate route id reserver: %w", err) } + defer func() { + if err != nil { + log.WithError(idR.Close()).Warn("Closing router clients due to error.") + } + }() - sn.logger.Infof("Returning route rules to initiating visor: %v", initRouteRules) - - return initRouteRules, nil + if err = idR.ReserveIDs(ctx); err != nil { + return nil, fmt.Errorf("failed to reserve route ids: %w", err) + } + return idR, nil } -func (sn *Node) addIntermediaryRules(ctx context.Context, intermediaryRules RulesMap) error { - errCh := make(chan error, len(intermediaryRules)) - - var wg sync.WaitGroup +// GenerateRules generates rules for given forward and reverse routes. +// The outputs are as follows: +// - maps that relate slices of forward, consume and intermediary routing rules to a given visor's public key. +// - an error (if any). +func GenerateRules(idR IDReserver, routes []routing.Route) (fwdRules, revRules, interRules RulesMap, err error) { + fwdRules = make(RulesMap) + revRules = make(RulesMap) + interRules = make(RulesMap) + + for _, route := range routes { + // 'firstRID' is the first visor's key routeID + firstRID, ok := idR.PopID(route.Hops[0].From) + if !ok { + return nil, nil, nil, ErrNoKey + } - for pk, rules := range intermediaryRules { - pk, rules := pk, rules + desc := route.Desc + srcPK := desc.SrcPK() + dstPK := desc.DstPK() + srcPort := desc.SrcPort() + dstPort := desc.DstPort() - sn.logger.WithField("remote", pk).Info("Adding rules to intermediary visor") + var rID = firstRID - wg.Add(1) + for i, hop := range route.Hops { + nxtRID, ok := idR.PopID(hop.To) + if !ok { + return nil, nil, nil, ErrNoKey + } - go func() { - defer wg.Done() - if _, err := routerclient.AddIntermediaryRules(ctx, sn.logger, sn.dmsgC, pk, rules); err != nil { - sn.logger.WithField("remote", pk).WithError(err).Warn("failed to add rules") - errCh <- err + if i == 0 { + rule := routing.ForwardRule(route.KeepAlive, rID, nxtRID, hop.TpID, srcPK, dstPK, srcPort, dstPort) + fwdRules[hop.From] = append(fwdRules[hop.From], rule) + } else { + rule := routing.IntermediaryForwardRule(route.KeepAlive, rID, nxtRID, hop.TpID) + interRules[hop.From] = append(interRules[hop.From], rule) } - }() - } - wg.Wait() - close(errCh) + rID = nxtRID + } + + rule := routing.ConsumeRule(route.KeepAlive, rID, srcPK, dstPK, srcPort, dstPort) + revRules[dstPK] = append(revRules[dstPK], rule) + } - return finalError(len(intermediaryRules), errCh) + return fwdRules, revRules, interRules, nil } -func (sn *Node) reserveRouteIDs(ctx context.Context, route routing.BidirectionalRoute) (*idReservoir, error) { - reservoir, total := newIDReservoir(route.Forward, route.Reverse) - sn.logger.Infof("There are %d route IDs to reserve.", total) +// BroadcastIntermediaryRules broadcasts routing rules to the intermediary routers. +func BroadcastIntermediaryRules(ctx context.Context, log logrus.FieldLogger, rtIDR IDReserver, interRules RulesMap) (err error) { + log.WithField("intermediary_routers", len(interRules)).Debug("Broadcasting intermediary rules...") + defer func() { + if err != nil { + log.WithError(err).Warn("Failed to broadcast intermediary rules.") + } + }() - err := reservoir.ReserveIDs(ctx, sn.logger, sn.dmsgC, routerclient.ReserveIDs) + ctx, cancel := context.WithCancel(ctx) + defer cancel() - if err != nil { - sn.logger.WithError(err).Warnf("Failed to reserve route IDs.") - return nil, err - } + errCh := make(chan error, len(interRules)) + defer close(errCh) - sn.logger.Infof("Successfully reserved route IDs.") + for pk, rules := range interRules { + go func(pk cipher.PubKey, rules []routing.Rule) { + _, err := rtIDR.Client(pk).AddIntermediaryRules(ctx, rules) + if err != nil { + cancel() + } + errCh <- err + }(pk, rules) + } - return reservoir, err + return firstError(len(interRules), errCh) } diff --git a/pkg/setup/node_test.go b/pkg/setup/node_test.go index bbf6bb586..0367efa93 100644 --- a/pkg/setup/node_test.go +++ b/pkg/setup/node_test.go @@ -1,31 +1,23 @@ -// +build !no_ci - package setup import ( "context" "fmt" - "log" - "net" - "net/rpc" + "math/rand" "os" + "strconv" + "sync" "testing" "time" - "github.com/SkycoinProject/dmsg" "github.com/SkycoinProject/dmsg/cipher" "github.com/SkycoinProject/skycoin/src/util/logging" "github.com/google/uuid" - "github.com/stretchr/testify/mock" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/SkycoinProject/skywire-mainnet/internal/testhelpers" - "github.com/SkycoinProject/skywire-mainnet/pkg/metrics" - "github.com/SkycoinProject/skywire-mainnet/pkg/router" "github.com/SkycoinProject/skywire-mainnet/pkg/routing" - "github.com/SkycoinProject/skywire-mainnet/pkg/setup/setupclient" - "github.com/SkycoinProject/skywire-mainnet/pkg/skyenv" - "github.com/SkycoinProject/skywire-mainnet/pkg/snet/snettest" ) func TestMain(m *testing.M) { @@ -44,230 +36,326 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) } -type clientWithDMSGAddrAndListener struct { - *dmsg.Client - Addr dmsg.Addr - Listener *dmsg.Listener - AppliedIntermediaryRules []routing.Rule - AppliedEdgeRules routing.EdgeRules -} - -func TestNode(t *testing.T) { - // We are generating five key pairs - one for the `Router` of setup node, - // the other ones - for the clients along the desired route. - keys := snettest.GenKeyPairs(5) +func TestCreateRouteGroup(t *testing.T) { + pkA, _ := cipher.GenerateKeyPair() + pkB, _ := cipher.GenerateKeyPair() + pkC, _ := cipher.GenerateKeyPair() + pkD, _ := cipher.GenerateKeyPair() + + type testCase struct { + fwdPKs []cipher.PubKey + revPKs []cipher.PubKey + SrcPort routing.Port + DstPort routing.Port + } - // create test env - nEnv := snettest.NewEnv(t, keys, []string{dmsg.Type}) - defer nEnv.Teardown() + testCases := []testCase{ + { + fwdPKs: []cipher.PubKey{pkA, pkB, pkC, pkD}, + revPKs: []cipher.PubKey{pkD, pkC, pkB, pkA}, + SrcPort: 1, + DstPort: 5, + }, + } - reservedIDs := []routing.RouteID{1, 2} + for i, tc := range testCases { + t.Run(strconv.Itoa(i), func(t *testing.T) { + // arrange: router keys + routerPKs := append(tc.fwdPKs, tc.revPKs...) + routerCount := countUniquePKs(append(tc.fwdPKs, tc.revPKs...)) + initPK := routerPKs[0] + + // arrange: routers + routers := make(map[cipher.PubKey]interface{}, routerCount) + for _, pk := range routerPKs { + routers[pk] = newMockRouterGateway(pk) + } - // TEST: Emulates the communication between 4 visors and a setup node, - // where the first client visor initiates a route to the last. - t.Run("DialRouteGroup", func(t *testing.T) { - testDialRouteGroup(t, keys, nEnv, reservedIDs) - }) -} + // arrange: mock dialer + dialer := newMockDialer(t, routers) -func testDialRouteGroup(t *testing.T, keys []snettest.KeyPair, nEnv *snettest.Env, reservedIDs []routing.RouteID) { - // client index 0 is for setup node. - // clients index 1 to 4 are for visors. - clients, closeClients := prepClients(t, keys, nEnv, reservedIDs, 5) - defer closeClients() + // arrange: bidirectional route input + biRt := biRouteFromKeys(tc.fwdPKs, tc.revPKs, tc.SrcPort, tc.DstPort) - // prepare and serve setup node (using client 0). - _, closeSetup := prepSetupNode(t, clients[0].Client, clients[0].Listener) - defer closeSetup() + // act + resp, err := CreateRouteGroup(context.TODO(), dialer, biRt) + if err == nil { + // if successful, inject response (response edge rules) to responding router + var ok bool + _ = routers[initPK].(*mockRouterGateway).AddEdgeRules(resp, &ok) // nolint:errcheck + } - route := prepBidirectionalRoute(clients) + // assert: no error + assert.NoError(t, err) - forwardRules, consumeRules, intermediaryRules := generateRules(t, route, reservedIDs) + // assert: valid route ID keys + for pk, r := range routers { + mr := r.(*mockRouterGateway) + t.Logf("Checking router %s: lastRtID=%d edgeRules=%d interRules=%d", + pk, mr.lastRtID, len(mr.edgeRules), len(mr.interRules)) + checkRtIDKeysOfRouterRules(t, mr) + } - forwardRoute, reverseRoute := route.ForwardAndReverse() + // TODO: assert: edge routers + // * Ensure edge routers have 1 edge rule each, and no inter rules. + // * Edge rule's descriptor should be of provided src/dst pk/port. - wantEdgeRules := routing.EdgeRules{ - Desc: reverseRoute.Desc, - Forward: forwardRules[route.Desc.SrcPK()], - Reverse: consumeRules[route.Desc.SrcPK()], + // TODO: assert: inter routers + // * Ensure inter routers have 2 or more inter rules (depending on routes). + // * Ensure inter routers have no edge rules. + }) } +} - testLogger := logging.MustGetLogger("setupclient_test") - pks := []cipher.PubKey{clients[0].Addr.PK} - gotEdgeRules, err := setupclient.NewSetupNodeDialer().Dial(context.TODO(), testLogger, nEnv.Nets[1], pks, route) - require.NoError(t, err) - require.Equal(t, wantEdgeRules, gotEdgeRules) - - for pk, rules := range intermediaryRules { - for _, cl := range clients { - if cl.Addr.PK == pk { - require.Equal(t, cl.AppliedIntermediaryRules, rules) - break - } +// checkRtIDKeysOfRouterRules ensures that the rules advertised to the router (from the setup logic) has route ID keys +// which are valid. +func checkRtIDKeysOfRouterRules(t *testing.T, r *mockRouterGateway) { + r.mx.Lock() + defer r.mx.Unlock() + + var rtIDKeys []routing.RouteID + + for _, edge := range r.edgeRules { + rtIDKeys = append(rtIDKeys, edge.Forward.KeyRouteID(), edge.Reverse.KeyRouteID()) + } + for _, rules := range r.interRules { + for _, rule := range rules { + rtIDKeys = append(rtIDKeys, rule.KeyRouteID()) } } - respRouteRules := routing.EdgeRules{ - Desc: forwardRoute.Desc, - Forward: forwardRules[route.Desc.DstPK()], - Reverse: consumeRules[route.Desc.DstPK()], + // assert: no duplicate rtIDs + dupM := make(map[routing.RouteID]struct{}) + for _, rtID := range rtIDKeys { + dupM[rtID] = struct{}{} } + assert.Len(t, dupM, len(rtIDKeys), "rtIDKeys=%v dupM=%v", rtIDKeys, dupM) - require.Equal(t, respRouteRules, clients[4].AppliedEdgeRules) + // assert: all routes IDs are explicitly reserved by router + for _, rtID := range rtIDKeys { + assert.LessOrEqual(t, uint32(rtID), r.lastRtID) + } } -func prepBidirectionalRoute(clients []clientWithDMSGAddrAndListener) routing.BidirectionalRoute { - // prepare route group creation (client_1 will use this to request a route group creation with setup node). - desc := routing.NewRouteDescriptor(clients[1].Addr.PK, clients[4].Addr.PK, 1, 1) - - forwardHops := []routing.Hop{ - {From: clients[1].Addr.PK, To: clients[2].Addr.PK, TpID: uuid.New()}, - {From: clients[2].Addr.PK, To: clients[3].Addr.PK, TpID: uuid.New()}, - {From: clients[3].Addr.PK, To: clients[4].Addr.PK, TpID: uuid.New()}, +func countUniquePKs(pks []cipher.PubKey) int { + m := make(map[cipher.PubKey]struct{}) + for _, pk := range pks { + m[pk] = struct{}{} } + return len(m) +} - reverseHops := []routing.Hop{ - {From: clients[4].Addr.PK, To: clients[3].Addr.PK, TpID: uuid.New()}, - {From: clients[3].Addr.PK, To: clients[2].Addr.PK, TpID: uuid.New()}, - {From: clients[2].Addr.PK, To: clients[1].Addr.PK, TpID: uuid.New()}, +func biRouteFromKeys(fwdPKs, revPKs []cipher.PubKey, srcPort, dstPort routing.Port) routing.BidirectionalRoute { + fwdHops := make([]routing.Hop, len(fwdPKs)-1) + for i, srcPK := range fwdPKs[:len(fwdPKs)-1] { + dstPK := fwdPKs[i+1] + fwdHops[i] = routing.Hop{TpID: determineTpID(srcPK, dstPK), From: srcPK, To: dstPK} } - route := routing.BidirectionalRoute{ - Desc: desc, - KeepAlive: 1 * time.Hour, - Forward: forwardHops, - Reverse: reverseHops, + revHops := make([]routing.Hop, len(revPKs)-1) + for i, srcPK := range revPKs[:len(revPKs)-1] { + dstPK := revPKs[i+1] + revHops[i] = routing.Hop{TpID: determineTpID(srcPK, dstPK), From: srcPK, To: dstPK} } - return route + // TODO: This should also return a map of format: map[uuid.UUID][]cipher.PubKey + // This way, we can associate transport IDs to the two transport edges, allowing for more checks. + return routing.BidirectionalRoute{ + Desc: routing.NewRouteDescriptor(fwdPKs[0], revPKs[0], srcPort, dstPort), + KeepAlive: 0, + Forward: fwdHops, + Reverse: revHops, + } } -func generateRules( - t *testing.T, - route routing.BidirectionalRoute, - reservedIDs []routing.RouteID, -) ( - forwardRules map[cipher.PubKey]routing.Rule, - consumeRules map[cipher.PubKey]routing.Rule, - intermediaryRules RulesMap, -) { - wantIDR, _ := newIDReservoir(route.Forward, route.Reverse) - for pk := range wantIDR.rec { - wantIDR.ids[pk] = reservedIDs +// for tests, we make transport IDs deterministic +// hence, we can derive the tpID from any pk pair +func determineTpID(pk1, pk2 cipher.PubKey) (tpID uuid.UUID) { + v1, v2 := pk1.Big(), pk2.Big() + + var hash cipher.SHA256 + if v1.Cmp(v2) > 0 { + hash = cipher.SumSHA256(append(pk1[:], pk2[:]...)) + } else { + hash = cipher.SumSHA256(append(pk2[:], pk1[:]...)) } - forwardRoute, reverseRoute := route.ForwardAndReverse() + copy(tpID[:], hash[:]) + return tpID +} - forwardRules, consumeRules, intermediaryRules, err := wantIDR.GenerateRules(forwardRoute, reverseRoute) - require.NoError(t, err) +// mockRouterGateway mocks router.RPCGateway and has an internal state machine that records all remote calls. +// mockRouterGateway acts as a well behaved router, and no error will be returned on any of it's endpoints. +type mockRouterGateway struct { + pk cipher.PubKey // router's public key + lastRtID uint32 // last route ID that was reserved (the first returned rtID would be 1 if this starts as 0). + edgeRules []routing.EdgeRules // edge rules added by remote. + interRules [][]routing.Rule // intermediary rules added by remote. + mx sync.Mutex +} - return forwardRules, consumeRules, intermediaryRules +func newMockRouterGateway(pk cipher.PubKey) *mockRouterGateway { + return &mockRouterGateway{pk: pk} } -func prepClients( - t *testing.T, - keys []snettest.KeyPair, - nEnv *snettest.Env, - reservedIDs []routing.RouteID, - n int, -) ([]clientWithDMSGAddrAndListener, func()) { - clients := make([]clientWithDMSGAddrAndListener, n) - - for i := 0; i < n; i++ { - var port uint16 - // setup node - if i == 0 { - port = skyenv.DmsgSetupPort - } else { - port = skyenv.DmsgAwaitSetupPort - } +func (gw *mockRouterGateway) AddEdgeRules(rules routing.EdgeRules, ok *bool) error { + gw.mx.Lock() + defer gw.mx.Unlock() - pk, sk := keys[i].PK, keys[i].SK - t.Logf("client[%d] PK: %s\n", i, pk) + gw.edgeRules = append(gw.edgeRules, rules) + *ok = true + return nil +} - clientLogger := logging.MustGetLogger(fmt.Sprintf("client_%d:%s:%d", i, pk, port)) - c := dmsg.NewClient(pk, sk, nEnv.DmsgD, &dmsg.Config{MinSessions: 1}) - c.SetLogger(clientLogger) +func (gw *mockRouterGateway) AddIntermediaryRules(rules []routing.Rule, ok *bool) error { + gw.mx.Lock() + defer gw.mx.Unlock() - go c.Serve() + gw.interRules = append(gw.interRules, rules) + *ok = true + return nil +} - listener, err := c.Listen(port) - require.NoError(t, err) +func (gw *mockRouterGateway) ReserveIDs(n uint8, routeIDs *[]routing.RouteID) error { + gw.mx.Lock() + defer gw.mx.Unlock() - clients[i] = clientWithDMSGAddrAndListener{ - Client: c, - Addr: dmsg.Addr{ - PK: pk, - Port: port, - }, - Listener: listener, - } + out := make([]routing.RouteID, n) + for i := range out { + gw.lastRtID++ + out[i] = routing.RouteID(gw.lastRtID) + } + *routeIDs = out + return nil +} - fmt.Printf("Client %d PK: %s\n", i, clients[i].Addr.PK) +// There are no distinctive goals for this test yet. +// As of writing, we only check whether GenerateRules() returns any errors. +func TestGenerateRules(t *testing.T) { + pkA, _ := cipher.GenerateKeyPair() + pkB, _ := cipher.GenerateKeyPair() + pkC, _ := cipher.GenerateKeyPair() + pkD, _ := cipher.GenerateKeyPair() + + type testCase struct { + fwd routing.Route + rev routing.Route + } - // exclude setup node - if i == 0 { - continue - } + testCases := []testCase{ + { + fwd: routing.Route{ + Desc: routing.NewRouteDescriptor(pkA, pkC, 1, 0), + Hops: []routing.Hop{ + {TpID: uuid.New(), From: pkA, To: pkB}, + {TpID: uuid.New(), From: pkB, To: pkD}, + {TpID: uuid.New(), From: pkD, To: pkC}, + }, + }, + rev: routing.Route{ + Desc: routing.NewRouteDescriptor(pkC, pkA, 0, 1), + Hops: []routing.Hop{ + {TpID: uuid.New(), From: pkC, To: pkB}, + {TpID: uuid.New(), From: pkB, To: pkA}, + }, + }, + }, + } - r := prepRouter(&clients[i], reservedIDs, i == n-1) + for i, tc := range testCases { + t.Run(strconv.Itoa(i), func(t *testing.T) { + // arrange + rtIDR := newMockReserver(t, nil) + + // act + fwd, rev, inter, err := GenerateRules(rtIDR, []routing.Route{tc.fwd, tc.rev}) + t.Log("FORWARD:", fwd) + t.Log("REVERSE:", rev) + t.Log("INTERMEDIARY:", inter) + + // assert + // TODO: We need more checks here + require.NoError(t, err) + require.Len(t, fwd, 2) + require.Len(t, rev, 2) + }) + } +} - startRPC(t, r, listener) +func TestBroadcastIntermediaryRules(t *testing.T) { + const ctxTimeout = time.Second + const failingTimeout = time.Second * 5 + + type testCase struct { + workingRouters int // number of working routers + failingRouters int // number of failing routers } - return clients, func() { - for _, c := range clients { - require.NoError(t, c.Close()) - } + testCases := []testCase{ + {workingRouters: 4, failingRouters: 0}, + {workingRouters: 12, failingRouters: 1}, + {workingRouters: 9, failingRouters: 2}, + {workingRouters: 0, failingRouters: 3}, } -} -func prepRouter(client *clientWithDMSGAddrAndListener, reservedIDs []routing.RouteID, last bool) *router.MockRouter { - r := &router.MockRouter{} - // passing two rules to each visor (forward and reverse routes). Simulate - // applying intermediary rules. - r.On("SaveRoutingRules", mock.Anything, mock.Anything). - Return(func(rules ...routing.Rule) error { - client.AppliedIntermediaryRules = append(client.AppliedIntermediaryRules, rules...) - return nil - }) + for _, tc := range testCases { + name := fmt.Sprintf("%d_normal_%d_failing", tc.workingRouters, tc.failingRouters) + + t.Run(name, func(t *testing.T) { + // arrange + workingPKs := randPKs(tc.workingRouters) + failingPKs := randPKs(tc.failingRouters) + + gateways := make(map[cipher.PubKey]interface{}, tc.workingRouters+tc.failingRouters) + for _, pk := range workingPKs { + gateways[pk] = &mockGatewayForReserver{} + } + for _, pk := range failingPKs { + gateways[pk] = &mockGatewayForReserver{hangDuration: failingTimeout} + } + + rtIDR := newMockReserver(t, gateways) + rules := randRulesMap(append(workingPKs, failingPKs...)) + + ctx, cancel := context.WithDeadline(context.TODO(), time.Now().Add(ctxTimeout)) + defer cancel() - // simulate reserving IDs. - r.On("ReserveKeys", 2).Return(reservedIDs, testhelpers.NoErr) + // act + err := BroadcastIntermediaryRules(ctx, logrus.New(), rtIDR, rules) - // destination visor. Simulate applying edge rules. - if last { - r.On("IntroduceRules", mock.Anything).Return(func(rules routing.EdgeRules) error { - client.AppliedEdgeRules = rules - return nil + // assert + if tc.failingRouters > 0 { + assert.EqualError(t, err, context.DeadlineExceeded.Error()) + } else { + assert.NoError(t, err) + } }) } - - return r } -func startRPC(t *testing.T, r router.Router, listener net.Listener) { - rpcServer := rpc.NewServer() - require.NoError(t, rpcServer.Register(router.NewRPCGateway(r))) - - go rpcServer.Accept(listener) +func randPKs(n int) []cipher.PubKey { + out := make([]cipher.PubKey, n) + for i := range out { + out[i], _ = cipher.GenerateKeyPair() + } + return out } -func prepSetupNode(t *testing.T, c *dmsg.Client, listener *dmsg.Listener) (*Node, func()) { - sn := &Node{ - logger: logging.MustGetLogger("setup_node"), - dmsgC: c, - dmsgL: listener, - metrics: metrics.NewDummy(), +func randRulesMap(pks []cipher.PubKey) RulesMap { + rules := make(RulesMap, len(pks)) + for _, pk := range pks { + rules[pk] = randIntermediaryRules(2) } + return rules +} - go func() { - if err := sn.Serve(); err != nil { - sn.logger.WithError(err).Error("Failed to serve") - } - }() +func randIntermediaryRules(n int) []routing.Rule { + const keepAlive = time.Second + randRtID := func() routing.RouteID { return routing.RouteID(rand.Uint32()) } - return sn, func() { - require.NoError(t, sn.Close()) + out := make([]routing.Rule, n) + for i := range out { + out[i] = routing.IntermediaryForwardRule(keepAlive, randRtID(), randRtID(), uuid.New()) } + return out } diff --git a/pkg/setup/rpc_gateway.go b/pkg/setup/rpc_gateway.go index e5be746c0..444d1cfce 100644 --- a/pkg/setup/rpc_gateway.go +++ b/pkg/setup/rpc_gateway.go @@ -2,53 +2,51 @@ package setup import ( "context" - "fmt" + "net" "time" "github.com/SkycoinProject/dmsg/cipher" "github.com/SkycoinProject/skycoin/src/util/logging" + "github.com/SkycoinProject/skywire-mainnet/pkg/metrics" "github.com/SkycoinProject/skywire-mainnet/pkg/routing" + "github.com/SkycoinProject/skywire-mainnet/pkg/snet" ) // RPCGateway is a RPC interface for setup node. type RPCGateway struct { - logger *logging.Logger - reqPK cipher.PubKey - sn *Node - timeout time.Duration -} + Metrics metrics.Recorder -// NewRPCGateway returns a new RPCGateway. -func NewRPCGateway(reqPK cipher.PubKey, sn *Node, timeout time.Duration) *RPCGateway { - return &RPCGateway{ - logger: logging.MustGetLogger(fmt.Sprintf("setup-gateway (%s)", reqPK)), - reqPK: reqPK, - sn: sn, - timeout: timeout, - } + Ctx context.Context + Conn net.Conn + ReqPK cipher.PubKey + Dialer snet.Dialer + Timeout time.Duration } // DialRouteGroup dials RouteGroups for route and rules. func (g *RPCGateway) DialRouteGroup(route routing.BidirectionalRoute, rules *routing.EdgeRules) (err error) { - startTime := time.Now() - - defer func() { - g.sn.metrics.Record(time.Since(startTime), err != nil) - }() + log := logging.MustGetLogger("request:" + g.ReqPK.String()) - g.logger.Infof("Received RPC DialRouteGroup request") + startTime := time.Now() + defer func() { g.Metrics.Record(time.Since(startTime), err != nil) }() - ctx, cancel := context.WithTimeout(context.Background(), g.timeout) + ctx, cancel := context.WithTimeout(g.Ctx, g.Timeout) defer cancel() + go func() { + if <-ctx.Done(); ctx.Err() == context.DeadlineExceeded { + log.WithError(ctx.Err()). + WithField("close_error", g.Conn.Close()). + Warn("Closed underlying connection because deadline was exceeded.") + } + }() - initRules, err := g.sn.handleDialRouteGroup(ctx, route) + initRules, err := CreateRouteGroup(ctx, g.Dialer, route) if err != nil { return err } // Confirm routes with initiating visor. *rules = initRules - return nil } diff --git a/pkg/setup/rules_map.go b/pkg/setup/rules_map.go new file mode 100644 index 000000000..24cee045c --- /dev/null +++ b/pkg/setup/rules_map.go @@ -0,0 +1,33 @@ +package setup + +import ( + "encoding/json" + + "github.com/SkycoinProject/dmsg/cipher" + + "github.com/SkycoinProject/skywire-mainnet/pkg/routing" +) + +// RulesMap associates a slice of rules to a visor's public key. +type RulesMap map[cipher.PubKey][]routing.Rule + +// String implements fmt.Stringer +func (rm RulesMap) String() string { + out := make(map[cipher.PubKey][]string, len(rm)) + + for pk, rules := range rm { + str := make([]string, len(rules)) + for i, rule := range rules { + str[i] = rule.String() + } + + out[pk] = str + } + + jb, err := json.MarshalIndent(out, "", "\t") + if err != nil { + panic(err) + } + + return string(jb) +} diff --git a/pkg/setup/testing_test.go b/pkg/setup/testing_test.go new file mode 100644 index 000000000..d3b7a542d --- /dev/null +++ b/pkg/setup/testing_test.go @@ -0,0 +1,131 @@ +package setup + +import ( + "context" + "fmt" + "net" + "net/rpc" + "sync/atomic" + "testing" + "time" + + "github.com/SkycoinProject/dmsg" + "github.com/SkycoinProject/dmsg/cipher" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/SkycoinProject/skywire-mainnet/pkg/router/routerclient" + "github.com/SkycoinProject/skywire-mainnet/pkg/routing" + "github.com/SkycoinProject/skywire-mainnet/pkg/snet" +) + +// creates a mock dialer +func newMockDialer(t *testing.T, gateways map[cipher.PubKey]interface{}) snet.Dialer { + newRPCConn := func(gw interface{}) net.Conn { + connC, connS := net.Pipe() + t.Cleanup(func() { + assert.NoError(t, connC.Close()) + assert.NoError(t, connS.Close()) + }) + + rpcS := rpc.NewServer() + require.NoError(t, rpcS.RegisterName(routerclient.RPCName, gw)) + go rpcS.ServeConn(connS) + + return connC + } + + if gateways == nil { + conn := newRPCConn(new(mockGatewayForDialer)) + dialer := new(snet.MockDialer) + dialer.On("Dial", mock.Anything, mock.Anything, mock.Anything).Return(conn, nil) + return dialer + } + + dialer := make(mockDialer, len(gateways)) + for pk, gw := range gateways { + dialer[pk] = newRPCConn(gw) + } + return dialer +} + +type mockDialer map[cipher.PubKey]net.Conn + +func (d mockDialer) Type() string { return dmsg.Type } + +func (d mockDialer) Dial(_ context.Context, remote cipher.PubKey, _ uint16) (net.Conn, error) { + conn, ok := d[remote] + if !ok { + return nil, fmt.Errorf("cannot dial to given pk %s", remote) + } + return conn, nil +} + +// mockGatewayForDialer is the default mock router.RPCGateway for newMockDialer. +// It reserves route IDs sequentially for each .ReserveIDs call. +// If hangDuration is > 0, calling .ReserveIDS would hang for the given duration before returning. +type mockGatewayForDialer struct { + hangDuration time.Duration + nextID uint32 +} + +func (gw *mockGatewayForDialer) ReserveIDs(n uint8, routeIDs *[]routing.RouteID) error { + if gw.hangDuration != 0 { + time.Sleep(gw.hangDuration) + } + + out := make([]routing.RouteID, n) + for i := 0; i < int(n); i++ { + out[i] = routing.RouteID(atomic.AddUint32(&gw.nextID, 1)) + } + *routeIDs = out + return nil +} + +// create a mock id reserver +func newMockReserver(t *testing.T, gateways map[cipher.PubKey]interface{}) IDReserver { + rtIDR := new(MockIDReserver) + + handlePK := func(pk, gw interface{}) { + connC, connS := net.Pipe() + t.Cleanup(func() { + assert.NoError(t, connC.Close()) + assert.NoError(t, connS.Close()) + }) + + rpcS := rpc.NewServer() + require.NoError(t, rpcS.RegisterName(routerclient.RPCName, gw)) + go rpcS.ServeConn(connS) + + pkRaw, _ := pk.(cipher.PubKey) + rc := routerclient.NewClientFromRaw(connC, pkRaw) + rtIDR.On("Client", pk).Return(rc) + rtIDR.On("PopID", mock.Anything).Return(routing.RouteID(1), true) + } + + if gateways == nil { + handlePK(mock.Anything, new(mockGatewayForReserver)) + } else { + for pk, gw := range gateways { + handlePK(pk, gw) + } + } + + return rtIDR +} + +// mockGatewayForReserver is the default mock router.RPCGateway for newMockReserver. +// It pretends to successfully trigger .AddIntermediaryRules. +// If handDuration is set, calling .ReserveIDs should hang for given duration before returning +type mockGatewayForReserver struct { + hangDuration time.Duration +} + +func (gw *mockGatewayForReserver) AddIntermediaryRules(_ []routing.Rule, ok *bool) error { + if gw.hangDuration > 0 { + time.Sleep(gw.hangDuration) + } + *ok = true + return nil +} diff --git a/pkg/snet/dialer.go b/pkg/snet/dialer.go new file mode 100644 index 000000000..66d0c6210 --- /dev/null +++ b/pkg/snet/dialer.go @@ -0,0 +1,16 @@ +package snet + +import ( + "context" + "net" + + "github.com/SkycoinProject/dmsg/cipher" +) + +//go:generate mockery -name Dialer -case underscore -inpkg + +// Dialer is an entity that can be dialed and asked for its type. +type Dialer interface { + Dial(ctx context.Context, remote cipher.PubKey, port uint16) (net.Conn, error) + Type() string +} diff --git a/pkg/snet/mock_dialer.go b/pkg/snet/mock_dialer.go new file mode 100644 index 000000000..5fde908bf --- /dev/null +++ b/pkg/snet/mock_dialer.go @@ -0,0 +1,53 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package snet + +import ( + context "context" + net "net" + + cipher "github.com/SkycoinProject/dmsg/cipher" + mock "github.com/stretchr/testify/mock" +) + +// MockDialer is an autogenerated mock type for the Dialer type +type MockDialer struct { + mock.Mock +} + +// Dial provides a mock function with given fields: ctx, remote, port +func (_m *MockDialer) Dial(ctx context.Context, remote cipher.PubKey, port uint16) (net.Conn, error) { + ret := _m.Called(ctx, remote, port) + + var r0 net.Conn + if rf, ok := ret.Get(0).(func(context.Context, cipher.PubKey, uint16) net.Conn); ok { + r0 = rf(ctx, remote, port) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(net.Conn) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, cipher.PubKey, uint16) error); ok { + r1 = rf(ctx, remote, port) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Type provides a mock function with given fields: +func (_m *MockDialer) Type() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} diff --git a/pkg/snet/network.go b/pkg/snet/network.go index 819c28d19..2c5517828 100644 --- a/pkg/snet/network.go +++ b/pkg/snet/network.go @@ -317,12 +317,6 @@ func (n *Network) STcpr() *stcpr.Client { return n.clients.StcprC } // STcpH returns the underlying stcph.Client. func (n *Network) STcpH() *stcph.Client { return n.clients.StcphC } -// Dialer is an entity that can be dialed and asked for its type. -type Dialer interface { - Dial(ctx context.Context, remote cipher.PubKey, port uint16) (net.Conn, error) - Type() string -} - // Dial dials a visor by its public key and returns a connection. func (n *Network) Dial(ctx context.Context, network string, pk cipher.PubKey, port uint16) (*Conn, error) { switch network { diff --git a/pkg/snet/snettest/env.go b/pkg/snet/snettest/env.go index dd8015056..a87d8f4af 100644 --- a/pkg/snet/snettest/env.go +++ b/pkg/snet/snettest/env.go @@ -13,10 +13,7 @@ import ( "github.com/SkycoinProject/skywire-mainnet/pkg/skyenv" "github.com/SkycoinProject/skywire-mainnet/pkg/snet" - "github.com/SkycoinProject/skywire-mainnet/pkg/snet/arclient" "github.com/SkycoinProject/skywire-mainnet/pkg/snet/stcp" - "github.com/SkycoinProject/skywire-mainnet/pkg/snet/stcph" - "github.com/SkycoinProject/skywire-mainnet/pkg/snet/stcpr" ) // KeyPair holds a public/private key pair. @@ -66,7 +63,10 @@ func NewEnv(t *testing.T, keys []KeyPair, networks []string) *Env { table := stcp.NewTable(tableEntries) - var hasDmsg, hasStcp, hasStcpr, hasStcph bool + var hasDmsg, hasStcp bool + + // TODO: https://github.com/SkycoinProject/skywire-mainnet/issues/395 + // var hasStcpr, hasStcph bool for _, network := range networks { switch network { @@ -74,10 +74,12 @@ func NewEnv(t *testing.T, keys []KeyPair, networks []string) *Env { hasDmsg = true case stcp.Type: hasStcp = true - case stcpr.Type: - hasStcpr = true - case stcph.Type: - hasStcph = true + + // TODO: https://github.com/SkycoinProject/skywire-mainnet/issues/395 + // case stcpr.Type: + // hasStcpr = true + // case stcph.Type: + // hasStcph = true } } @@ -94,24 +96,26 @@ func NewEnv(t *testing.T, keys []KeyPair, networks []string) *Env { go clients.DmsgC.Serve() } - addr := "127.0.0.1:" + strconv.Itoa(stcpBasePort+i) - - addressResolver, err := arclient.NewHTTP(skyenv.TestAddressResolverAddr, pairs.PK, pairs.SK) - if err != nil { - panic(err) - } + // TODO: https://github.com/SkycoinProject/skywire-mainnet/issues/395 + // addr := "127.0.0.1:" + strconv.Itoa(stcpBasePort+i) + // + // addressResolver, err := arclient.NewHTTP(skyenv.TestAddressResolverAddr, pairs.PK, pairs.SK) + // if err != nil { + // panic(err) + // } if hasStcp { clients.StcpC = stcp.NewClient(pairs.PK, pairs.SK, table) } - if hasStcpr { - clients.StcprC = stcpr.NewClient(pairs.PK, pairs.SK, addressResolver, addr) - } - - if hasStcph { - clients.StcphC = stcph.NewClient(pairs.PK, pairs.SK, addressResolver) - } + // TODO: https://github.com/SkycoinProject/skywire-mainnet/issues/395 + // if hasStcpr { + // clients.StcprC = stcpr.NewClient(pairs.PK, pairs.SK, addressResolver, addr) + // } + // + // if hasStcph { + // clients.StcphC = stcph.NewClient(pairs.PK, pairs.SK, addressResolver) + // } networkConfigs := snet.NetworkConfigs{ Dmsg: &snet.DmsgConfig{ diff --git a/pkg/visor/rpc.go b/pkg/visor/rpc.go index 67150131e..2302f6aec 100644 --- a/pkg/visor/rpc.go +++ b/pkg/visor/rpc.go @@ -458,7 +458,7 @@ func (r *RPC) RouteGroups(_ *struct{}, out *[]RouteGroupInfo) (err error) { rules := r.visor.router.Rules() for _, rule := range rules { - if rule.Type() != routing.RuleConsume { + if rule.Type() != routing.RuleReverse { continue } diff --git a/pkg/visor/rpc_client.go b/pkg/visor/rpc_client.go index c612655fd..e36eb0156 100644 --- a/pkg/visor/rpc_client.go +++ b/pkg/visor/rpc_client.go @@ -648,7 +648,7 @@ func (mc *mockRPCClient) RouteGroups() ([]RouteGroupInfo, error) { rules := mc.rt.AllRules() for _, rule := range rules { - if rule.Type() != routing.RuleConsume { + if rule.Type() != routing.RuleReverse { continue } diff --git a/pkg/visor/visorconfig/README.md b/pkg/visor/visorconfig/README.md index ba3326e8b..31b13182a 100644 --- a/pkg/visor/visorconfig/README.md +++ b/pkg/visor/visorconfig/README.md @@ -16,17 +16,13 @@ - `restart_check_delay` (string) -# V1UptimeTracker - -- `addr` (string) - - -# V1Dmsgpty +# V1Launcher -- `port` (uint16) -- `authorization_file` (string) -- `cli_network` (string) -- `cli_address` (string) +- `discovery` (*[V1AppDisc](#V1AppDisc)) +- `apps` ([][AppConfig](#AppConfig)) +- `server_addr` (string) +- `bin_path` (string) +- `local_path` (string) # V1Transport @@ -36,13 +32,18 @@ - `trusted_visors` () -# V1Launcher +# V1LogStore -- `discovery` (*[V1AppDisc](#V1AppDisc)) -- `apps` ([][AppConfig](#AppConfig)) -- `server_addr` (string) -- `bin_path` (string) -- `local_path` (string) +- `type` (string) - Type defines the log store type. Valid values: file, memory. +- `location` (string) + + +# V1Dmsgpty + +- `port` (uint16) +- `authorization_file` (string) +- `cli_network` (string) +- `cli_address` (string) # V1Routing @@ -52,18 +53,25 @@ - `route_finder_timeout` (Duration) -# V1LogStore - -- `type` (string) - Type defines the log store type. Valid values: file, memory. -- `location` (string) - - # V1AppDisc - `update_interval` (Duration) - `proxy_discovery_addr` (string) +# V1UptimeTracker + +- `addr` (string) + + +# AppConfig + +- `name` (string) +- `args` ([]string) +- `auto_start` (bool) +- `port` (Port) + + # STCPConfig - `pk_table` () @@ -74,11 +82,3 @@ - `discovery` (string) - `sessions_count` (int) - - -# AppConfig - -- `name` (string) -- `args` ([]string) -- `auto_start` (bool) -- `port` (Port) diff --git a/pkg/visor/visorconfig/types.go b/pkg/visor/visorconfig/types.go index d938d9250..755c1d480 100644 --- a/pkg/visor/visorconfig/types.go +++ b/pkg/visor/visorconfig/types.go @@ -27,6 +27,11 @@ func (d Duration) MarshalJSON() ([]byte, error) { // UnmarshalJSON implements unmarshal from json func (d *Duration) UnmarshalJSON(b []byte) error { + if len(b) == 0 { + *d = 0 + return nil + } + var v interface{} if err := json.Unmarshal(b, &v); err != nil { return err diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md b/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md index 09a4a35c9..195333e51 100644 --- a/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md +++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md @@ -27,7 +27,6 @@ We thank all the authors who provided code to this library: * Felix Kollmann * Nicolas Perraut -* @dirty49374 ## License diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go index 57f530ae8..ef18d8f97 100644 --- a/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go +++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go @@ -4,6 +4,7 @@ package sequences import ( "syscall" + "unsafe" ) var ( @@ -26,7 +27,7 @@ func EnableVirtualTerminalProcessing(stream syscall.Handle, enable bool) error { mode &^= ENABLE_VIRTUAL_TERMINAL_PROCESSING } - ret, _, err := setConsoleMode.Call(uintptr(stream), uintptr(mode)) + ret, _, err := setConsoleMode.Call(uintptr(unsafe.Pointer(stream)), uintptr(mode)) if ret == 0 { return err } diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml index d4b92663b..9159de03e 100644 --- a/vendor/github.com/pkg/errors/.travis.yml +++ b/vendor/github.com/pkg/errors/.travis.yml @@ -1,15 +1,10 @@ language: go go_import_path: github.com/pkg/errors go: - - 1.4.x - - 1.5.x - - 1.6.x - - 1.7.x - - 1.8.x - - 1.9.x - - 1.10.x - 1.11.x + - 1.12.x + - 1.13.x - tip script: - - go test -v ./... + - make check diff --git a/vendor/github.com/pkg/errors/Makefile b/vendor/github.com/pkg/errors/Makefile new file mode 100644 index 000000000..ce9d7cded --- /dev/null +++ b/vendor/github.com/pkg/errors/Makefile @@ -0,0 +1,44 @@ +PKGS := github.com/pkg/errors +SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS)) +GO := go + +check: test vet gofmt misspell unconvert staticcheck ineffassign unparam + +test: + $(GO) test $(PKGS) + +vet: | test + $(GO) vet $(PKGS) + +staticcheck: + $(GO) get honnef.co/go/tools/cmd/staticcheck + staticcheck -checks all $(PKGS) + +misspell: + $(GO) get github.com/client9/misspell/cmd/misspell + misspell \ + -locale GB \ + -error \ + *.md *.go + +unconvert: + $(GO) get github.com/mdempsky/unconvert + unconvert -v $(PKGS) + +ineffassign: + $(GO) get github.com/gordonklaus/ineffassign + find $(SRCDIRS) -name '*.go' | xargs ineffassign + +pedantic: check errcheck + +unparam: + $(GO) get mvdan.cc/unparam + unparam ./... + +errcheck: + $(GO) get github.com/kisielk/errcheck + errcheck $(PKGS) + +gofmt: + @echo Checking code is gofmted + @test -z "$(shell gofmt -s -l -d -e $(SRCDIRS) | tee /dev/stderr)" diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md index 6483ba2af..54dfdcb12 100644 --- a/vendor/github.com/pkg/errors/README.md +++ b/vendor/github.com/pkg/errors/README.md @@ -41,11 +41,18 @@ default: [Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). +## Roadmap + +With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows: + +- 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible) +- 1.0. Final release. + ## Contributing -We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. +Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports. -Before proposing a change, please discuss your change by raising an issue. +Before sending a PR, please discuss your change by raising an issue. ## License diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go index 7421f326f..161aea258 100644 --- a/vendor/github.com/pkg/errors/errors.go +++ b/vendor/github.com/pkg/errors/errors.go @@ -82,7 +82,7 @@ // // if err, ok := err.(stackTracer); ok { // for _, f := range err.StackTrace() { -// fmt.Printf("%+s:%d", f) +// fmt.Printf("%+s:%d\n", f, f) // } // } // @@ -159,6 +159,9 @@ type withStack struct { func (w *withStack) Cause() error { return w.error } +// Unwrap provides compatibility for Go 1.13 error chains. +func (w *withStack) Unwrap() error { return w.error } + func (w *withStack) Format(s fmt.State, verb rune) { switch verb { case 'v': @@ -241,6 +244,9 @@ type withMessage struct { func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } func (w *withMessage) Cause() error { return w.cause } +// Unwrap provides compatibility for Go 1.13 error chains. +func (w *withMessage) Unwrap() error { return w.cause } + func (w *withMessage) Format(s fmt.State, verb rune) { switch verb { case 'v': diff --git a/vendor/github.com/pkg/errors/go113.go b/vendor/github.com/pkg/errors/go113.go new file mode 100644 index 000000000..be0d10d0c --- /dev/null +++ b/vendor/github.com/pkg/errors/go113.go @@ -0,0 +1,38 @@ +// +build go1.13 + +package errors + +import ( + stderrors "errors" +) + +// Is reports whether any error in err's chain matches target. +// +// The chain consists of err itself followed by the sequence of errors obtained by +// repeatedly calling Unwrap. +// +// An error is considered to match a target if it is equal to that target or if +// it implements a method Is(error) bool such that Is(target) returns true. +func Is(err, target error) bool { return stderrors.Is(err, target) } + +// As finds the first error in err's chain that matches target, and if so, sets +// target to that error value and returns true. +// +// The chain consists of err itself followed by the sequence of errors obtained by +// repeatedly calling Unwrap. +// +// An error matches target if the error's concrete value is assignable to the value +// pointed to by target, or if the error has a method As(interface{}) bool such that +// As(target) returns true. In the latter case, the As method is responsible for +// setting target. +// +// As will panic if target is not a non-nil pointer to either a type that implements +// error, or to any interface type. As returns false if err is nil. +func As(err error, target interface{}) bool { return stderrors.As(err, target) } + +// Unwrap returns the result of calling the Unwrap method on err, if err's +// type contains an Unwrap method returning error. +// Otherwise, Unwrap returns nil. +func Unwrap(err error) error { + return stderrors.Unwrap(err) +} diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go index 2874a048c..779a8348f 100644 --- a/vendor/github.com/pkg/errors/stack.go +++ b/vendor/github.com/pkg/errors/stack.go @@ -5,10 +5,13 @@ import ( "io" "path" "runtime" + "strconv" "strings" ) // Frame represents a program counter inside a stack frame. +// For historical reasons if Frame is interpreted as a uintptr +// its value represents the program counter + 1. type Frame uintptr // pc returns the program counter for this frame; @@ -37,6 +40,15 @@ func (f Frame) line() int { return line } +// name returns the name of this function, if known. +func (f Frame) name() string { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return "unknown" + } + return fn.Name() +} + // Format formats the frame according to the fmt.Formatter interface. // // %s source file @@ -54,22 +66,16 @@ func (f Frame) Format(s fmt.State, verb rune) { case 's': switch { case s.Flag('+'): - pc := f.pc() - fn := runtime.FuncForPC(pc) - if fn == nil { - io.WriteString(s, "unknown") - } else { - file, _ := fn.FileLine(pc) - fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file) - } + io.WriteString(s, f.name()) + io.WriteString(s, "\n\t") + io.WriteString(s, f.file()) default: io.WriteString(s, path.Base(f.file())) } case 'd': - fmt.Fprintf(s, "%d", f.line()) + io.WriteString(s, strconv.Itoa(f.line())) case 'n': - name := runtime.FuncForPC(f.pc()).Name() - io.WriteString(s, funcname(name)) + io.WriteString(s, funcname(f.name())) case 'v': f.Format(s, 's') io.WriteString(s, ":") @@ -77,6 +83,16 @@ func (f Frame) Format(s fmt.State, verb rune) { } } +// MarshalText formats a stacktrace Frame as a text string. The output is the +// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs. +func (f Frame) MarshalText() ([]byte, error) { + name := f.name() + if name == "unknown" { + return []byte(name), nil + } + return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil +} + // StackTrace is stack of Frames from innermost (newest) to outermost (oldest). type StackTrace []Frame @@ -94,16 +110,30 @@ func (st StackTrace) Format(s fmt.State, verb rune) { switch { case s.Flag('+'): for _, f := range st { - fmt.Fprintf(s, "\n%+v", f) + io.WriteString(s, "\n") + f.Format(s, verb) } case s.Flag('#'): fmt.Fprintf(s, "%#v", []Frame(st)) default: - fmt.Fprintf(s, "%v", []Frame(st)) + st.formatSlice(s, verb) } case 's': - fmt.Fprintf(s, "%s", []Frame(st)) + st.formatSlice(s, verb) + } +} + +// formatSlice will format this StackTrace into the given buffer as a slice of +// Frame, only valid when called with '%s' or '%v'. +func (st StackTrace) formatSlice(s fmt.State, verb rune) { + io.WriteString(s, "[") + for i, f := range st { + if i > 0 { + io.WriteString(s, " ") + } + f.Format(s, verb) } + io.WriteString(s, "]") } // stack represents a stack of program counters. diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b.go b/vendor/golang.org/x/crypto/blake2b/blake2b.go index d2e98d429..c160e1a4e 100644 --- a/vendor/golang.org/x/crypto/blake2b/blake2b.go +++ b/vendor/golang.org/x/crypto/blake2b/blake2b.go @@ -5,8 +5,6 @@ // Package blake2b implements the BLAKE2b hash algorithm defined by RFC 7693 // and the extendable output function (XOF) BLAKE2Xb. // -// BLAKE2b is optimized for 64-bit platforms—including NEON-enabled ARMs—and -// produces digests of any size between 1 and 64 bytes. // For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf // and for BLAKE2Xb see https://blake2.net/blake2x.pdf // diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s.go b/vendor/golang.org/x/crypto/blake2s/blake2s.go index e3f46aab3..5fb4a9ecd 100644 --- a/vendor/golang.org/x/crypto/blake2s/blake2s.go +++ b/vendor/golang.org/x/crypto/blake2s/blake2s.go @@ -5,8 +5,6 @@ // Package blake2s implements the BLAKE2s hash algorithm defined by RFC 7693 // and the extendable output function (XOF) BLAKE2Xs. // -// BLAKE2s is optimized for 8- to 32-bit platforms and produces digests of any -// size between 1 and 32 bytes. // For a detailed specification of BLAKE2s see https://blake2.net/blake2.pdf // and for BLAKE2Xs see https://blake2.net/blake2x.pdf // diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_generic.go b/vendor/golang.org/x/crypto/chacha20/chacha_generic.go index a2ecf5c32..7c498e90d 100644 --- a/vendor/golang.org/x/crypto/chacha20/chacha_generic.go +++ b/vendor/golang.org/x/crypto/chacha20/chacha_generic.go @@ -42,14 +42,10 @@ type Cipher struct { // The last len bytes of buf are leftover key stream bytes from the previous // XORKeyStream invocation. The size of buf depends on how many blocks are - // computed at a time by xorKeyStreamBlocks. + // computed at a time. buf [bufSize]byte len int - // overflow is set when the counter overflowed, no more blocks can be - // generated, and the next XORKeyStream call should panic. - overflow bool - // The counter-independent results of the first round are cached after they // are computed the first time. precompDone bool @@ -93,7 +89,6 @@ func newUnauthenticatedCipher(c *Cipher, key, nonce []byte) (*Cipher, error) { return nil, errors.New("chacha20: wrong nonce size") } - key, nonce = key[:KeySize], nonce[:NonceSize] // bounds check elimination hint c.key = [8]uint32{ binary.LittleEndian.Uint32(key[0:4]), binary.LittleEndian.Uint32(key[4:8]), @@ -144,18 +139,15 @@ func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) { // SetCounter sets the Cipher counter. The next invocation of XORKeyStream will // behave as if (64 * counter) bytes had been encrypted so far. // -// To prevent accidental counter reuse, SetCounter panics if counter is less -// than the current value. -// -// Note that the execution time of XORKeyStream is not independent of the -// counter value. +// To prevent accidental counter reuse, SetCounter panics if counter is +// less than the current value. func (s *Cipher) SetCounter(counter uint32) { // Internally, s may buffer multiple blocks, which complicates this // implementation slightly. When checking whether the counter has rolled // back, we must use both s.counter and s.len to determine how many blocks // we have already output. outputCounter := s.counter - uint32(s.len)/blockSize - if s.overflow || counter < outputCounter { + if counter < outputCounter { panic("chacha20: SetCounter attempted to rollback counter") } @@ -204,52 +196,34 @@ func (s *Cipher) XORKeyStream(dst, src []byte) { dst[i] = src[i] ^ b } s.len -= len(keyStream) - dst, src = dst[len(keyStream):], src[len(keyStream):] - } - if len(src) == 0 { - return + src = src[len(keyStream):] + dst = dst[len(keyStream):] } - // If we'd need to let the counter overflow and keep generating output, - // panic immediately. If instead we'd only reach the last block, remember - // not to generate any more output after the buffer is drained. - numBlocks := (uint64(len(src)) + blockSize - 1) / blockSize - if s.overflow || uint64(s.counter)+numBlocks > 1<<32 { + const blocksPerBuf = bufSize / blockSize + numBufs := (uint64(len(src)) + bufSize - 1) / bufSize + if uint64(s.counter)+numBufs*blocksPerBuf >= 1<<32 { panic("chacha20: counter overflow") - } else if uint64(s.counter)+numBlocks == 1<<32 { - s.overflow = true } // xorKeyStreamBlocks implementations expect input lengths that are a // multiple of bufSize. Platform-specific ones process multiple blocks at a // time, so have bufSizes that are a multiple of blockSize. - full := len(src) - len(src)%bufSize + rem := len(src) % bufSize + full := len(src) - rem + if full > 0 { s.xorKeyStreamBlocks(dst[:full], src[:full]) } - dst, src = dst[full:], src[full:] - - // If using a multi-block xorKeyStreamBlocks would overflow, use the generic - // one that does one block at a time. - const blocksPerBuf = bufSize / blockSize - if uint64(s.counter)+blocksPerBuf > 1<<32 { - s.buf = [bufSize]byte{} - numBlocks := (len(src) + blockSize - 1) / blockSize - buf := s.buf[bufSize-numBlocks*blockSize:] - copy(buf, src) - s.xorKeyStreamBlocksGeneric(buf, buf) - s.len = len(buf) - copy(dst, buf) - return - } // If we have a partial (multi-)block, pad it for xorKeyStreamBlocks, and // keep the leftover keystream for the next XORKeyStream invocation. - if len(src) > 0 { + if rem > 0 { s.buf = [bufSize]byte{} - copy(s.buf[:], src) + copy(s.buf[:], src[full:]) s.xorKeyStreamBlocks(s.buf[:], s.buf[:]) - s.len = bufSize - copy(dst, s.buf[:]) + s.len = bufSize - copy(dst[full:], s.buf[:]) } } @@ -286,9 +260,7 @@ func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) { s.precompDone = true } - // A condition of len(src) > 0 would be sufficient, but this also - // acts as a bounds check elimination hint. - for len(src) >= 64 && len(dst) >= 64 { + for i := 0; i < len(src); i += blockSize { // The remainder of the first column round. fcr0, fcr4, fcr8, fcr12 := quarterRound(c0, c4, c8, s.counter) @@ -313,28 +285,49 @@ func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) { x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) } - // Add back the initial state to generate the key stream, then - // XOR the key stream with the source and write out the result. - addXor(dst[0:4], src[0:4], x0, c0) - addXor(dst[4:8], src[4:8], x1, c1) - addXor(dst[8:12], src[8:12], x2, c2) - addXor(dst[12:16], src[12:16], x3, c3) - addXor(dst[16:20], src[16:20], x4, c4) - addXor(dst[20:24], src[20:24], x5, c5) - addXor(dst[24:28], src[24:28], x6, c6) - addXor(dst[28:32], src[28:32], x7, c7) - addXor(dst[32:36], src[32:36], x8, c8) - addXor(dst[36:40], src[36:40], x9, c9) - addXor(dst[40:44], src[40:44], x10, c10) - addXor(dst[44:48], src[44:48], x11, c11) - addXor(dst[48:52], src[48:52], x12, s.counter) - addXor(dst[52:56], src[52:56], x13, c13) - addXor(dst[56:60], src[56:60], x14, c14) - addXor(dst[60:64], src[60:64], x15, c15) + // Finally, add back the initial state to generate the key stream. + x0 += c0 + x1 += c1 + x2 += c2 + x3 += c3 + x4 += c4 + x5 += c5 + x6 += c6 + x7 += c7 + x8 += c8 + x9 += c9 + x10 += c10 + x11 += c11 + x12 += s.counter + x13 += c13 + x14 += c14 + x15 += c15 s.counter += 1 + if s.counter == 0 { + panic("chacha20: internal error: counter overflow") + } - src, dst = src[blockSize:], dst[blockSize:] + in, out := src[i:], dst[i:] + in, out = in[:blockSize], out[:blockSize] // bounds check elimination hint + + // XOR the key stream with the source and write out the result. + xor(out[0:], in[0:], x0) + xor(out[4:], in[4:], x1) + xor(out[8:], in[8:], x2) + xor(out[12:], in[12:], x3) + xor(out[16:], in[16:], x4) + xor(out[20:], in[20:], x5) + xor(out[24:], in[24:], x6) + xor(out[28:], in[28:], x7) + xor(out[32:], in[32:], x8) + xor(out[36:], in[36:], x9) + xor(out[40:], in[40:], x10) + xor(out[44:], in[44:], x11) + xor(out[48:], in[48:], x12) + xor(out[52:], in[52:], x13) + xor(out[56:], in[56:], x14) + xor(out[60:], in[60:], x15) } } diff --git a/vendor/golang.org/x/crypto/chacha20/xor.go b/vendor/golang.org/x/crypto/chacha20/xor.go index c2d04851e..0110c9865 100644 --- a/vendor/golang.org/x/crypto/chacha20/xor.go +++ b/vendor/golang.org/x/crypto/chacha20/xor.go @@ -13,10 +13,10 @@ const unaligned = runtime.GOARCH == "386" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x" -// addXor reads a little endian uint32 from src, XORs it with (a + b) and +// xor reads a little endian uint32 from src, XORs it with u and // places the result in little endian byte order in dst. -func addXor(dst, src []byte, a, b uint32) { - _, _ = src[3], dst[3] // bounds check elimination hint +func xor(dst, src []byte, u uint32) { + _, _ = src[3], dst[3] // eliminate bounds checks if unaligned { // The compiler should optimize this code into // 32-bit unaligned little endian loads and stores. @@ -27,16 +27,15 @@ func addXor(dst, src []byte, a, b uint32) { v |= uint32(src[1]) << 8 v |= uint32(src[2]) << 16 v |= uint32(src[3]) << 24 - v ^= a + b + v ^= u dst[0] = byte(v) dst[1] = byte(v >> 8) dst[2] = byte(v >> 16) dst[3] = byte(v >> 24) } else { - a += b - dst[0] = src[0] ^ byte(a) - dst[1] = src[1] ^ byte(a>>8) - dst[2] = src[2] ^ byte(a>>16) - dst[3] = src[3] ^ byte(a>>24) + dst[0] = src[0] ^ byte(u) + dst[1] = src[1] ^ byte(u>>8) + dst[2] = src[2] ^ byte(u>>16) + dst[3] = src[3] ^ byte(u>>24) } } diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go index fe191d395..91b38568c 100644 --- a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go @@ -12,64 +12,56 @@ import ( "golang.org/x/crypto/poly1305" ) -func writeWithPadding(p *poly1305.MAC, b []byte) { - p.Write(b) - if rem := len(b) % 16; rem != 0 { - var buf [16]byte - padLen := 16 - rem - p.Write(buf[:padLen]) - } -} - -func writeUint64(p *poly1305.MAC, n int) { - var buf [8]byte - binary.LittleEndian.PutUint64(buf[:], uint64(n)) - p.Write(buf[:]) +func roundTo16(n int) int { + return 16 * ((n + 15) / 16) } func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte { ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize) - ciphertext, tag := out[:len(plaintext)], out[len(plaintext):] if subtle.InexactOverlap(out, plaintext) { panic("chacha20poly1305: invalid buffer overlap") } - var polyKey [32]byte + var polyKey, discardBuf [32]byte s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce) s.XORKeyStream(polyKey[:], polyKey[:]) - s.SetCounter(1) // set the counter to 1, skipping 32 bytes - s.XORKeyStream(ciphertext, plaintext) + s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes + s.XORKeyStream(out, plaintext) + + polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(plaintext))+8+8) + copy(polyInput, additionalData) + copy(polyInput[roundTo16(len(additionalData)):], out[:len(plaintext)]) + binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData))) + binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(plaintext))) - p := poly1305.New(&polyKey) - writeWithPadding(p, additionalData) - writeWithPadding(p, ciphertext) - writeUint64(p, len(additionalData)) - writeUint64(p, len(plaintext)) - p.Sum(tag[:0]) + var tag [poly1305.TagSize]byte + poly1305.Sum(&tag, polyInput, &polyKey) + copy(out[len(plaintext):], tag[:]) return ret } func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { - tag := ciphertext[len(ciphertext)-16:] + var tag [poly1305.TagSize]byte + copy(tag[:], ciphertext[len(ciphertext)-16:]) ciphertext = ciphertext[:len(ciphertext)-16] - var polyKey [32]byte + var polyKey, discardBuf [32]byte s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce) s.XORKeyStream(polyKey[:], polyKey[:]) - s.SetCounter(1) // set the counter to 1, skipping 32 bytes + s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes - p := poly1305.New(&polyKey) - writeWithPadding(p, additionalData) - writeWithPadding(p, ciphertext) - writeUint64(p, len(additionalData)) - writeUint64(p, len(ciphertext)) + polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(ciphertext))+8+8) + copy(polyInput, additionalData) + copy(polyInput[roundTo16(len(additionalData)):], ciphertext) + binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData))) + binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(ciphertext))) ret, out := sliceForAppend(dst, len(ciphertext)) if subtle.InexactOverlap(out, ciphertext) { panic("chacha20poly1305: invalid buffer overlap") } - if !p.Verify(tag) { + if !poly1305.Verify(&tag, polyInput, &polyKey) { for i := range out { out[i] = 0 } diff --git a/vendor/golang.org/x/crypto/poly1305/mac_noasm.go b/vendor/golang.org/x/crypto/poly1305/mac_noasm.go index 347c8b15f..b0c2cd056 100644 --- a/vendor/golang.org/x/crypto/poly1305/mac_noasm.go +++ b/vendor/golang.org/x/crypto/poly1305/mac_noasm.go @@ -7,3 +7,5 @@ package poly1305 type mac struct{ macGeneric } + +func newMAC(key *[32]byte) mac { return mac{newMACGeneric(key)} } diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305.go b/vendor/golang.org/x/crypto/poly1305/poly1305.go index 3c75c2a67..066159b79 100644 --- a/vendor/golang.org/x/crypto/poly1305/poly1305.go +++ b/vendor/golang.org/x/crypto/poly1305/poly1305.go @@ -46,9 +46,10 @@ func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { // two different messages with the same key allows an attacker // to forge messages at will. func New(key *[32]byte) *MAC { - m := &MAC{} - initialize(key, &m.macState) - return m + return &MAC{ + mac: newMAC(key), + finalized: false, + } } // MAC is an io.Writer computing an authentication tag @@ -57,7 +58,7 @@ func New(key *[32]byte) *MAC { // MAC cannot be used like common hash.Hash implementations, // because using a poly1305 key twice breaks its security. // Therefore writing data to a running MAC after calling -// Sum or Verify causes it to panic. +// Sum causes it to panic. type MAC struct { mac // platform-dependent implementation @@ -70,10 +71,10 @@ func (h *MAC) Size() int { return TagSize } // Write adds more data to the running message authentication code. // It never returns an error. // -// It must not be called after the first call of Sum or Verify. +// It must not be called after the first call of Sum. func (h *MAC) Write(p []byte) (n int, err error) { if h.finalized { - panic("poly1305: write to MAC after Sum or Verify") + panic("poly1305: write to MAC after Sum") } return h.mac.Write(p) } @@ -86,12 +87,3 @@ func (h *MAC) Sum(b []byte) []byte { h.finalized = true return append(b, mac[:]...) } - -// Verify returns whether the authenticator of all data written to -// the message authentication code matches the expected value. -func (h *MAC) Verify(expected []byte) bool { - var mac [TagSize]byte - h.mac.Sum(&mac) - h.finalized = true - return subtle.ConstantTimeCompare(expected, mac[:]) == 1 -} diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.go b/vendor/golang.org/x/crypto/poly1305/sum_amd64.go index 99e5a1d50..35b9e38c9 100644 --- a/vendor/golang.org/x/crypto/poly1305/sum_amd64.go +++ b/vendor/golang.org/x/crypto/poly1305/sum_amd64.go @@ -9,6 +9,17 @@ package poly1305 //go:noescape func update(state *macState, msg []byte) +func sum(out *[16]byte, m []byte, key *[32]byte) { + h := newMAC(key) + h.Write(m) + h.Sum(out) +} + +func newMAC(key *[32]byte) (h mac) { + initialize(key, &h.r, &h.s) + return +} + // mac is a wrapper for macGeneric that redirects calls that would have gone to // updateGeneric to update. // diff --git a/vendor/golang.org/x/crypto/poly1305/sum_generic.go b/vendor/golang.org/x/crypto/poly1305/sum_generic.go index c77ff179d..1187eab78 100644 --- a/vendor/golang.org/x/crypto/poly1305/sum_generic.go +++ b/vendor/golang.org/x/crypto/poly1305/sum_generic.go @@ -31,10 +31,9 @@ func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) { h.Sum(out) } -func newMACGeneric(key *[32]byte) macGeneric { - m := macGeneric{} - initialize(key, &m.macState) - return m +func newMACGeneric(key *[32]byte) (h macGeneric) { + initialize(key, &h.r, &h.s) + return } // macState holds numbers in saturated 64-bit little-endian limbs. That is, @@ -98,12 +97,11 @@ const ( rMask1 = 0x0FFFFFFC0FFFFFFC ) -// initialize loads the 256-bit key into the two 128-bit secret values r and s. -func initialize(key *[32]byte, m *macState) { - m.r[0] = binary.LittleEndian.Uint64(key[0:8]) & rMask0 - m.r[1] = binary.LittleEndian.Uint64(key[8:16]) & rMask1 - m.s[0] = binary.LittleEndian.Uint64(key[16:24]) - m.s[1] = binary.LittleEndian.Uint64(key[24:32]) +func initialize(key *[32]byte, r, s *[2]uint64) { + r[0] = binary.LittleEndian.Uint64(key[0:8]) & rMask0 + r[1] = binary.LittleEndian.Uint64(key[8:16]) & rMask1 + s[0] = binary.LittleEndian.Uint64(key[16:24]) + s[1] = binary.LittleEndian.Uint64(key[24:32]) } // uint128 holds a 128-bit number as two 64-bit limbs, for use with the diff --git a/vendor/golang.org/x/crypto/poly1305/sum_noasm.go b/vendor/golang.org/x/crypto/poly1305/sum_noasm.go index 2b55a29c5..2e3ae34c7 100644 --- a/vendor/golang.org/x/crypto/poly1305/sum_noasm.go +++ b/vendor/golang.org/x/crypto/poly1305/sum_noasm.go @@ -2,17 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// At this point only s390x has an assembly implementation of sum. All other -// platforms have assembly implementations of mac, and just define sum as using -// that through New. Once s390x is ported, this file can be deleted and the body -// of sum moved into Sum. - -// +build !go1.11 !s390x gccgo purego +// +build s390x,!go1.11 !amd64,!s390x,!ppc64le gccgo purego package poly1305 func sum(out *[TagSize]byte, msg []byte, key *[32]byte) { - h := New(key) + h := newMAC(key) h.Write(msg) - h.Sum(out[:0]) + h.Sum(out) } diff --git a/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go b/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go index 2e7a120b1..92597bb8c 100644 --- a/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go +++ b/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go @@ -9,6 +9,17 @@ package poly1305 //go:noescape func update(state *macState, msg []byte) +func sum(out *[16]byte, m []byte, key *[32]byte) { + h := newMAC(key) + h.Write(m) + h.Sum(out) +} + +func newMAC(key *[32]byte) (h mac) { + initialize(key, &h.r, &h.s) + return +} + // mac is a wrapper for macGeneric that redirects calls that would have gone to // updateGeneric to update. // diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go index 2ffb97bfb..d1b4fca3a 100644 --- a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go +++ b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go @@ -113,7 +113,6 @@ func NewTerminal(c io.ReadWriter, prompt string) *Terminal { } const ( - keyCtrlC = 3 keyCtrlD = 4 keyCtrlU = 21 keyEnter = '\r' @@ -152,12 +151,8 @@ func bytesToKey(b []byte, pasteActive bool) (rune, []byte) { switch b[0] { case 1: // ^A return keyHome, b[1:] - case 2: // ^B - return keyLeft, b[1:] case 5: // ^E return keyEnd, b[1:] - case 6: // ^F - return keyRight, b[1:] case 8: // ^H return keyBackspace, b[1:] case 11: // ^K @@ -743,9 +738,6 @@ func (t *Terminal) readLine() (line string, err error) { return "", io.EOF } } - if key == keyCtrlC { - return "", io.EOF - } if key == keyPasteStart { t.pasteActive = true if len(t.line) == 0 { diff --git a/vendor/golang.org/x/sys/unix/README.md b/vendor/golang.org/x/sys/unix/README.md index 579d2d735..ab433ccfb 100644 --- a/vendor/golang.org/x/sys/unix/README.md +++ b/vendor/golang.org/x/sys/unix/README.md @@ -89,7 +89,7 @@ constants. Adding new syscall numbers is mostly done by running the build on a sufficiently new installation of the target OS (or updating the source checkouts for the -new build system). However, depending on the OS, you may need to update the +new build system). However, depending on the OS, you make need to update the parsing in mksysnum. ### mksyscall.go @@ -163,7 +163,7 @@ The merge is performed in the following steps: ## Generated files -### `zerrors_${GOOS}_${GOARCH}.go` +### `zerror_${GOOS}_${GOARCH}.go` A file containing all of the system's generated error numbers, error strings, signal numbers, and constants. Generated by `mkerrors.sh` (see above). diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh index ab09aafcf..bc076cf62 100644 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -200,7 +200,6 @@ struct ltchars { #include #include #include -#include #include #include #include @@ -486,7 +485,6 @@ ccflags="$@" $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || $2 ~ /^MODULE_INIT_/ || $2 !~ "NLA_TYPE_MASK" && - $2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ && $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ || $2 ~ /^SIOC/ || $2 ~ /^TIOC/ || @@ -508,8 +506,7 @@ ccflags="$@" $2 ~ /^CAP_/ || $2 ~ /^ALG_/ || $2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ || - $2 ~ /^FS_IOC_.*(ENCRYPTION|VERITY|GETFLAGS)/ || - $2 ~ /^FS_VERITY_/ || + $2 ~ /^FS_IOC_.*ENCRYPTION/ || $2 ~ /^FSCRYPT_/ || $2 ~ /^GRND_/ || $2 ~ /^RND/ || diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go index 84ff9fa64..807a0b20c 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -25,7 +25,7 @@ func EpollCreate(size int) (fd int, err error) { //sysnb Getegid() (egid int) //sysnb Geteuid() (euid int) //sysnb Getgid() (gid int) -//sysnb getrlimit(resource int, rlim *Rlimit) (err error) +//sysnb Getrlimit(resource int, rlim *Rlimit) (err error) //sysnb Getuid() (uid int) //sys Listen(s int, n int) (err error) //sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 @@ -47,7 +47,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err //sysnb Setregid(rgid int, egid int) (err error) //sysnb Setresgid(rgid int, egid int, sgid int) (err error) //sysnb Setresuid(ruid int, euid int, suid int) (err error) -//sysnb setrlimit(resource int, rlim *Rlimit) (err error) +//sysnb Setrlimit(resource int, rlim *Rlimit) (err error) //sysnb Setreuid(ruid int, euid int) (err error) //sys Shutdown(fd int, how int) (err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) @@ -168,24 +168,6 @@ func Pipe2(p []int, flags int) (err error) { return } -// Getrlimit prefers the prlimit64 system call. See issue 38604. -func Getrlimit(resource int, rlim *Rlimit) error { - err := prlimit(0, resource, nil, rlim) - if err != ENOSYS { - return err - } - return getrlimit(resource, rlim) -} - -// Setrlimit prefers the prlimit64 system call. See issue 38604. -func Setrlimit(resource int, rlim *Rlimit) error { - err := prlimit(0, resource, rlim, nil) - if err != ENOSYS { - return err - } - return setrlimit(resource, rlim) -} - func (r *PtraceRegs) PC() uint64 { return r.Pc } func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc } diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go index 219739407..84c599c52 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -216,7 +216,6 @@ const ( BPF_F_RDONLY = 0x8 BPF_F_RDONLY_PROG = 0x80 BPF_F_RECOMPUTE_CSUM = 0x1 - BPF_F_REPLACE = 0x4 BPF_F_REUSE_STACKID = 0x400 BPF_F_SEQ_NUMBER = 0x8 BPF_F_SKIP_FIELD_MASK = 0xff @@ -390,7 +389,6 @@ const ( CLONE_NEWNET = 0x40000000 CLONE_NEWNS = 0x20000 CLONE_NEWPID = 0x20000000 - CLONE_NEWTIME = 0x80 CLONE_NEWUSER = 0x10000000 CLONE_NEWUTS = 0x4000000 CLONE_PARENT = 0x8000 @@ -673,7 +671,6 @@ const ( FS_IOC_ADD_ENCRYPTION_KEY = 0xc0506617 FS_IOC_GET_ENCRYPTION_KEY_STATUS = 0xc080661a FS_IOC_GET_ENCRYPTION_POLICY_EX = 0xc0096616 - FS_IOC_MEASURE_VERITY = 0xc0046686 FS_IOC_REMOVE_ENCRYPTION_KEY = 0xc0406618 FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS = 0xc0406619 FS_KEY_DESCRIPTOR_SIZE = 0x8 @@ -686,9 +683,6 @@ const ( FS_POLICY_FLAGS_PAD_8 = 0x1 FS_POLICY_FLAGS_PAD_MASK = 0x3 FS_POLICY_FLAGS_VALID = 0xf - FS_VERITY_FL = 0x100000 - FS_VERITY_HASH_ALG_SHA256 = 0x1 - FS_VERITY_HASH_ALG_SHA512 = 0x2 FUTEXFS_SUPER_MAGIC = 0xbad1dea F_ADD_SEALS = 0x409 F_DUPFD = 0x0 @@ -739,7 +733,6 @@ const ( GENL_NAMSIZ = 0x10 GENL_START_ALLOC = 0x13 GENL_UNS_ADMIN_PERM = 0x10 - GRND_INSECURE = 0x4 GRND_NONBLOCK = 0x1 GRND_RANDOM = 0x2 HDIO_DRIVE_CMD = 0x31f @@ -1490,7 +1483,6 @@ const ( PR_GET_FPEMU = 0x9 PR_GET_FPEXC = 0xb PR_GET_FP_MODE = 0x2e - PR_GET_IO_FLUSHER = 0x3a PR_GET_KEEPCAPS = 0x7 PR_GET_NAME = 0x10 PR_GET_NO_NEW_PRIVS = 0x27 @@ -1526,7 +1518,6 @@ const ( PR_SET_FPEMU = 0xa PR_SET_FPEXC = 0xc PR_SET_FP_MODE = 0x2d - PR_SET_IO_FLUSHER = 0x39 PR_SET_KEEPCAPS = 0x8 PR_SET_MM = 0x23 PR_SET_MM_ARG_END = 0x9 @@ -1755,15 +1746,12 @@ const ( RTM_DELRULE = 0x21 RTM_DELTCLASS = 0x29 RTM_DELTFILTER = 0x2d - RTM_DELVLAN = 0x71 RTM_F_CLONED = 0x200 RTM_F_EQUALIZE = 0x400 RTM_F_FIB_MATCH = 0x2000 RTM_F_LOOKUP_TABLE = 0x1000 RTM_F_NOTIFY = 0x100 - RTM_F_OFFLOAD = 0x4000 RTM_F_PREFIX = 0x800 - RTM_F_TRAP = 0x8000 RTM_GETACTION = 0x32 RTM_GETADDR = 0x16 RTM_GETADDRLABEL = 0x4a @@ -1785,8 +1773,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_GETVLAN = 0x72 - RTM_MAX = 0x73 + RTM_MAX = 0x6f RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1801,7 +1788,6 @@ const ( RTM_NEWNETCONF = 0x50 RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 - RTM_NEWNVLAN = 0x70 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 RTM_NEWROUTE = 0x18 @@ -1809,8 +1795,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x19 - RTM_NR_MSGTYPES = 0x64 + RTM_NR_FAMILIES = 0x18 + RTM_NR_MSGTYPES = 0x60 RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -2100,7 +2086,7 @@ const ( TASKSTATS_GENL_NAME = "TASKSTATS" TASKSTATS_GENL_VERSION = 0x1 TASKSTATS_TYPE_MAX = 0x6 - TASKSTATS_VERSION = 0xa + TASKSTATS_VERSION = 0x9 TCIFLUSH = 0x0 TCIOFF = 0x2 TCIOFLUSH = 0x2 @@ -2281,7 +2267,7 @@ const ( VMADDR_CID_ANY = 0xffffffff VMADDR_CID_HOST = 0x2 VMADDR_CID_HYPERVISOR = 0x0 - VMADDR_CID_LOCAL = 0x1 + VMADDR_CID_RESERVED = 0x1 VMADDR_PORT_ANY = 0xffffffff VM_SOCKETS_INVALID_VERSION = 0xffffffff VQUIT = 0x1 @@ -2408,7 +2394,6 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 Z3FOLD_MAGIC = 0x33 - ZONEFS_MAGIC = 0x5a4f4653 ZSMALLOC_MAGIC = 0x58295829 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 028c9d878..0876cf92f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -73,8 +73,6 @@ const ( FFDLY = 0x8000 FLUSHO = 0x1000 FP_XSTATE_MAGIC2 = 0x46505845 - FS_IOC_ENABLE_VERITY = 0x40806685 - FS_IOC_GETFLAGS = 0x80046601 FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index 005970f71..d5be2e837 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -73,8 +73,6 @@ const ( FFDLY = 0x8000 FLUSHO = 0x1000 FP_XSTATE_MAGIC2 = 0x46505845 - FS_IOC_ENABLE_VERITY = 0x40806685 - FS_IOC_GETFLAGS = 0x80086601 FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 0541f36ee..fbeef8325 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -72,8 +72,6 @@ const ( FF1 = 0x8000 FFDLY = 0x8000 FLUSHO = 0x1000 - FS_IOC_ENABLE_VERITY = 0x40806685 - FS_IOC_GETFLAGS = 0x80046601 FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 9ee8d1bc8..06daa50eb 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -75,8 +75,6 @@ const ( FFDLY = 0x8000 FLUSHO = 0x1000 FPSIMD_MAGIC = 0x46508001 - FS_IOC_ENABLE_VERITY = 0x40806685 - FS_IOC_GETFLAGS = 0x80086601 FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 4826bd705..7c866b8f5 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -72,8 +72,6 @@ const ( FF1 = 0x8000 FFDLY = 0x8000 FLUSHO = 0x2000 - FS_IOC_ENABLE_VERITY = 0x80806685 - FS_IOC_GETFLAGS = 0x40046601 FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 2346dc554..c42966d19 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -72,8 +72,6 @@ const ( FF1 = 0x8000 FFDLY = 0x8000 FLUSHO = 0x2000 - FS_IOC_ENABLE_VERITY = 0x80806685 - FS_IOC_GETFLAGS = 0x40086601 FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index e758b61e3..a5b2b4273 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -72,8 +72,6 @@ const ( FF1 = 0x8000 FFDLY = 0x8000 FLUSHO = 0x2000 - FS_IOC_ENABLE_VERITY = 0x80806685 - FS_IOC_GETFLAGS = 0x40086601 FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 2dfe6bba1..7f91881b8 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -72,8 +72,6 @@ const ( FF1 = 0x8000 FFDLY = 0x8000 FLUSHO = 0x2000 - FS_IOC_ENABLE_VERITY = 0x80806685 - FS_IOC_GETFLAGS = 0x40046601 FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 518586670..63df35597 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -72,8 +72,6 @@ const ( FF1 = 0x4000 FFDLY = 0x4000 FLUSHO = 0x800000 - FS_IOC_ENABLE_VERITY = 0x80806685 - FS_IOC_GETFLAGS = 0x40086601 FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 4231b20b5..7ab68f7c8 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -72,8 +72,6 @@ const ( FF1 = 0x4000 FFDLY = 0x4000 FLUSHO = 0x800000 - FS_IOC_ENABLE_VERITY = 0x80806685 - FS_IOC_GETFLAGS = 0x40086601 FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 6a0b2d293..f99cf1b9e 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -72,8 +72,6 @@ const ( FF1 = 0x8000 FFDLY = 0x8000 FLUSHO = 0x1000 - FS_IOC_ENABLE_VERITY = 0x40806685 - FS_IOC_GETFLAGS = 0x80086601 FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 95e950fc8..613ee237e 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -72,8 +72,6 @@ const ( FF1 = 0x8000 FFDLY = 0x8000 FLUSHO = 0x1000 - FS_IOC_ENABLE_VERITY = 0x40806685 - FS_IOC_GETFLAGS = 0x80086601 FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 079762fa9..1f7a68d5c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -76,8 +76,6 @@ const ( FF1 = 0x8000 FFDLY = 0x8000 FLUSHO = 0x1000 - FS_IOC_ENABLE_VERITY = 0x80806685 - FS_IOC_GETFLAGS = 0x40086601 FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go index 1b897dee0..f0d2890b1 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go @@ -151,7 +151,7 @@ func Getgid() (gid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getrlimit(resource int, rlim *Rlimit) (err error) { +func Getrlimit(resource int, rlim *Rlimit) (err error) { _, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) if e1 != 0 { err = errnoErr(e1) @@ -307,7 +307,7 @@ func Setresuid(ruid int, euid int, suid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func setrlimit(resource int, rlim *Rlimit) (err error) { +func Setrlimit(resource int, rlim *Rlimit) (err error) { _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) if e1 != 0 { err = errnoErr(e1) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index 54559a895..7aae554f2 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -431,6 +431,4 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 054a741b7..7968439a9 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -353,6 +353,4 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 307f2ba12..3c663c69d 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -395,6 +395,4 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index e9404dd54..1f3b4d150 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -298,6 +298,4 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index 68bb6d29b..00da3de90 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -416,6 +416,4 @@ const ( SYS_FSPICK = 4433 SYS_PIDFD_OPEN = 4434 SYS_CLONE3 = 4435 - SYS_OPENAT2 = 4437 - SYS_PIDFD_GETFD = 4438 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 4e5251185..d404fbd4d 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -346,6 +346,4 @@ const ( SYS_FSPICK = 5433 SYS_PIDFD_OPEN = 5434 SYS_CLONE3 = 5435 - SYS_OPENAT2 = 5437 - SYS_PIDFD_GETFD = 5438 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index 4d9aa3003..bfbf242f3 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -346,6 +346,4 @@ const ( SYS_FSPICK = 5433 SYS_PIDFD_OPEN = 5434 SYS_CLONE3 = 5435 - SYS_OPENAT2 = 5437 - SYS_PIDFD_GETFD = 5438 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index 64af0707d..3826f497a 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -416,6 +416,4 @@ const ( SYS_FSPICK = 4433 SYS_PIDFD_OPEN = 4434 SYS_CLONE3 = 4435 - SYS_OPENAT2 = 4437 - SYS_PIDFD_GETFD = 4438 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index cc3c067ba..52e3da649 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -395,6 +395,4 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 4050ff983..6141f90a8 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -395,6 +395,4 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 529abb6a7..4f7261a88 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -297,6 +297,4 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index 276650010..f47014ac0 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -360,6 +360,4 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 4dc82bb24..dd78abb0d 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -374,6 +374,4 @@ const ( SYS_FSMOUNT = 432 SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 ) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go index af5ab4552..cb5e06c60 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -114,8 +114,7 @@ type FscryptKeySpecifier struct { type FscryptAddKeyArg struct { Key_spec FscryptKeySpecifier Raw_size uint32 - Key_id uint32 - _ [8]uint32 + _ [9]uint32 } type FscryptRemoveKeyArg struct { @@ -480,7 +479,7 @@ const ( IFLA_NEW_IFINDEX = 0x31 IFLA_MIN_MTU = 0x32 IFLA_MAX_MTU = 0x33 - IFLA_MAX = 0x36 + IFLA_MAX = 0x35 IFLA_INFO_KIND = 0x1 IFLA_INFO_DATA = 0x2 IFLA_INFO_XSTATS = 0x3 @@ -2292,49 +2291,3 @@ const ( DEVLINK_DPIPE_HEADER_IPV4 = 0x1 DEVLINK_DPIPE_HEADER_IPV6 = 0x2 ) - -type FsverityDigest struct { - Algorithm uint16 - Size uint16 -} - -type FsverityEnableArg struct { - Version uint32 - Hash_algorithm uint32 - Block_size uint32 - Salt_size uint32 - Salt_ptr uint64 - Sig_size uint32 - _ uint32 - Sig_ptr uint64 - _ [11]uint64 -} - -type Nhmsg struct { - Family uint8 - Scope uint8 - Protocol uint8 - Resvd uint8 - Flags uint32 -} - -type NexthopGrp struct { - Id uint32 - Weight uint8 - Resvd1 uint8 - Resvd2 uint16 -} - -const ( - NHA_UNSPEC = 0x0 - NHA_ID = 0x1 - NHA_GROUP = 0x2 - NHA_GROUP_TYPE = 0x3 - NHA_BLACKHOLE = 0x4 - NHA_OIF = 0x5 - NHA_GATEWAY = 0x6 - NHA_ENCAP_TYPE = 0x7 - NHA_ENCAP = 0x8 - NHA_GROUPS = 0x9 - NHA_MASTER = 0xa -) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 761b67c86..fc6b3fb5c 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -287,7 +287,6 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Ac_btime64 uint64 } type cpuMask uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index 201fb3482..26c30b84d 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -298,7 +298,6 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Ac_btime64 uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 8051b5610..814d42d54 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -276,7 +276,6 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Ac_btime64 uint64 } type cpuMask uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index a936f2169..d9664c713 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -277,7 +277,6 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Ac_btime64 uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index aaca03dd7..0d721454f 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -281,7 +281,6 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Ac_btime64 uint64 } type cpuMask uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 2e7f3b8ca..ef697684d 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -280,7 +280,6 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Ac_btime64 uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 16add5a25..485fda70b 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -280,7 +280,6 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Ac_btime64 uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index 4ed2c8e54..569477eef 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -281,7 +281,6 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Ac_btime64 uint64 } type cpuMask uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 741519099..602d8b4ee 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -287,7 +287,6 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Ac_btime64 uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 046c2debd..6db9a7b73 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -287,7 +287,6 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Ac_btime64 uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index 0f2f61a6a..52b5348c2 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -305,7 +305,6 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Ac_btime64 uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index cca1b6be2..a111387b3 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -300,7 +300,6 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Ac_btime64 uint64 } type cpuMask uint64 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 33a73bf18..8153af181 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -282,7 +282,6 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Ac_btime64 uint64 } type cpuMask uint64 diff --git a/vendor/modules.txt b/vendor/modules.txt index 2a2d128f5..2edd9ec9e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,4 +1,5 @@ # github.com/SkycoinProject/dmsg v0.2.2 +## explicit github.com/SkycoinProject/dmsg github.com/SkycoinProject/dmsg/buildinfo github.com/SkycoinProject/dmsg/cipher @@ -10,6 +11,7 @@ github.com/SkycoinProject/dmsg/ioutil github.com/SkycoinProject/dmsg/netutil github.com/SkycoinProject/dmsg/noise # github.com/SkycoinProject/skycoin v0.27.0 +## explicit github.com/SkycoinProject/skycoin/src/cipher github.com/SkycoinProject/skycoin/src/cipher/base58 github.com/SkycoinProject/skycoin/src/cipher/ripemd160 @@ -17,6 +19,7 @@ github.com/SkycoinProject/skycoin/src/cipher/secp256k1-go github.com/SkycoinProject/skycoin/src/cipher/secp256k1-go/secp256k1-go2 github.com/SkycoinProject/skycoin/src/util/logging # github.com/SkycoinProject/yamux v0.0.0-20191213015001-a36efeefbf6a +## explicit github.com/SkycoinProject/yamux # github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 github.com/alecthomas/template @@ -26,6 +29,7 @@ github.com/alecthomas/units # github.com/andybalholm/brotli v0.0.0-20190621154722-5f990b63d2d6 github.com/andybalholm/brotli # github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 +## explicit github.com/armon/go-socks5 # github.com/beorn7/perks v1.0.1 github.com/beorn7/perks/quantile @@ -45,6 +49,7 @@ github.com/dsnet/compress/internal/prefix # github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 github.com/flynn/noise # github.com/go-chi/chi v4.0.2+incompatible +## explicit github.com/go-chi/chi github.com/go-chi/chi/middleware # github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721 @@ -55,10 +60,12 @@ github.com/golang/protobuf/proto # github.com/golang/snappy v0.0.1 github.com/golang/snappy # github.com/google/uuid v1.1.1 +## explicit github.com/google/uuid # github.com/gorilla/handlers v1.4.2 github.com/gorilla/handlers # github.com/gorilla/securecookie v1.1.1 +## explicit github.com/gorilla/securecookie # github.com/inconshreveable/mousetrap v1.0.0 github.com/inconshreveable/mousetrap @@ -71,9 +78,10 @@ github.com/klauspost/compress/zstd github.com/klauspost/compress/zstd/internal/xxhash # github.com/klauspost/pgzip v1.2.1 github.com/klauspost/pgzip -# github.com/konsorten/go-windows-terminal-sequences v1.0.3 +# github.com/konsorten/go-windows-terminal-sequences v1.0.2 github.com/konsorten/go-windows-terminal-sequences # github.com/libp2p/go-reuseport v0.0.1 +## explicit github.com/libp2p/go-reuseport # github.com/mattn/go-colorable v0.1.6 github.com/mattn/go-colorable @@ -84,6 +92,7 @@ github.com/matttproud/golang_protobuf_extensions/pbutil # github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b github.com/mgutz/ansi # github.com/mholt/archiver/v3 v3.3.0 +## explicit github.com/mholt/archiver/v3 # github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db github.com/mitchellh/colorstring @@ -92,13 +101,16 @@ github.com/nwaples/rardecode # github.com/pierrec/lz4 v2.0.5+incompatible github.com/pierrec/lz4 github.com/pierrec/lz4/internal/xxh32 -# github.com/pkg/errors v0.8.1 +# github.com/pkg/errors v0.9.1 +## explicit github.com/pkg/errors # github.com/pkg/profile v1.3.0 +## explicit github.com/pkg/profile # github.com/pmezard/go-difflib v1.0.0 github.com/pmezard/go-difflib/difflib # github.com/prometheus/client_golang v1.3.0 +## explicit github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus/internal github.com/prometheus/client_golang/prometheus/promauto @@ -106,6 +118,7 @@ github.com/prometheus/client_golang/prometheus/promhttp # github.com/prometheus/client_model v0.1.0 github.com/prometheus/client_model/go # github.com/prometheus/common v0.7.0 +## explicit github.com/prometheus/common/expfmt github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg github.com/prometheus/common/log @@ -115,21 +128,27 @@ github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/util # github.com/rakyll/statik v0.1.7 +## explicit github.com/rakyll/statik/fs # github.com/schollz/progressbar/v2 v2.15.0 +## explicit github.com/schollz/progressbar/v2 # github.com/sirupsen/logrus v1.5.0 +## explicit github.com/sirupsen/logrus github.com/sirupsen/logrus/hooks/syslog # github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 +## explicit github.com/songgao/water # github.com/spf13/cobra v0.0.5 +## explicit github.com/spf13/cobra # github.com/spf13/pflag v1.0.3 github.com/spf13/pflag # github.com/stretchr/objx v0.1.1 github.com/stretchr/objx # github.com/stretchr/testify v1.5.1 +## explicit github.com/stretchr/testify/assert github.com/stretchr/testify/mock github.com/stretchr/testify/require @@ -141,8 +160,9 @@ github.com/ulikunitz/xz/lzma # github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 github.com/xi2/xz # go.etcd.io/bbolt v1.3.4 +## explicit go.etcd.io/bbolt -# golang.org/x/crypto v0.0.0-20200427165652-729f1e841bcc +# golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 golang.org/x/crypto/blake2b golang.org/x/crypto/blake2s golang.org/x/crypto/chacha20 @@ -152,6 +172,7 @@ golang.org/x/crypto/internal/subtle golang.org/x/crypto/poly1305 golang.org/x/crypto/ssh/terminal # golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e +## explicit golang.org/x/net/bpf golang.org/x/net/context golang.org/x/net/internal/iana @@ -160,7 +181,7 @@ golang.org/x/net/internal/socks golang.org/x/net/ipv6 golang.org/x/net/nettest golang.org/x/net/proxy -# golang.org/x/sys v0.0.0-20200428200454-593003d681fa +# golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd golang.org/x/sys/cpu golang.org/x/sys/unix golang.org/x/sys/windows @@ -170,6 +191,7 @@ golang.org/x/sys/windows/svc/eventlog golang.org/x/text/transform golang.org/x/text/unicode/norm # golang.zx2c4.com/wireguard v0.0.20200320 +## explicit golang.zx2c4.com/wireguard/rwcancel golang.zx2c4.com/wireguard/tun golang.zx2c4.com/wireguard/tun/wintun @@ -183,6 +205,7 @@ gopkg.in/alecthomas/kingpin.v2 # gopkg.in/yaml.v2 v2.2.4 gopkg.in/yaml.v2 # nhooyr.io/websocket v1.8.2 +## explicit nhooyr.io/websocket nhooyr.io/websocket/internal/bpool nhooyr.io/websocket/internal/errd